2009-02-23 Alejandro G. Castro <alex@igalia.com>
authorAlejandro G. Castro <alex@igalia.com>
Mon, 23 Feb 2009 17:16:57 +0000 (17:16 +0000)
committerAlejandro G. Castro <alex@igalia.com>
Mon, 23 Feb 2009 17:16:57 +0000 (17:16 +0000)
This patch was applied before but reverted because it caused
problems, we have changed the main condition and tested the
regressions we detected before and they work ok. We have done a
complete review of the topmost algorithm in order to get a more
general solution.

        * src/hildon-pannable-area.c,
        (hildon_pannable_area_get_topmost): Added a new parameter to
        filter the the windows that do not include those events.
        (hildon_pannable_area_button_press_cb),
        (hildon_pannable_area_button_release_cb),
        (hildon_pannable_get_child_widget_at): Reviewed the call the the
        topmost function, we have added the new parameter.

        Fixes: NB#97458 (Pannable area prevents propagation of button
        press events)

ChangeLog
src/hildon-pannable-area.c

index 14ef95c..c442106 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2009-02-23  Alejandro G. Castro  <alex@igalia.com>
+
+       This patch was applied before but reverted because it caused
+       problems, we have changed the main condition and tested the
+       regressions we detected before and they work ok. We have done a
+       complete review of the topmost algorithm in order to get a more
+       general solution.
+
+        * src/hildon-pannable-area.c,
+        (hildon_pannable_area_get_topmost): Added a new parameter to
+        filter the the windows that do not include those events.
+        (hildon_pannable_area_button_press_cb),
+        (hildon_pannable_area_button_release_cb),
+        (hildon_pannable_get_child_widget_at): Reviewed the call the the
+        topmost function, we have added the new parameter.
+
+        Fixes: NB#97458 (Pannable area prevents propagation of button
+        press events)
+
 2009-02-23  Claudio Saavedra  <csaavedra@igalia.com>
 
        * src/hildon-picker-dialog.c (+selection_completed): Returns TRUE
index 4fc8854..cb2c386 100644 (file)
@@ -213,7 +213,8 @@ static gboolean hildon_pannable_area_expose_event (GtkWidget * widget,
                                                    GdkEventExpose * event);
 static GdkWindow * hildon_pannable_area_get_topmost (GdkWindow * window,
                                                      gint x, gint y,
-                                                     gint * tx, gint * ty);
+                                                     gint * tx, gint * ty,
+                                                     GdkEventMask mask);
 static void synth_crossing (GdkWindow * child,
                             gint x, gint y,
                             gint x_root, gint y_root,
@@ -1533,51 +1534,64 @@ hildon_pannable_area_expose_event (GtkWidget * widget,
 static GdkWindow *
 hildon_pannable_area_get_topmost (GdkWindow * window,
                                   gint x, gint y,
-                                  gint * tx, gint * ty)
+                                  gint * tx, gint * ty,
+                                  GdkEventMask mask)
 {
   /* Find the GdkWindow at the given point, by recursing from a given
    * parent GdkWindow. Optionally return the co-ordinates transformed
    * relative to the child window.
    */
   gint width, height;
+  GList *c, *children;
+  GdkWindow *selected_window = NULL;
 
   gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
   if ((x < 0) || (x >= width) || (y < 0) || (y >= height))
     return NULL;
 
-  while (window) {
-    gint child_x = 0, child_y = 0;
-    GList *c, *children = gdk_window_peek_children (window);
-    GdkWindow *old_window = window;
+  children = gdk_window_peek_children (window);
 
-    for (c = children; c; c = c->next) {
-      GdkWindow *child = (GdkWindow *) c->data;
-      gint wx, wy;
-
-      gdk_drawable_get_size (GDK_DRAWABLE (child), &width, &height);
-      gdk_window_get_position (child, &wx, &wy);
+  if (!children) {
+    if (tx)
+      *tx = x;
+    if (ty)
+      *ty = y;
+    selected_window = window;
+  }
 
-      if (((x >= wx) && (x < (wx + width)) && (y >= wy)
-           && (y < (wy + height))) && (gdk_window_is_visible (child))) {
-       child_x = x - wx;
-       child_y = y - wy;
-       window = child;
+  for (c = children; c; c = c->next) {
+    GdkWindow *child = (GdkWindow *) c->data;
+    gint wx, wy;
+
+    gdk_drawable_get_size (GDK_DRAWABLE (child), &width, &height);
+    gdk_window_get_position (child, &wx, &wy);
+
+    if ((x >= wx) && (x < (wx + width)) && (y >= wy) && (y < (wy + height)) &&
+        (gdk_window_is_visible (child))) {
+
+      if (gdk_window_peek_children (child)) {
+        selected_window = hildon_pannable_area_get_topmost (child, x-wx, y-wy,
+                                                            tx, ty, mask);
+        if (!selected_window) {
+          if (tx)
+            *tx = x;
+          if (ty)
+            *ty = y;
+          selected_window = child;
+        }
+      } else {
+        if ((gdk_window_get_events (child)&mask)) {
+          if (tx)
+            *tx = x-wx;
+          if (ty)
+            *ty = y-wy;
+          selected_window = child;
+        }
       }
     }
-
-    if (window == old_window)
-      break;
-
-    x = child_x;
-    y = child_y;
   }
 
-  if (tx)
-    *tx = x;
-  if (ty)
-    *ty = y;
-
-  return window;
+  return selected_window;
 }
 
 static void
@@ -1647,7 +1661,7 @@ hildon_pannable_area_button_press_cb (GtkWidget * widget,
       (ABS (priv->vel_y) <= (priv->vmax * priv->vfast_factor)))
     priv->child =
       hildon_pannable_area_get_topmost (gtk_bin_get_child (GTK_BIN (widget))->window,
-                                       event->x, event->y, &x, &y);
+                                       event->x, event->y, &x, &y, GDK_BUTTON_PRESS_MASK);
   else
     priv->child = NULL;
 
@@ -2282,7 +2296,7 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget,
 
   child =
     hildon_pannable_area_get_topmost (gtk_bin_get_child (GTK_BIN (widget))->window,
-                                     event->x, event->y, &x, &y);
+                                     event->x, event->y, &x, &y, GDK_BUTTON_RELEASE_MASK);
 
   event = (GdkEventButton *) gdk_event_copy ((GdkEvent *) event);
   event->x = x;
@@ -2832,7 +2846,7 @@ hildon_pannable_get_child_widget_at (HildonPannableArea *area,
 
   window = hildon_pannable_area_get_topmost
     (gtk_bin_get_child (GTK_BIN (area))->window,
-     x, y, NULL, NULL);
+     x, y, NULL, NULL, GDK_ALL_EVENTS_MASK);
 
   gdk_window_get_user_data (window, (gpointer) &child_widget);