Fix 'mono' package typo
[mono-project.git] / bockbuild / mac-sdk / patches / gtk / 0011-scrolledwindow-Kinetic-scrolling-support.patch
blob0a27ac38a7f6431eec34fc359a6f205cace53251
1 From 5001b3d9a9b6445ac199156c0f91f28c2112e262 Mon Sep 17 00:00:00 2001
2 From: Carlos Garcia Campos <cgarcia@igalia.com>
3 Date: Fri, 11 Feb 2011 13:43:56 +0100
4 Subject: [PATCH 11/68] scrolledwindow: Kinetic scrolling support
6 If the scrolling doesn't start after a long press, the scrolling is
7 cancelled and events are handled by child widgets normally.
9 When clicked again close to the previous button press location
10 (assuming it had ~0 movement), the scrolled window will allow
11 the child to handle the events immediately.
13 This is so the user doesn't have to wait to the press-and-hold
14 timeout in order to operate on the scrolledwindow child.
16 The innermost scrolled window always gets to capture the events, all
17 scrolled windows above it just let the event go through. Ideally
18 reaching a limit on the innermost scrolled window would propagate
19 the dragging up the hierarchy in order to keep following the touch
20 coords, although that'd involve rather evil hacks just to cater
21 for broken UIs.
23 Conflicts:
25 docs/reference/gtk/gtk3-sections.txt
26 gtk/gtk.symbols
27 gtk/gtkscrolledwindow.c
28 gtk/gtkscrolledwindow.h
29 ---
30 gtk/gtk.symbols | 4 +
31 gtk/gtkscrolledwindow.c | 1061 ++++++++++++++++++++++++++++++++++++++++++++++-
32 gtk/gtkscrolledwindow.h | 8 +
33 3 files changed, 1058 insertions(+), 15 deletions(-)
35 diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
36 index 6d5d5b6..d13ca41 100644
37 --- a/gtk/gtk.symbols
38 +++ b/gtk/gtk.symbols
39 @@ -3730,6 +3730,8 @@ gtk_scrollbar_get_type G_GNUC_CONST
40 gtk_scrolled_window_add_with_viewport
41 gtk_scrolled_window_get_hadjustment
42 gtk_scrolled_window_get_hscrollbar
43 +gtk_scrolled_window_get_kinetic_scrolling
44 +gtk_scrolled_window_get_capture_button_press
45 gtk_scrolled_window_get_placement
46 gtk_scrolled_window_get_policy
47 gtk_scrolled_window_get_shadow_type
48 @@ -3738,6 +3740,8 @@ gtk_scrolled_window_get_vadjustment
49 gtk_scrolled_window_get_vscrollbar
50 gtk_scrolled_window_new
51 gtk_scrolled_window_set_hadjustment
52 +gtk_scrolled_window_set_kinetic_scrolling
53 +gtk_scrolled_window_set_capture_button_press
54 gtk_scrolled_window_set_placement
55 gtk_scrolled_window_set_policy
56 gtk_scrolled_window_set_shadow_type
57 diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
58 index 2288b2f..694d20a 100644
59 --- a/gtk/gtkscrolledwindow.c
60 +++ b/gtk/gtkscrolledwindow.c
61 @@ -33,6 +33,8 @@
62 #include "gtkwindow.h"
63 #include "gtkprivate.h"
64 #include "gtkintl.h"
65 +#include "gtkmain.h"
66 +#include "gtkdnd.h"
67 #include "gtkalias.h"
70 @@ -72,14 +74,58 @@
73 #define DEFAULT_SCROLLBAR_SPACING 3
74 +#define TOUCH_BYPASS_CAPTURED_THRESHOLD 30
76 +/* Kinetic scrolling */
77 +#define FRAME_INTERVAL (1000 / 60)
78 +#define MAX_OVERSHOOT_DISTANCE 50
79 +#define FRICTION_DECELERATION 0.003
80 +#define OVERSHOOT_INVERSE_ACCELERATION 0.003
81 +#define RELEASE_EVENT_TIMEOUT 1000
83 typedef struct {
84 - gboolean window_placement_set;
85 - GtkCornerType real_window_placement;
86 + gboolean window_placement_set;
87 + GtkCornerType real_window_placement;
89 + /* Kinetic scrolling */
90 + GdkEvent *button_press_event;
91 + GdkWindow *overshoot_window;
92 + guint pointer_grabbed : 1;
93 + guint kinetic_scrolling : 1;
94 + guint capture_button_press : 1;
95 + guint in_drag : 1;
96 + guint last_button_event_valid : 1;
98 + guint release_timeout_id;
99 + guint deceleration_id;
101 + gdouble last_button_event_x_root;
102 + gdouble last_button_event_y_root;
104 + gdouble last_motion_event_x_root;
105 + gdouble last_motion_event_y_root;
106 + guint32 last_motion_event_time;
108 + gdouble x_velocity;
109 + gdouble y_velocity;
111 + gdouble unclamped_hadj_value;
112 + gdouble unclamped_vadj_value;
113 } GtkScrolledWindowPrivate;
115 #define GTK_SCROLLED_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCROLLED_WINDOW, GtkScrolledWindowPrivate))
117 +typedef struct
119 + GtkScrolledWindow *scrolled_window;
120 + gint64 last_deceleration_time;
122 + gdouble x_velocity;
123 + gdouble y_velocity;
124 + gdouble vel_cosine;
125 + gdouble vel_sine;
126 +} KineticScrollData;
128 enum {
129 PROP_0,
130 PROP_HADJUSTMENT,
131 @@ -88,7 +134,8 @@ enum {
132 PROP_VSCROLLBAR_POLICY,
133 PROP_WINDOW_PLACEMENT,
134 PROP_WINDOW_PLACEMENT_SET,
135 - PROP_SHADOW_TYPE
136 + PROP_SHADOW_TYPE,
137 + PROP_KINETIC_SCROLLING
140 /* Signals */
141 @@ -119,6 +166,8 @@ static void gtk_scrolled_window_size_allocate (GtkWidget *widge
142 GtkAllocation *allocation);
143 static gboolean gtk_scrolled_window_scroll_event (GtkWidget *widget,
144 GdkEventScroll *event);
145 +static gboolean gtk_scrolled_window_captured_event (GtkWidget *widget,
146 + GdkEvent *event);
147 static gboolean gtk_scrolled_window_focus (GtkWidget *widget,
148 GtkDirectionType direction);
149 static void gtk_scrolled_window_add (GtkContainer *container,
150 @@ -139,9 +188,24 @@ static void gtk_scrolled_window_relative_allocation(GtkWidget *widge
151 GtkAllocation *allocation);
152 static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
153 gpointer data);
154 +static void gtk_scrolled_window_adjustment_value_changed (GtkAdjustment *adjustment,
155 + gpointer data);
157 static void gtk_scrolled_window_update_real_placement (GtkScrolledWindow *scrolled_window);
159 +static void gtk_scrolled_window_realize (GtkWidget *widget);
160 +static void gtk_scrolled_window_unrealize (GtkWidget *widget);
161 +static void gtk_scrolled_window_map (GtkWidget *widget);
162 +static void gtk_scrolled_window_unmap (GtkWidget *widget);
163 +static void gtk_scrolled_window_grab_notify (GtkWidget *widget,
164 + gboolean was_grabbed);
166 +static gboolean _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window,
167 + GtkAdjustment *adjustment,
168 + gdouble value,
169 + gboolean allow_overshooting,
170 + gboolean snap_to_border);
172 static guint signals[LAST_SIGNAL] = {0};
174 G_DEFINE_TYPE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
175 @@ -202,6 +266,11 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
176 widget_class->size_allocate = gtk_scrolled_window_size_allocate;
177 widget_class->scroll_event = gtk_scrolled_window_scroll_event;
178 widget_class->focus = gtk_scrolled_window_focus;
179 + widget_class->realize = gtk_scrolled_window_realize;
180 + widget_class->unrealize = gtk_scrolled_window_unrealize;
181 + widget_class->map = gtk_scrolled_window_map;
182 + widget_class->unmap = gtk_scrolled_window_unmap;
183 + widget_class->grab_notify = gtk_scrolled_window_grab_notify;
185 container_class->add = gtk_scrolled_window_add;
186 container_class->remove = gtk_scrolled_window_remove;
187 @@ -301,6 +370,22 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
188 GTK_PARAM_READABLE));
191 + * GtkScrolledWindow:kinetic-scrolling:
193 + * The kinetic scrolling behavior flags.
195 + * Since: X.XX
196 + */
197 + g_object_class_install_property (gobject_class,
198 + PROP_KINETIC_SCROLLING,
199 + g_param_spec_boolean ("kinetic-scrolling",
200 + P_("Kinetic Scrolling"),
201 + P_("Kinetic scrolling mode."),
202 + TRUE,
203 + GTK_PARAM_READABLE |
204 + GTK_PARAM_WRITABLE));
206 + /**
207 * GtkScrolledWindow::scroll-child:
208 * @scrolled_window: a #GtkScrolledWindow
209 * @scroll: a #GtkScrollType describing how much to scroll
210 @@ -371,6 +456,12 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
211 scrolled_window->focus_out = FALSE;
212 scrolled_window->window_placement = GTK_CORNER_TOP_LEFT;
213 gtk_scrolled_window_update_real_placement (scrolled_window);
215 + if (g_getenv ("GTK2_KINETIC_SCROLLING"))
217 + gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE);
218 + gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE);
223 @@ -458,8 +549,13 @@ gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window,
224 "changed",
225 G_CALLBACK (gtk_scrolled_window_adjustment_changed),
226 scrolled_window);
227 + g_signal_connect (hadjustment,
228 + "value-changed",
229 + G_CALLBACK (gtk_scrolled_window_adjustment_value_changed),
230 + scrolled_window);
231 gtk_scrolled_window_adjustment_changed (hadjustment, scrolled_window);
233 + gtk_scrolled_window_adjustment_value_changed (hadjustment, scrolled_window);
235 if (bin->child)
236 gtk_widget_set_scroll_adjustments (bin->child,
237 gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
238 @@ -519,7 +615,12 @@ gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window,
239 "changed",
240 G_CALLBACK (gtk_scrolled_window_adjustment_changed),
241 scrolled_window);
242 + g_signal_connect (vadjustment,
243 + "value-changed",
244 + G_CALLBACK (gtk_scrolled_window_adjustment_value_changed),
245 + scrolled_window);
246 gtk_scrolled_window_adjustment_changed (vadjustment, scrolled_window);
247 + gtk_scrolled_window_adjustment_value_changed (vadjustment, scrolled_window);
249 if (bin->child)
250 gtk_widget_set_scroll_adjustments (bin->child,
251 @@ -842,10 +943,135 @@ gtk_scrolled_window_get_shadow_type (GtkScrolledWindow *scrolled_window)
252 return scrolled_window->shadow_type;
255 +/**
256 + * gtk_scrolled_window_set_kinetic_scrolling:
257 + * @scrolled_window: a #GtkScrolledWindow
258 + * @kinetic_scrolling: %TRUE to enable kinetic scrolling
260 + * Turns kinetic scrolling on or off.
261 + * Kinetic scrolling only applies to devices with source
262 + * %GDK_SOURCE_TOUCHSCREEN.
264 + * Since: X.XX
265 + **/
266 +void
267 +gtk_scrolled_window_set_kinetic_scrolling (GtkScrolledWindow *scrolled_window,
268 + gboolean kinetic_scrolling)
270 + GtkScrolledWindowPrivate *priv;
272 + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
274 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
276 + if (priv->kinetic_scrolling == kinetic_scrolling)
277 + return;
279 + priv->kinetic_scrolling = kinetic_scrolling;
280 + if (priv->kinetic_scrolling)
282 + _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window),
283 + gtk_scrolled_window_captured_event);
285 + else
287 + _gtk_widget_set_captured_event_handler (GTK_WIDGET (scrolled_window), NULL);
288 + if (priv->release_timeout_id)
290 + g_source_remove (priv->release_timeout_id);
291 + priv->release_timeout_id = 0;
293 + if (priv->deceleration_id)
295 + g_source_remove (priv->deceleration_id);
296 + priv->deceleration_id = 0;
299 + g_object_notify (G_OBJECT (scrolled_window), "kinetic-scrolling");
302 +/**
303 + * gtk_scrolled_window_get_kinetic_scrolling:
304 + * @scrolled_window: a #GtkScrolledWindow
306 + * Returns the specified kinetic scrolling behavior.
308 + * Return value: the scrolling behavior flags.
310 + * Since: X.XX
311 + */
312 +gboolean
313 +gtk_scrolled_window_get_kinetic_scrolling (GtkScrolledWindow *scrolled_window)
315 + GtkScrolledWindowPrivate *priv;
317 + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), FALSE);
319 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
321 + return priv->kinetic_scrolling;
324 +/**
325 + * gtk_scrolled_window_set_capture_button_press:
326 + * @scrolled_window: a #GtkScrolledWindow
327 + * @capture_button_press: %TRUE to capture button presses
329 + * Changes the behaviour of @scrolled_window wrt. to the initial
330 + * event that possibly starts kinetic scrolling. When @capture_button_press
331 + * is set to %TRUE, the event is captured by the scrolled window, and
332 + * then later replayed if it is meant to go to the child widget.
334 + * This should be enabled if any child widgets perform non-reversible
335 + * actions on #GtkWidget::button-press-event. If they don't, and handle
336 + * additionally handle #GtkWidget::grab-broken-event, it might be better
337 + * to set @capture_button_press to %FALSE.
339 + * This setting only has an effect if kinetic scrolling is enabled.
341 + * Since: X.XX
342 + */
343 +void
344 +gtk_scrolled_window_set_capture_button_press (GtkScrolledWindow *scrolled_window,
345 + gboolean capture_button_press)
347 + GtkScrolledWindowPrivate *priv;
349 + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
351 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
352 + priv->capture_button_press = capture_button_press;
355 +/**
356 + * gtk_scrolled_window_get_capture_button_press:
357 + * @scrolled_window: a #GtkScrolledWindow
359 + * Return whether button presses are captured during kinetic
360 + * scrolling. See gtk_scrolled_window_set_capture_button_press().
362 + * Returns: %TRUE if button presses are captured during kinetic scrolling
364 + * Since: X.XX
365 + */
366 +gboolean
367 +gtk_scrolled_window_get_capture_button_press (GtkScrolledWindow *scrolled_window)
369 + GtkScrolledWindowPrivate *priv;
371 + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), FALSE);
373 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
375 + return priv->capture_button_press;
379 static void
380 gtk_scrolled_window_destroy (GtkObject *object)
382 GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (object);
383 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
385 if (scrolled_window->hscrollbar)
387 @@ -868,6 +1094,23 @@ gtk_scrolled_window_destroy (GtkObject *object)
388 scrolled_window->vscrollbar = NULL;
391 + if (priv->release_timeout_id)
393 + g_source_remove (priv->release_timeout_id);
394 + priv->release_timeout_id = 0;
396 + if (priv->deceleration_id)
398 + g_source_remove (priv->deceleration_id);
399 + priv->deceleration_id = 0;
402 + if (priv->button_press_event)
404 + gdk_event_free (priv->button_press_event);
405 + priv->button_press_event = NULL;
408 GTK_OBJECT_CLASS (gtk_scrolled_window_parent_class)->destroy (object);
411 @@ -912,6 +1155,10 @@ gtk_scrolled_window_set_property (GObject *object,
412 gtk_scrolled_window_set_shadow_type (scrolled_window,
413 g_value_get_enum (value));
414 break;
415 + case PROP_KINETIC_SCROLLING:
416 + gtk_scrolled_window_set_kinetic_scrolling (scrolled_window,
417 + g_value_get_boolean (value));
418 + break;
419 default:
420 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
421 break;
422 @@ -952,6 +1199,9 @@ gtk_scrolled_window_get_property (GObject *object,
423 case PROP_SHADOW_TYPE:
424 g_value_set_enum (value, scrolled_window->shadow_type);
425 break;
426 + case PROP_KINETIC_SCROLLING:
427 + g_value_set_boolean (value, priv->kinetic_scrolling);
428 + break;
429 default:
430 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
431 break;
432 @@ -1019,10 +1269,10 @@ gtk_scrolled_window_paint (GtkWidget *widget,
433 GdkRectangle *area)
435 GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
436 + GtkAllocation relative_allocation;
438 if (scrolled_window->shadow_type != GTK_SHADOW_NONE)
440 - GtkAllocation relative_allocation;
441 gboolean scrollbars_within_bevel;
443 gtk_widget_style_get (widget, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL);
444 @@ -1378,6 +1628,111 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget,
448 +static gboolean
449 +_gtk_scrolled_window_get_overshoot (GtkScrolledWindow *scrolled_window,
450 + gint *overshoot_x,
451 + gint *overshoot_y)
453 + GtkScrolledWindowPrivate *priv;
454 + GtkAdjustment *vadjustment, *hadjustment;
455 + gdouble lower, upper, x, y;
457 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
459 + /* Vertical overshoot */
460 + vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
461 + lower = gtk_adjustment_get_lower (vadjustment);
462 + upper = gtk_adjustment_get_upper (vadjustment) -
463 + gtk_adjustment_get_page_size (vadjustment);
465 + if (priv->unclamped_vadj_value < lower)
466 + y = priv->unclamped_vadj_value - lower;
467 + else if (priv->unclamped_vadj_value > upper)
468 + y = priv->unclamped_vadj_value - upper;
469 + else
470 + y = 0;
472 + /* Horizontal overshoot */
473 + hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
474 + lower = gtk_adjustment_get_lower (hadjustment);
475 + upper = gtk_adjustment_get_upper (hadjustment) -
476 + gtk_adjustment_get_page_size (hadjustment);
478 + if (priv->unclamped_hadj_value < lower)
479 + x = priv->unclamped_hadj_value - lower;
480 + else if (priv->unclamped_hadj_value > upper)
481 + x = priv->unclamped_hadj_value - upper;
482 + else
483 + x = 0;
485 + if (overshoot_x)
486 + *overshoot_x = x;
488 + if (overshoot_y)
489 + *overshoot_y = y;
491 + return (x != 0 || y != 0);
494 +static void
495 +_gtk_scrolled_window_allocate_overshoot_window (GtkScrolledWindow *scrolled_window)
497 + GtkAllocation window_allocation, relative_allocation, allocation;
498 + GtkScrolledWindowPrivate *priv;
499 + GtkWidget *widget = GTK_WIDGET (scrolled_window);
500 + gint overshoot_x, overshoot_y;
502 + if (!gtk_widget_get_realized (widget))
503 + return;
505 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
507 + gtk_widget_get_allocation (widget, &allocation);
508 + gtk_scrolled_window_relative_allocation (widget, &relative_allocation);
509 + _gtk_scrolled_window_get_overshoot (scrolled_window,
510 + &overshoot_x, &overshoot_y);
512 + window_allocation = relative_allocation;
513 + window_allocation.x += allocation.x;
514 + window_allocation.y += allocation.y;
516 + if (overshoot_x < 0)
517 + window_allocation.x += -overshoot_x;
519 + if (overshoot_y < 0)
520 + window_allocation.y += -overshoot_y;
522 + window_allocation.width -= ABS (overshoot_x);
523 + window_allocation.height -= ABS (overshoot_y);
525 + gdk_window_move_resize (priv->overshoot_window,
526 + window_allocation.x, window_allocation.y,
527 + window_allocation.width, window_allocation.height);
530 +static void
531 +gtk_scrolled_window_allocate_child (GtkScrolledWindow *swindow,
532 + GtkAllocation *relative_allocation)
534 + GtkWidget *widget = GTK_WIDGET (swindow), *child;
535 + GtkAllocation allocation;
536 + GtkAllocation child_allocation;
537 + gint overshoot_x, overshoot_y;
539 + child = gtk_bin_get_child (GTK_BIN (widget));
541 + gtk_widget_get_allocation (widget, &allocation);
543 + gtk_scrolled_window_relative_allocation (widget, relative_allocation);
544 + _gtk_scrolled_window_get_overshoot (swindow, &overshoot_x, &overshoot_y);
546 + child_allocation.x = child_allocation.y = 0;
547 + child_allocation.width = relative_allocation->width;
548 + child_allocation.height = relative_allocation->height;
550 + gtk_widget_size_allocate (child, &child_allocation);
553 static void
554 gtk_scrolled_window_size_allocate (GtkWidget *widget,
555 GtkAllocation *allocation)
556 @@ -1389,7 +1744,7 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
557 GtkAllocation child_allocation;
558 gboolean scrollbars_within_bevel;
559 gint scrollbar_spacing;
562 g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
563 g_return_if_fail (allocation != NULL);
565 @@ -1420,17 +1775,9 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
569 - gtk_scrolled_window_relative_allocation (widget, &relative_allocation);
571 - child_allocation.x = relative_allocation.x + allocation->x;
572 - child_allocation.y = relative_allocation.y + allocation->y;
573 - child_allocation.width = relative_allocation.width;
574 - child_allocation.height = relative_allocation.height;
576 previous_hvis = scrolled_window->hscrollbar_visible;
577 previous_vvis = scrolled_window->vscrollbar_visible;
579 - gtk_widget_size_allocate (bin->child, &child_allocation);
580 + gtk_scrolled_window_allocate_child (scrolled_window, &relative_allocation);
582 /* If, after the first iteration, the hscrollbar and the
583 * vscrollbar flip visiblity, then we need both.
584 @@ -1442,6 +1789,8 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
585 scrolled_window->hscrollbar_visible = TRUE;
586 scrolled_window->vscrollbar_visible = TRUE;
588 + gtk_scrolled_window_allocate_child (scrolled_window, &relative_allocation);
590 /* a new resize is already queued at this point,
591 * so we will immediatedly get reinvoked
593 @@ -1559,6 +1908,8 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
595 else if (gtk_widget_get_visible (scrolled_window->vscrollbar))
596 gtk_widget_hide (scrolled_window->vscrollbar);
598 + _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
601 static gboolean
602 @@ -1639,6 +1990,555 @@ gtk_scrolled_window_scroll_event (GtkWidget *widget,
605 static gboolean
606 +_gtk_scrolled_window_set_adjustment_value (GtkScrolledWindow *scrolled_window,
607 + GtkAdjustment *adjustment,
608 + gdouble value,
609 + gboolean allow_overshooting,
610 + gboolean snap_to_border)
612 + GtkScrolledWindowPrivate *priv;
613 + gdouble lower, upper, *prev_value;
615 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
617 + lower = gtk_adjustment_get_lower (adjustment);
618 + upper = gtk_adjustment_get_upper (adjustment) -
619 + gtk_adjustment_get_page_size (adjustment);
621 + if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)))
622 + prev_value = &priv->unclamped_hadj_value;
623 + else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)))
624 + prev_value = &priv->unclamped_vadj_value;
625 + else
626 + return FALSE;
628 + if (snap_to_border)
630 + if (*prev_value < 0 && value > 0)
631 + value = 0;
632 + else if (*prev_value > upper && value < upper)
633 + value = upper;
636 + if (allow_overshooting)
638 + lower -= MAX_OVERSHOOT_DISTANCE;
639 + upper += MAX_OVERSHOOT_DISTANCE;
642 + *prev_value = CLAMP (value, lower, upper);
643 + gtk_adjustment_set_value (adjustment, *prev_value);
645 + return (*prev_value != value);
648 +static gboolean
649 +scrolled_window_deceleration_cb (gpointer user_data)
651 + KineticScrollData *data = user_data;
652 + GtkScrolledWindow *scrolled_window = data->scrolled_window;
653 + GtkScrolledWindowPrivate *priv;
654 + GtkAdjustment *hadjustment, *vadjustment;
655 + gint old_overshoot_x, old_overshoot_y, overshoot_x, overshoot_y;
656 + gdouble value;
657 + gint64 current_time;
658 + guint elapsed;
660 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
661 + hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
662 + vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
664 + _gtk_scrolled_window_get_overshoot (scrolled_window,
665 + &old_overshoot_x, &old_overshoot_y);
667 + current_time = g_get_monotonic_time ();
668 + elapsed = (current_time - data->last_deceleration_time) / 1000;
669 + data->last_deceleration_time = current_time;
671 + if (hadjustment && scrolled_window->hscrollbar_visible)
673 + value = priv->unclamped_hadj_value + (data->x_velocity * elapsed);
675 + if (_gtk_scrolled_window_set_adjustment_value (scrolled_window,
676 + hadjustment,
677 + value, TRUE, TRUE))
678 + data->x_velocity = 0;
680 + else
681 + data->x_velocity = 0;
683 + if (vadjustment && scrolled_window->vscrollbar_visible)
685 + value = priv->unclamped_vadj_value + (data->y_velocity * elapsed);
687 + if (_gtk_scrolled_window_set_adjustment_value (scrolled_window,
688 + vadjustment,
689 + value, TRUE, TRUE))
690 + data->y_velocity = 0;
692 + else
693 + data->y_velocity = 0;
695 + _gtk_scrolled_window_get_overshoot (scrolled_window,
696 + &overshoot_x, &overshoot_y);
698 + if (overshoot_x == 0)
700 + if (old_overshoot_x != 0)
702 + /* Overshooting finished snapping back */
703 + data->x_velocity = 0;
705 + else if (data->x_velocity > 0)
707 + data->x_velocity -= FRICTION_DECELERATION * elapsed * data->vel_sine;
708 + data->x_velocity = MAX (0, data->x_velocity);
710 + else if (data->x_velocity < 0)
712 + data->x_velocity += FRICTION_DECELERATION * elapsed * data->vel_sine;
713 + data->x_velocity = MIN (0, data->x_velocity);
716 + else if (overshoot_x < 0)
717 + data->x_velocity += OVERSHOOT_INVERSE_ACCELERATION * elapsed;
718 + else if (overshoot_x > 0)
719 + data->x_velocity -= OVERSHOOT_INVERSE_ACCELERATION * elapsed;
721 + if (overshoot_y == 0)
723 + if (old_overshoot_y != 0)
725 + /* Overshooting finished snapping back */
726 + data->y_velocity = 0;
728 + else if (data->y_velocity > 0)
730 + data->y_velocity -= FRICTION_DECELERATION * elapsed * data->vel_cosine;
731 + data->y_velocity = MAX (0, data->y_velocity);
733 + else if (data->y_velocity < 0)
735 + data->y_velocity += FRICTION_DECELERATION * elapsed * data->vel_cosine;
736 + data->y_velocity = MIN (0, data->y_velocity);
739 + else if (overshoot_y < 0)
740 + data->y_velocity += OVERSHOOT_INVERSE_ACCELERATION * elapsed;
741 + else if (overshoot_y > 0)
742 + data->y_velocity -= OVERSHOOT_INVERSE_ACCELERATION * elapsed;
744 + if (old_overshoot_x != overshoot_x ||
745 + old_overshoot_y != overshoot_y)
746 + _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
748 + if (overshoot_x != 0 || overshoot_y != 0 ||
749 + data->x_velocity != 0 || data->y_velocity != 0)
750 + return TRUE;
751 + else
753 + priv->deceleration_id = 0;
754 + return FALSE;
758 +static void
759 +gtk_scrolled_window_cancel_deceleration (GtkScrolledWindow *scrolled_window)
761 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
763 + if (priv->deceleration_id)
765 + g_source_remove (priv->deceleration_id);
766 + priv->deceleration_id = 0;
770 +static void
771 +gtk_scrolled_window_start_deceleration (GtkScrolledWindow *scrolled_window)
773 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
774 + KineticScrollData *data;
775 + gdouble angle;
777 + data = g_new0 (KineticScrollData, 1);
778 + data->scrolled_window = scrolled_window;
779 + data->last_deceleration_time = g_get_monotonic_time ();
780 + data->x_velocity = priv->x_velocity;
781 + data->y_velocity = priv->y_velocity;
783 + /* We use sine/cosine as a factor to deceleration x/y components
784 + * of the vector, so we care about the sign later.
785 + */
786 + angle = atan2 (ABS (data->x_velocity), ABS (data->y_velocity));
787 + data->vel_cosine = cos (angle);
788 + data->vel_sine = sin (angle);
790 + priv->deceleration_id =
791 + gdk_threads_add_timeout_full (G_PRIORITY_DEFAULT,
792 + FRAME_INTERVAL,
793 + scrolled_window_deceleration_cb,
794 + data, (GDestroyNotify) g_free);
797 +static gboolean
798 +gtk_scrolled_window_release_captured_event (GtkScrolledWindow *scrolled_window)
800 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
802 + /* Cancel the scrolling and send the button press
803 + * event to the child widget
804 + */
805 + if (!priv->button_press_event)
806 + return FALSE;
808 + if (priv->pointer_grabbed)
810 + gtk_grab_remove (GTK_WIDGET (scrolled_window));
811 + priv->pointer_grabbed = FALSE;
814 + if (priv->capture_button_press)
816 + GtkWidget *event_widget;
818 + event_widget = gtk_get_event_widget (priv->button_press_event);
820 + if (!_gtk_propagate_captured_event (event_widget,
821 + priv->button_press_event,
822 + gtk_bin_get_child (GTK_BIN (scrolled_window))))
823 + gtk_propagate_event (event_widget, priv->button_press_event);
825 + gdk_event_free (priv->button_press_event);
826 + priv->button_press_event = NULL;
829 + if (_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
830 + gtk_scrolled_window_start_deceleration (scrolled_window);
832 + return FALSE;
835 +static gboolean
836 +gtk_scrolled_window_calculate_velocity (GtkScrolledWindow *scrolled_window,
837 + GdkEvent *event)
839 + GtkScrolledWindowPrivate *priv;
840 + gdouble x_root, y_root;
841 + guint32 _time;
843 +#define STILL_THRESHOLD 40
845 + if (!gdk_event_get_root_coords (event, &x_root, &y_root))
846 + return FALSE;
848 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
849 + _time = gdk_event_get_time (event);
851 + if (priv->last_motion_event_x_root != x_root ||
852 + priv->last_motion_event_y_root != y_root ||
853 + ABS (_time - priv->last_motion_event_time) > STILL_THRESHOLD)
855 + priv->x_velocity = (priv->last_motion_event_x_root - x_root) /
856 + (gdouble) (_time - priv->last_motion_event_time);
857 + priv->y_velocity = (priv->last_motion_event_y_root - y_root) /
858 + (gdouble) (_time - priv->last_motion_event_time);
861 + priv->last_motion_event_x_root = x_root;
862 + priv->last_motion_event_y_root = y_root;
863 + priv->last_motion_event_time = _time;
865 +#undef STILL_THRESHOLD
867 + return TRUE;
870 +static gboolean
871 +gtk_scrolled_window_captured_button_release (GtkWidget *widget,
872 + GdkEvent *event)
874 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
875 + GtkScrolledWindowPrivate *priv;
876 + GtkWidget *child;
877 + gboolean overshoot;
878 + gdouble x_root, y_root;
880 + if (event->button.button != 1)
881 + return FALSE;
883 + child = gtk_bin_get_child (GTK_BIN (widget));
884 + if (!child)
885 + return FALSE;
887 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
888 + gtk_grab_remove (widget);
889 + priv->pointer_grabbed = FALSE;
891 + if (priv->release_timeout_id)
893 + g_source_remove (priv->release_timeout_id);
894 + priv->release_timeout_id = 0;
897 + overshoot = _gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL);
899 + if (priv->in_drag)
900 + gdk_pointer_ungrab (gdk_event_get_time (event));
901 + else
903 + /* There hasn't been scrolling at all, so just let the
904 + * child widget handle the button press normally
905 + */
906 + gtk_scrolled_window_release_captured_event (scrolled_window);
908 + if (!overshoot)
909 + return FALSE;
911 + priv->in_drag = FALSE;
913 + if (priv->button_press_event)
915 + gdk_event_free (priv->button_press_event);
916 + priv->button_press_event = NULL;
919 + gtk_scrolled_window_calculate_velocity (scrolled_window, event);
921 + /* Zero out vector components without a visible scrollbar */
922 + if (!scrolled_window->hscrollbar_visible)
923 + priv->x_velocity = 0;
924 + if (!scrolled_window->vscrollbar_visible)
925 + priv->y_velocity = 0;
927 + if (priv->x_velocity != 0 || priv->y_velocity != 0 || overshoot)
929 + gtk_scrolled_window_start_deceleration (scrolled_window);
930 + priv->x_velocity = priv->y_velocity = 0;
931 + priv->last_button_event_valid = FALSE;
933 + else
935 + gdk_event_get_root_coords (event, &x_root, &y_root);
936 + priv->last_button_event_x_root = x_root;
937 + priv->last_button_event_y_root = y_root;
938 + priv->last_button_event_valid = TRUE;
941 + if (priv->capture_button_press)
942 + return TRUE;
943 + else
944 + return FALSE;
947 +static gboolean
948 +gtk_scrolled_window_captured_motion_notify (GtkWidget *widget,
949 + GdkEvent *event)
951 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
952 + GtkScrolledWindowPrivate *priv;
953 + gint old_overshoot_x, old_overshoot_y;
954 + gint new_overshoot_x, new_overshoot_y;
955 + GtkWidget *child;
956 + GtkAdjustment *hadjustment;
957 + GtkAdjustment *vadjustment;
958 + gdouble dx, dy;
959 + GdkModifierType state;
960 + gdouble x_root, y_root;
962 + gdk_event_get_state (event, &state);
963 + if (!(state & GDK_BUTTON1_MASK))
964 + return FALSE;
966 + child = gtk_bin_get_child (GTK_BIN (widget));
967 + if (!child)
968 + return FALSE;
970 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
972 + /* Check if we've passed the drag threshold */
973 + gdk_event_get_root_coords (event, &x_root, &y_root);
974 + if (!priv->in_drag)
976 + if (gtk_drag_check_threshold (widget,
977 + priv->last_button_event_x_root,
978 + priv->last_button_event_y_root,
979 + x_root, y_root))
981 + if (priv->release_timeout_id)
983 + g_source_remove (priv->release_timeout_id);
984 + priv->release_timeout_id = 0;
987 + priv->last_button_event_valid = FALSE;
988 + priv->in_drag = TRUE;
990 + else
991 + return TRUE;
994 + gdk_pointer_grab (gtk_widget_get_window (widget),
995 + TRUE,
996 + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK,
997 + NULL, NULL,
998 + gdk_event_get_time (event));
1000 + priv->last_button_event_valid = FALSE;
1002 + if (priv->button_press_event)
1004 + gdk_event_free (priv->button_press_event);
1005 + priv->button_press_event = NULL;
1008 + _gtk_scrolled_window_get_overshoot (scrolled_window,
1009 + &old_overshoot_x, &old_overshoot_y);
1011 + hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
1012 + if (hadjustment && scrolled_window->hscrollbar_visible)
1014 + dx = (priv->last_motion_event_x_root - x_root) + priv->unclamped_hadj_value;
1015 + _gtk_scrolled_window_set_adjustment_value (scrolled_window, hadjustment,
1016 + dx, TRUE, FALSE);
1019 + vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
1020 + if (vadjustment && scrolled_window->vscrollbar_visible)
1022 + dy = (priv->last_motion_event_y_root - y_root) + priv->unclamped_vadj_value;
1023 + _gtk_scrolled_window_set_adjustment_value (scrolled_window, vadjustment,
1024 + dy, TRUE, FALSE);
1027 + _gtk_scrolled_window_get_overshoot (scrolled_window,
1028 + &new_overshoot_x, &new_overshoot_y);
1030 + if (old_overshoot_x != new_overshoot_x ||
1031 + old_overshoot_y != new_overshoot_y)
1032 + _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
1034 + gtk_scrolled_window_calculate_velocity (scrolled_window, event);
1036 + return TRUE;
1039 +static gboolean
1040 +gtk_scrolled_window_captured_button_press (GtkWidget *widget,
1041 + GdkEvent *event)
1043 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
1044 + GtkScrolledWindowPrivate *priv;
1045 + GtkWidget *child;
1046 + GtkWidget *event_widget;
1047 + gdouble x_root, y_root;
1049 + /* If scrollbars are not visible, we don't do kinetic scrolling */
1050 + if (!scrolled_window->vscrollbar_visible &&
1051 + !scrolled_window->hscrollbar_visible)
1052 + return FALSE;
1054 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1056 + event_widget = gtk_get_event_widget (event);
1058 + /* If there's another scrolled window between the widget
1059 + * receiving the event and this capturing scrolled window,
1060 + * let it handle the events.
1061 + */
1062 + if (widget != gtk_widget_get_ancestor (event_widget, GTK_TYPE_SCROLLED_WINDOW))
1063 + return FALSE;
1065 + /* Check whether the button press is close to the previous one,
1066 + * take that as a shortcut to get the child widget handle events
1067 + */
1068 + gdk_event_get_root_coords (event, &x_root, &y_root);
1069 + if (priv->last_button_event_valid &&
1070 + ABS (x_root - priv->last_button_event_x_root) < TOUCH_BYPASS_CAPTURED_THRESHOLD &&
1071 + ABS (y_root - priv->last_button_event_y_root) < TOUCH_BYPASS_CAPTURED_THRESHOLD)
1073 + priv->last_button_event_valid = FALSE;
1074 + return FALSE;
1077 + priv->last_button_event_x_root = priv->last_motion_event_x_root = x_root;
1078 + priv->last_button_event_y_root = priv->last_motion_event_y_root = y_root;
1079 + priv->last_motion_event_time = gdk_event_get_time (event);
1080 + priv->last_button_event_valid = TRUE;
1082 + if (event->button.button != 1)
1083 + return FALSE;
1085 + child = gtk_bin_get_child (GTK_BIN (widget));
1086 + if (!child)
1087 + return FALSE;
1089 + if (scrolled_window->hscrollbar == event_widget ||
1090 + scrolled_window->vscrollbar == event_widget)
1091 + return FALSE;
1093 + priv->pointer_grabbed = TRUE;
1094 + gtk_grab_add (widget);
1096 + gtk_scrolled_window_cancel_deceleration (scrolled_window);
1098 + /* Only set the timeout if we're going to store an event */
1099 + if (priv->capture_button_press)
1100 + priv->release_timeout_id =
1101 + gdk_threads_add_timeout (RELEASE_EVENT_TIMEOUT,
1102 + (GSourceFunc) gtk_scrolled_window_release_captured_event,
1103 + scrolled_window);
1105 + priv->in_drag = FALSE;
1107 + if (priv->capture_button_press)
1109 + /* Store the button press event in
1110 + * case we need to propagate it later
1111 + */
1112 + priv->button_press_event = gdk_event_copy (event);
1113 + return TRUE;
1115 + else
1116 + return FALSE;
1119 +static gboolean
1120 +gtk_scrolled_window_captured_event (GtkWidget *widget,
1121 + GdkEvent *event)
1123 + gboolean retval = FALSE;
1124 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (widget);
1126 + switch (event->type)
1128 + case GDK_BUTTON_PRESS:
1129 + retval = gtk_scrolled_window_captured_button_press (widget, event);
1130 + break;
1131 + case GDK_BUTTON_RELEASE:
1132 + if (priv->pointer_grabbed)
1133 + retval = gtk_scrolled_window_captured_button_release (widget, event);
1134 + else
1135 + priv->last_button_event_valid = FALSE;
1136 + break;
1137 + case GDK_MOTION_NOTIFY:
1138 + if (priv->pointer_grabbed)
1139 + retval = gtk_scrolled_window_captured_motion_notify (widget, event);
1140 + break;
1141 + case GDK_LEAVE_NOTIFY:
1142 + case GDK_ENTER_NOTIFY:
1143 + if (priv->in_drag &&
1144 + event->crossing.mode != GDK_CROSSING_GRAB)
1145 + retval = TRUE;
1146 + break;
1147 + default:
1148 + break;
1151 + return retval;
1154 +static gboolean
1155 gtk_scrolled_window_focus (GtkWidget *widget,
1156 GtkDirectionType direction)
1158 @@ -1714,17 +2614,42 @@ gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
1161 static void
1162 +gtk_scrolled_window_adjustment_value_changed (GtkAdjustment *adjustment,
1163 + gpointer user_data)
1165 + GtkScrolledWindow *scrolled_window = user_data;
1166 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1168 + /* Allow overshooting for kinetic scrolling operations */
1169 + if (priv->pointer_grabbed || priv->deceleration_id)
1170 + return;
1172 + /* Ensure GtkAdjustment and unclamped values are in sync */
1173 + if (scrolled_window->vscrollbar &&
1174 + adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)))
1175 + priv->unclamped_vadj_value = gtk_adjustment_get_value (adjustment);
1176 + else if (scrolled_window->hscrollbar &&
1177 + adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)))
1178 + priv->unclamped_hadj_value = gtk_adjustment_get_value (adjustment);
1181 +static void
1182 gtk_scrolled_window_add (GtkContainer *container,
1183 GtkWidget *child)
1185 GtkScrolledWindow *scrolled_window;
1186 + GtkScrolledWindowPrivate *priv;
1187 GtkBin *bin;
1189 bin = GTK_BIN (container);
1190 + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (container);
1191 g_return_if_fail (bin->child == NULL);
1193 scrolled_window = GTK_SCROLLED_WINDOW (container);
1195 + if (gtk_widget_get_realized (GTK_WIDGET (bin)))
1196 + gtk_widget_set_parent_window (child, priv->overshoot_window);
1198 bin->child = child;
1199 gtk_widget_set_parent (child, GTK_WIDGET (bin));
1201 @@ -1837,5 +2762,111 @@ _gtk_scrolled_window_get_scrollbar_spacing (GtkScrolledWindow *scrolled_window)
1205 +static void
1206 +gtk_scrolled_window_realize (GtkWidget *widget)
1208 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
1209 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1210 + GtkAllocation allocation, relative_allocation;
1211 + GdkWindowAttr attributes;
1212 + GtkWidget *child_widget;
1213 + gint attributes_mask;
1215 + gtk_widget_set_realized (widget, TRUE);
1216 + gtk_widget_get_allocation (widget, &allocation);
1217 + gtk_scrolled_window_relative_allocation (widget, &relative_allocation);
1219 + attributes.window_type = GDK_WINDOW_CHILD;
1220 + attributes.x = allocation.x + relative_allocation.x;
1221 + attributes.y = allocation.y + relative_allocation.y;
1222 + attributes.width = relative_allocation.width;
1223 + attributes.height = relative_allocation.height;
1224 + attributes.wclass = GDK_INPUT_OUTPUT;
1225 + attributes.visual = gtk_widget_get_visual (widget);
1226 + attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK |
1227 + GDK_BUTTON_MOTION_MASK;
1229 + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
1231 + priv->overshoot_window =
1232 + gdk_window_new (gtk_widget_get_parent_window (widget),
1233 + &attributes, attributes_mask);
1235 + gdk_window_set_user_data (priv->overshoot_window, widget);
1237 + child_widget = gtk_bin_get_child (GTK_BIN (widget));
1239 + if (child_widget)
1240 + gtk_widget_set_parent_window (child_widget,
1241 + priv->overshoot_window);
1243 + GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->realize (widget);
1246 +static void
1247 +gtk_scrolled_window_unrealize (GtkWidget *widget)
1249 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
1250 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1252 + gdk_window_set_user_data (priv->overshoot_window, NULL);
1253 + gdk_window_destroy (priv->overshoot_window);
1254 + priv->overshoot_window = NULL;
1256 + gtk_widget_set_realized (widget, FALSE);
1258 + GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->unrealize (widget);
1261 +static void
1262 +gtk_scrolled_window_map (GtkWidget *widget)
1264 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
1265 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1267 + gdk_window_show (priv->overshoot_window);
1269 + GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->map (widget);
1272 +static void
1273 +gtk_scrolled_window_unmap (GtkWidget *widget)
1275 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
1276 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1278 + gdk_window_hide (priv->overshoot_window);
1280 + GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->unmap (widget);
1283 +static void
1284 +gtk_scrolled_window_grab_notify (GtkWidget *widget,
1285 + gboolean was_grabbed)
1287 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
1288 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1290 + if (priv->pointer_grabbed && !was_grabbed)
1292 + gdk_pointer_ungrab (gtk_get_current_event_time ());
1293 + priv->pointer_grabbed = FALSE;
1294 + priv->in_drag = FALSE;
1296 + if (priv->release_timeout_id)
1298 + g_source_remove (priv->release_timeout_id);
1299 + priv->release_timeout_id = 0;
1302 + if (_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
1303 + gtk_scrolled_window_start_deceleration (scrolled_window);
1304 + else
1305 + gtk_scrolled_window_cancel_deceleration (scrolled_window);
1307 + priv->last_button_event_valid = FALSE;
1311 #define __GTK_SCROLLED_WINDOW_C__
1312 #include "gtkaliasdef.c"
1313 diff --git a/gtk/gtkscrolledwindow.h b/gtk/gtkscrolledwindow.h
1314 index 5407547..1f555e0 100644
1315 --- a/gtk/gtkscrolledwindow.h
1316 +++ b/gtk/gtkscrolledwindow.h
1317 @@ -127,6 +127,14 @@ GtkShadowType gtk_scrolled_window_get_shadow_type (GtkScrolledWindow *scrolle
1318 void gtk_scrolled_window_add_with_viewport (GtkScrolledWindow *scrolled_window,
1319 GtkWidget *child);
1321 +void gtk_scrolled_window_set_kinetic_scrolling (GtkScrolledWindow *scrolled_window,
1322 + gboolean kinetic_scrolling);
1323 +gboolean gtk_scrolled_window_get_kinetic_scrolling (GtkScrolledWindow *scrolled_window);
1325 +void gtk_scrolled_window_set_capture_button_press (GtkScrolledWindow *scrolled_window,
1326 + gboolean capture_button_press);
1327 +gboolean gtk_scrolled_window_get_capture_button_press (GtkScrolledWindow *scrolled_window);
1329 gint _gtk_scrolled_window_get_scrollbar_spacing (GtkScrolledWindow *scrolled_window);
1333 1.7.10.2 (Apple Git-33)