[gtk+/touchscreens: 28/67] gtk, pah: Hook directly into gtk_main_do_event()



commit 3657ba1d5dc56af853aae37cddf751ef3f7df983
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Nov 6 12:03:22 2011 +0100

    gtk,pah: Hook directly into gtk_main_do_event()
    
    Press and hold couldn't reasonably work if nested widgets
    handle ::captured-event, once the widget inits press-and-hold,
    it'd better also handle possible cancellation on motion and
    button release, which isn't guaranteed with ::capture-event.
    
    Also, tentatively start press-and-hold by default on the
    grab_widget, and before event capturing happens, this avoids
    awkward situations like the scrolled window preventing/delaying
    press-and-hold to happen on the child textview for example.

 gtk/gtkmain.c          |   17 +++++++
 gtk/gtkwidget.c        |  120 +++++++++++++++++++-----------------------------
 gtk/gtkwidgetprivate.h |    7 +++
 3 files changed, 72 insertions(+), 72 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index c761d90..670705b 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1644,6 +1644,16 @@ gtk_main_do_event (GdkEvent *event)
     case GDK_BUTTON_PRESS:
     case GDK_2BUTTON_PRESS:
     case GDK_3BUTTON_PRESS:
+      if ((event->type == GDK_BUTTON_PRESS) &&
+          event->button.button == 1)
+        {
+          /* Handle press and hold on the grab widget before propagating up,
+           * so a parent capturing events doesn't delay nor prevent a child
+           * from doing the press-and-hold action.
+           */
+          _gtk_widget_press_and_hold_check_start (grab_widget, &event->button);
+        }
+
       if (!gtk_propagate_captured_event (grab_widget, event, topmost_widget))
         gtk_propagate_event (grab_widget, event);
       break;
@@ -1697,6 +1707,13 @@ gtk_main_do_event (GdkEvent *event)
     case GDK_BUTTON_RELEASE:
     case GDK_PROXIMITY_IN:
     case GDK_PROXIMITY_OUT:
+      if ((event->type == GDK_BUTTON_RELEASE) &&
+          event->button.button == 1)
+        _gtk_widget_press_and_hold_check_cancel (grab_widget, &event->button);
+      else if (event->type == GDK_MOTION_NOTIFY)
+        _gtk_widget_press_and_hold_check_threshold (grab_widget,
+                                                    &event->motion);
+
       if (!gtk_propagate_captured_event (grab_widget, event, topmost_widget))
         gtk_propagate_event (grab_widget, event);
       break;
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 55f1bd4..21ae6ba 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -545,11 +545,6 @@ typedef struct
   GtkWidget *popup;
   guint delay_animation_id;
 
-  /* signal handlers */
-  guint motion_id;
-  guint button_release_id;
-  guint grab_notify_id;
-
   gint start_x;
   gint start_y;
   gint current_x;
@@ -665,8 +660,6 @@ static gboolean         gtk_widget_real_can_activate_accel      (GtkWidget *widg
 static void             gtk_widget_real_set_has_tooltip         (GtkWidget *widget,
 								 gboolean   has_tooltip,
 								 gboolean   force);
-static gboolean         gtk_widget_press_and_hold_start         (GtkWidget      *widget,
-                                                                 GdkEventButton *button);
 static void             gtk_widget_buildable_interface_init     (GtkBuildableIface *iface);
 static void             gtk_widget_buildable_set_name           (GtkBuildable     *buildable,
                                                                  const gchar      *name);
@@ -728,6 +721,9 @@ static void gtk_widget_set_device_enabled_internal (GtkWidget *widget,
                                                     gboolean   enabled);
 static gboolean event_window_is_still_viewable (GdkEvent *event);
 
+static gboolean gtk_widget_press_and_hold_cancel (GtkWidget *widget);
+
+
 /* --- variables --- */
 static gpointer         gtk_widget_parent_class = NULL;
 static guint            widget_signals[LAST_SIGNAL] = { 0 };
@@ -6011,15 +6007,6 @@ _gtk_widget_captured_event (GtkWidget *widget,
 
   g_object_ref (widget);
 
-  if ((event->type == GDK_BUTTON_PRESS ||
-       event->type == GDK_TOUCH_PRESS) &&
-      event->button.button == 1)
-    {
-      /* Handle press and hold */
-      gtk_widget_press_and_hold_start (widget,
-                                       (GdkEventButton *)event);
-    }
-
   g_signal_emit (widget, widget_signals[CAPTURED_EVENT], 0, event, &return_val);
   return_val |= !WIDGET_REALIZED_FOR_EVENT (widget, event);
 
@@ -6565,6 +6552,14 @@ void
 _gtk_widget_grab_notify (GtkWidget *widget,
 			 gboolean   was_grabbed)
 {
+  PressAndHoldData *data;
+
+  data = g_object_get_qdata (G_OBJECT (widget), quark_press_and_hold);
+
+  if (data && data->device &&
+      gtk_widget_device_is_shadowed (widget, data->device))
+    gtk_widget_press_and_hold_cancel (widget);
+
   g_signal_emit (widget, widget_signals[GRAB_NOTIFY], 0, was_grabbed);
 }
 
@@ -6896,15 +6891,6 @@ press_and_hold_data_free (PressAndHoldData *data)
   if (data->delay_animation_id)
     g_source_remove (data->delay_animation_id);
 
-  if (data->motion_id)
-    g_signal_handler_disconnect (data->widget, data->motion_id);
-
-  if (data->button_release_id)
-    g_signal_handler_disconnect (data->widget, data->button_release_id);
-
-  if (data->grab_notify_id)
-    g_signal_handler_disconnect (data->widget, data->grab_notify_id);
-
   g_slice_free (PressAndHoldData, data);
 }
 
@@ -6955,43 +6941,43 @@ gtk_widget_press_and_hold_cancel (GtkWidget *widget)
   return FALSE;
 }
 
