From b2113b73843a180747ccec43a48e369617ddabd0 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 7 Aug 2013 12:18:38 +0200 Subject: [PATCH] gdk: Add gdk_cursor_new_from_surface We need this to be able to handle scaled cursor images. We implement the new _from_pixbuf by converting to a surface and assuming the scale was 1. --- gdk/broadway/gdkcursor-broadway.c | 8 +- gdk/broadway/gdkdisplay-broadway.c | 2 +- gdk/broadway/gdkprivate-broadway.h | 8 +- gdk/gdkcursor.c | 74 ++++++++++++++- gdk/gdkcursor.h | 5 + gdk/gdkdisplayprivate.h | 8 +- gdk/wayland/gdkcursor-wayland.c | 144 +++++++++++------------------ gdk/wayland/gdkdevice-wayland.c | 5 +- gdk/wayland/gdkdisplay-wayland.c | 2 +- gdk/wayland/gdkprivate-wayland.h | 11 ++- gdk/x11/gdkcursor-x11.c | 110 ++++++++++++---------- gdk/x11/gdkdisplay-x11.c | 2 +- gdk/x11/gdkprivate-x11.h | 8 +- 13 files changed, 220 insertions(+), 167 deletions(-) diff --git a/gdk/broadway/gdkcursor-broadway.c b/gdk/broadway/gdkcursor-broadway.c index 72fc84e1e2..dccccc63f8 100644 --- a/gdk/broadway/gdkcursor-broadway.c +++ b/gdk/broadway/gdkcursor-broadway.c @@ -118,10 +118,10 @@ _gdk_broadway_cursor_update_theme (GdkCursor *cursor) } GdkCursor * -_gdk_broadway_display_get_cursor_for_pixbuf (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y) +_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y) { GdkBroadwayCursor *private; GdkCursor *cursor; diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c index dff7457147..36ce56921d 100644 --- a/gdk/broadway/gdkdisplay-broadway.c +++ b/gdk/broadway/gdkdisplay-broadway.c @@ -375,7 +375,7 @@ gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class) display_class->list_devices = gdk_broadway_display_list_devices; display_class->get_cursor_for_type = _gdk_broadway_display_get_cursor_for_type; display_class->get_cursor_for_name = _gdk_broadway_display_get_cursor_for_name; - display_class->get_cursor_for_pixbuf = _gdk_broadway_display_get_cursor_for_pixbuf; + display_class->get_cursor_for_surface = _gdk_broadway_display_get_cursor_for_surface; display_class->get_default_cursor_size = _gdk_broadway_display_get_default_cursor_size; display_class->get_maximal_cursor_size = _gdk_broadway_display_get_maximal_cursor_size; display_class->supports_cursor_alpha = _gdk_broadway_display_supports_cursor_alpha; diff --git a/gdk/broadway/gdkprivate-broadway.h b/gdk/broadway/gdkprivate-broadway.h index acbd8a281f..efc66c0bcb 100644 --- a/gdk/broadway/gdkprivate-broadway.h +++ b/gdk/broadway/gdkprivate-broadway.h @@ -125,10 +125,10 @@ GdkCursor*_gdk_broadway_display_get_cursor_for_type (GdkDisplay *display, GdkCursorType cursor_type); GdkCursor*_gdk_broadway_display_get_cursor_for_name (GdkDisplay *display, const gchar *name); -GdkCursor *_gdk_broadway_display_get_cursor_for_pixbuf (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y); +GdkCursor *_gdk_broadway_display_get_cursor_for_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y); gboolean _gdk_broadway_display_supports_cursor_alpha (GdkDisplay *display); gboolean _gdk_broadway_display_supports_cursor_color (GdkDisplay *display); void _gdk_broadway_display_get_default_cursor_size (GdkDisplay *display, diff --git a/gdk/gdkcursor.c b/gdk/gdkcursor.c index d1825913d6..a336ea79ef 100644 --- a/gdk/gdkcursor.c +++ b/gdk/gdkcursor.c @@ -34,6 +34,7 @@ #include "gdkinternals.h" #include +#include /** * SECTION:cursors @@ -351,12 +352,81 @@ gdk_cursor_new_from_pixbuf (GdkDisplay *display, gint x, gint y) { + cairo_surface_t *surface; + const char *option; + char *end; + gint64 value; + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); - return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_pixbuf (display, pixbuf, x, y); + if (x == -1 && (option = gdk_pixbuf_get_option (pixbuf, "x_hot"))) + { + errno = 0; + end = NULL; + value = g_ascii_strtoll (option, &end, 10); + if (errno == 0 && + end != option && + value >= 0 && value < G_MAXINT) + x = (gint) value; + } + + if (y == -1 && (option = gdk_pixbuf_get_option (pixbuf, "y_hot"))) + { + errno = 0; + end = NULL; + value = g_ascii_strtoll (option, &end, 10); + if (errno == 0 && + end != option && + value >= 0 && value < G_MAXINT) + y = (gint) value; + } + + surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL); + + return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display, surface, x, y); } +/** + * gdk_cursor_new_from_surface: + * @display: the #GdkDisplay for which the cursor will be created + * @surface: the cairo image surface containing the cursor pixel data + * @x: the horizontal offset of the 'hotspot' of the cursor. + * @y: the vertical offset of the 'hotspot' of the cursor. + * + * Creates a new cursor from a pixbuf. + * + * Not all GDK backends support RGBA cursors. If they are not + * supported, a monochrome approximation will be displayed. + * The functions gdk_display_supports_cursor_alpha() and + * gdk_display_supports_cursor_color() can be used to determine + * whether RGBA cursors are supported; + * gdk_display_get_default_cursor_size() and + * gdk_display_get_maximal_cursor_size() give information about + * cursor sizes. + * + * On the X backend, support for RGBA cursors requires a + * sufficently new version of the X Render extension. + * + * Returns: a new #GdkCursor. + * + * Since: 3.10 + */ +GdkCursor * +gdk_cursor_new_from_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + g_return_val_if_fail (surface != NULL, NULL); + g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL); + g_return_val_if_fail (0 <= x && x < cairo_image_surface_get_width (surface), NULL); + g_return_val_if_fail (0 <= y && y < cairo_image_surface_get_height (surface), NULL); + + return GDK_DISPLAY_GET_CLASS (display)->get_cursor_for_surface (display, + surface, x, y); +} /** * gdk_cursor_get_display: * @cursor: a #GdkCursor. @@ -405,7 +475,7 @@ gdk_cursor_get_image (GdkCursor *cursor) surface = gdk_cursor_get_surface (cursor, &x_hot, &y_hot); if (surface == NULL) return NULL; - + w = cairo_image_surface_get_width (surface); h = cairo_image_surface_get_height (surface); diff --git a/gdk/gdkcursor.h b/gdk/gdkcursor.h index 50880b3e66..af843605a3 100644 --- a/gdk/gdkcursor.h +++ b/gdk/gdkcursor.h @@ -228,6 +228,11 @@ GdkCursor* gdk_cursor_new_from_pixbuf (GdkDisplay *display, GdkPixbuf *pixbuf, gint x, gint y); +GDK_AVAILABLE_IN_3_10 +GdkCursor* gdk_cursor_new_from_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y); GDK_AVAILABLE_IN_ALL GdkCursor* gdk_cursor_new_from_name (GdkDisplay *display, const gchar *name); diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 582c2791d6..365b429c33 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -170,10 +170,10 @@ struct _GdkDisplayClass GdkCursorType type); GdkCursor * (*get_cursor_for_name) (GdkDisplay *display, const gchar *name); - GdkCursor * (*get_cursor_for_pixbuf) (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y); + GdkCursor * (*get_cursor_for_surface) (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y); GList * (*list_devices) (GdkDisplay *display); GdkAppLaunchContext * (*get_app_launch_context) (GdkDisplay *display); diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c index 035106fd6d..76d0fbdf12 100644 --- a/gdk/wayland/gdkcursor-wayland.c +++ b/gdk/wayland/gdkcursor-wayland.c @@ -55,9 +55,9 @@ struct _GdkWaylandCursor struct { int hotspot_x, hotspot_y; - int width, height; + int width, height, scale; struct wl_buffer *buffer; - } pixbuf; + } surface; struct wl_cursor *wl_cursor; }; @@ -168,8 +168,8 @@ gdk_wayland_cursor_finalize (GObject *object) GdkWaylandCursor *cursor = GDK_WAYLAND_CURSOR (object); g_free (cursor->name); - if (cursor->pixbuf.buffer) - wl_buffer_destroy (cursor->pixbuf.buffer); + if (cursor->surface.buffer) + wl_buffer_destroy (cursor->surface.buffer); G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object); } @@ -188,7 +188,8 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor, int *hotspot_x, int *hotspot_y, int *w, - int *h) + int *h, + int *scale) { GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor); @@ -211,18 +212,20 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor, *w = image->width; *h = image->height; + *scale = 1; return wl_cursor_image_get_buffer (image); } - else /* From pixbuf */ + else /* From surface */ { - *hotspot_x = wayland_cursor->pixbuf.hotspot_x; - *hotspot_y = wayland_cursor->pixbuf.hotspot_y; + *hotspot_x = wayland_cursor->surface.hotspot_x; + *hotspot_y = wayland_cursor->surface.hotspot_y; - *w = wayland_cursor->pixbuf.width; - *h = wayland_cursor->pixbuf.height; + *w = wayland_cursor->surface.width / wayland_cursor->surface.scale; + *h = wayland_cursor->surface.height / wayland_cursor->surface.scale; + *scale = wayland_cursor->surface.scale; - return wayland_cursor->pixbuf.buffer; + return wayland_cursor->surface.buffer; } } @@ -268,60 +271,6 @@ _gdk_wayland_cursor_init (GdkWaylandCursor *cursor) { } -/* Used to implement from_pixbuf below */ -static void -set_pixbuf (gpointer argb_pixels, int width, int height, GdkPixbuf *pixbuf) -{ - int stride, i, n_channels; - unsigned char *pixels, *end, *s, *d; - - stride = gdk_pixbuf_get_rowstride(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - n_channels = gdk_pixbuf_get_n_channels(pixbuf); - -#define MULT(_d,c,a,t) \ - do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0) - - if (n_channels == 4) - { - for (i = 0; i < height; i++) - { - s = pixels + i * stride; - end = s + width * 4; - d = argb_pixels + i * width * 4; - while (s < end) - { - unsigned int t; - - MULT(d[0], s[2], s[3], t); - MULT(d[1], s[1], s[3], t); - MULT(d[2], s[0], s[3], t); - d[3] = s[3]; - s += 4; - d += 4; - } - } - } - else if (n_channels == 3) - { - for (i = 0; i < height; i++) - { - s = pixels + i * stride; - end = s + width * 3; - d = argb_pixels + i * width * 4; - while (s < end) - { - d[0] = s[2]; - d[1] = s[1]; - d[2] = s[0]; - d[3] = 0xff; - s += 3; - d += 4; - } - } - } -} - GdkCursor * _gdk_wayland_display_get_cursor_for_type (GdkDisplay *display, GdkCursorType cursor_type) @@ -382,10 +331,10 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay *display, } GdkCursor * -_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y) +_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y) { GdkWaylandCursor *cursor; GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display); @@ -393,11 +342,8 @@ _gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display, size_t size; gpointer data; struct wl_shm_pool *pool; - - g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); - g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); - g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL); - g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL); + cairo_surface_t *buffer_surface; + cairo_t *cr; cursor = g_object_new (GDK_TYPE_WAYLAND_CURSOR, "cursor-type", GDK_CURSOR_IS_PIXMAP, @@ -405,35 +351,55 @@ _gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display, NULL); cursor->name = NULL; cursor->serial = theme_serial; - cursor->pixbuf.hotspot_x = x; - cursor->pixbuf.hotspot_y = y; + cursor->surface.hotspot_x = x; + cursor->surface.hotspot_y = y; - if (pixbuf) + cursor->surface.scale = 1; + + if (surface) { - cursor->pixbuf.width = gdk_pixbuf_get_width (pixbuf); - cursor->pixbuf.height = gdk_pixbuf_get_height (pixbuf); +#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE + { + double sx, sy; + cairo_surface_get_device_scale (surface, &sx, &sy); + cursor->surface.scale = (int)sx; + } +#endif + cursor->surface.width = cairo_image_surface_get_width (surface); + cursor->surface.height = cairo_image_surface_get_height (surface); } else { - cursor->pixbuf.width = 1; - cursor->pixbuf.height = 1; + cursor->surface.width = 1; + cursor->surface.height = 1; } pool = _create_shm_pool (wayland_display->shm, - cursor->pixbuf.width, - cursor->pixbuf.height, + cursor->surface.width, + cursor->surface.height, &size, &data); - if (pixbuf) - set_pixbuf (data, cursor->pixbuf.width, cursor->pixbuf.height, pixbuf); + if (surface) + { + buffer_surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + cursor->surface.width, + cursor->surface.height, + cursor->surface.width * 4); + cr = cairo_create (buffer_surface); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); + cairo_surface_destroy (buffer_surface); + } else memset (data, 0, 4); - stride = cursor->pixbuf.width * 4; - cursor->pixbuf.buffer = wl_shm_pool_create_buffer (pool, 0, - cursor->pixbuf.width, - cursor->pixbuf.height, + stride = cursor->surface.width * 4; + cursor->surface.buffer = wl_shm_pool_create_buffer (pool, 0, + cursor->surface.width, + cursor->surface.height, stride, WL_SHM_FORMAT_ARGB8888); diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 61cf9bc58c..6027e8d1b9 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -161,16 +161,17 @@ static gboolean gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd) { struct wl_buffer *buffer; - int x, y, w, h; + int x, y, w, h, scale; guint next_image_index, next_image_delay; buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, wd->cursor_image_index, - &x, &y, &w, &h); + &x, &y, &w, &h, &scale); wl_pointer_set_cursor (wd->wl_pointer, wd->enter_serial, wd->pointer_surface, x, y); wl_surface_attach (wd->pointer_surface, buffer, 0, 0); + wl_surface_set_buffer_scale (wd->pointer_surface, scale); wl_surface_damage (wd->pointer_surface, 0, 0, w, h); wl_surface_commit (wd->pointer_surface); diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 7d748e05a2..db47bfe0cc 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -587,7 +587,7 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass * class) display_class->get_maximal_cursor_size = _gdk_wayland_display_get_maximal_cursor_size; display_class->get_cursor_for_type = _gdk_wayland_display_get_cursor_for_type; display_class->get_cursor_for_name = _gdk_wayland_display_get_cursor_for_name; - display_class->get_cursor_for_pixbuf = _gdk_wayland_display_get_cursor_for_pixbuf; + display_class->get_cursor_for_surface = _gdk_wayland_display_get_cursor_for_surface; display_class->supports_cursor_alpha = _gdk_wayland_display_supports_cursor_alpha; display_class->supports_cursor_color = _gdk_wayland_display_supports_cursor_color; display_class->before_process_all_updates = gdk_wayland_display_before_process_all_updates; diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index ebe4f43bd4..e0d48d370d 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -63,10 +63,10 @@ GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display, GdkCursorType cursor_type); GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display, const gchar *name); -GdkCursor *_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y); +GdkCursor *_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y); void _gdk_wayland_display_get_default_cursor_size (GdkDisplay *display, guint *width, guint *height); @@ -81,7 +81,8 @@ struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkCursor *cursor, int *hotspot_x, int *hotspot_y, int *w, - int *h); + int *h, + int *scale); guint _gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor, guint current_image_index, guint *next_image_delay); diff --git a/gdk/x11/gdkcursor-x11.c b/gdk/x11/gdkcursor-x11.c index 507ec4258b..e0c9f15112 100644 --- a/gdk/x11/gdkcursor-x11.c +++ b/gdk/x11/gdkcursor-x11.c @@ -43,6 +43,7 @@ #endif #include #include +#include struct _GdkX11Cursor { @@ -514,23 +515,46 @@ _gdk_x11_cursor_update_theme (GdkCursor *cursor) #ifdef HAVE_XCURSOR -static XcursorImage* -create_cursor_image (GdkPixbuf *pixbuf, - gint x, - gint y) +static void +get_surface_size (cairo_surface_t *surface, + int *width, + int *height) { - guint width, height; + double x_scale, y_scale; + + x_scale = y_scale = 1; + +#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE + cairo_surface_get_device_scale (surface, &x_scale, &y_scale); +#endif + + /* Assume any set scaling is icon scale */ + *width = + ceil (cairo_image_surface_get_width (surface) / x_scale); + *height = + ceil (cairo_image_surface_get_height (surface) / y_scale); +} + +static XcursorImage* +create_cursor_image (cairo_surface_t *source_surface, + gint x, + gint y, + gint scale) +{ + gint width, height; XcursorImage *xcimage; cairo_surface_t *surface; cairo_t *cr; - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); + get_surface_size (source_surface, &width, &height); + width *= scale; + height *= scale; + xcimage = XcursorImageCreate (width, height); - xcimage->xhot = x; - xcimage->yhot = y; + xcimage->xhot = x * scale; + xcimage->yhot = y * scale; surface = cairo_image_surface_create_for_data ((guchar *) xcimage->pixels, CAIRO_FORMAT_ARGB32, @@ -538,53 +562,30 @@ create_cursor_image (GdkPixbuf *pixbuf, height, width * 4); +#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE + cairo_surface_set_device_scale (surface, scale, scale); +#endif + cr = cairo_create (surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_set_source_surface (cr, source_surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); - cairo_surface_destroy (surface); return xcimage; } GdkCursor * -_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y) +_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y) { XcursorImage *xcimage; Cursor xcursor; GdkX11Cursor *private; - const char *option; - char *end; - gint64 value; - - if (x == -1 && (option = gdk_pixbuf_get_option (pixbuf, "x_hot"))) - { - errno = 0; - end = NULL; - value = g_ascii_strtoll (option, &end, 10); - if (errno == 0 && - end != option && - value >= 0 && value < G_MAXINT) - x = (gint) value; - } - if (y == -1 && (option = gdk_pixbuf_get_option (pixbuf, "y_hot"))) - { - errno = 0; - end = NULL; - value = g_ascii_strtoll (option, &end, 10); - if (errno == 0 && - end != option && - value >= 0 && value < G_MAXINT) - y = (gint) value; - } - - g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL); - g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL); + int target_scale; if (gdk_display_is_closed (display)) { @@ -592,7 +593,9 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display, } else { - xcimage = create_cursor_image (pixbuf, x, y); + target_scale = + gdk_screen_get_monitor_scale_factor (gdk_display_get_default_screen (display), 0); + xcimage = create_cursor_image (surface, x, y, target_scale); xcursor = XcursorImageLoadCursor (GDK_DISPLAY_XDISPLAY (display), xcimage); XcursorImageDestroy (xcimage); } @@ -714,10 +717,10 @@ gdk_cursor_new_from_pixmap (GdkDisplay *display, } GdkCursor * -_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y) +_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y) { GdkCursor *cursor; cairo_surface_t *pixmap, *mask; @@ -728,13 +731,18 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display, GdkScreen *screen; cairo_surface_t *image; cairo_t *cr; + GdkPixbuf *pixbuf; - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); + width = cairo_image_surface_get_width (surface); + height = cairo_image_surface_get_height (surface); g_return_val_if_fail (0 <= x && x < width, NULL); g_return_val_if_fail (0 <= y && y < height, NULL); + /* Note: This does not support scaled surfaced, if you need that you + want XCursor anyway */ + pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height); + n_channels = gdk_pixbuf_get_n_channels (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); @@ -766,6 +774,8 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display, } } + g_object_unref (pixbuf); + screen = gdk_display_get_default_screen (display); pixmap = _gdk_x11_window_create_bitmap_surface (gdk_screen_get_root_window (screen), @@ -798,7 +808,7 @@ _gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display, cairo_surface_destroy (pixmap); cairo_surface_destroy (mask); - + g_free (data); g_free (mask_data); diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 6f56e21ab6..575a3b7b03 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -2825,7 +2825,7 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class) display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context; display_class->get_cursor_for_type = _gdk_x11_display_get_cursor_for_type; display_class->get_cursor_for_name = _gdk_x11_display_get_cursor_for_name; - display_class->get_cursor_for_pixbuf = _gdk_x11_display_get_cursor_for_pixbuf; + display_class->get_cursor_for_surface = _gdk_x11_display_get_cursor_for_surface; display_class->get_default_cursor_size = _gdk_x11_display_get_default_cursor_size; display_class->get_maximal_cursor_size = _gdk_x11_display_get_maximal_cursor_size; display_class->supports_cursor_alpha = _gdk_x11_display_supports_cursor_alpha; diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 57f7d89d43..543c42d0ea 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -259,10 +259,10 @@ GdkCursor *_gdk_x11_display_get_cursor_for_type (GdkDisplay *display, GdkCursorType type); GdkCursor *_gdk_x11_display_get_cursor_for_name (GdkDisplay *display, const gchar *name); -GdkCursor *_gdk_x11_display_get_cursor_for_pixbuf (GdkDisplay *display, - GdkPixbuf *pixbuf, - gint x, - gint y); +GdkCursor *_gdk_x11_display_get_cursor_for_surface (GdkDisplay *display, + cairo_surface_t *surface, + gdouble x, + gdouble y); gboolean _gdk_x11_display_supports_cursor_alpha (GdkDisplay *display); gboolean _gdk_x11_display_supports_cursor_color (GdkDisplay *display); void _gdk_x11_display_get_default_cursor_size (GdkDisplay *display,