forked from AuroraMiddleware/gtk
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.
This commit is contained in:
parent
54f5e4af53
commit
71fe43543c
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
return GDK_CURSOR_GET_CLASS (cursor)->get_image (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);
|
||||
|
||||
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_surface (cursor,
|
||||
x_hot, y_hot);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB, TRUE,
|
||||
8, image->width, image->height,
|
||||
4 * image->width,
|
||||
(GdkPixbufDestroyNotify)g_free, NULL);
|
||||
memcpy (cairo_image_surface_get_data (surface),
|
||||
image->pixels, 4 * image->width * image->height);
|
||||
|
||||
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);
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user