[gtk+] gdk: Add gdk_cursor_new_from_surface
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] gdk: Add gdk_cursor_new_from_surface
- Date: Wed, 7 Aug 2013 11:24:31 +0000 (UTC)
commit b2113b73843a180747ccec43a48e369617ddabd0
Author: Alexander Larsson <alexl redhat com>
Date: Wed Aug 7 12:18:38 2013 +0200
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 | 106 ++++++++++++++------------
gdk/x11/gdkdisplay-x11.c | 2 +-
gdk/x11/gdkprivate-x11.h | 8 +-
13 files changed, 218 insertions(+), 165 deletions(-)
---
diff --git a/gdk/broadway/gdkcursor-broadway.c b/gdk/broadway/gdkcursor-broadway.c
index 72fc84e..dccccc6 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 dff7457..36ce569 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 acbd8a2..efc66c0 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 d182591..a336ea7 100644
--- a/gdk/gdkcursor.c
+++ b/gdk/gdkcursor.c
@@ -34,6 +34,7 @@
#include "gdkinternals.h"
#include <math.h>
+#include <errno.h>
/**
* SECTION:cursors
@@ -351,13 +352,82 @@ 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 50880b3..af84360 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 582c279..365b429 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 035106f..76d0fbd 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 61cf9bc..6027e8d 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 7d748e0..db47bfe 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 ebe4f43..e0d48d3 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 507ec42..e0c9f15 100644
--- a/gdk/x11/gdkcursor-x11.c
+++ b/gdk/x11/gdkcursor-x11.c
@@ -43,6 +43,7 @@
#endif
#include <string.h>
#include <errno.h>
+#include <math.h>
struct _GdkX11Cursor
{
@@ -514,23 +515,46 @@ _gdk_x11_cursor_update_theme (GdkCursor *cursor)
#ifdef HAVE_XCURSOR
+static void
+get_surface_size (cairo_surface_t *surface,
+ int *width,
+ int *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 (GdkPixbuf *pixbuf,
+create_cursor_image (cairo_surface_t *source_surface,
gint x,
- gint y)
+ gint y,
+ gint scale)
{
- guint width, height;
+ 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 6f56e21..575a3b7 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 57f7d89..543c42d 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,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]