1 From ab426801023babba7513d9e27a4dbdd44bdbc318 Mon Sep 17 00:00:00 2001
2 From: Michael Natterer <mitch@gimp.org>
3 Date: Tue, 8 May 2012 14:11:50 +0200
4 Subject: [PATCH 08/68] Smooth scrolling
7 gdk/gdkevents.c | 32 +++++++++++++++++
8 gdk/gdkevents.h | 6 ++++
10 gdk/quartz/gdkevents-quartz.c | 80 +++++++++++++++++++++++++++++++----------
11 gtk/gtkrange.c | 51 +++++++++++++++++++-------
12 gtk/gtkrange.h | 4 +--
13 gtk/gtkscrolledwindow.c | 74 ++++++++++++++++++++++++++++++--------
14 7 files changed, 203 insertions(+), 47 deletions(-)
16 diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
17 index 53833a0..0f8bba2 100644
20 @@ -392,6 +392,8 @@ gdk_event_new (GdkEventType type)
21 new_event->scroll.y = 0.;
22 new_event->scroll.x_root = 0.;
23 new_event->scroll.y_root = 0.;
24 + new_event->scroll.delta_x = 0.;
25 + new_event->scroll.delta_y = 0.;
27 case GDK_ENTER_NOTIFY:
28 case GDK_LEAVE_NOTIFY:
29 @@ -845,6 +847,36 @@ gdk_event_get_root_coords (const GdkEvent *event,
34 +gdk_event_get_scroll_deltas (const GdkEvent *event,
38 + gboolean fetched = TRUE;
42 + switch (event->type)
45 + fetched = event->scroll.has_deltas;
46 + dx = event->scroll.delta_x;
47 + dy = event->scroll.delta_y;
66 diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
67 index 0602bd0..f6b4e04 100644
70 @@ -337,6 +337,9 @@ struct _GdkEventScroll
71 GdkScrollDirection direction;
73 gdouble x_root, y_root;
74 + gboolean has_deltas;
80 @@ -537,6 +540,9 @@ gboolean gdk_event_get_coords (const GdkEvent *event,
81 gboolean gdk_event_get_root_coords (const GdkEvent *event,
84 +gboolean gdk_event_get_scroll_deltas (const GdkEvent *event,
87 gboolean gdk_event_get_axis (const GdkEvent *event,
90 diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
91 index f5f0339..d48751e 100644
94 @@ -10800,6 +10800,9 @@ proxy_button_event (GdkEvent *source_event,
95 event->scroll.y_root = source_event->scroll.y_root;
96 event->scroll.state = state;
97 event->scroll.device = source_event->scroll.device;
98 + event->scroll.has_deltas = source_event->scroll.has_deltas;
99 + event->scroll.delta_x = source_event->scroll.delta_x;
100 + event->scroll.delta_y = source_event->scroll.delta_y;
104 diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c
105 index c99a2c9..e7d97dc 100644
106 --- a/gdk/quartz/gdkevents-quartz.c
107 +++ b/gdk/quartz/gdkevents-quartz.c
108 @@ -57,6 +57,13 @@ static GdkWindow *find_toplevel_under_pointer (GdkDisplay *display,
112 +/* Protocol to build cleanly for OSX < 10.7 */
113 +@protocol PreciseDeltas
114 +- (BOOL) hasPreciseScrollingDeltas;
115 +- (CGFloat) scrollingDeltaX;
116 +- (CGFloat) scrollingDeltaY;
121 gdk_quartz_event_get_nsevent (GdkEvent *event)
122 @@ -980,6 +987,9 @@ fill_scroll_event (GdkWindow *window,
126 + gboolean has_deltas,
129 GdkScrollDirection direction)
131 GdkWindowObject *private;
132 @@ -999,6 +1009,9 @@ fill_scroll_event (GdkWindow *window,
133 event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
134 event->scroll.direction = direction;
135 event->scroll.device = _gdk_display->core_pointer;
136 + event->scroll.has_deltas = has_deltas;
137 + event->scroll.delta_x = delta_x;
138 + event->scroll.delta_y = delta_y;
142 @@ -1471,28 +1484,59 @@ gdk_event_translate (GdkEvent *event,
146 - float dx = [nsevent deltaX];
147 - float dy = [nsevent deltaY];
148 - GdkScrollDirection direction;
153 - direction = GDK_SCROLL_DOWN;
155 - direction = GDK_SCROLL_UP;
156 + GdkScrollDirection direction;
160 - fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
162 + if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
163 + [(id <PreciseDeltas>) nsevent hasPreciseScrollingDeltas])
165 + dx = [(id <PreciseDeltas>) nsevent scrollingDeltaX];
166 + dy = [(id <PreciseDeltas>) nsevent scrollingDeltaY];
171 - direction = GDK_SCROLL_RIGHT;
172 + if (fabs (dy) > fabs (dx))
175 + direction = GDK_SCROLL_DOWN;
177 + direction = GDK_SCROLL_UP;
180 - direction = GDK_SCROLL_LEFT;
183 + direction = GDK_SCROLL_RIGHT;
185 + direction = GDK_SCROLL_LEFT;
188 - fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
189 + fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
190 + TRUE, -dx, -dy, direction);
194 + dx = [nsevent deltaX];
195 + dy = [nsevent deltaY];
200 + direction = GDK_SCROLL_DOWN;
202 + direction = GDK_SCROLL_UP;
204 + fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
205 + FALSE, 0.0, fabs (dy), direction);
207 + else if (dx != 0.0)
210 + direction = GDK_SCROLL_RIGHT;
212 + direction = GDK_SCROLL_LEFT;
214 + fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
215 + FALSE, fabs (dx), 0.0, direction);
220 diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
221 index 245fbf6..d39f045 100644
224 @@ -2561,7 +2561,7 @@ gtk_range_button_release (GtkWidget *widget,
226 * _gtk_range_get_wheel_delta:
227 * @range: a #GtkRange
228 - * @direction: A #GdkScrollDirection
229 + * @event: A #GdkEventScroll
231 * Returns a good step value for the mouse wheel.
233 @@ -2570,27 +2570,52 @@ gtk_range_button_release (GtkWidget *widget,
237 -_gtk_range_get_wheel_delta (GtkRange *range,
238 - GdkScrollDirection direction)
239 +_gtk_range_get_wheel_delta (GtkRange *range,
240 + GdkEventScroll *event)
242 GtkAdjustment *adj = range->adjustment;
246 - if (GTK_IS_SCROLLBAR (range))
247 - delta = pow (adj->page_size, 2.0 / 3.0);
248 + if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &dx, &dy))
250 + GtkAllocation allocation;
252 + gtk_widget_get_allocation (GTK_WIDGET (range), &allocation);
254 + if (gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL)
256 + if (GTK_IS_SCROLLBAR (range) && adj->page_size > 0)
257 + delta = dx * adj->page_size / allocation.width;
259 + delta = dx * (adj->upper - adj->lower) / allocation.width;
263 + if (GTK_IS_SCROLLBAR (range) && adj->page_size > 0)
264 + delta = dy * adj->page_size / allocation.height;
266 + delta = dy * (adj->upper - adj->lower) / allocation.height;
270 - delta = adj->step_increment * 2;
272 - if (direction == GDK_SCROLL_UP ||
273 - direction == GDK_SCROLL_LEFT)
277 + if (GTK_IS_SCROLLBAR (range))
278 + delta = pow (adj->page_size, 2.0 / 3.0);
280 + delta = adj->step_increment * 2;
282 + if (event->direction == GDK_SCROLL_UP ||
283 + event->direction == GDK_SCROLL_LEFT)
295 gtk_range_scroll_event (GtkWidget *widget,
296 GdkEventScroll *event)
297 @@ -2603,7 +2628,7 @@ gtk_range_scroll_event (GtkWidget *widget,
301 - delta = _gtk_range_get_wheel_delta (range, event->direction);
302 + delta = _gtk_range_get_wheel_delta (range, event);
304 g_signal_emit (range, signals[CHANGE_VALUE], 0,
305 GTK_SCROLL_JUMP, adj->value + delta,
306 diff --git a/gtk/gtkrange.h b/gtk/gtkrange.h
307 index 5463140..c672acb 100644
310 @@ -199,8 +199,8 @@ gint gtk_range_get_round_digits (GtkRange *range
314 -gdouble _gtk_range_get_wheel_delta (GtkRange *range,
315 - GdkScrollDirection direction);
316 +gdouble _gtk_range_get_wheel_delta (GtkRange *range,
317 + GdkEventScroll *event);
319 void _gtk_range_set_stop_values (GtkRange *range,
321 diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
322 index 1704d3c..2288b2f 100644
323 --- a/gtk/gtkscrolledwindow.c
324 +++ b/gtk/gtkscrolledwindow.c
325 @@ -1565,31 +1565,77 @@ static gboolean
326 gtk_scrolled_window_scroll_event (GtkWidget *widget,
327 GdkEventScroll *event)
330 + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
331 + gboolean handled = FALSE;
335 g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (widget), FALSE);
336 g_return_val_if_fail (event != NULL, FALSE);
338 - if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
339 - range = GTK_SCROLLED_WINDOW (widget)->vscrollbar;
341 - range = GTK_SCROLLED_WINDOW (widget)->hscrollbar;
342 + if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
344 + if (delta_x != 0.0 && scrolled_window->hscrollbar &&
345 + gtk_widget_get_visible (scrolled_window->hscrollbar))
347 + GtkAdjustment *adj;
350 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
352 + new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_x,
353 + gtk_adjustment_get_lower (adj),
354 + gtk_adjustment_get_upper (adj) -
355 + gtk_adjustment_get_page_size (adj));
357 + gtk_adjustment_set_value (adj, new_value);
362 + if (delta_y != 0.0 && scrolled_window->vscrollbar &&
363 + gtk_widget_get_visible (scrolled_window->vscrollbar))
365 + GtkAdjustment *adj;
368 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
370 + new_value = CLAMP (gtk_adjustment_get_value (adj) + delta_y,
371 + gtk_adjustment_get_lower (adj),
372 + gtk_adjustment_get_upper (adj) -
373 + gtk_adjustment_get_page_size (adj));
375 - if (range && gtk_widget_get_visible (range))
376 + gtk_adjustment_set_value (adj, new_value);
383 - GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
384 - gdouble delta, new_value;
387 - delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event->direction);
388 + if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
389 + range = scrolled_window->vscrollbar;
391 + range = scrolled_window->hscrollbar;
393 - new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size);
395 - gtk_adjustment_set_value (adj, new_value);
396 + if (range && gtk_widget_get_visible (range))
398 + GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
399 + gdouble delta, new_value;
402 + delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event);
404 + new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size);
406 + gtk_adjustment_set_value (adj, new_value);
418 1.7.10.2 (Apple Git-33)