[gtk+/touch-for-3.4: 17/65] scrolledwindow: Grab only after starting drag



commit 903fe8e89211a3509b38321fddfbe42e06c2e98c
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Dec 5 00:17:58 2011 +0100

    scrolledwindow: Grab only after starting drag
    
    This is so the grab doesn't break the implicit grab on the
    child widget's window, which avoids that the button press and
    release are possibly sent to different windows, and after the
    grab was actually broken.

 gtk/gtkscrolledwindow.c |   65 +++++++++++++++++++++++++++++++++++-----------
 1 files changed, 49 insertions(+), 16 deletions(-)
---
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
index ab36bee..bd57ecb 100644
--- a/gtk/gtkscrolledwindow.c
+++ b/gtk/gtkscrolledwindow.c
@@ -154,6 +154,7 @@ struct _GtkScrolledWindowPrivate
   /* Kinetic scrolling */
   GdkEvent              *button_press_event;
   GdkWindow             *overshoot_window;
+  GdkDevice             *drag_device;
   guint                  kinetic_scrolling_enabled : 1;
   guint                  in_drag                   : 1;
   guint                  last_button_event_valid   : 1;
@@ -275,6 +276,8 @@ static void  gtk_scrolled_window_realize               (GtkWidget           *wid
 static void  gtk_scrolled_window_unrealize             (GtkWidget           *widget);
 static void  gtk_scrolled_window_map                   (GtkWidget           *widget);
 static void  gtk_scrolled_window_unmap                 (GtkWidget           *widget);
+static void  gtk_scrolled_window_grab_notify           (GtkWidget           *widget,
+                                                        gboolean             was_grabbed);
 
 static gboolean _gtk_scrolled_window_set_adjustment_value      (GtkScrolledWindow *scrolled_window,
                                                                 GtkAdjustment     *adjustment,
@@ -347,6 +350,7 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
   widget_class->unrealize = gtk_scrolled_window_unrealize;
   widget_class->map = gtk_scrolled_window_map;
   widget_class->unmap = gtk_scrolled_window_unmap;
+  widget_class->grab_notify = gtk_scrolled_window_grab_notify;
 
   container_class->add = gtk_scrolled_window_add;
   container_class->remove = gtk_scrolled_window_remove;
@@ -2436,9 +2440,8 @@ gtk_scrolled_window_release_captured_events (GtkScrolledWindow *scrolled_window)
   if (!priv->button_press_event)
     return FALSE;
 
-  device = gdk_event_get_device (priv->button_press_event);
-  gdk_device_ungrab (device, GDK_CURRENT_TIME);
-  gtk_device_grab_remove (GTK_WIDGET (scrolled_window), device);
+  gtk_device_grab_remove (GTK_WIDGET (scrolled_window), priv->drag_device);
+  priv->drag_device = NULL;
 
   if (priv->motion_notify_id > 0)
     {
@@ -2488,7 +2491,8 @@ gtk_scrolled_window_button_release_event (GtkWidget *widget,
   if (!child)
     return FALSE;
 
-  gdk_device_ungrab (gdk_event_get_device (_event), event->time);
+  gtk_device_grab_remove (widget, priv->drag_device);
+  priv->drag_device = NULL;
 
   if (priv->motion_notify_id > 0)
     {
@@ -2506,7 +2510,9 @@ gtk_scrolled_window_button_release_event (GtkWidget *widget,
       priv->release_timeout_id = 0;
     }
 
-  if (!priv->in_drag)
+  if (priv->in_drag)
+    gdk_device_ungrab (event->device, event->time);
+  else
     {
       /* There hasn't been scrolling at all, so just let the
        * child widget handle the events normally
@@ -2600,6 +2606,14 @@ gtk_scrolled_window_motion_notify_event (GtkWidget *widget,
         return TRUE;
     }
 
+  gdk_device_grab (priv->drag_device,
+                   gtk_widget_get_window (widget),
+                   GDK_OWNERSHIP_WINDOW,
+                   TRUE,
+                   GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK,
+                   NULL,
+                   event->time);
+
   priv->last_button_event_valid = FALSE;
 
   if (priv->button_press_event)
@@ -2670,7 +2684,7 @@ gtk_scrolled_window_button_press_event (GtkWidget *widget,
   GtkWidget *child;
   GtkWidget *event_widget;
   GdkEventButton *event;
-  GdkDevice *device, *source_device;
+  GdkDevice *source_device;
   GdkInputSource source;
 
   if (_event->type != GDK_BUTTON_PRESS)
@@ -2722,15 +2736,8 @@ gtk_scrolled_window_button_press_event (GtkWidget *widget,
   if (priv->hscrollbar == event_widget || priv->vscrollbar == event_widget)
     return FALSE;
 
-  device = gdk_event_get_device (_event);
-  gdk_device_grab (device,
-                   gtk_widget_get_window (widget),
-                   GDK_OWNERSHIP_WINDOW,
-                   TRUE,
-                   GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK,
-                   NULL,
-                   event->time);
-  gtk_device_grab_add (widget, device, TRUE);
+  priv->drag_device = gdk_event_get_device (_event);
+  gtk_device_grab_add (widget, priv->drag_device, TRUE);
 
   gtk_scrolled_window_cancel_deceleration (scrolled_window);
 
@@ -2846,7 +2853,7 @@ gtk_scrolled_window_adjustment_value_changed (GtkAdjustment *adjustment,
   GtkScrolledWindowPrivate *priv = scrolled_window->priv;
 
   /* Allow overshooting for kinetic scrolling operations */
-  if (priv->deceleration_id)
+  if (priv->drag_device || priv->deceleration_id)
     return;
 
   /* Ensure GtkAdjustment and unclamped values are in sync */
@@ -3261,6 +3268,32 @@ gtk_scrolled_window_unmap (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->unmap (widget);
 }
 
+static void
+gtk_scrolled_window_grab_notify (GtkWidget *widget,
+                                 gboolean   was_grabbed)
+{
+  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
+  GtkScrolledWindowPrivate *priv = scrolled_window->priv;
+
+  if (priv->drag_device &&
+      gtk_widget_device_is_shadowed (widget,
+                                     priv->drag_device))
+    {
+      gdk_device_ungrab (priv->drag_device,
+                         gtk_get_current_event_time ());
+      priv->drag_device = NULL;
+      priv->in_drag = FALSE;
+
+      if (priv->release_timeout_id)
+        {
+          g_source_remove (priv->release_timeout_id);
+          priv->release_timeout_id = 0;
+        }
+
+      gtk_scrolled_window_cancel_deceleration (scrolled_window);
+    }
+}
+
 /**
  * gtk_scrolled_window_get_min_content_width:
  * @scrolled_window: a #GtkScrolledWindow



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