[gtk+/rendering-cleanup: 49/144] API: Add gtk_drag_set_icon_surface()



commit 5bb0591ddef51c8d0ed940d648f5090a3838e7f6
Author: Benjamin Otte <otte redhat com>
Date:   Sun Aug 15 16:52:25 2010 +0200

    API: Add gtk_drag_set_icon_surface()
    
    The function is supposed to replace gtk_drag_set_icon_pixmap().

 docs/reference/gtk/gtk3-sections.txt |    1 +
 gtk/gtk.symbols                      |    1 +
 gtk/gtkdnd.c                         |  125 ++++++++++++++++++++++++++++++++++
 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 3effdf5..6625b16 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -5440,6 +5440,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 c0db4c7..6bda3d6 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 9b54a1c..8612532 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>
 
@@ -3360,6 +3361,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 e26b2fa..1bfc045 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,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]