diff options
author | Benjamin Otte <otte@redhat.com> | 2010-08-15 16:52:25 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2010-09-26 15:03:00 +0200 |
commit | 3dfb47bc3cb62e07a23c02f5374a43362d5aa158 (patch) | |
tree | abfd086846031a3a1cf0a639c3cc0bbaf571a9ca | |
parent | 0d9d599b50d4b12b0b64f2efaf0ea8f2204eb257 (diff) | |
download | gtk+-3dfb47bc3cb62e07a23c02f5374a43362d5aa158.tar.gz |
API: Add gtk_drag_set_icon_surface()
The function is supposed to replace gtk_drag_set_icon_pixmap().
-rw-r--r-- | docs/reference/gtk/gtk3-sections.txt | 1 | ||||
-rw-r--r-- | gtk/gtk.symbols | 1 | ||||
-rw-r--r-- | gtk/gtkdnd.c | 125 | ||||
-rw-r--r-- | gtk/gtkdnd.h | 22 |
4 files changed, 139 insertions, 10 deletions
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index 8d0c258970..7028b7b182 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -5441,6 +5441,7 @@ gtk_drag_set_icon_widget gtk_drag_set_icon_pixmap gtk_drag_set_icon_pixbuf gtk_drag_set_icon_stock +gtk_drag_set_icon_surface gtk_drag_set_icon_name gtk_drag_set_icon_default gtk_drag_check_threshold diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 44f85ae715..4979316c82 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -949,6 +949,7 @@ gtk_drag_set_icon_name gtk_drag_set_icon_pixbuf gtk_drag_set_icon_pixmap gtk_drag_set_icon_stock +gtk_drag_set_icon_surface gtk_drag_set_icon_widget gtk_drag_source_add_image_targets gtk_drag_source_add_text_targets diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index eb08735ab8..8448a7a691 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -26,6 +26,7 @@ #include "config.h" +#include <math.h> #include <stdlib.h> #include <string.h> @@ -3351,6 +3352,130 @@ gtk_drag_set_icon_pixmap (GdkDragContext *context, gtk_drag_set_icon_window (context, window, hot_x, hot_y, TRUE); } +/* 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 + * with a context for the source side of a drag) + * @surface: the surface to use as icon + * + * Sets @surface as the icon for a given drag. GTK+ retains + * references for the arguments, and will release them when + * they are no longer needed. + **/ +void +gtk_drag_set_icon_surface (GdkDragContext *context, + cairo_surface_t *surface) +{ + GtkWidget *window; + GdkScreen *screen; + GdkRectangle extents; + cairo_pattern_t *pattern; + + g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (context->is_source); + g_return_if_fail (surface != NULL); + + _gtk_cairo_surface_extents (surface, &extents); + + + screen = gdk_drawable_get_screen (context->source_window); + + /* Push a NULL colormap to guard against gtk_widget_push_colormap() */ + gtk_widget_push_colormap (NULL); + window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND); + gtk_window_set_screen (GTK_WINDOW (window), screen); + set_can_change_screen (window, TRUE); + gtk_widget_pop_colormap (); + + gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + gtk_widget_set_app_paintable (window, TRUE); + + gtk_widget_set_size_request (window, extents.width, extents.height); + gtk_widget_realize (window); + + if (cairo_surface_get_content (surface) != CAIRO_CONTENT_COLOR) + { + cairo_surface_t *saturated; + cairo_region_t *region; + cairo_t *cr; + + region = gdk_cairo_region_create_from_surface (surface); + gtk_widget_shape_combine_region (window, region); + cairo_region_destroy (region); + + /* Need to saturate the colors, so it doesn't look like semi-transparent + * pixels were painted on black. */ + saturated = gdk_window_create_similar_surface (gtk_widget_get_window (window), + CAIRO_CONTENT_COLOR, + extents.width, + extents.height); + + cr = cairo_create (saturated); + cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA); + cairo_set_source_surface (cr, surface, extents.x, extents.y); + cairo_paint (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE); + cairo_paint (cr); + cairo_pop_group_to_source (cr); + cairo_paint (cr); + cairo_destroy (cr); + + pattern = cairo_pattern_create_for_surface (saturated); + + cairo_surface_destroy (saturated); + } + else + { + cairo_matrix_t matrix; + + pattern = cairo_pattern_create_for_surface (surface); + cairo_matrix_init_translate (&matrix, extents.x, extents.y); + cairo_pattern_set_matrix (pattern, &matrix); + } + + gdk_window_set_background_pattern (gtk_widget_get_window (window), pattern); + + gtk_drag_set_icon_window (context, window, extents.x, extents.y, TRUE); +} + /** * gtk_drag_set_icon_name: * @context: the context for a drag. (This must be called diff --git a/gtk/gtkdnd.h b/gtk/gtkdnd.h index e26b2fa85d..1bfc045f92 100644 --- a/gtk/gtkdnd.h +++ b/gtk/gtkdnd.h @@ -115,16 +115,16 @@ void gtk_drag_source_add_text_targets (GtkWidget *widget); void gtk_drag_source_add_image_targets (GtkWidget *widget); void gtk_drag_source_add_uri_targets (GtkWidget *widget); -void gtk_drag_source_set_icon (GtkWidget *widget, - GdkColormap *colormap, - GdkPixmap *pixmap, - GdkBitmap *mask); -void gtk_drag_source_set_icon_pixbuf (GtkWidget *widget, - GdkPixbuf *pixbuf); -void gtk_drag_source_set_icon_stock (GtkWidget *widget, - const gchar *stock_id); -void gtk_drag_source_set_icon_name (GtkWidget *widget, - const gchar *icon_name); +void gtk_drag_source_set_icon (GtkWidget *widget, + GdkColormap *colormap, + GdkPixmap *pixmap, + GdkBitmap *mask); +void gtk_drag_source_set_icon_pixbuf (GtkWidget *widget, + GdkPixbuf *pixbuf); +void gtk_drag_source_set_icon_stock (GtkWidget *widget, + const gchar *stock_id); +void gtk_drag_source_set_icon_name (GtkWidget *widget, + const gchar *icon_name); /* There probably should be functions for setting the targets * as a GtkTargetList @@ -156,6 +156,8 @@ void gtk_drag_set_icon_stock (GdkDragContext *context, const gchar *stock_id, gint hot_x, gint hot_y); +void gtk_drag_set_icon_surface(GdkDragContext *context, + cairo_surface_t *surface); void gtk_drag_set_icon_name (GdkDragContext *context, const gchar *icon_name, gint hot_x, |