[gtk+] Bug 615162 - Fix tooltips on offscreen widgets



commit ece97b23597b8ec3c761d3d90030876b81ca7b09
Author: Michael Natterer <mitch gimp org>
Date:   Thu Apr 15 13:03:43 2010 +0200

    Bug 615162 - Fix tooltips on offscreen widgets
    
    Fix the "widget under pointer" logic and keyboard tooltip positioning
    to do the right thing on offscreen widgets.

 gtk/gtktooltip.c |   86 +++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 59 insertions(+), 27 deletions(-)
---
diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c
index 87871e8..5cc2334 100644
--- a/gtk/gtktooltip.c
+++ b/gtk/gtktooltip.c
@@ -20,6 +20,10 @@
  */
 
 #include "config.h"
+
+#include <math.h>
+#include <string.h>
+
 #include "gtktooltip.h"
 #include "gtkintl.h"
 #include "gtkwindow.h"
@@ -31,8 +35,6 @@
 
 #include "gtkalias.h"
 
-#include <string.h>
-
 #undef DEBUG_TOOLTIP
 
 
@@ -472,9 +474,9 @@ gtk_tooltip_trigger_tooltip_query (GdkDisplay *display)
   event.motion.y = y;
   event.motion.is_hint = FALSE;
 
-  gdk_window_get_origin (window, &x, &y);
-  event.motion.x_root = event.motion.x + x;
-  event.motion.y_root = event.motion.y + y;
+  gdk_window_get_root_coords (window, x, y, &x, &y);
+  event.motion.x_root = x;
+  event.motion.y_root = y;
 
   _gtk_tooltip_handle_event (&event);
 }
@@ -674,13 +676,15 @@ find_widget_under_pointer (GdkWindow *window,
    */
   while (window && window != event_widget->window)
     {
-      gint px, py;
+      gdouble px, py;
 
-      gdk_window_get_position (window, &px, &py);
-      child_loc.x += px;
-      child_loc.y += py;
+      gdk_window_coords_to_parent (window,
+                                   child_loc.x, child_loc.y,
+                                   &px, &py);
+      child_loc.x = px;
+      child_loc.y = py;
 
-      window = gdk_window_get_parent (window);
+      window = gdk_window_get_effective_parent (window);
     }
 
   /* Failing to find widget->window can happen for e.g. a detached handle box;
@@ -860,6 +864,39 @@ gtk_tooltip_run_requery (GtkWidget  **widget,
 }
 
 static void
+get_bounding_box (GtkWidget    *widget,
+                  GdkRectangle *bounds)
+{
+  GdkWindow *window;
+  gint x, y;
+  gint w, h;
+  gint x1, y1;
+  gint x2, y2;
+  gint x3, y3;
+  gint x4, y4;
+
+  window = gtk_widget_get_parent_window (widget);
+
+  x = widget->allocation.x;
+  y = widget->allocation.y;
+  w = widget->allocation.width;
+  h = widget->allocation.height;
+
+  gdk_window_get_root_coords (window, x, y, &x1, &y1);
+  gdk_window_get_root_coords (window, x + w, y, &x2, &y2);
+  gdk_window_get_root_coords (window, x, y + h, &x3, &y3);
+  gdk_window_get_root_coords (window, x + w, y + h, &x4, &y4);
+
+#define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
+#define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d))
+
+  bounds->x = floor (MIN4 (x1, x2, x3, x4));
+  bounds->y = floor (MIN4 (y1, y2, y3, y4));
+  bounds->width = ceil (MAX4 (x1, x2, x3, x4)) - bounds->x;
+  bounds->height = ceil (MAX4 (y1, y2, y3, y4)) - bounds->y;
+}
+
+static void
 gtk_tooltip_position (GtkTooltip *tooltip,
 		      GdkDisplay *display,
 		      GtkWidget  *new_tooltip_widget)
@@ -873,18 +910,15 @@ gtk_tooltip_position (GtkTooltip *tooltip,
   /* FIXME: should we swap this when RTL is enabled? */
   if (tooltip->keyboard_mode_enabled)
     {
-      gdk_window_get_origin (new_tooltip_widget->window, &x, &y);
-      if (!gtk_widget_get_has_window (new_tooltip_widget))
-        {
-	  x += new_tooltip_widget->allocation.x;
-	  y += new_tooltip_widget->allocation.y;
-	}
+      GdkRectangle bounds;
+
+      get_bounding_box (new_tooltip_widget, &bounds);
 
       /* For keyboard mode we position the tooltip below the widget,
        * right of the center of the widget.
        */
-      x += new_tooltip_widget->allocation.width / 2;
-      y += new_tooltip_widget->allocation.height + 4;
+      x = bounds.x + bounds.width / 2;
+      y = bounds.y + bounds.height + 4;
     }
   else
     {
@@ -960,14 +994,18 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
     }
   else
     {
+      gint tx, ty;
+
       window = tooltip->last_window;
 
       if (!GDK_IS_WINDOW (window))
 	return;
 
-      gdk_window_get_origin (window, &x, &y);
-      x = tooltip->last_x - x;
-      y = tooltip->last_y - y;
+      gdk_window_get_pointer (window, &x, &y, NULL);
+
+      gdk_window_get_root_coords (window, x, y, &tx, &ty);
+      tooltip->last_x = tx;
+      tooltip->last_y = ty;
 
       pointer_widget = tooltip_widget = find_widget_under_pointer (window,
 								   &x, &y);
@@ -1290,9 +1328,6 @@ _gtk_tooltip_handle_event (GdkEvent *event)
   if (current_tooltip)
     {
       gtk_tooltip_set_last_window (current_tooltip, event->any.window);
-      gdk_event_get_root_coords (event,
-				&current_tooltip->last_x,
-				&current_tooltip->last_y);
     }
 
   if (current_tooltip && current_tooltip->keyboard_mode_enabled)
@@ -1398,9 +1433,6 @@ _gtk_tooltip_handle_event (GdkEvent *event)
 			      current_tooltip);
 
 	    gtk_tooltip_set_last_window (current_tooltip, event->any.window);
-	    gdk_event_get_root_coords (event,
-				       &current_tooltip->last_x,
-				       &current_tooltip->last_y);
 
 	    gtk_tooltip_start_delay (display);
 	  }



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