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.
This commit is contained in:
committed by
Matthias Clasen
parent
c64fd529c1
commit
903fe8e892
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user