[gtk+] gdk: Add gdk_cursor_get_surface()
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] gdk: Add gdk_cursor_get_surface()
- Date: Wed, 7 Aug 2013 11:24:26 +0000 (UTC)
commit 71fe43543c765f12b22e7c6508ed4d58ea5075a6
Author: Alexander Larsson <alexl redhat com>
Date: Tue Aug 6 16:21:05 2013 +0200
gdk: Add gdk_cursor_get_surface()
We want a surface so we can properly represent the scale factor for it.
All backends are converted to use surfaces and we reimplement the
backwards compat code in the generic code.
gdk/broadway/gdkcursor-broadway.c | 12 ++++--
gdk/gdkcursor.c | 73 ++++++++++++++++++++++++++++++++++++-
gdk/gdkcursor.h | 4 ++
gdk/gdkcursorprivate.h | 4 ++-
gdk/quartz/gdkcursor-quartz.c | 12 ++++--
gdk/wayland/gdkcursor-wayland.c | 8 +++--
gdk/win32/gdkcursor-win32.c | 32 +++++++++++-----
gdk/x11/gdkcursor-x11.c | 66 ++++++++++++++++++---------------
8 files changed, 158 insertions(+), 53 deletions(-)
---
diff --git a/gdk/broadway/gdkcursor-broadway.c b/gdk/broadway/gdkcursor-broadway.c
index 92acbda..72fc84e 100644
--- a/gdk/broadway/gdkcursor-broadway.c
+++ b/gdk/broadway/gdkcursor-broadway.c
@@ -51,7 +51,9 @@ struct _GdkBroadwayCursorClass
G_DEFINE_TYPE (GdkBroadwayCursor, gdk_broadway_cursor, GDK_TYPE_CURSOR)
-static GdkPixbuf* gdk_broadway_cursor_get_image (GdkCursor *cursor);
+static cairo_surface_t * gdk_broadway_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
static void
gdk_broadway_cursor_finalize (GObject *object)
@@ -67,7 +69,7 @@ gdk_broadway_cursor_class_init (GdkBroadwayCursorClass *xcursor_class)
object_class->finalize = gdk_broadway_cursor_finalize;
- cursor_class->get_image = gdk_broadway_cursor_get_image;
+ cursor_class->get_surface = gdk_broadway_cursor_get_surface;
}
static void
@@ -99,8 +101,10 @@ _gdk_broadway_display_get_cursor_for_type (GdkDisplay *display,
return GDK_CURSOR (private);
}
-static GdkPixbuf*
-gdk_broadway_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_broadway_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
g_return_val_if_fail (cursor != NULL, NULL);
diff --git a/gdk/gdkcursor.c b/gdk/gdkcursor.c
index 0b2b80d..d182591 100644
--- a/gdk/gdkcursor.c
+++ b/gdk/gdkcursor.c
@@ -24,12 +24,16 @@
#include "config.h"
+#define GDK_PIXBUF_ENABLE_BACKEND
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
#include "gdkcursor.h"
#include "gdkcursorprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkintl.h"
#include "gdkinternals.h"
+#include <math.h>
/**
* SECTION:cursors
@@ -389,7 +393,74 @@ gdk_cursor_get_display (GdkCursor *cursor)
GdkPixbuf*
gdk_cursor_get_image (GdkCursor *cursor)
{
+ int w, h;
+ cairo_surface_t *surface;
+ GdkPixbuf *pixbuf;
+ gchar buf[32];
+ double x_hot, y_hot;
+ double x_scale, y_scale;
+
+ g_return_val_if_fail (GDK_IS_CURSOR (cursor), NULL);
+
+ 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);
+
+ x_scale = y_scale = 1;
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+ cairo_surface_get_device_scale (surface, &x_scale, &y_scale);
+#endif
+
+ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, w, h);
+ cairo_surface_destroy (surface);
+
+ if (x_scale != 1)
+ {
+ GdkPixbuf *old;
+
+ old = pixbuf;
+ pixbuf = gdk_pixbuf_scale_simple (old,
+ w / x_scale, h / y_scale,
+ GDK_INTERP_HYPER);
+ g_object_unref (old);
+ }
+
+
+ g_snprintf (buf, 32, "%d", (int)x_hot);
+ gdk_pixbuf_set_option (pixbuf, "x_hot", buf);
+
+ g_snprintf (buf, 32, "%d", (int)y_hot);
+ gdk_pixbuf_set_option (pixbuf, "y_hot", buf);
+
+ return pixbuf;
+}
+
+/**
+ * gdk_cursor_get_surface:
+ * @cursor: a #GdkCursor
+ * @x_hot: Location to store the hotspot x position, or %NULL
+ * @y_hot: Location to store the hotspot y position, or %NULL
+ *
+ * Returns a #cairo_surface_t (image surface) with the image used to display the cursor.
+ *
+ * Note that depending on the capabilities of the windowing system and
+ * on the cursor, GDK may not be able to obtain the image data. In this
+ * case, %NULL is returned.
+ *
+ * Returns: (transfer full): a #cairo_surface_t representing @cursor, or %NULL
+ *
+ * Since: 3.10
+ */
+cairo_surface_t *
+gdk_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
+{
g_return_val_if_fail (GDK_IS_CURSOR (cursor), NULL);
- return GDK_CURSOR_GET_CLASS (cursor)->get_image (cursor);
+ return GDK_CURSOR_GET_CLASS (cursor)->get_surface (cursor,
+ x_hot, y_hot);
}
diff --git a/gdk/gdkcursor.h b/gdk/gdkcursor.h
index c526101..50880b3 100644
--- a/gdk/gdkcursor.h
+++ b/gdk/gdkcursor.h
@@ -239,6 +239,10 @@ GDK_DEPRECATED_IN_3_0_FOR(g_object_unref)
void gdk_cursor_unref (GdkCursor *cursor);
GDK_AVAILABLE_IN_ALL
GdkPixbuf* gdk_cursor_get_image (GdkCursor *cursor);
+GDK_AVAILABLE_IN_3_10
+cairo_surface_t *gdk_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
GDK_AVAILABLE_IN_ALL
GdkCursorType gdk_cursor_get_cursor_type (GdkCursor *cursor);
diff --git a/gdk/gdkcursorprivate.h b/gdk/gdkcursorprivate.h
index e637d3d..15dbe03 100644
--- a/gdk/gdkcursorprivate.h
+++ b/gdk/gdkcursorprivate.h
@@ -47,7 +47,9 @@ struct _GdkCursorClass
{
GObjectClass parent_class;
- GdkPixbuf * (* get_image) (GdkCursor * cursor);
+ cairo_surface_t * (* get_surface) (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
};
G_END_DECLS
diff --git a/gdk/quartz/gdkcursor-quartz.c b/gdk/quartz/gdkcursor-quartz.c
index 7e5adc5..1b1ed3e 100644
--- a/gdk/quartz/gdkcursor-quartz.c
+++ b/gdk/quartz/gdkcursor-quartz.c
@@ -284,7 +284,9 @@ _gdk_quartz_display_get_cursor_for_name (GdkDisplay *display,
G_DEFINE_TYPE (GdkQuartzCursor, gdk_quartz_cursor, GDK_TYPE_CURSOR)
-static GdkPixbuf *gdk_quartz_cursor_get_image (GdkCursor *cursor);
+static cairo_surface_t *gdk_quartz_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
static void
gdk_quartz_cursor_finalize (GObject *object)
@@ -304,7 +306,7 @@ gdk_quartz_cursor_class_init (GdkQuartzCursorClass *quartz_cursor_class)
object_class->finalize = gdk_quartz_cursor_finalize;
- cursor_class->get_image = gdk_quartz_cursor_get_image;
+ cursor_class->get_surface = gdk_quartz_cursor_get_surface;
}
static void
@@ -360,8 +362,10 @@ _gdk_quartz_cursor_get_ns_cursor (GdkCursor *cursor)
return cursor_private->nscursor;
}
-static GdkPixbuf *
-gdk_quartz_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_quartz_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
/* FIXME: Implement */
return NULL;
diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c
index 25a86de..035106f 100644
--- a/gdk/wayland/gdkcursor-wayland.c
+++ b/gdk/wayland/gdkcursor-wayland.c
@@ -174,8 +174,10 @@ gdk_wayland_cursor_finalize (GObject *object)
G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object);
}
-static GdkPixbuf*
-gdk_wayland_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_wayland_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
return NULL;
}
@@ -258,7 +260,7 @@ _gdk_wayland_cursor_class_init (GdkWaylandCursorClass *wayland_cursor_class)
object_class->finalize = gdk_wayland_cursor_finalize;
- cursor_class->get_image = gdk_wayland_cursor_get_image;
+ cursor_class->get_surface = gdk_wayland_cursor_get_surface;
}
static void
diff --git a/gdk/win32/gdkcursor-win32.c b/gdk/win32/gdkcursor-win32.c
index 86e7d7b..1ce7cb1 100644
--- a/gdk/win32/gdkcursor-win32.c
+++ b/gdk/win32/gdkcursor-win32.c
@@ -250,7 +250,7 @@ _gdk_win32_display_get_cursor_for_name (GdkDisplay *display,
}
GdkPixbuf *
-gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon)
+gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon, gint *x_hot, gint *y_hot)
{
GdkPixbuf *pixbuf = NULL;
ICONINFO ii;
@@ -407,11 +407,10 @@ gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon)
}
}
- g_snprintf (buf, sizeof (buf), "%ld", ii.xHotspot);
- gdk_pixbuf_set_option (pixbuf, "x_hot", buf);
-
- g_snprintf (buf, sizeof (buf), "%ld", ii.yHotspot);
- gdk_pixbuf_set_option (pixbuf, "y_hot", buf);
+ if (x_hot)
+ *x_hot = ii.xHotspot;
+ if (y_hot)
+ *y_hot = ii.yHotspot;
/* release temporary resources */
out2:
@@ -425,12 +424,25 @@ gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon)
return pixbuf;
}
-static GdkPixbuf *
-_gdk_win32_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+_gdk_win32_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
+ GdkPixbuf *pixbuf;
+ cairo_surface_t *surface
+
g_return_val_if_fail (cursor != NULL, NULL);
- return gdk_win32_icon_to_pixbuf_libgtk_only (((GdkWin32Cursor *) cursor)->hcursor);
+ pixbuf = gdk_win32_icon_to_pixbuf_libgtk_only (((GdkWin32Cursor *) cursor)->hcursor, x_hot, y_hot);
+
+ if (pixbuf == NULL)
+ return NULL;
+
+ surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
+ g_object_unref (pixbuf);
+
+ return surface;
}
GdkCursor *
@@ -830,5 +842,5 @@ gdk_win32_cursor_class_init(GdkWin32CursorClass *klass)
object_class->finalize = _gdk_win32_cursor_finalize;
- cursor_class->get_image = _gdk_win32_cursor_get_image;
+ cursor_class->get_surface = _gdk_win32_cursor_get_surface;
}
diff --git a/gdk/x11/gdkcursor-x11.c b/gdk/x11/gdkcursor-x11.c
index 8d4da14..507ec42 100644
--- a/gdk/x11/gdkcursor-x11.c
+++ b/gdk/x11/gdkcursor-x11.c
@@ -169,7 +169,9 @@ _gdk_x11_cursor_display_finalize (GdkDisplay *display)
G_DEFINE_TYPE (GdkX11Cursor, gdk_x11_cursor, GDK_TYPE_CURSOR)
-static GdkPixbuf* gdk_x11_cursor_get_image (GdkCursor *cursor);
+static cairo_surface_t *gdk_x11_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
static void
gdk_x11_cursor_finalize (GObject *object)
@@ -194,7 +196,7 @@ gdk_x11_cursor_class_init (GdkX11CursorClass *xcursor_class)
object_class->finalize = gdk_x11_cursor_finalize;
- cursor_class->get_image = gdk_x11_cursor_get_image;
+ cursor_class->get_surface = gdk_x11_cursor_get_surface;
}
static void
@@ -316,22 +318,25 @@ gdk_x11_cursor_get_xcursor (GdkCursor *cursor)
#if defined(HAVE_XCURSOR) && defined(HAVE_XFIXES) && XFIXES_MAJOR >= 2
-static GdkPixbuf*
-gdk_x11_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_x11_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
+ GdkDisplay *display;
Display *xdisplay;
GdkX11Cursor *private;
XcursorImages *images = NULL;
XcursorImage *image;
gint size;
- gchar buf[32];
- guchar *data, *p, tmp;
- GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
+ gint scale;
gchar *theme;
private = GDK_X11_CURSOR (cursor);
-
- xdisplay = GDK_DISPLAY_XDISPLAY (gdk_cursor_get_display (cursor));
+
+ display = gdk_cursor_get_display (cursor);
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
size = XcursorGetDefaultSize (xdisplay);
theme = XcursorGetTheme (xdisplay);
@@ -349,31 +354,30 @@ gdk_x11_cursor_get_image (GdkCursor *cursor)
image = images->images[0];
- data = g_malloc (4 * image->width * image->height);
- memcpy (data, image->pixels, 4 * image->width * image->height);
+ /* Assume the currently set cursor was defined for the screen
+ scale */
+ scale =
+ gdk_screen_get_monitor_scale_factor (gdk_display_get_default_screen (display), 0);
- for (p = data; p < data + (4 * image->width * image->height); p += 4)
- {
- tmp = p[0];
- p[0] = p[2];
- p[2] = tmp;
- }
+ surface = gdk_window_create_similar_image_surface (NULL,
+ CAIRO_FORMAT_ARGB32,
+ image->width,
+ image->height,
+ scale);
+
+ memcpy (cairo_image_surface_get_data (surface),
+ image->pixels, 4 * image->width * image->height);
- pixbuf = gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB, TRUE,
- 8, image->width, image->height,
- 4 * image->width,
- (GdkPixbufDestroyNotify)g_free, NULL);
+ cairo_surface_mark_dirty (surface);
- if (private->name)
- gdk_pixbuf_set_option (pixbuf, "name", private->name);
- g_snprintf (buf, 32, "%d", image->xhot);
- gdk_pixbuf_set_option (pixbuf, "x_hot", buf);
- g_snprintf (buf, 32, "%d", image->yhot);
- gdk_pixbuf_set_option (pixbuf, "y_hot", buf);
+ if (x_hot)
+ *x_hot = (double)image->xhot / scale;
+ if (y_hot)
+ *y_hot = (double)image->yhot / scale;
XcursorImagesDestroy (images);
- return pixbuf;
+ return surface;
}
void
@@ -484,8 +488,10 @@ gdk_x11_display_set_cursor_theme (GdkDisplay *display,
#else
-static GdkPixbuf*
-gdk_x11_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_x11_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
return NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]