From 7baf687499d1eb0d7223536810889dbeb85245f9 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Fri, 6 Sep 2013 10:37:03 +0200 Subject: [PATCH] MetaCursorTracker: add support for loading cursors from the theme Not only this way we get the right Adwaita cursor as the default (instead of shipping our own in png format), but we also add support for all MetaCursors as root cursor (which most important should allow us to have I-beams in shell entries) https://bugzilla.gnome.org/show_bug.cgi?id=707573 --- Makefile.am | 2 +- configure.ac | 15 +-- data/Makefile.am | 3 - data/left_ptr.png | Bin 736 -> 0 bytes src/core/display.c | 9 -- src/core/meta-cursor-tracker.c | 204 ++++++++++++++++++--------------- 6 files changed, 116 insertions(+), 117 deletions(-) delete mode 100644 data/Makefile.am delete mode 100644 data/left_ptr.png diff --git a/Makefile.am b/Makefile.am index 18afe05c7..979ba2573 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ -SUBDIRS=src protocol data po doc +SUBDIRS=src protocol po doc EXTRA_DIST = HACKING MAINTAINERS rationales.txt diff --git a/configure.ac b/configure.ac index 432f74c8b..0e98cd53c 100644 --- a/configure.ac +++ b/configure.ac @@ -209,19 +209,7 @@ if test x$found_introspection != xno; then AC_SUBST(META_GIR) fi -AC_MSG_CHECKING([Xcursor]) -if $PKG_CONFIG xcursor; then - have_xcursor=yes - else - have_xcursor=no - fi - AC_MSG_RESULT($have_xcursor) - -if test x$have_xcursor = xyes; then - echo "Building with Xcursor" - MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor" - AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support]) -fi +MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor" # We always build with wayland enabled AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support]) @@ -473,7 +461,6 @@ src/Makefile src/libmutter-wayland.pc src/compositor/plugins/Makefile protocol/Makefile -data/Makefile po/Makefile.in ]) diff --git a/data/Makefile.am b/data/Makefile.am deleted file mode 100644 index 58f590006..000000000 --- a/data/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -defaultcursordir = $(pkgdatadir)/cursors - -dist_defaultcursor_DATA = left_ptr.png diff --git a/data/left_ptr.png b/data/left_ptr.png deleted file mode 100644 index d3818ccfb7cbad66fe321f1ff1a3bfa2e5ddd35b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 736 zcmV<60w4W}P)m2~@wG(y}3WZMq)zrX((fYNG2 zCdo)7!mFz*?(FP*1mJHaB9o-o>*d761a)2K=H_M&z=KvHGD%93#6TdxSS&`vFqp|? zvH*OoKxC41I2`o(d<=y`OeT{wO_R&Z%kKf)hy9fA1^}SPTnDg`V6hbhSO0B`pNmIxl003oKW=~HK2L}f^Ha5n^ z#YGAsI6FK08bDVw$Th&_a#2wf_Vx8~baa%_Xq2m~s}w>okx0A(;JFEL+(xr3>)NbV zt2jD3g4^vzHk-}F<8d>e&wl_=u5YTb4ggS+BnE>)7K=p+At;1krBY$7R-pEvc#r{dVXYNBn{v(0Qdh2-6VI^=kFZ+z3!^R1YiKD;+ElR%lHM&^I8OL S #endif -#ifdef HAVE_XCURSOR #include -#endif #include #include #include @@ -828,14 +826,10 @@ meta_display_open (void) meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n"); } -#ifdef HAVE_XCURSOR { XcursorSetTheme (the_display->xdisplay, meta_prefs_get_cursor_theme ()); XcursorSetDefaultSize (the_display->xdisplay, meta_prefs_get_cursor_size ()); } -#else /* HAVE_XCURSOR */ - meta_verbose ("Not compiled with Xcursor support\n"); -#endif /* !HAVE_XCURSOR */ /* Create the leader window here. Set its properties and * use the timestamp from one of the PropertyNotify events @@ -4726,7 +4720,6 @@ void meta_display_set_cursor_theme (const char *theme, int size) { -#ifdef HAVE_XCURSOR GSList *tmp; MetaDisplay *display = meta_get_display (); @@ -4743,8 +4736,6 @@ meta_display_set_cursor_theme (const char *theme, tmp = tmp->next; } - -#endif } /* diff --git a/src/core/meta-cursor-tracker.c b/src/core/meta-cursor-tracker.c index 2971c7b2b..cee0a99aa 100644 --- a/src/core/meta-cursor-tracker.c +++ b/src/core/meta-cursor-tracker.c @@ -43,6 +43,7 @@ #include #include +#include #include "meta-cursor-tracker-private.h" #include "screen-private.h" @@ -71,7 +72,7 @@ struct _MetaCursorTracker { MetaCursorReference *sprite; MetaCursorReference *root_cursor; - MetaCursorReference *default_cursor; + MetaCursorReference *default_cursors[META_CURSOR_LAST]; int current_x, current_y; MetaRectangle current_rect; @@ -127,49 +128,107 @@ meta_cursor_reference_unref (MetaCursorReference *self) } } -static MetaCursorReference * -meta_cursor_reference_from_file (MetaCursorTracker *tracker, - const char *filename, - GError **error) +static const char * +get_cursor_filename (MetaCursor cursor) { - GdkPixbuf *pixbuf; + switch (cursor) + { + case META_CURSOR_DEFAULT: + return "left_ptr"; + break; + case META_CURSOR_NORTH_RESIZE: + return "top_side"; + break; + case META_CURSOR_SOUTH_RESIZE: + return "bottom_side"; + break; + case META_CURSOR_WEST_RESIZE: + return "left_side"; + break; + case META_CURSOR_EAST_RESIZE: + return "right_side"; + break; + case META_CURSOR_SE_RESIZE: + return "bottom_right_corner"; + break; + case META_CURSOR_SW_RESIZE: + return "bottom_left_corner"; + break; + case META_CURSOR_NE_RESIZE: + return "top_right_corner"; + break; + case META_CURSOR_NW_RESIZE: + return "top_left_corner"; + break; + case META_CURSOR_MOVE_OR_RESIZE_WINDOW: + return "fleur"; + break; + case META_CURSOR_BUSY: + return "busy"; + break; + case META_CURSOR_DND_IN_DRAG: + return "dnd-in-drag"; + break; + case META_CURSOR_DND_MOVE: + return "dnd-copy"; + break; + case META_CURSOR_DND_UNSUPPORTED_TARGET: + return "dnd-none"; + break; + case META_CURSOR_POINTING_HAND: + return "hand"; + break; + case META_CURSOR_CROSSHAIR: + return "crosshair"; + break; + case META_CURSOR_IBEAM: + return "xterm"; + break; + + default: + g_assert_not_reached (); + return NULL; + } +} + +static MetaCursorReference * +meta_cursor_reference_from_theme (MetaCursorTracker *tracker, + MetaCursor cursor) +{ + const char *theme; + const char *filename; + int size; + XcursorImage *image; int width, height, rowstride; - int bits_per_sample; - int n_channels; - gboolean has_alpha; CoglPixelFormat cogl_format; uint32_t gbm_format; ClutterBackend *clutter_backend; CoglContext *cogl_context; MetaCursorReference *self; - pixbuf = gdk_pixbuf_new_from_file (filename, error); - if (!pixbuf) + filename = get_cursor_filename (cursor); + theme = XcursorGetTheme (tracker->screen->display->xdisplay); + size = XcursorGetDefaultSize (tracker->screen->display->xdisplay); + + image = XcursorLibraryLoadImage (filename, theme, size); + if (!image) return NULL; - has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf); - n_channels = gdk_pixbuf_get_n_channels (pixbuf); + width = image->width; + height = image->height; + rowstride = width * 4; - g_assert (bits_per_sample == 8); - if (has_alpha) - { - g_assert (n_channels == 4); - cogl_format = COGL_PIXEL_FORMAT_RGBA_8888; - gbm_format = GBM_FORMAT_ARGB8888; - } - else - { - g_assert (n_channels == 3); - cogl_format = COGL_PIXEL_FORMAT_RGB_888; - gbm_format = GBM_FORMAT_XRGB8888; - } + gbm_format = GBM_FORMAT_ARGB8888; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; +#else + cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; +#endif self = g_slice_new0 (MetaCursorReference); self->ref_count = 1; + self->hot_x = image->xhot; + self->hot_y = image->yhot; clutter_backend = clutter_get_default_backend (); cogl_context = clutter_backend_get_cogl_context (clutter_backend); @@ -178,54 +237,29 @@ meta_cursor_reference_from_file (MetaCursorTracker *tracker, cogl_format, COGL_PIXEL_FORMAT_ANY, rowstride, - gdk_pixbuf_get_pixels (pixbuf), + (uint8_t*)image->pixels, NULL); if (tracker->gbm) { if (width > 64 || height > 64) { - meta_warning ("Invalid default cursor size (must be at most 64x64)\n"); + meta_warning ("Invalid theme cursor size (must be at most 64x64)\n"); goto out; } if (gbm_device_is_format_supported (tracker->gbm, gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE)) { - uint8_t *data; - uint8_t buf[4 * 64 * 64]; - int i, j; + uint32_t buf[64 * 64]; + int i; self->bo = gbm_bo_create (tracker->gbm, 64, 64, gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); - data = gdk_pixbuf_get_pixels (pixbuf); memset (buf, 0, sizeof(buf)); for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - /* The byte order is B G R (A) */ - buf[i * 4 * 64 + j * 4 + 0] = data[i * rowstride + j * n_channels + 2]; - buf[i * 4 * 64 + j * 4 + 1] = data[i * rowstride + j * n_channels + 1]; - buf[i * 4 * 64 + j * 4 + 2] = data[i * rowstride + j * n_channels + 0]; - if (has_alpha) - buf[i * 4 * 64 + j * 4 + 3] = data[i * rowstride + j * n_channels + 3]; - else - buf[i * 4 * 64 + j * 4 + 3] = 0; -#else - /* The byte order is (A) R G B */ - buf[i * 4 * 64 + j * 4 + 3] = data[i * rowstride + j * n_channels + 2]; - buf[i * 4 * 64 + j * 4 + 2] = data[i * rowstride + j * n_channels + 1]; - buf[i * 4 * 64 + j * 4 + 1] = data[i * rowstride + j * n_channels + 0]; - if (has_alpha) - buf[i * 4 * 64 + j * 4 + 0] = data[i * rowstride + j * n_channels + 3]; - else - buf[i * 4 * 64 + j * 4 + 0] = 0; -#endif - } - } + memcpy (buf + i * 64, image->pixels + i * width, width * 4); gbm_bo_write (self->bo, buf, 64 * 64 * 4); } @@ -234,7 +268,7 @@ meta_cursor_reference_from_file (MetaCursorTracker *tracker, } out: - g_object_unref (pixbuf); + XcursorImageDestroy (image); return self; } @@ -431,13 +465,17 @@ static void meta_cursor_tracker_finalize (GObject *object) { MetaCursorTracker *self = META_CURSOR_TRACKER (object); + int i; if (self->sprite) meta_cursor_reference_unref (self->sprite); if (self->root_cursor) meta_cursor_reference_unref (self->root_cursor); - if (self->default_cursor) - meta_cursor_reference_unref (self->default_cursor); + + for (i = 0; i < META_CURSOR_LAST; i++) + if (self->default_cursors[i]) + meta_cursor_reference_unref (self->default_cursors[i]); + if (self->pipeline) cogl_object_unref (self->pipeline); if (self->gbm) @@ -693,33 +731,18 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, } } -static void -ensure_wayland_cursor (MetaCursorTracker *tracker) +static MetaCursorReference * +ensure_wayland_cursor (MetaCursorTracker *tracker, + MetaCursor cursor) { - char *filename; - GError *error; + if (tracker->default_cursors[cursor]) + return tracker->default_cursors[cursor]; - if (tracker->default_cursor) - return; + tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor); + if (!tracker->default_cursors[cursor]) + meta_warning ("Failed to load cursor from theme\n"); - filename = g_build_filename (MUTTER_PKGDATADIR, - "cursors/left_ptr.png", - NULL); - - error = NULL; - tracker->default_cursor = meta_cursor_reference_from_file (tracker, filename, &error); - if (!tracker->default_cursor) - { - if (error) - g_error ("Failed to load default cursor: %s", error->message); - else - g_error ("Failed to load default cursor"); - } - - tracker->default_cursor->hot_x = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X; - tracker->default_cursor->hot_y = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y; - - g_free (filename); + return tracker->default_cursors[cursor]; } void @@ -739,11 +762,12 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, /* Now update the real root cursor */ if (meta_is_wayland_compositor ()) { - /* FIXME! We need to load all the other cursors too */ - ensure_wayland_cursor (tracker); + MetaCursorReference *ref; + + ref = ensure_wayland_cursor (tracker, cursor); g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref); - tracker->root_cursor = meta_cursor_reference_ref (tracker->default_cursor); + tracker->root_cursor = meta_cursor_reference_ref (ref); } }