Fix 'mono' package typo
[mono.git] / bockbuild / mac-sdk / patches / gtk / 0021-Make-scrolled-window-work-well-with-Mac-touchpad.patch
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
5
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.
12
13 Other changes made are:
14  - Increased the kinetic scrolling distance, this makes things feel
15  nicer IMHO.
16  - Removed everything related to handling kinetic scrolling by making
17  drag gestures. We don't need this code.
18 ---
19  gtk/gtkscrolledwindow.c |  680 +++++++++++------------------------------------
20  1 file changed, 157 insertions(+), 523 deletions(-)
21
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
26 @@ -79,7 +79,7 @@
27
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;
41    guint                  in_drag                   : 1;
42 -  guint                  last_button_event_valid   : 1;
43
44 -  guint                  release_timeout_id;
45    guint                  deceleration_id;
46
47 -  gdouble                last_button_event_x_root;
48 -  gdouble                last_button_event_y_root;
49 -
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;
54
55    gdouble                x_velocity;
56    gdouble                y_velocity;
57 @@ -144,6 +135,7 @@ typedef struct {
58    guint          sb_scroll_timeout_id;
59
60    gboolean       overlay_scrollbars;
61 +  gboolean       is_snapping_back;
62  } GtkScrolledWindowPrivate;
63
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,
69 -  PROP_SHADOW_TYPE,
70 -  PROP_KINETIC_SCROLLING
71 +  PROP_SHADOW_TYPE
72  };
73
74  /* Signals */
75 @@ -268,6 +259,13 @@ static void gtk_scrolled_window_overlay_scrollbars_changed (GtkSettings *setting
76                                                              GParamSpec  *arg,
77                                                              gpointer     user_data);
78
79 +
80 +static void gtk_scrolled_window_start_deceleration      (GtkScrolledWindow *scrolled_window);
81 +static gboolean gtk_scrolled_window_calculate_velocity  (GtkScrolledWindow *scrolled_window,
82 +                                                         GdkEvent          *event);
83 +static void gtk_scrolled_window_init_overlay_scrollbars (GtkScrolledWindow *window);
84 +
85 +
86  static guint signals[LAST_SIGNAL] = {0};
87
88  G_DEFINE_TYPE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
89 @@ -432,22 +430,6 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
90                                                              GTK_PARAM_READABLE));
91
92    /**
93 -   * GtkScrolledWindow:kinetic-scrolling:
94 -   *
95 -   * The kinetic scrolling behavior flags.
96 -   *
97 -   * Since: X.XX
98 -   */
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."),
104 -                                                         TRUE,
105 -                                                         GTK_PARAM_READABLE |
106 -                                                         GTK_PARAM_WRITABLE));
107 -
108 -  /**
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),
114                      scrolled_window);
115
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);
119
120    priv->opacity = g_object_new (GTK_TYPE_ADJUSTMENT,
121                                  "lower", 0.0,
122 @@ -1075,130 +1056,6 @@ gtk_scrolled_window_get_shadow_type (GtkScrolledWindow *scrolled_window)
123    return scrolled_window->shadow_type;
124  }
125
126 -/**
127 - * gtk_scrolled_window_set_kinetic_scrolling:
128 - * @scrolled_window: a #GtkScrolledWindow
129 - * @kinetic_scrolling: %TRUE to enable kinetic scrolling
130 - *
131 - * Turns kinetic scrolling on or off.
132 - * Kinetic scrolling only applies to devices with source
133 - * %GDK_SOURCE_TOUCHSCREEN.
134 - *
135 - * Since: X.XX
136 - **/
137 -void
138 -gtk_scrolled_window_set_kinetic_scrolling (GtkScrolledWindow *scrolled_window,
139 -                                           gboolean           kinetic_scrolling)
140 -{
141 -  GtkScrolledWindowPrivate *priv;
142 -
143 -  g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
144 -
145 -  priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
146 -
147 -  if (priv->kinetic_scrolling == kinetic_scrolling)
148 -    return;
149 -
150 -  priv->kinetic_scrolling = kinetic_scrolling;
151 -  if (priv->kinetic_scrolling)
152 -    {
153 -      _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window),
154 -                                              gtk_scrolled_window_captured_event);
155 -    }
156 -  else
157 -    {
158 -      _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window), NULL);
159 -      if (priv->release_timeout_id)
160 -        {
161 -          g_source_remove (priv->release_timeout_id);
162 -          priv->release_timeout_id = 0;
163 -        }
164 -      if (priv->deceleration_id)
165 -        {
166 -          g_source_remove (priv->deceleration_id);
167 -          priv->deceleration_id = 0;
168 -        }
169 -    }
170 -  g_object_notify (G_OBJECT (scrolled_window), "kinetic-scrolling");
171 -}
172 -
173 -/**
174 - * gtk_scrolled_window_get_kinetic_scrolling:
175 - * @scrolled_window: a #GtkScrolledWindow
176 - *
177 - * Returns the specified kinetic scrolling behavior.
178 - *
179 - * Return value: the scrolling behavior flags.
180 - *
181 - * Since: X.XX
182 - */
183 -gboolean
184 -gtk_scrolled_window_get_kinetic_scrolling (GtkScrolledWindow *scrolled_window)
185 -{
186 -  GtkScrolledWindowPrivate *priv;
187 -
188 -  g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), FALSE);
189 -
190 -  priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
191 -
192 -  return priv->kinetic_scrolling;
193 -}
194 -
195 -/**
196 - * gtk_scrolled_window_set_capture_button_press:
197 - * @scrolled_window: a #GtkScrolledWindow
198 - * @capture_button_press: %TRUE to capture button presses
199 - *
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.
204 - *
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.
209 - *
210 - * This setting only has an effect if kinetic scrolling is enabled.
211 - *
212 - * Since: X.XX
213 - */
214 -void
215 -gtk_scrolled_window_set_capture_button_press (GtkScrolledWindow *scrolled_window,
216 -                                              gboolean           capture_button_press)
217 -{
218 -  GtkScrolledWindowPrivate *priv;
219 -
220 -  g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
221 -
222 -  priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
223 -  priv->capture_button_press = capture_button_press;
224 -}
225 -
226 -/**
227 - * gtk_scrolled_window_get_capture_button_press:
228 - * @scrolled_window: a #GtkScrolledWindow
229 - *
230 - * Return whether button presses are captured during kinetic
231 - * scrolling. See gtk_scrolled_window_set_capture_button_press().
232 - *
233 - * Returns: %TRUE if button presses are captured during kinetic scrolling
234 - *
235 - * Since: X.XX
236 - */
237 -gboolean
238 -gtk_scrolled_window_get_capture_button_press (GtkScrolledWindow *scrolled_window)
239 -{
240 -  GtkScrolledWindowPrivate *priv;
241 -
242 -  g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), FALSE);
243 -
244 -  priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
245 -
246 -  return priv->capture_button_press;
247 -}
248 -
249 -
250  static void
251  gtk_scrolled_window_destroy (GtkObject *object)
252  {
253 @@ -1246,11 +1103,6 @@ gtk_scrolled_window_destroy (GtkObject *object)
254                                          G_CALLBACK (gtk_scrolled_window_overlay_scrollbars_changed),
255                                          scrolled_window);
256
257 -  if (priv->release_timeout_id)
258 -    {
259 -      g_source_remove (priv->release_timeout_id);
260 -      priv->release_timeout_id = 0;
261 -    }
262    if (priv->deceleration_id)
263      {
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));
268        break;
269 -    case PROP_KINETIC_SCROLLING:
270 -      gtk_scrolled_window_set_kinetic_scrolling (scrolled_window,
271 -                                                 g_value_get_boolean (value));
272 -      break;
273      default:
274        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275        break;
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);
279        break;
280 -    case PROP_KINETIC_SCROLLING:
281 -      g_value_set_boolean (value, priv->kinetic_scrolling);
282 -      break;
283      default:
284        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
285        break;
286 @@ -2152,40 +1997,146 @@ gtk_scrolled_window_scroll_event (GtkWidget      *widget,
287
288    if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
289      {
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;
297 +
298 +      _gtk_scrolled_window_get_overshoot (scrolled_window,
299 +                                          &old_overshoot_x, &old_overshoot_y);
300 +
301 +      /* Check if the view is currently overshot. */
302 +      if (old_overshoot_x != 0 || old_overshoot_y != 0)
303 +        is_overshot = TRUE;
304 +
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).
309 +       */
310 +      if (!is_overshot && priv->deceleration_id == 0 && !is_momentum_event)
311 +        priv->is_snapping_back = FALSE;
312 +
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.
318 +       *
319 +       * For both cases we only allow overshooting in a direction if
320 +       * that particular scrollbar is actually visible.
321 +       */
322 +      if ((!is_overshot && !priv->is_snapping_back) ||
323 +          (is_overshot && !is_momentum_event))
324          {
325 -          GtkAdjustment *adj;
326 -          gdouble new_value;
327 +          if (delta_x != 0.0 && scrolled_window->hscrollbar &&
328 +              (priv->overlay_scrollbars || gtk_widget_get_visible (scrolled_window->hscrollbar)))
329 +            {
330 +              GtkAdjustment *adj;
331
332 -          adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
333 +              adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
334
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)
340 +                {
341 +                  _gtk_scrolled_window_set_adjustment_value (scrolled_window,
342 +                                                             adj,
343 +                                                             priv->unclamped_hadj_value + delta_x,
344 +                                                             TRUE,
345 +                                                             FALSE);
346 +                }
347 +              else
348 +                {
349 +                  gdouble new_value;
350
351 -          gtk_adjustment_set_value (adj, new_value);
352 +                  /* If the scrollbar is not visible, clamp the value and
353 +                   * don't trigger overshooting.
354 +                   */
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));
359
360 -          handled = TRUE;
361 +                  gtk_adjustment_set_value (adj, new_value);
362 +                }
363 +
364 +              handled = TRUE;
365 +            }
366 +
367 +          if (delta_y != 0.0 && scrolled_window->vscrollbar &&
368 +              (priv->overlay_scrollbars || gtk_widget_get_visible (scrolled_window->vscrollbar)))
369 +            {
370 +              GtkAdjustment *adj;
371 +
372 +              adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
373 +
374 +              if (scrolled_window->vscrollbar_visible)
375 +                {
376 +                  _gtk_scrolled_window_set_adjustment_value (scrolled_window,
377 +                                                             adj,
378 +                                                             priv->unclamped_vadj_value + delta_y,
379 +                                                             TRUE,
380 +                                                             FALSE);
381 +                }
382 +              else
383 +                {
384 +                  gdouble new_value;
385 +
386 +                  /* If the scrollbar is not visible, clamp the value and
387 +                   * don't trigger overshooting.
388 +                   */
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));
393 +
394 +                  gtk_adjustment_set_value (adj, new_value);
395 +                }
396 +
397 +              handled = TRUE;
398 +            }
399 +
400 +
401 +          priv->last_scroll_event_time = gdk_event_get_time ((GdkEvent *)event);
402 +          gtk_scrolled_window_calculate_velocity (scrolled_window, (GdkEvent *)event);
403          }
404
405 -      if (delta_y != 0.0 && scrolled_window->vscrollbar &&
406 -          (priv->overlay_scrollbars || gtk_widget_get_visible (scrolled_window->vscrollbar)))
407 -        {
408 -          GtkAdjustment *adj;
409 -          gdouble new_value;
410 +      _gtk_scrolled_window_get_overshoot (scrolled_window,
411 +                                          &new_overshoot_x, &new_overshoot_y);
412
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);
417
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.
427 +       */
428 +      if (is_overshot &&
429 +          ((delta_x == 0.0 && delta_y == 0.0) || is_momentum_event))
430 +        start_snap_back = TRUE;
431
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.
435 +       */
436 +      if (start_snap_back && priv->deceleration_id == 0)
437 +        {
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;
443
444 -          handled = TRUE;
445 +          priv->is_snapping_back = TRUE;
446 +
447 +          if (new_overshoot_x != 0 || new_overshoot_y != 0)
448 +            {
449 +              gtk_scrolled_window_start_deceleration (scrolled_window);
450 +              priv->x_velocity = 0.0;
451 +              priv->y_velocity = 0.0;
452 +            }
453          }
454      }
455    else
456 @@ -2369,18 +2320,6 @@ scrolled_window_deceleration_cb (gpointer user_data)
457  }
458
459  static void
460 -gtk_scrolled_window_cancel_deceleration (GtkScrolledWindow *scrolled_window)
461 -{
462 -  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
463 -
464 -  if (priv->deceleration_id)
465 -    {
466 -      g_source_remove (priv->deceleration_id);
467 -      priv->deceleration_id = 0;
468 -    }
469 -}
470 -
471 -static void
472  gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
473  {
474    GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
475 @@ -2408,327 +2347,36 @@ gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
476  }
477
478  static gboolean
479 -gtk_scrolled_window_release_captured_event (GtkScrolledWindow *scrolled_window)
480 -{
481 -  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
482 -
483 -  /* Cancel the scrolling and send the button press
484 -   * event to the child widget
485 -   */
486 -  if (!priv->button_press_event)
487 -    return FALSE;
488 -
489 -  if (priv->pointer_grabbed)
490 -    {
491 -      gtk_grab_remove (GTK_WIDGET (scrolled_window));
492 -      priv->pointer_grabbed = FALSE;
493 -    }
494 -
495 -  if (priv->capture_button_press)
496 -    {
497 -      GtkWidget *event_widget;
498 -
499 -      event_widget = gtk_get_event_widget (priv->button_press_event);
500 -
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);
505 -
506 -      gdk_event_free (priv->button_press_event);
507 -      priv->button_press_event = NULL;
508 -    }
509 -
510 -  if (_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
511 -    gtk_scrolled_window_start_deceleration (scrolled_window);
512 -
513 -  return FALSE;
514 -}
515 -
516 -static gboolean
517  gtk_scrolled_window_calculate_velocity (GtkScrolledWindow *scrolled_window,
518                                         GdkEvent          *event)
519  {
520    GtkScrolledWindowPrivate *priv;
521 -  gdouble x_root, y_root;
522    guint32 _time;
523
524 -#define STILL_THRESHOLD 40
525 -
526 -  if (!gdk_event_get_root_coords (event, &x_root, &y_root))
527 -    return FALSE;
528 -
529    priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
530    _time = gdk_event_get_time (event);
531
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)
535 -    {
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);
540 -    }
541 -
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;
545 -
546 -#undef STILL_THRESHOLD
547 -
548 -  return TRUE;
549 -}
550 -
551 -static gboolean
552 -gtk_scrolled_window_captured_button_release_kinetic (GtkWidget *widget,
553 -                                                     GdkEvent  *event)
554 -{
555 -  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
556 -  GtkScrolledWindowPrivate *priv;
557 -  GtkWidget *child;
558 -  gboolean overshoot;
559 -  gdouble x_root, y_root;
560 -
561 -  if (event->button.button != 1)
562 -    return FALSE;
563 -
564 -  child = gtk_bin_get_child (GTK_BIN (widget));
565 -  if (!child)
566 -    return FALSE;
567 -
568 -  priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
569 -  gtk_grab_remove (widget);
570 -  priv->pointer_grabbed = FALSE;
571 -
572 -  if (priv->release_timeout_id)
573 -    {
574 -      g_source_remove (priv->release_timeout_id);
575 -      priv->release_timeout_id = 0;
576 -    }
577 -
578 -  overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL);
579 -
580 -  if (priv->in_drag)
581 -    gdk_pointer_ungrab (gdk_event_get_time (event));
582 -  else
583 -    {
584 -      /* There hasn't been scrolling at all, so just let the
585 -       * child widget handle the button press normally
586 -       */
587 -      gtk_scrolled_window_release_captured_event (scrolled_window);
588 -
589 -      if (!overshoot)
590 -        return FALSE;
591 -    }
592 -  priv->in_drag = FALSE;
593 -
594 -  if (priv->button_press_event)
595 -    {
596 -      gdk_event_free (priv->button_press_event);
597 -      priv->button_press_event = NULL;
598 -    }
599 -
600 -  gtk_scrolled_window_calculate_velocity (scrolled_window, event);
601 -
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
608
609 -  if (priv->x_velocity != 0 || priv->y_velocity != 0 || overshoot)
610 +  if (event->type == GDK_SCROLL)
611      {
612 -      gtk_scrolled_window_start_deceleration (scrolled_window);
613 -      priv->x_velocity = priv->y_velocity = 0;
614 -      priv->last_button_event_valid = FALSE;
615 -    }
616 -  else
617 -    {
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;
622 -    }
623 -
624 -  if (priv->capture_button_press)
625 -    return TRUE;
626 -  else
627 -    return FALSE;
628 -}
629 +      gdouble delta_x, delta_y;
630
631 -static gboolean
632 -gtk_scrolled_window_captured_motion_notify_kinetic (GtkWidget *widget,
633 -                                                    GdkEvent  *event)
634 -{
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;
639 -  GtkWidget *child;
640 -  GtkAdjustment *hadjustment;
641 -  GtkAdjustment *vadjustment;
642 -  gdouble dx, dy;
643 -  GdkModifierType state;
644 -  gdouble x_root, y_root;
645 -
646 -  gdk_event_get_state (event, &state);
647 -  if (!(state & GDK_BUTTON1_MASK))
648 -    return FALSE;
649 -
650 -  child = gtk_bin_get_child (GTK_BIN (widget));
651 -  if (!child)
652 -    return FALSE;
653 -
654 -  priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
655 -
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)
659 -    {
660 -      if (gtk_drag_check_threshold (widget,
661 -                                    priv->last_button_event_x_root,
662 -                                    priv->last_button_event_y_root,
663 -                                    x_root, y_root))
664 +      if (gdk_event_get_scroll_deltas (event, &delta_x, &delta_y) &&
665 +          ABS (_time - priv->last_scroll_event_time) > STILL_THRESHOLD)
666          {
667 -          if (priv->release_timeout_id)
668 -            {
669 -              g_source_remove (priv->release_timeout_id);
670 -              priv->release_timeout_id = 0;
671 -            }
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);
674
675 -          priv->last_button_event_valid = FALSE;
676 -          priv->in_drag = TRUE;
677 +          priv->last_scroll_event_time = _time;
678          }
679 -      else
680 -        return TRUE;
681 -    }
682 -
683 -  gdk_pointer_grab (gtk_widget_get_window (widget),
684 -                    TRUE,
685 -                    GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK,
686 -                    NULL, NULL,
687 -                    gdk_event_get_time (event));
688 -
689 -  priv->last_button_event_valid = FALSE;
690 -
691 -  if (priv->button_press_event)
692 -    {
693 -      gdk_event_free (priv->button_press_event);
694 -      priv->button_press_event = NULL;
695 -    }
696 -
697 -  _gtk_scrolled_window_get_overshoot (scrolled_window,
698 -                                      &old_overshoot_x, &old_overshoot_y);
699 -
700 -  hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
701 -  if (hadjustment && scrolled_window->hscrollbar_visible)
702 -    {
703 -      dx = (priv->last_motion_event_x_root - x_root) + priv->unclamped_hadj_value;
704 -      _gtk_scrolled_window_set_adjustment_value (scrolled_window, hadjustment,
705 -                                                 dx, TRUE, FALSE);
706 -    }
707 -
708 -  vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
709 -  if (vadjustment && scrolled_window->vscrollbar_visible)
710 -    {
711 -      dy = (priv->last_motion_event_y_root - y_root) + priv->unclamped_vadj_value;
712 -      _gtk_scrolled_window_set_adjustment_value (scrolled_window, vadjustment,
713 -                                                 dy, TRUE, FALSE);
714      }
715
716 -  _gtk_scrolled_window_get_overshoot (scrolled_window,
717 -                                      &new_overshoot_x, &new_overshoot_y);
718 -
719 -  if (old_overshoot_x != new_overshoot_x ||
720 -      old_overshoot_y != new_overshoot_y)
721 -    _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
722 -
723 -  gtk_scrolled_window_calculate_velocity (scrolled_window, event);
724 +#undef STILL_THRESHOLD
725
726    return TRUE;
727  }
728
729 -static gboolean
730 -gtk_scrolled_window_captured_button_press_kinetic (GtkWidget *widget,
731 -                                                   GdkEvent  *event)
732 -{
733 -  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
734 -  GtkScrolledWindowPrivate *priv;
735 -  GtkWidget *child;
736 -  GtkWidget *event_widget;
737 -  gdouble x_root, y_root;
738 -
739 -  /* If scrollbars are not visible, we don't do kinetic scrolling */
740 -  if (!scrolled_window->vscrollbar_visible &&
741 -      !scrolled_window->hscrollbar_visible)
742 -    return FALSE;
743 -
744 -  priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
745 -
746 -  event_widget = gtk_get_event_widget (event);
747 -
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.
751 -   */
752 -  if (widget != gtk_widget_get_ancestor (event_widget, GTK_TYPE_SCROLLED_WINDOW))
753 -    return FALSE;
754 -
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
757 -   */
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)
762 -    {
763 -      priv->last_button_event_valid = FALSE;
764 -      return FALSE;
765 -    }
766 -
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;
771 -
772 -  if (event->button.button != 1)
773 -    return FALSE;
774 -
775 -  child = gtk_bin_get_child (GTK_BIN (widget));
776 -  if (!child)
777 -    return FALSE;
778 -
779 -  if (scrolled_window->hscrollbar == event_widget ||
780 -      scrolled_window->vscrollbar == event_widget)
781 -    return FALSE;
782 -
783 -  priv->pointer_grabbed = TRUE;
784 -  gtk_grab_add (widget);
785 -
786 -  gtk_scrolled_window_cancel_deceleration (scrolled_window);
787 -
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,
793 -                               scrolled_window);
794 -
795 -  priv->in_drag = FALSE;
796 -
797 -  if (priv->capture_button_press)
798 -    {
799 -      /* Store the button press event in
800 -       * case we need to propagate it later
801 -       */
802 -      priv->button_press_event = gdk_event_copy (event);
803 -      return TRUE;
804 -    }
805 -  else
806 -    return FALSE;
807 -}
808 -
809  static void
810  gtk_scrolled_window_scroll_step (GtkScrolledWindow *scrolled_window)
811  {
812 @@ -3011,22 +2659,14 @@ gtk_scrolled_window_captured_event (GtkWidget *widget,
813      {
814      case GDK_BUTTON_PRESS:
815        retval = gtk_scrolled_window_captured_button_press_scrollbar (widget, event);
816 -      if (!retval)
817 -        retval = gtk_scrolled_window_captured_button_press_kinetic (widget, event);
818        break;
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);
824 -      else
825 -        priv->last_button_event_valid = FALSE;
826        break;
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);
832        break;
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;
839 -
840 -      if (priv->release_timeout_id)
841 -        {
842 -          g_source_remove (priv->release_timeout_id);
843 -          priv->release_timeout_id = 0;
844 -        }
845 -
846 -      if (_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
847 -        gtk_scrolled_window_start_deceleration (scrolled_window);
848 -      else
849 -        gtk_scrolled_window_cancel_deceleration (scrolled_window);
850 -
851 -      priv->last_button_event_valid = FALSE;
852      }
853
854    if (priv->sb_pointer_grabbed && !was_grabbed)
855 @@ -3923,6 +3550,13 @@ gtk_scrolled_window_expose_scrollbars (GtkAdjustment     *adj,
856  }
857
858  static void
859 +gtk_scrolled_window_init_overlay_scrollbars (GtkScrolledWindow *scrolled_window)
860 +{
861 +  _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window),
862 +                                          gtk_scrolled_window_captured_event);
863 +}
864 +
865 +static void
866  gtk_scrolled_window_overlay_scrollbars_changed (GtkSettings *settings,
867                                                  GParamSpec  *arg,
868                                                  gpointer     user_data)
869 --
870 1.7.10.2 (Apple Git-33)