]> Pileus Git - ~andy/gtk/commitdiff
Fix #457642, reported by Christian Persch.
authorKristian Rietveld <kris@imendio.com>
Tue, 21 Aug 2007 10:52:43 +0000 (10:52 +0000)
committerKristian Rietveld <kristian@src.gnome.org>
Tue, 21 Aug 2007 10:52:43 +0000 (10:52 +0000)
2007-08-21  Kristian Rietveld  <kris@imendio.com>

Fix #457642, reported by Christian Persch.

* gtk/gtktooltip.c: added debugging output which can be compiled
in with a #define, annotated all coordinate translations in the
source code,
(find_widget_under_pointer): remove the "no-window correction";
always convert the coordinates from window relative to allocation
relative; after recursing through a container, translate the
coordinates from container allocation relative to child widget
allocation relative;
(find_topmost_widget_from_event): now we get allocation relative
coordinates here we do not have to distinguish no-window and window
widgets.

svn path=/trunk/; revision=18663

ChangeLog
gtk/gtktooltip.c

index dc5f7024ebb34f96bbc1fa73d20b1cf0f0b851f2..31951ed6f2010fc1684073c5b876d1be1b5dc562 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-08-21  Kristian Rietveld  <kris@imendio.com>
+
+       Fix #457642, reported by Christian Persch.
+
+       * gtk/gtktooltip.c: added debugging output which can be compiled
+       in with a #define, annotated all coordinate translations in the
+       source code,
+       (find_widget_under_pointer): remove the "no-window correction";
+       always convert the coordinates from window relative to allocation
+       relative; after recursing through a container, translate the
+       coordinates from container allocation relative to child widget
+       allocation relative;
+       (find_topmost_widget_from_event): now we get allocation relative
+       coordinates here we do not have to distinguish no-window and window
+       widgets.
+
 2007-08-18  Cody Russell  <bratsche@gnome.org>
 
        * gtk/gtkimcontextsimple.c: Fixed incorrect compose mapping
index cc44d5d50ae7f4ec4e4a5c0282356bf041a0d809..46ca8179abe3b42f884a4228e2f486eb8b4bf8b5 100644 (file)
@@ -33,6 +33,8 @@
 
 #include <string.h>
 
+#undef DEBUG_TOOLTIP
+
 
 #define GTK_TOOLTIP_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TOOLTIP, GtkTooltipClass))
 #define GTK_IS_TOOLTIP_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TOOLTIP))
