1 From 79c1e789097b4e46b9f3fdcbc96a2aae69e24144 Mon Sep 17 00:00:00 2001
2 From: Kristian Rietveld <kris@lanedo.com>
3 Date: Mon, 3 Sep 2012 10:45:13 +0200
4 Subject: [PATCH 21/68] Make scrolled window work well with Mac touchpad
6 Modify the scrolled window code to work with a Mac touchpad as you
7 would expect. When precise deltas are received from the Mac touchpad,
8 overshooting and snapping back will work. The existing kinetic scrolling
9 code is only used for snapping back. The amount of pixels to overshoot
10 is determined by the incoming scroll events from the touchpad. We use
11 the deceleration mechanism that was already in place to snap back.
13 Other changes made are:
14 - Increased the kinetic scrolling distance, this makes things feel
16 - Removed everything related to handling kinetic scrolling by making
17 drag gestures. We don't need this code.
19 gtk/gtkscrolledwindow.c | 680 +++++++++++------------------------------------
20 1 file changed, 157 insertions(+), 523 deletions(-)
22 diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
23 index 9d0d87a..5341b50 100644
24 --- a/gtk/gtkscrolledwindow.c
25 +++ b/gtk/gtkscrolledwindow.c
28 /* Kinetic scrolling */
29 #define FRAME_INTERVAL (1000 / 60)
30 -#define MAX_OVERSHOOT_DISTANCE 50
31 +#define MAX_OVERSHOOT_DISTANCE 100
32 #define FRICTION_DECELERATION 0.003
33 #define OVERSHOOT_INVERSE_ACCELERATION 0.003
34 #define RELEASE_EVENT_TIMEOUT 1000
35 @@ -98,20 +98,11 @@ typedef struct {
36 GdkWindow *vbackground_window;
37 GdkWindow *hbackground_window;
38 guint pointer_grabbed : 1;
39 - guint kinetic_scrolling : 1;
40 - guint capture_button_press : 1;
42 - guint last_button_event_valid : 1;
44 - guint release_timeout_id;
45 guint deceleration_id;
47 - gdouble last_button_event_x_root;
48 - gdouble last_button_event_y_root;
50 - gdouble last_motion_event_x_root;
51 - gdouble last_motion_event_y_root;
52 - guint32 last_motion_event_time;
53 + guint32 last_scroll_event_time;
57 @@ -144,6 +135,7 @@ typedef struct {
58 guint sb_scroll_timeout_id;
60 gboolean overlay_scrollbars;
61 + gboolean is_snapping_back;
62 } GtkScrolledWindowPrivate;
64 #define GTK_SCROLLED_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCROLLED_WINDOW, GtkScrolledWindowPrivate))
65 @@ -167,8 +159,7 @@ enum {
66 PROP_VSCROLLBAR_POLICY,
67 PROP_WINDOW_PLACEMENT,
68 PROP_WINDOW_PLACEMENT_SET,
70 - PROP_KINETIC_SCROLLING
75 @@ -268,6 +259,13 @@ static void gtk_scrolled_window_overlay_scrollbars_changed (GtkSettings *setting
80 +static void gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window);
81 +static gboolean gtk_scrolled_window_calculate_velocity (GtkScrolledWindow *scrolled_window,
83 +static void gtk_scrolled_window_init_overlay_scrollbars (GtkScrolledWindow *window);
86 static guint signals[LAST_SIGNAL] = {0};
88 G_DEFINE_TYPE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
89 @@ -432,22 +430,6 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
93 - * GtkScrolledWindow:kinetic-scrolling:
95 - * The kinetic scrolling behavior flags.
99 - g_object_class_install_property (gobject_class,
100 - PROP_KINETIC_SCROLLING,
101 - g_param_spec_boolean ("kinetic-scrolling",
102 - P_("Kinetic Scrolling"),
103 - P_("Kinetic scrolling mode."),
105 - GTK_PARAM_READABLE |
106 - GTK_PARAM_WRITABLE));
109 * GtkScrolledWindow::scroll-child:
110 * @scrolled_window: a #GtkScrolledWindow
111 * @scroll: a #GtkScrollType describing how much to scroll
112 @@ -531,8 +513,7 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
113 G_CALLBACK (gtk_scrolled_window_overlay_scrollbars_changed),
116 - gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE);
117 - gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE);
118 + gtk_scrolled_window_init_overlay_scrollbars (scrolled_window);
120 priv->opacity = g_object_new (GTK_TYPE_ADJUSTMENT,
122 @@ -1075,130 +1056,6 @@ gtk_scrolled_window_get_shadow_type (GtkScrolledWindow *scrolled_window)
123 return scrolled_window->shadow_type;
127 - * gtk_scrolled_window_set_kinetic_scrolling:
128 - * @scrolled_window: a #GtkScrolledWindow
129 - * @kinetic_scrolling: %TRUE to enable kinetic scrolling
131 - * Turns kinetic scrolling on or off.
132 - * Kinetic scrolling only applies to devices with source
133 - * %GDK_SOURCE_TOUCHSCREEN.
138 -gtk_scrolled_window_set_kinetic_scrolling (GtkScrolledWindow *scrolled_window,
139 - gboolean kinetic_scrolling)
141 - GtkScrolledWindowPrivate *priv;
143 - g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
145 - priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
147 - if (priv->kinetic_scrolling == kinetic_scrolling)
150 - priv->kinetic_scrolling = kinetic_scrolling;
151 - if (priv->kinetic_scrolling)
153 - _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window),
154 - gtk_scrolled_window_captured_event);
158 - _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window), NULL);
159 - if (priv->release_timeout_id)
161 - g_source_remove (priv->release_timeout_id);
162 - priv->release_timeout_id = 0;
164 - if (priv->deceleration_id)
166 - g_source_remove (priv->deceleration_id);
167 - priv->deceleration_id = 0;
170 - g_object_notify (G_OBJECT (scrolled_window), "kinetic-scrolling");
174 - * gtk_scrolled_window_get_kinetic_scrolling:
175 - * @scrolled_window: a #GtkScrolledWindow
177 - * Returns the specified kinetic scrolling behavior.
179 - * Return value: the scrolling behavior flags.
184 -gtk_scrolled_window_get_kinetic_scrolling (GtkScrolledWindow *scrolled_window)
186 - GtkScrolledWindowPrivate *priv;
188 - g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), FALSE);
190 - priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
192 - return priv->kinetic_scrolling;
196 - * gtk_scrolled_window_set_capture_button_press:
197 - * @scrolled_window: a #GtkScrolledWindow
198 - * @capture_button_press: %TRUE to capture button presses
200 - * Changes the behaviour of @scrolled_window wrt. to the initial
201 - * event that possibly starts kinetic scrolling. When @capture_button_press
202 - * is set to %TRUE, the event is captured by the scrolled window, and
203 - * then later replayed if it is meant to go to the child widget.
205 - * This should be enabled if any child widgets perform non-reversible
206 - * actions on #GtkWidget::button-press-event. If they don't, and handle
207 - * additionally handle #GtkWidget::grab-broken-event, it might be better
208 - * to set @capture_button_press to %FALSE.
210 - * This setting only has an effect if kinetic scrolling is enabled.
215 -gtk_scrolled_window_set_capture_button_press (GtkScrolledWindow *scrolled_window,
216 - gboolean capture_button_press)
218 - GtkScrolledWindowPrivate *priv;
220 - g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
222 - priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
223 - priv->capture_button_press = capture_button_press;
227 - * gtk_scrolled_window_get_capture_button_press:
228 - * @scrolled_window: a #GtkScrolledWindow
230 - * Return whether button presses are captured during kinetic
231 - * scrolling. See gtk_scrolled_window_set_capture_button_press().
233 - * Returns: %TRUE if button presses are captured during kinetic scrolling
238 -gtk_scrolled_window_get_capture_button_press (GtkScrolledWindow *scrolled_window)
240 - GtkScrolledWindowPrivate *priv;
242 - g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), FALSE);
244 - priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
246 - return priv->capture_button_press;
251 gtk_scrolled_window_destroy (GtkObject *object)
253 @@ -1246,11 +1103,6 @@ gtk_scrolled_window_destroy (GtkObject *object)
254 G_CALLBACK (gtk_scrolled_window_overlay_scrollbars_changed),
257 - if (priv->release_timeout_id)
259 - g_source_remove (priv->release_timeout_id);
260 - priv->release_timeout_id = 0;
262 if (priv->deceleration_id)
264 g_source_remove (priv->deceleration_id);
265 @@ -1313,10 +1165,6 @@ gtk_scrolled_window_set_property (GObject *object,
266 gtk_scrolled_window_set_shadow_type (scrolled_window,
267 g_value_get_enum (value));
269 - case PROP_KINETIC_SCROLLING:
270 - gtk_scrolled_window_set_kinetic_scrolling (scrolled_window,
271 - g_value_get_boolean (value));
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
276 @@ -1357,9 +1205,6 @@ gtk_scrolled_window_get_property (GObject *object,
277 case PROP_SHADOW_TYPE:
278 g_value_set_enum (value, scrolled_window->shadow_type);
280 - case PROP_KINETIC_SCROLLING:
281 - g_value_set_boolean (value, priv->kinetic_scrolling);
284 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
286 @@ -2152,40 +1997,146 @@ gtk_scrolled_window_scroll_event (GtkWidget *widget,
288 if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
290 - if (delta_x != 0.0 && scrolled_window->hscrollbar &&
291 - (priv->overlay_scrollbars || gtk_widget_get_visible (scrolled_window->hscrollbar)))
292 + gint new_overshoot_x, new_overshoot_y;
293 + gint old_overshoot_x, old_overshoot_y;
294 + gboolean start_snap_back = FALSE;
295 + gboolean is_overshot = FALSE;
296 + gboolean is_momentum_event = event->phase == GDK_EVENT_SCROLL_PHASE_NONE;
298 + _gtk_scrolled_window_get_overshoot (scrolled_window,
299 + &old_overshoot_x, &old_overshoot_y);
301 + /* Check if the view is currently overshot. */
302 + if (old_overshoot_x != 0 || old_overshoot_y != 0)
303 + is_overshot = TRUE;
305 + /* In case the view is not overshot, no snap back is active
306 + * and this event is not a momentum event, then a new scrolling
307 + * gesture has started. In case we are still in snapping back
308 + * state we can reset this (because the snapback has ended).
310 + if (!is_overshot && priv->deceleration_id == 0 && !is_momentum_event)
311 + priv->is_snapping_back = FALSE;
313 + /* Scroll events are handled in two cases:
314 + * 1) We are not overshot and not snapping back, so scroll as
315 + * usual and also handle momentum events.
316 + * 2) If the view is currently overshot, then do not handle
317 + * momentum events but handle non-momentum events as usual.
319 + * For both cases we only allow overshooting in a direction if
320 + * that particular scrollbar is actually visible.
322 + if ((!is_overshot && !priv->is_snapping_back) ||
323 + (is_overshot && !is_momentum_event))
325 - GtkAdjustment *adj;
327 + if (delta_x != 0.0 && scrolled_window->hscrollbar &&
328 + (priv->overlay_scrollbars || gtk_widget_get_visible (scrolled_window->hscrollbar)))
330 + GtkAdjustment *adj;
332 - adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
333 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
335 - new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_x,
336 - gtk_adjustment_get_lower (adj),
337 - gtk_adjustment_get_upper (adj) -
338 - gtk_adjustment_get_page_size (adj));
339 + if (scrolled_window->hscrollbar_visible)
341 + _gtk_scrolled_window_set_adjustment_value (scrolled_window,
343 + priv->unclamped_hadj_value + delta_x,
351 - gtk_adjustment_set_value (adj, new_value);
352 + /* If the scrollbar is not visible, clamp the value and
353 + * don't trigger overshooting.
355 + new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_x,
356 + gtk_adjustment_get_lower (adj),
357 + gtk_adjustment_get_upper (adj) -
358 + gtk_adjustment_get_page_size (adj));
361 + gtk_adjustment_set_value (adj, new_value);
367 + if (delta_y != 0.0 && scrolled_window->vscrollbar &&
368 + (priv->overlay_scrollbars || gtk_widget_get_visible (scrolled_window->vscrollbar)))
370 + GtkAdjustment *adj;
372 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
374 + if (scrolled_window->vscrollbar_visible)
376 + _gtk_scrolled_window_set_adjustment_value (scrolled_window,
378 + priv->unclamped_vadj_value + delta_y,
386 + /* If the scrollbar is not visible, clamp the value and
387 + * don't trigger overshooting.
389 + new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_y,
390 + gtk_adjustment_get_lower (adj),
391 + gtk_adjustment_get_upper (adj) -
392 + gtk_adjustment_get_page_size (adj));
394 + gtk_adjustment_set_value (adj, new_value);
401 + priv->last_scroll_event_time = gdk_event_get_time ((GdkEvent *)event);
402 + gtk_scrolled_window_calculate_velocity (scrolled_window, (GdkEvent *)event);
405 - if (delta_y != 0.0 && scrolled_window->vscrollbar &&
406 - (priv->overlay_scrollbars || gtk_widget_get_visible (scrolled_window->vscrollbar)))
408 - GtkAdjustment *adj;
410 + _gtk_scrolled_window_get_overshoot (scrolled_window,
411 + &new_overshoot_x, &new_overshoot_y);
413 - adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
414 + if (old_overshoot_x != new_overshoot_x ||
415 + old_overshoot_y != new_overshoot_y)
416 + _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
418 - new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_y,
419 - gtk_adjustment_get_lower (adj),
420 - gtk_adjustment_get_upper (adj) -
421 - gtk_adjustment_get_page_size (adj));
422 + /* In two cases we want to start snapping back:
423 + * 1) The view is overshot and the gesture has ended (signalled
424 + * by an event with both deltas set to zero.
425 + * 2) The view is overshot and we receive a momentum event, which
426 + * also signals that the user's gesture has ended.
429 + ((delta_x == 0.0 && delta_y == 0.0) || is_momentum_event))
430 + start_snap_back = TRUE;
432 - gtk_adjustment_set_value (adj, new_value);
433 + /* If we should start a snap back and no current deceleration
434 + * is active, start the snap back.
436 + if (start_snap_back && priv->deceleration_id == 0)
438 + /* Zero out vector components without a visible scrollbar */
439 + if (!scrolled_window->hscrollbar_visible)
440 + priv->x_velocity = 0;
441 + if (!scrolled_window->vscrollbar_visible)
442 + priv->y_velocity = 0;
445 + priv->is_snapping_back = TRUE;
447 + if (new_overshoot_x != 0 || new_overshoot_y != 0)
449 + gtk_scrolled_window_start_deceleration (scrolled_window);
450 + priv->x_velocity = 0.0;
451 + priv->y_velocity = 0.0;
456 @@ -2369,18 +2320,6 @@ scrolled_window_deceleration_cb (gpointer user_data)
460 -gtk_scrolled_window_cancel_deceleration (GtkScrolledWindow *scrolled_window)
462 - GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
464 - if (priv->deceleration_id)
466 - g_source_remove (priv->deceleration_id);
467 - priv->deceleration_id = 0;
472 gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
474 GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
475 @@ -2408,327 +2347,36 @@ gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
479 -gtk_scrolled_window_release_captured_event (GtkScrolledWindow *scrolled_window)
481 - GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
483 - /* Cancel the scrolling and send the button press
484 - * event to the child widget
486 - if (!priv->button_press_event)
489 - if (priv->pointer_grabbed)
491 - gtk_grab_remove (GTK_WIDGET (scrolled_window));
492 - priv->pointer_grabbed = FALSE;
495 - if (priv->capture_button_press)
497 - GtkWidget *event_widget;
499 - event_widget = gtk_get_event_widget (priv->button_press_event);
501 - if (!_gtk_propagate_captured_event (event_widget,
502 - priv->button_press_event,
503 - gtk_bin_get_child (GTK_BIN (scrolled_window))))
504 - gtk_propagate_event (event_widget, priv->button_press_event);
506 - gdk_event_free (priv->button_press_event);
507 - priv->button_press_event = NULL;
510 - if (_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
511 - gtk_scrolled_window_start_deceleration (scrolled_window);
517 gtk_scrolled_window_calculate_velocity (GtkScrolledWindow *scrolled_window,
520 GtkScrolledWindowPrivate *priv;
521 - gdouble x_root, y_root;
524 -#define STILL_THRESHOLD 40
526 - if (!gdk_event_get_root_coords (event, &x_root, &y_root))
529 priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
530 _time = gdk_event_get_time (event);
532 - if (priv->last_motion_event_x_root != x_root ||
533 - priv->last_motion_event_y_root != y_root ||
534 - ABS (_time - priv->last_motion_event_time) > STILL_THRESHOLD)
536 - priv->x_velocity = (priv->last_motion_event_x_root - x_root) /
537 - (gdouble) (_time - priv->last_motion_event_time);
538 - priv->y_velocity = (priv->last_motion_event_y_root - y_root) /
539 - (gdouble) (_time - priv->last_motion_event_time);
542 - priv->last_motion_event_x_root = x_root;
543 - priv->last_motion_event_y_root = y_root;
544 - priv->last_motion_event_time = _time;
546 -#undef STILL_THRESHOLD
552 -gtk_scrolled_window_captured_button_release_kinetic (GtkWidget *widget,
555 - GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
556 - GtkScrolledWindowPrivate *priv;
558 - gboolean overshoot;
559 - gdouble x_root, y_root;
561 - if (event->button.button != 1)
564 - child = gtk_bin_get_child (GTK_BIN (widget));
568 - priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
569 - gtk_grab_remove (widget);
570 - priv->pointer_grabbed = FALSE;
572 - if (priv->release_timeout_id)
574 - g_source_remove (priv->release_timeout_id);
575 - priv->release_timeout_id = 0;
578 - overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL);
581 - gdk_pointer_ungrab (gdk_event_get_time (event));
584 - /* There hasn't been scrolling at all, so just let the
585 - * child widget handle the button press normally
587 - gtk_scrolled_window_release_captured_event (scrolled_window);
592 - priv->in_drag = FALSE;
594 - if (priv->button_press_event)
596 - gdk_event_free (priv->button_press_event);
597 - priv->button_press_event = NULL;
600 - gtk_scrolled_window_calculate_velocity (scrolled_window, event);
602 - /* Zero out vector components without a visible scrollbar */
603 - if (!scrolled_window->hscrollbar_visible)
604 - priv->x_velocity = 0;
605 - if (!scrolled_window->vscrollbar_visible)
606 - priv->y_velocity = 0;
607 +#define STILL_THRESHOLD 40
609 - if (priv->x_velocity != 0 || priv->y_velocity != 0 || overshoot)
610 + if (event->type == GDK_SCROLL)
612 - gtk_scrolled_window_start_deceleration (scrolled_window);
613 - priv->x_velocity = priv->y_velocity = 0;
614 - priv->last_button_event_valid = FALSE;
618 - gdk_event_get_root_coords (event, &x_root, &y_root);
619 - priv->last_button_event_x_root = x_root;
620 - priv->last_button_event_y_root = y_root;
621 - priv->last_button_event_valid = TRUE;
624 - if (priv->capture_button_press)
629 + gdouble delta_x, delta_y;
632 -gtk_scrolled_window_captured_motion_notify_kinetic (GtkWidget *widget,
635 - GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
636 - GtkScrolledWindowPrivate *priv;
637 - gint old_overshoot_x, old_overshoot_y;
638 - gint new_overshoot_x, new_overshoot_y;
640 - GtkAdjustment *hadjustment;
641 - GtkAdjustment *vadjustment;
643 - GdkModifierType state;
644 - gdouble x_root, y_root;
646 - gdk_event_get_state (event, &state);
647 - if (!(state & GDK_BUTTON1_MASK))
650 - child = gtk_bin_get_child (GTK_BIN (widget));
654 - priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
656 - /* Check if we've passed the drag threshold */
657 - gdk_event_get_root_coords (event, &x_root, &y_root);
658 - if (!priv->in_drag)
660 - if (gtk_drag_check_threshold (widget,
661 - priv->last_button_event_x_root,
662 - priv->last_button_event_y_root,
664 + if (gdk_event_get_scroll_deltas (event, &delta_x, &delta_y) &&
665 + ABS (_time - priv->last_scroll_event_time) > STILL_THRESHOLD)
667 - if (priv->release_timeout_id)
669 - g_source_remove (priv->release_timeout_id);
670 - priv->release_timeout_id = 0;
672 + priv->x_velocity = delta_x / (gdouble) (_time - priv->last_scroll_event_time);
673 + priv->y_velocity = delta_y / (gdouble) (_time - priv->last_scroll_event_time);
675 - priv->last_button_event_valid = FALSE;
676 - priv->in_drag = TRUE;
677 + priv->last_scroll_event_time = _time;
683 - gdk_pointer_grab (gtk_widget_get_window (widget),
685 - GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK,
687 - gdk_event_get_time (event));
689 - priv->last_button_event_valid = FALSE;
691 - if (priv->button_press_event)
693 - gdk_event_free (priv->button_press_event);
694 - priv->button_press_event = NULL;
697 - _gtk_scrolled_window_get_overshoot (scrolled_window,
698 - &old_overshoot_x, &old_overshoot_y);
700 - hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
701 - if (hadjustment && scrolled_window->hscrollbar_visible)
703 - dx = (priv->last_motion_event_x_root - x_root) + priv->unclamped_hadj_value;
704 - _gtk_scrolled_window_set_adjustment_value (scrolled_window, hadjustment,
708 - vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
709 - if (vadjustment && scrolled_window->vscrollbar_visible)
711 - dy = (priv->last_motion_event_y_root - y_root) + priv->unclamped_vadj_value;
712 - _gtk_scrolled_window_set_adjustment_value (scrolled_window, vadjustment,
716 - _gtk_scrolled_window_get_overshoot (scrolled_window,
717 - &new_overshoot_x, &new_overshoot_y);
719 - if (old_overshoot_x != new_overshoot_x ||
720 - old_overshoot_y != new_overshoot_y)
721 - _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
723 - gtk_scrolled_window_calculate_velocity (scrolled_window, event);
724 +#undef STILL_THRESHOLD
730 -gtk_scrolled_window_captured_button_press_kinetic (GtkWidget *widget,
733 - GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
734 - GtkScrolledWindowPrivate *priv;
736 - GtkWidget *event_widget;
737 - gdouble x_root, y_root;
739 - /* If scrollbars are not visible, we don't do kinetic scrolling */
740 - if (!scrolled_window->vscrollbar_visible &&
741 - !scrolled_window->hscrollbar_visible)
744 - priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
746 - event_widget = gtk_get_event_widget (event);
748 - /* If there's another scrolled window between the widget
749 - * receiving the event and this capturing scrolled window,
750 - * let it handle the events.
752 - if (widget != gtk_widget_get_ancestor (event_widget, GTK_TYPE_SCROLLED_WINDOW))
755 - /* Check whether the button press is close to the previous one,
756 - * take that as a shortcut to get the child widget handle events
758 - gdk_event_get_root_coords (event, &x_root, &y_root);
759 - if (priv->last_button_event_valid &&
760 - ABS (x_root - priv->last_button_event_x_root) < TOUCH_BYPASS_CAPTURED_THRESHOLD &&
761 - ABS (y_root - priv->last_button_event_y_root) < TOUCH_BYPASS_CAPTURED_THRESHOLD)
763 - priv->last_button_event_valid = FALSE;
767 - priv->last_button_event_x_root = priv->last_motion_event_x_root = x_root;
768 - priv->last_button_event_y_root = priv->last_motion_event_y_root = y_root;
769 - priv->last_motion_event_time = gdk_event_get_time (event);
770 - priv->last_button_event_valid = TRUE;
772 - if (event->button.button != 1)
775 - child = gtk_bin_get_child (GTK_BIN (widget));
779 - if (scrolled_window->hscrollbar == event_widget ||
780 - scrolled_window->vscrollbar == event_widget)
783 - priv->pointer_grabbed = TRUE;
784 - gtk_grab_add (widget);
786 - gtk_scrolled_window_cancel_deceleration (scrolled_window);
788 - /* Only set the timeout if we're going to store an event */
789 - if (priv->capture_button_press)
790 - priv->release_timeout_id =
791 - gdk_threads_add_timeout (RELEASE_EVENT_TIMEOUT,
792 - (GSourceFunc) gtk_scrolled_window_release_captured_event,
795 - priv->in_drag = FALSE;
797 - if (priv->capture_button_press)
799 - /* Store the button press event in
800 - * case we need to propagate it later
802 - priv->button_press_event = gdk_event_copy (event);
810 gtk_scrolled_window_scroll_step (GtkScrolledWindow *scrolled_window)
812 @@ -3011,22 +2659,14 @@ gtk_scrolled_window_captured_event (GtkWidget *widget,
814 case GDK_BUTTON_PRESS:
815 retval = gtk_scrolled_window_captured_button_press_scrollbar (widget, event);
817 - retval = gtk_scrolled_window_captured_button_press_kinetic (widget, event);
819 case GDK_BUTTON_RELEASE:
820 if (priv->sb_pointer_grabbed)
821 retval = gtk_scrolled_window_captured_button_release_scrollbar (widget, event);
822 - else if (priv->pointer_grabbed)
823 - retval = gtk_scrolled_window_captured_button_release_kinetic (widget, event);
825 - priv->last_button_event_valid = FALSE;
827 case GDK_MOTION_NOTIFY:
828 if (priv->sb_pointer_grabbed || !priv->pointer_grabbed)
829 retval = gtk_scrolled_window_captured_motion_notify_scrollbar (widget, event);
830 - else if (priv->pointer_grabbed)
831 - retval = gtk_scrolled_window_captured_motion_notify_kinetic (widget, event);
833 case GDK_LEAVE_NOTIFY:
834 if (!priv->in_drag && !priv->sb_pointer_grabbed)
835 @@ -3439,19 +3079,6 @@ gtk_scrolled_window_grab_notify (GtkWidget *widget,
836 gdk_pointer_ungrab (gtk_get_current_event_time ());
837 priv->pointer_grabbed = FALSE;
838 priv->in_drag = FALSE;
840 - if (priv->release_timeout_id)
842 - g_source_remove (priv->release_timeout_id);
843 - priv->release_timeout_id = 0;
846 - if (_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
847 - gtk_scrolled_window_start_deceleration (scrolled_window);
849 - gtk_scrolled_window_cancel_deceleration (scrolled_window);
851 - priv->last_button_event_valid = FALSE;
854 if (priv->sb_pointer_grabbed && !was_grabbed)
855 @@ -3923,6 +3550,13 @@ gtk_scrolled_window_expose_scrollbars (GtkAdjustment *adj,
859 +gtk_scrolled_window_init_overlay_scrollbars (GtkScrolledWindow *scrolled_window)
861 + _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window),
862 + gtk_scrolled_window_captured_event);
866 gtk_scrolled_window_overlay_scrollbars_changed (GtkSettings *settings,
870 1.7.10.2 (Apple Git-33)