[gtk+] tooltip: add support for opacity and rounded corners for tooltips



commit febc29852b5feec2071b92bdd8d088c23a5affb0
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Thu Oct 6 17:06:57 2011 -0400

    tooltip: add support for opacity and rounded corners for tooltips
    
    Rounded corners now will always work, using XShape in case we're not
    running a composite manager.
    Also, setting an RGBA visual (if available) on the tooltip toplevel
    enables them to be transparent if the theme specifies so.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=599617

 gtk/gtktooltip.c |   90 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 81 insertions(+), 9 deletions(-)
---
diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c
index f65e08d..29f4630 100644
--- a/gtk/gtktooltip.c
+++ b/gtk/gtktooltip.c
@@ -157,6 +157,9 @@ static void       gtk_tooltip_dispose              (GObject         *object);
 
 static gboolean   gtk_tooltip_paint_window         (GtkTooltip      *tooltip,
                                                     cairo_t         *cr);
+static void       gtk_tooltip_realize_window       (GtkTooltip      *tooltip,
+                                                    GtkWidget       *widget);
+static void       maybe_update_shape               (GtkTooltip      *tooltip);
 static void       gtk_tooltip_window_hide          (GtkWidget       *widget,
 						    gpointer         user_data);
 static void       gtk_tooltip_display_closed       (GdkDisplay      *display,
@@ -186,6 +189,8 @@ gtk_tooltip_init (GtkTooltip *tooltip)
   GtkWidget *box;
   GtkWidget *image;
   GtkWidget *label;
+  GdkScreen *screen;
+  GdkVisual *visual;
 
   tooltip->timeout_id = 0;
   tooltip->browse_mode_timeout_id = 0;
@@ -202,6 +207,12 @@ gtk_tooltip_init (GtkTooltip *tooltip)
   tooltip->last_window = NULL;
 
   window = g_object_ref (gtk_window_new (GTK_WINDOW_POPUP));
+  screen = gtk_widget_get_screen (window);
+  visual = gdk_screen_get_rgba_visual (screen);
+
+  if (visual != NULL)
+    gtk_widget_set_visual (window, visual);
+
   gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_TOOLTIP);
   gtk_widget_set_app_paintable (window, TRUE);
   gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
@@ -214,6 +225,10 @@ gtk_tooltip_init (GtkTooltip *tooltip)
 
   g_signal_connect_swapped (window, "draw",
                             G_CALLBACK (gtk_tooltip_paint_window), tooltip);
+  g_signal_connect_swapped (window, "realize",
+                            G_CALLBACK (gtk_tooltip_realize_window), tooltip);
+  g_signal_connect_swapped (window, "composited-changed",
+                            G_CALLBACK (maybe_update_shape), tooltip);
 
   /* FIXME: don't hardcode the padding */
   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
@@ -569,20 +584,77 @@ gtk_tooltip_reset (GtkTooltip *tooltip)
   tooltip->custom_was_reset = FALSE;
 }
 
-static gboolean
-gtk_tooltip_paint_window (GtkTooltip *tooltip,
-                          cairo_t    *cr)
+static void
+paint_background_and_frame (GtkTooltip *tooltip,
+                            cairo_t *cr)
 {
   GtkStyleContext *context;
+  gint width, height;
 
+  width = gtk_widget_get_allocated_width (tooltip->window);
+  height = gtk_widget_get_allocated_height (tooltip->window);
   context = gtk_widget_get_style_context (tooltip->window);
 
-  gtk_render_background (context, cr, 0, 0,
-			 gtk_widget_get_allocated_width (tooltip->window),
-			 gtk_widget_get_allocated_height (tooltip->window));
-  gtk_render_frame (context, cr, 0, 0,
-                    gtk_widget_get_allocated_width (tooltip->window),
-                    gtk_widget_get_allocated_height (tooltip->window));
+  gtk_render_background (context, cr,
+                         0, 0, width, height);
+  gtk_render_frame (context, cr,
+                    0, 0, width, height);  
+}
+
+static void
+maybe_update_shape (GtkTooltip *tooltip)
+{
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  cairo_region_t *region;
+  gint width, height;
+
+  /* fallback to XShape only for non-composited clients */
+  if (gtk_widget_is_composited (tooltip->window))
+    {
+      gtk_widget_shape_combine_region (tooltip->window, NULL);
+      return;
+    }
+
+  surface = gdk_window_create_similar_surface (gtk_widget_get_window (tooltip->window),
+                                               CAIRO_CONTENT_COLOR_ALPHA,
+                                               gtk_widget_get_allocated_width (tooltip->window),
+                                               gtk_widget_get_allocated_height (tooltip->window));
+
+  cr = cairo_create (surface);
+  paint_background_and_frame (tooltip, cr);
+  cairo_destroy (cr);
+
+  region = gdk_cairo_region_create_from_surface (surface);
+  gtk_widget_shape_combine_region (tooltip->window, region);
+
+  cairo_surface_destroy (surface);
+  cairo_region_destroy (region);
+}
+
+static void
+gtk_tooltip_realize_window (GtkTooltip *tooltip,
+                            GtkWidget *widget)
+{
+  maybe_update_shape (tooltip);
+}
+
+static gboolean
+gtk_tooltip_paint_window (GtkTooltip *tooltip,
+                          cairo_t    *cr)
+{
+  if (gtk_widget_is_composited (tooltip->window))
+    {
+      /* clear any background */
+      cairo_save (cr);
+      cairo_set_source_rgba (cr, 0, 0, 0, 0);
+      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+      cairo_paint (cr);
+      cairo_restore (cr);
+    }
+
+  maybe_update_shape (tooltip);
+  paint_background_and_frame (tooltip, cr);
 
   return FALSE;
 }



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