@@ -456,11 +458,27 @@ child_location_foreach (GtkWidget *child,
   if (!GTK_WIDGET_DRAWABLE (child))
     return;
 
+  /* (child_loc->x, child_loc->y) are relative to
+   * child_loc->container's allocation.
+   */
+
   if (!child_loc->child &&
       gtk_widget_translate_coordinates (child_loc->container, child,
                                        child_loc->x, child_loc->y,
                                        &x, &y))
     {
+#ifdef DEBUG_TOOLTIP
+      g_print ("candidate: %s  alloc=[(%d,%d)  %dx%d]     (%d, %d)->(%d, %d)\n",
+              gtk_widget_get_name (child),
+              child->allocation.x,
+              child->allocation.y,
+              child->allocation.width,
+              child->allocation.height,
+              child_loc->x, child_loc->y,
+              x, y);
+#endif /* DEBUG_TOOLTIP */
+
+      /* (x, y) relative to child's allocation. */
       if (x >= 0 && x < child->allocation.width
          && y >= 0 && y < child->allocation.height)
         {
@@ -468,6 +486,9 @@ child_location_foreach (GtkWidget *child,
            {
              struct ChildLocation tmp = { NULL, NULL, 0, 0 };
 
+             /* Take (x, y) relative the child's allocation and
+              * recurse.
+              */
              tmp.x = x;
              tmp.y = y;
              tmp.container = child;
@@ -486,6 +507,9 @@ child_location_foreach (GtkWidget *child,
     }
 }
 
+/* Translates coordinates from dest_widget->window relative (src_x, src_y),
+ * to allocation relative (dest_x, dest_y) of dest_widget.
+ */
 static void
 window_to_alloc (GtkWidget *dest_widget,
                 gint       src_x,
@@ -499,6 +523,9 @@ window_to_alloc (GtkWidget *dest_widget,
       gint wx, wy;
       gdk_window_get_position (dest_widget->window, &wx, &wy);
 
+      /* Offset coordinates if widget->window is smaller than
+       * widget->allocation.
+       */
       src_x += wx - dest_widget->allocation.x;
       src_y += wy - dest_widget->allocation.y;
     }
@@ -514,6 +541,9 @@ window_to_alloc (GtkWidget *dest_widget,
     *dest_y = src_y;
 }
 
+/* Translates coordinates from window relative (x, y) to
+ * allocation relative (x, y) of the returned widget.
+ */
 static GtkWidget *
 find_widget_under_pointer (GdkWindow *window,
                           gint      *x,
@@ -527,9 +557,20 @@ find_widget_under_pointer (GdkWindow *window,
   if (!event_widget)
     return NULL;
 
+#ifdef DEBUG_TOOLTIP
+  g_print ("event window %p (belonging to %p (%s))  (%d, %d)\n",
+          window, event_widget, gtk_widget_get_name (event_widget),
+          *x, *y);
+#endif
+
+  /* Coordinates are relative to event window */
   child_loc.x = *x;
   child_loc.y = *y;
 
+  /* We go down the window hierarchy to the widget->window,
+   * coordinates stay relative to the current window.
+   * We end up with window == widget->window, coordinates relative to that.
+   */
   while (window && window != event_widget->window)
     {
       gint px, py;
@@ -541,12 +582,6 @@ find_widget_under_pointer (GdkWindow *window,
       window = gdk_window_get_parent (window);
     }
 
-  if (GTK_WIDGET_NO_WINDOW (event_widget))
-    {
-      child_loc.x += event_widget->allocation.x;
-      child_loc.y += event_widget->allocation.y;
-    }
-
   /* Failing to find widget->window can happen for e.g. a detached handle box;
    * chaining ::query-tooltip up to its parent probably makes little sense,
    * and users better implement tooltips on handle_box->child.
@@ -555,11 +590,16 @@ find_widget_under_pointer (GdkWindow *window,
   if (!window)
     return NULL;
 
+  /* Convert the window relative coordinates to allocation
+   * relative coordinates.
+   */
+  window_to_alloc (event_widget,
+                  child_loc.x, child_loc.y,
+                  &child_loc.x, &child_loc.y);
+
   if (GTK_IS_CONTAINER (event_widget))
     {
-      window_to_alloc (event_widget,
-                      child_loc.x, child_loc.y,
-                      &child_loc.x, &child_loc.y);
+      GtkWidget *container = event_widget;
 
       child_loc.container = event_widget;
       child_loc.child = NULL;
@@ -567,12 +607,23 @@ find_widget_under_pointer (GdkWindow *window,
       gtk_container_forall (GTK_CONTAINER (event_widget),
                            child_location_foreach, &child_loc);
 
+      /* Here we have a widget, with coordinates relative to
+       * child_loc.container's allocation.
+       */
+
       if (child_loc.child)
        event_widget = child_loc.child;
       else if (child_loc.container)
        event_widget = child_loc.container;
+
+      /* Translate to event_widget's allocation */
+      gtk_widget_translate_coordinates (container, event_widget,
+                                       child_loc.x, child_loc.y,
+                                       &child_loc.x, &child_loc.y);
+
     }
 
+  /* We return (x, y) relative to the allocation of event_widget. */
   if (x)
     *x = child_loc.x;
   if (y)
@@ -581,6 +632,9 @@ find_widget_under_pointer (GdkWindow *window,
   return event_widget;
 }
 
+/* Ignores (x, y) on input, translates event coordinates to
+ * allocation relative (x, y) of the returned widget.
+ */
 static GtkWidget *
 find_topmost_widget_coords_from_event (GdkEvent *event,
                                       gint     *x,
@@ -594,26 +648,16 @@ find_topmost_widget_coords_from_event (GdkEvent *event,
   tx = dx;
   ty = dy;
 
+  /* Returns coordinates relative to tmp's allocation. */
   tmp = find_widget_under_pointer (event->any.window, &tx, &ty);
 
   if (!tmp)
     return NULL;
 
-  /* Make sure the pointer can actually be on the widget returned */
-  if (GTK_WIDGET_NO_WINDOW (tmp))
-    {
-      if (tx < tmp->allocation.x ||
-         tx >= tmp->allocation.x + tmp->allocation.width ||
-         ty < tmp->allocation.y ||
-         ty >= tmp->allocation.y + tmp->allocation.height)
-       return NULL;
-    }
-  else
-    {
-      if (tx < 0 || tx >= tmp->allocation.width ||
-         ty < 0 || ty >= tmp->allocation.height)
-       return NULL;
-    }
+  /* Make sure the pointer can actually be on the widget returned. */
+  if (tx < 0 || tx >= tmp->allocation.width ||
+      ty < 0 || ty >= tmp->allocation.height)
+    return NULL;
 
   if (x)
     *x = tx;
@@ -1093,6 +1137,7 @@ _gtk_tooltip_handle_event (GdkEvent *event)
   if (touchscreen)
     return;
 
+  /* Returns coordinates relative to has_tooltip_widget's allocation. */
   has_tooltip_widget = find_topmost_widget_coords_from_event (event, &x, &y);
   display = gdk_drawable_get_display (event->any.window);
   current_tooltip = g_object_get_data (G_OBJECT (display),
@@ -1124,6 +1169,17 @@ _gtk_tooltip_handle_event (GdkEvent *event)
       return;
     }
 
+#ifdef DEBUG_TOOLTIP
+  if (has_tooltip_widget)
+    g_print ("%p (%s) at (%d, %d) %dx%d     pointer: (%d, %d)\n",
+            has_tooltip_widget, gtk_widget_get_name (has_tooltip_widget),
+            has_tooltip_widget->allocation.x,
+            has_tooltip_widget->allocation.y,
+            has_tooltip_widget->allocation.width,
+            has_tooltip_widget->allocation.height,
+            x, y);
+#endif /* DEBUG_TOOLTIP */
+
   /* Always poll for a next motion event */
   gdk_event_request_motions (&event->motion);