[gtk/wayland-cursors: 2/2] Make wayland load cursors on demand



commit fa28101b55a81b9944c9b4e223698d62390d2629
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jan 24 14:36:21 2020 -0500

    Make wayland load cursors on demand
    
    This changes the startup cost for cursor theme loading
    from 25ms to 0.1ms.
    
    Only problem: the cursor is blank the first time I use it.

 gdk/wayland/cursor/wayland-cursor.c | 127 ++++++++----------------------------
 gdk/wayland/cursor/xcursor.c        |  13 ++++
 gdk/wayland/cursor/xcursor.h        |   4 ++
 gdk/wayland/gdkdisplay-wayland.c    |   5 +-
 4 files changed, 49 insertions(+), 100 deletions(-)
---
diff --git a/gdk/wayland/cursor/wayland-cursor.c b/gdk/wayland/cursor/wayland-cursor.c
index 0a208bc8ef..594239aaf7 100644
--- a/gdk/wayland/cursor/wayland-cursor.c
+++ b/gdk/wayland/cursor/wayland-cursor.c
@@ -36,6 +36,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <os-compatibility.h>
+#include <glib.h>
 
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 
@@ -134,8 +135,8 @@ struct wl_cursor_theme {
        struct wl_cursor **cursors;
        struct wl_shm *shm;
        struct shm_pool *pool;
-       char *name;
        int size;
+        char *path;
 };
 
 struct cursor_image {
@@ -200,7 +201,8 @@ wl_cursor_destroy(struct wl_cursor *cursor)
 
 static struct wl_cursor *
 wl_cursor_create_from_xcursor_images(XcursorImages *images,
-                                    struct wl_cursor_theme *theme)
+                                    struct wl_cursor_theme *theme,
+                                     const char *name)
 {
        struct cursor *cursor;
        struct cursor_image *image;
@@ -217,7 +219,7 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
                return NULL;
        }
 
-       cursor->cursor.name = strdup(images->name);
+       cursor->cursor.name = strdup(name);
        cursor->total_delay = 0;
 
        for (i = 0; i < images->nimage; i++) {
@@ -260,17 +262,15 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
 }
 
 static void
-load_callback(XcursorImages *images, void *data)
+load_cursor(struct wl_cursor_theme *theme, const char *name)
 {
-       struct wl_cursor_theme *theme = data;
+        XcursorImages *images;
        struct wl_cursor *cursor;
+        char *path;
 
-       if (wl_cursor_theme_get_cursor(theme, images->name)) {
-               XcursorImagesDestroy(images);
-               return;
-       }
-
-       cursor = wl_cursor_create_from_xcursor_images(images, theme);
+        path = g_strconcat (theme->path, "/", name, NULL);
+        images = xcursor_load_images (path, theme->size);
+       cursor = wl_cursor_create_from_xcursor_images(images, theme, name);
 
        if (cursor) {
                theme->cursor_count++;
@@ -287,6 +287,7 @@ load_callback(XcursorImages *images, void *data)
        }
 
        XcursorImagesDestroy(images);
+        g_free (path);
 }
 
 /** Load a cursor theme to memory shared with the compositor
@@ -301,7 +302,7 @@ load_callback(XcursorImages *images, void *data)
  * name exists, a default theme will be loaded.
  */
 WL_EXPORT struct wl_cursor_theme *
-wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
+wl_cursor_theme_load(const char *path, int size, struct wl_shm *shm)
 {
        struct wl_cursor_theme *theme;
 
@@ -309,29 +310,19 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
        if (!theme)
                return NULL;
 
-       if (!name)
-               name = "default";
-
-       theme->name = strdup(name);
-       if (!theme->name)
-               goto out_error_name;
+       theme->path = strdup (path);
        theme->size = size;
        theme->cursor_count = 0;
        theme->cursors = NULL;
 
        theme->pool = shm_pool_create(shm, size * size * 4);
-       if (!theme->pool)
-               goto out_error_pool;
-
-       xcursor_load_theme(name, size, load_callback, theme);
+       if (!theme->pool) {
+                free (theme->path);
+                free (theme);
+               return NULL;
+        }
 
        return theme;
-
-out_error_pool:
-       free(theme->name);
-out_error_name:
-       free(theme);
-       return NULL;
 }
 
 /** Destroys a cursor theme object
@@ -348,8 +339,8 @@ wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
 
        shm_pool_destroy(theme->pool);
 
-       free(theme->name);
        free(theme->cursors);
+        free(theme->path);
        free(theme);
 }
 
@@ -364,78 +355,16 @@ WL_EXPORT struct wl_cursor *
 wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
                           const char *name)
 {
+        int t;
        unsigned int i;
 
-       for (i = 0; i < theme->cursor_count; i++) {
-               if (strcmp(name, theme->cursors[i]->name) == 0)
-                       return theme->cursors[i];
-       }
+        for (t = 0; t < 1; t++) {
+               for (i = 0; i < theme->cursor_count; i++) {
+                       if (strcmp(name, theme->cursors[i]->name) == 0)
+                               return theme->cursors[i];
+               }
+                load_cursor (theme, name);
+        }
 
        return NULL;
 }
-
-/** Find the frame for a given elapsed time in a cursor animation
- *  as well as the time left until next cursor change.
- *
- * \param cursor The cursor
- * \param time Elapsed time in ms since the beginning of the animation
- * \param duration pointer to uint32_t to store time left for this image or
- *                 zero if the cursor won't change.
- *
- * \return The index of the image that should be displayed for the
- * given time in the cursor animation.
- */
-WL_EXPORT int
-wl_cursor_frame_and_duration(struct wl_cursor *_cursor, uint32_t time,
-                            uint32_t *duration)
-{
-       struct cursor *cursor = (struct cursor *) _cursor;
-       uint32_t t;
-       int i;
-
-       if (cursor->cursor.image_count == 1) {
-               if (duration)
-                       *duration = 0;
-               return 0;
-       }
-
-       i = 0;
-       t = time % cursor->total_delay;
-
-       /* If there is a 0 delay in the image set then this
-        * loop breaks on it and we display that cursor until
-        * time % cursor->total_delay wraps again.
-        * Since a 0 delay is silly, and we've never actually
-        * seen one in a cursor file, we haven't bothered to
-        * "fix" this.
-        */
-       while (t - cursor->cursor.images[i]->delay < t)
-               t -= cursor->cursor.images[i++]->delay;
-
-       if (!duration)
-               return i;
-
-       /* Make sure we don't accidentally tell the caller this is
-        * a static cursor image.
-        */
-       if (t >= cursor->cursor.images[i]->delay)
-               *duration = 1;
-       else
-               *duration = cursor->cursor.images[i]->delay - t;
-
-       return i;
-}
-
-/** Find the frame for a given elapsed time in a cursor animation
- *
- * \param cursor The cursor
- * \param time Elapsed time in ms since the beginning of the animation
- *
- * \return The index of the image that should be displayed for the
- * given time in the cursor animation.
- */
-WL_EXPORT int
-wl_cursor_frame(struct wl_cursor *_cursor, uint32_t time)
-{
-       return wl_cursor_frame_and_duration(_cursor, time, NULL);
-}
diff --git a/gdk/wayland/cursor/xcursor.c b/gdk/wayland/cursor/xcursor.c
index 689c702672..a88ad8b804 100644
--- a/gdk/wayland/cursor/xcursor.c
+++ b/gdk/wayland/cursor/xcursor.c
@@ -975,3 +975,16 @@ xcursor_load_theme(const char *theme, int size,
        if (inherits)
                free(inherits);
 }
+
+XcursorImages *
+xcursor_load_images (const char *path, int size)
+{
+        FILE    *f;
+        XcursorImages *images;
+
+        f = fopen (path, "r");
+        images = XcursorFileLoadImages (f, size);
+        fclose (f);
+
+        return images;
+}
diff --git a/gdk/wayland/cursor/xcursor.h b/gdk/wayland/cursor/xcursor.h
index 62e232202a..6a5a71648a 100644
--- a/gdk/wayland/cursor/xcursor.h
+++ b/gdk/wayland/cursor/xcursor.h
@@ -62,4 +62,8 @@ void
 xcursor_load_theme(const char *theme, int size,
                    void (*load_callback)(XcursorImages *, void *),
                    void *user_data);
+
+XcursorImages *
+xcursor_load_images (const char *path, int size);
+
 #endif
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index 57c15281c8..4533a87fa5 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -1068,6 +1068,7 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay  *display,
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY(display);
   struct wl_cursor_theme *theme;
   int i;
+  char *path;
 
   g_assert (display_wayland);
   g_assert (display_wayland->shm);
@@ -1076,7 +1077,9 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay  *display,
       display_wayland->cursor_theme_size == size)
     return;
 
-  theme = wl_cursor_theme_load (name, size, display_wayland->shm);
+  path = g_strconcat ("/usr/share/icons/", name, "/cursors", NULL);
+  theme = wl_cursor_theme_load (path, size, display_wayland->shm);
+  g_free (path);
   if (theme == NULL)
     {
       g_warning ("Failed to load cursor theme %s", name);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]