summaryrefslogtreecommitdiff
path: root/gtk/gtkdnd-quartz.c
diff options
context:
space:
mode:
authorChristoph Reiter <reiter.christoph@gmail.com>2015-07-24 15:09:48 +0200
committerChristoph Reiter <creiter@src.gnome.org>2015-07-27 17:28:14 +0200
commit4b23ba53c51a087851788c67f852281b085c9c33 (patch)
tree4ce856a9c8ad3a59d733cb285cb347cc5f37952d /gtk/gtkdnd-quartz.c
parent5003b5873a5e727a2b194bb5c4d8d784cc25b1e4 (diff)
downloadgtk+-4b23ba53c51a087851788c67f852281b085c9c33.tar.gz
quartz dnd: add hidpi support for gtk_drag_set_icon_surface()
Instead of storing the dnd icon as a pixbuf store it as a cairo surface and transfer the device scale when converting it to a NSImage. In the pixbuf/stock/named setters convert to a surface instead (no hidpi support yet)
Diffstat (limited to 'gtk/gtkdnd-quartz.c')
-rw-r--r--gtk/gtkdnd-quartz.c86
1 files changed, 30 insertions, 56 deletions
diff --git a/gtk/gtkdnd-quartz.c b/gtk/gtkdnd-quartz.c
index 97841d0496..f7f5182127 100644
--- a/gtk/gtkdnd-quartz.c
+++ b/gtk/gtkdnd-quartz.c
@@ -96,7 +96,7 @@ struct _GtkDragSourceInfo
GdkDragContext *context; /* drag context */
NSEvent *nsevent; /* what started it */
gint hot_x, hot_y; /* Hot spot for drag */
- GdkPixbuf *icon_pixbuf;
+ cairo_surface_t *icon_surface;
gboolean success;
gboolean delete;
};
@@ -1162,7 +1162,8 @@ gtk_drag_begin_idle (gpointer arg)
/* FIXME: If the event isn't a mouse event, use the global cursor position instead */
point = [info->nsevent locationInWindow];
- drag_image = _gtk_quartz_create_image_from_pixbuf (info->icon_pixbuf);
+ drag_image = _gtk_quartz_create_image_from_surface (info->icon_surface);
+
if (drag_image == NULL)
{
g_object_unref (info->context);
@@ -1290,7 +1291,7 @@ gtk_drag_begin_internal (GtkWidget *widget,
* application may have set one in ::drag_begin, or it may
* not have set one.
*/
- if (!info->icon_pixbuf)
+ if (!info->icon_surface)
{
if (!site || site->icon_type == GTK_IMAGE_EMPTY)
gtk_drag_set_icon_default (context);
@@ -1804,6 +1805,8 @@ set_icon_stock_pixbuf (GdkDragContext *context,
gint hot_y)
{
GtkDragSourceInfo *info;
+ cairo_surface_t *surface;
+ cairo_t *cr;
info = gtk_drag_get_source_info (context, FALSE);
@@ -1821,11 +1824,19 @@ set_icon_stock_pixbuf (GdkDragContext *context,
else
g_object_ref (pixbuf);
- if (info->icon_pixbuf)
- g_object_unref (info->icon_pixbuf);
- info->icon_pixbuf = pixbuf;
- info->hot_x = hot_x;
- info->hot_y = hot_y;
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+
+ cr = cairo_create (surface);
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+ g_object_unref (pixbuf);
+
+ cairo_surface_set_device_offset (surface, -hot_x, -hot_y);
+ gtk_drag_set_icon_surface (context, surface);
+ cairo_surface_destroy (surface);
}
/**
@@ -1873,44 +1884,6 @@ gtk_drag_set_icon_stock (GdkDragContext *context,
set_icon_stock_pixbuf (context, stock_id, NULL, hot_x, hot_y);
}
-
-/* XXX: This function is in gdk, too. Should it be in Cairo? */
-static gboolean
-_gtk_cairo_surface_extents (cairo_surface_t *surface,
- GdkRectangle *extents)
-{
- double x1, x2, y1, y2;
- cairo_t *cr;
-
- g_return_val_if_fail (surface != NULL, FALSE);
- g_return_val_if_fail (extents != NULL, FALSE);
-
- cr = cairo_create (surface);
- cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
-
- x1 = floor (x1);
- y1 = floor (y1);
- x2 = ceil (x2);
- y2 = ceil (y2);
- x2 -= x1;
- y2 -= y1;
-
- if (x1 < G_MININT || x1 > G_MAXINT ||
- y1 < G_MININT || y1 > G_MAXINT ||
- x2 > G_MAXINT || y2 > G_MAXINT)
- {
- extents->x = extents->y = extents->width = extents->height = 0;
- return FALSE;
- }
-
- extents->x = x1;
- extents->y = y1;
- extents->width = x2;
- extents->height = y2;
-
- return TRUE;
-}
-
/**
* gtk_drag_set_icon_surface:
* @context: the context for a drag. (This must be called
@@ -1930,21 +1903,22 @@ void
gtk_drag_set_icon_surface (GdkDragContext *context,
cairo_surface_t *surface)
{
- GdkPixbuf *pixbuf;
- GdkRectangle extents;
double x_offset, y_offset;
+ GtkDragSourceInfo *info;
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
g_return_if_fail (surface != NULL);
- _gtk_cairo_surface_extents (surface, &extents);
cairo_surface_get_device_offset (surface, &x_offset, &y_offset);
+ info = gtk_drag_get_source_info (context, FALSE);
+ cairo_surface_reference (surface);
- pixbuf = gdk_pixbuf_get_from_surface (surface,
- extents.x, extents.y,
- extents.width, extents.height);
- gtk_drag_set_icon_pixbuf (context, pixbuf, -x_offset, -y_offset);
- g_object_unref (pixbuf);
+ if (info->icon_surface)
+ cairo_surface_destroy (info->icon_surface);
+
+ info->icon_surface = surface;
+ info->hot_x = -x_offset;
+ info->hot_y = -y_offset;
}
/**
@@ -2021,8 +1995,8 @@ gtk_drag_source_info_destroy (GtkDragSourceInfo *info)
NSPasteboard *pasteboard;
NSAutoreleasePool *pool;
- if (info->icon_pixbuf)
- g_object_unref (info->icon_pixbuf);
+ if (info->icon_surface)
+ cairo_surface_destroy (info->icon_surface);
g_signal_emit_by_name (info->widget, "drag-end",
info->context);