[gtk+/touch-for-3.4: 17/65] scrolledwindow: Grab only after starting drag
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/touch-for-3.4: 17/65] scrolledwindow: Grab only after starting drag
- Date: Fri, 24 Feb 2012 15:26:16 +0000 (UTC)
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]