[gtk+] gtkdnd: Use surface based cursor APIs
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] gtkdnd: Use surface based cursor APIs
- Date: Wed, 7 Aug 2013 11:24:36 +0000 (UTC)
commit 8e423ba2927a4c27bc87e4e1d4e7bda480bda1b3
Author: Alexander Larsson <alexl redhat com>
Date: Wed Aug 7 13:32:38 2013 +0200
gtkdnd: Use surface based cursor APIs
This allows things to correctly scale things on HiDPI screens.
gtk/gtkdnd.c | 101 ++++++++++++++++++++++++++++++++++------------------------
1 files changed, 59 insertions(+), 42 deletions(-)
---
diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c
index d9d888f..22609d7 100644
--- a/gtk/gtkdnd.c
+++ b/gtk/gtkdnd.c
@@ -840,6 +840,26 @@ ensure_drag_cursor_pixbuf (int i)
}
}
+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 GdkCursor *
gtk_drag_get_cursor (GtkWidget *widget,
GdkDisplay *display,
@@ -888,9 +908,10 @@ gtk_drag_get_cursor (GtkWidget *widget,
gint cursor_width, cursor_height;
gint icon_width, icon_height;
gint width, height;
- GdkPixbuf *cursor_pixbuf, *pixbuf, *icon_pixbuf;
- gint hot_x, hot_y;
+ cairo_surface_t *icon_surface, *cursor_surface;
+ gdouble hot_x, hot_y;
gint icon_x, icon_y, ref_x, ref_y;
+ gint scale;
if (info->drag_cursors[i] != NULL)
{
@@ -901,29 +922,26 @@ gtk_drag_get_cursor (GtkWidget *widget,
info->drag_cursors[i] = NULL;
}
- icon_pixbuf = _gtk_icon_helper_ensure_pixbuf (info->icon_helper,
- gtk_widget_get_style_context (widget));
+ scale = gtk_widget_get_scale_factor (widget);
+ _gtk_icon_helper_get_size (info->icon_helper,
+ gtk_widget_get_style_context (widget),
+ &icon_width, &icon_height);
+ icon_surface = _gtk_icon_helper_ensure_surface (info->icon_helper,
+ gtk_widget_get_style_context (widget));
icon_x = info->hot_x;
icon_y = info->hot_y;
- icon_width = gdk_pixbuf_get_width (icon_pixbuf);
- icon_height = gdk_pixbuf_get_height (icon_pixbuf);
hot_x = hot_y = 0;
- cursor_pixbuf = gdk_cursor_get_image (drag_cursors[i].cursor);
- if (!cursor_pixbuf)
+ cursor_surface = gdk_cursor_get_surface (drag_cursors[i].cursor,
+ &hot_x, &hot_y);
+ if (!cursor_surface)
{
ensure_drag_cursor_pixbuf (i);
- cursor_pixbuf = g_object_ref (drag_cursors[i].pixbuf);
+ cursor_surface = gdk_cairo_surface_create_from_pixbuf (drag_cursors[i].pixbuf, 1, NULL);
}
else
{
- if (gdk_pixbuf_get_option (cursor_pixbuf, "x_hot"))
- hot_x = atoi (gdk_pixbuf_get_option (cursor_pixbuf, "x_hot"));
-
- if (gdk_pixbuf_get_option (cursor_pixbuf, "y_hot"))
- hot_y = atoi (gdk_pixbuf_get_option (cursor_pixbuf, "y_hot"));
-
#if 0
/* The code below is an attempt to let cursor themes
* determine the attachment of the icon to enable things
@@ -1001,46 +1019,45 @@ gtk_drag_get_cursor (GtkWidget *widget,
#endif
}
- cursor_width = gdk_pixbuf_get_width (cursor_pixbuf);
- cursor_height = gdk_pixbuf_get_height (cursor_pixbuf);
+ get_surface_size (cursor_surface, &cursor_width, &cursor_height);
ref_x = MAX (hot_x, icon_x);
ref_y = MAX (hot_y, icon_y);
width = ref_x + MAX (cursor_width - hot_x, icon_width - icon_x);
height = ref_y + MAX (cursor_height - hot_y, icon_height - icon_y);
-
- if (gtk_drag_can_use_rgba_cursor (display, width, height))
+
+ if (gtk_drag_can_use_rgba_cursor (display, width * scale, height * scale))
{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
/* Composite cursor and icon so that both hotspots
* end up at (ref_x, ref_y)
*/
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- width, height);
-
- gdk_pixbuf_fill (pixbuf, 0xff000000);
-
- gdk_pixbuf_composite (icon_pixbuf, pixbuf,
- ref_x - icon_x, ref_y - icon_y,
- icon_width, icon_height,
- ref_x - icon_x, ref_y - icon_y,
- 1.0, 1.0,
- GDK_INTERP_BILINEAR, 255);
-
- gdk_pixbuf_composite (cursor_pixbuf, pixbuf,
- ref_x - hot_x, ref_y - hot_y,
- cursor_width, cursor_height,
- ref_x - hot_x, ref_y - hot_y,
- 1.0, 1.0,
- GDK_INTERP_BILINEAR, 255);
-
+ surface =
+ gdk_window_create_similar_image_surface (NULL,
+ CAIRO_FORMAT_ARGB32,
+ width * scale, height * scale, scale);
+
+ cr = cairo_create (surface);
+ cairo_set_source_surface (cr, icon_surface,
+ ref_x - icon_x, ref_y - icon_y);
+ cairo_paint (cr);
+
+ cairo_set_source_surface (cr, cursor_surface,
+ ref_x - hot_x, ref_y - hot_y);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+
info->drag_cursors[i] =
- gdk_cursor_new_from_pixbuf (display, pixbuf, ref_x, ref_y);
+ gdk_cursor_new_from_surface (display, surface, ref_x, ref_y);
- g_object_unref (pixbuf);
+ cairo_surface_destroy (surface);
}
- g_object_unref (cursor_pixbuf);
- g_object_unref (icon_pixbuf);
+ cairo_surface_destroy (cursor_surface);
+ cairo_surface_destroy (icon_surface);
if (info->drag_cursors[i] != NULL)
return info->drag_cursors[i];
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]