-static gboolean
-gtk_widget_press_and_hold_button_release (GtkWidget        *widget,
-                                          GdkEvent         *_event,
-                                          PressAndHoldData *data)
+gboolean
+_gtk_widget_press_and_hold_check_cancel (GtkWidget      *widget,
+                                         GdkEventButton *event)
 {
-  if (_event->type != GDK_BUTTON_RELEASE)
+  PressAndHoldData *data;
+
+  if (event->type != GDK_BUTTON_RELEASE)
     return FALSE;
 
-  if (data->device == gdk_event_get_device (_event))
-    gtk_widget_press_and_hold_cancel (widget);
+  data = gtk_widget_peek_press_and_hold_data (widget);
 
-  return FALSE;
-}
+  if (data &&
+      data->device == gdk_event_get_device ((GdkEvent *) event))
+    {
+      gtk_widget_press_and_hold_cancel (widget);
+      return TRUE;
+    }
 
-static void
-gtk_widget_press_and_hold_grab_notify (GtkWidget        *widget,
-                                       gboolean          was_grabbed,
-                                       PressAndHoldData *data)
-{
-  if (data->device &&
-      gtk_widget_device_is_shadowed (widget, data->device))
-    gtk_widget_press_and_hold_cancel (widget);
+  return FALSE;
 }
 
-static gboolean
-gtk_widget_press_and_hold_motion_notify (GtkWidget        *widget,
-                                         GdkEvent         *_event,
-                                         PressAndHoldData *data)
+gboolean
+_gtk_widget_press_and_hold_check_threshold (GtkWidget      *widget,
+                                            GdkEventMotion *event)
 {
-  GdkEventMotion *event;
+  PressAndHoldData *data;
   GdkDevice *device;
 
-  if (_event->type != GDK_MOTION_NOTIFY)
+  if (event->type != GDK_MOTION_NOTIFY)
+    return FALSE;
+
+  data = gtk_widget_peek_press_and_hold_data (widget);
+
+  if (!data)
     return FALSE;
 
-  event = (GdkEventMotion *)_event;
-  device = gdk_event_get_device (_event);
+  device = gdk_event_get_device ((GdkEvent *) event);
 
   if (data->device != device)
     return FALSE;
@@ -7004,8 +6990,7 @@ gtk_widget_press_and_hold_motion_notify (GtkWidget        *widget,
                                 data->current_x, data->current_y))
     {
       gtk_widget_press_and_hold_cancel (widget);
-
-      return FALSE;
+      return TRUE;
     }
 
   if (data->popup)
@@ -7149,28 +7134,32 @@ gtk_widget_press_and_hold_query (GtkWidget *widget,
   return return_value;
 }
 
-static gboolean
-gtk_widget_press_and_hold_start (GtkWidget      *widget,
-                                 GdkEventButton *event)
+gboolean
+_gtk_widget_press_and_hold_check_start (GtkWidget      *widget,
+                                        GdkEventButton *event)
 {
   PressAndHoldData *data = gtk_widget_peek_press_and_hold_data (widget);
 
+  if (event->type != GDK_BUTTON_PRESS)
+    return FALSE;
+
   /* Press and hold already in process? */
   if (data)
     return FALSE;
 
   data = gtk_widget_get_press_and_hold_data (widget);
 
-  if (gtk_widget_press_and_hold_query (widget, data->device, event->x, event->y))
+  if (gtk_widget_press_and_hold_query (widget, data->device,
+                                       event->x, event->y))
     {
-      gint timeout, begin_ani_timeout;
+      gint timeout, begin_ani_timeout, cursor_size;
       GdkScreen *screen;
       GdkVisual *visual;
       GtkStyleContext *context;
       cairo_region_t *region;
-      guint cursor_size;
 
-      _gtk_widget_find_at_coords (event->window, event->x, event->y,
+      _gtk_widget_find_at_coords (event->window,
+                                  event->x, event->y,
                                   &data->start_x, &data->start_y);
 
       data->current_x = data->start_x;
@@ -7211,19 +7200,6 @@ gtk_widget_press_and_hold_start (GtkWidget      *widget,
                                  gtk_widget_press_and_hold_begin_animation_timeout,
                                  widget);
 
-      data->motion_id =
-        g_signal_connect (widget, "captured-event",
-                          G_CALLBACK (gtk_widget_press_and_hold_motion_notify),
-                          data);
-      data->button_release_id =
-        g_signal_connect (widget, "captured-event",
-                          G_CALLBACK (gtk_widget_press_and_hold_button_release),
-                          data);
-      data->grab_notify_id =
-        g_signal_connect (widget, "grab-notify",
-                          G_CALLBACK (gtk_widget_press_and_hold_grab_notify),
-                          data);
-
       data->device = gdk_event_get_device ((GdkEvent *) event);
     }
 
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 8716c67..f475e14 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -166,6 +166,13 @@ void              _gtk_widget_set_style                    (GtkWidget *widget,
 gboolean          _gtk_widget_captured_event               (GtkWidget *widget,
                                                             GdkEvent  *event);
 
+gboolean          _gtk_widget_press_and_hold_check_start     (GtkWidget      *widget,
+                                                              GdkEventButton *event);
+gboolean          _gtk_widget_press_and_hold_check_cancel    (GtkWidget      *widget,
+                                                              GdkEventButton *event);
+gboolean          _gtk_widget_press_and_hold_check_threshold (GtkWidget      *widget,
+                                                              GdkEventMotion *event);
+
 G_END_DECLS
 
 #endif /* __GTK_WIDGET_PRIVATE_H__ */



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