Transfer the Mac SDK bockbuild profiles & resources inside the Mono repository.
[mono.git] / bockbuild / mac-sdk / patches / gtk / 0008-Smooth-scrolling.patch
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
5
6 ---
7  gdk/gdkevents.c               |   32 +++++++++++++++++
8  gdk/gdkevents.h               |    6 ++++
9  gdk/gdkwindow.c               |    3 ++
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(-)
15
16 diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
17 index 53833a0..0f8bba2 100644
18 --- a/gdk/gdkevents.c
19 +++ b/gdk/gdkevents.c
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.;
26        break;
27      case GDK_ENTER_NOTIFY:
28      case GDK_LEAVE_NOTIFY:
29 @@ -845,6 +847,36 @@ gdk_event_get_root_coords (const GdkEvent *event,
30    return fetched;
31  }
32
33 +gboolean
34 +gdk_event_get_scroll_deltas (const GdkEvent *event,
35 +                             gdouble        *delta_x,
36 +                             gdouble        *delta_y)
37 +{
38 +  gboolean fetched = TRUE;
39 +  gdouble dx = 0.0;
40 +  gdouble dy = 0.0;
41 +
42 +  switch (event->type)
43 +    {
44 +    case GDK_SCROLL:
45 +      fetched = event->scroll.has_deltas;
46 +      dx = event->scroll.delta_x;
47 +      dy = event->scroll.delta_y;
48 +      break;
49 +    default:
50 +      fetched = FALSE;
51 +      break;
52 +    }
53 +
54 +  if (delta_x)
55 +    *delta_x = dx;
56 +
57 +  if (delta_y)
58 +    *delta_y = dy;
59 +
60 +  return fetched;
61 +}
62 +
63  /**
64   * gdk_event_get_axis:
65   * @event: a #GdkEvent
66 diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
67 index 0602bd0..f6b4e04 100644
68 --- a/gdk/gdkevents.h
69 +++ b/gdk/gdkevents.h
70 @@ -337,6 +337,9 @@ struct _GdkEventScroll
71    GdkScrollDirection direction;
72    GdkDevice *device;
73    gdouble x_root, y_root;
74 +  gboolean has_deltas;
75 +  gdouble delta_x;
76 +  gdouble delta_y;
77  };
78
79  struct _GdkEventKey
80 @@ -537,6 +540,9 @@ gboolean  gdk_event_get_coords              (const GdkEvent  *event,
81  gboolean  gdk_event_get_root_coords    (const GdkEvent  *event,
82                                          gdouble         *x_root,
83                                          gdouble         *y_root);
84 +gboolean  gdk_event_get_scroll_deltas   (const GdkEvent *event,
85 +                                         gdouble         *delta_x,
86 +                                         gdouble         *delta_y);
87  gboolean  gdk_event_get_axis            (const GdkEvent  *event,
88                                           GdkAxisUse       axis_use,
89                                           gdouble         *value);
90 diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
91 index f5f0339..d48751e 100644
92 --- a/gdk/gdkwindow.c
93 +++ b/gdk/gdkwindow.c
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;
101        return TRUE;
102
103      default:
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,
109                                                   gint       *x,
110                                                   gint       *y);
111
112 +/* Protocol to build cleanly for OSX < 10.7 */
113 +@protocol PreciseDeltas
114 +- (BOOL) hasPreciseScrollingDeltas;
115 +- (CGFloat) scrollingDeltaX;
116 +- (CGFloat) scrollingDeltaY;
117 +@end
118 +
119
120  NSEvent *
121  gdk_quartz_event_get_nsevent (GdkEvent *event)
122 @@ -980,6 +987,9 @@ fill_scroll_event (GdkWindow          *window,
123                     gint                y,
124                     gint                x_root,
125                     gint                y_root,
126 +                   gboolean            has_deltas,
127 +                   gdouble             delta_x,
128 +                   gdouble             delta_y,
129                     GdkScrollDirection  direction)
130  {
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;
139  }
140
141  static void
142 @@ -1471,28 +1484,59 @@ gdk_event_translate (GdkEvent *event,
143
144      case NSScrollWheel:
145        {
146 -       float dx = [nsevent deltaX];
147 -       float dy = [nsevent deltaY];
148 -       GdkScrollDirection direction;
149 -
150 -        if (dy != 0)
151 -          {
152 -            if (dy < 0.0)
153 -              direction = GDK_SCROLL_DOWN;
154 -            else
155 -              direction = GDK_SCROLL_UP;
156 +        GdkScrollDirection direction;
157 +       float dx;
158 +       float dy;
159
160 -            fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
161 -          }
162 +       if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
163 +           [(id <PreciseDeltas>) nsevent hasPreciseScrollingDeltas])
164 +         {
165 +           dx = [(id <PreciseDeltas>) nsevent scrollingDeltaX];
166 +           dy = [(id <PreciseDeltas>) nsevent scrollingDeltaY];
167
168 -        if (dx != 0)
169 -          {
170 -            if (dx < 0.0)
171 -              direction = GDK_SCROLL_RIGHT;
172 +            if (fabs (dy) > fabs (dx))
173 +              {
174 +                if (dy < 0.0)
175 +                  direction = GDK_SCROLL_DOWN;
176 +                else
177 +                  direction = GDK_SCROLL_UP;
178 +              }
179              else
180 -              direction = GDK_SCROLL_LEFT;
181 +              {
182 +                if (dx < 0.0)
183 +                  direction = GDK_SCROLL_RIGHT;
184 +                else
185 +                  direction = GDK_SCROLL_LEFT;
186 +              }
187
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);
191 +         }
192 +       else
193 +         {
194 +           dx = [nsevent deltaX];
195 +           dy = [nsevent deltaY];
196 +
197 +            if (dy != 0.0)
198 +              {
199 +                if (dy < 0.0)
200 +                  direction = GDK_SCROLL_DOWN;
201 +                else
202 +                  direction = GDK_SCROLL_UP;
203 +
204 +                fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
205 +                                   FALSE, 0.0, fabs (dy), direction);
206 +              }
207 +            else if (dx != 0.0)
208 +              {
209 +                if (dx < 0.0)
210 +                  direction = GDK_SCROLL_RIGHT;
211 +                else
212 +                  direction = GDK_SCROLL_LEFT;
213 +
214 +                fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
215 +                                   FALSE, fabs (dx), 0.0, direction);
216 +              }
217            }
218        }
219        break;
220 diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
221 index 245fbf6..d39f045 100644
222 --- a/gtk/gtkrange.c
223 +++ b/gtk/gtkrange.c
224 @@ -2561,7 +2561,7 @@ gtk_range_button_release (GtkWidget      *widget,
225  /**
226   * _gtk_range_get_wheel_delta:
227   * @range: a #GtkRange
228 - * @direction: A #GdkScrollDirection
229 + * @event: A #GdkEventScroll
230   *
231   * Returns a good step value for the mouse wheel.
232   *
233 @@ -2570,27 +2570,52 @@ gtk_range_button_release (GtkWidget      *widget,
234   * Since: 2.4
235   **/
236  gdouble
237 -_gtk_range_get_wheel_delta (GtkRange           *range,
238 -                           GdkScrollDirection  direction)
239 +_gtk_range_get_wheel_delta (GtkRange       *range,
240 +                            GdkEventScroll *event)
241  {
242    GtkAdjustment *adj = range->adjustment;
243 +  gdouble dx, dy;
244    gdouble delta;
245
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))
249 +    {
250 +      GtkAllocation allocation;
251 +
252 +      gtk_widget_get_allocation (GTK_WIDGET (range), &allocation);
253 +
254 +      if (gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL)
255 +        {
256 +          if (GTK_IS_SCROLLBAR (range) && adj->page_size > 0)
257 +            delta = dx * adj->page_size / allocation.width;
258 +          else
259 +            delta = dx * (adj->upper - adj->lower) / allocation.width;
260 +        }
261 +      else
262 +        {
263 +          if (GTK_IS_SCROLLBAR (range) && adj->page_size > 0)
264 +            delta = dy * adj->page_size / allocation.height;
265 +          else
266 +            delta = dy * (adj->upper - adj->lower) / allocation.height;
267 +        }
268 +    }
269    else
270 -    delta = adj->step_increment * 2;
271 -
272 -  if (direction == GDK_SCROLL_UP ||
273 -      direction == GDK_SCROLL_LEFT)
274 -    delta = - delta;
275 -
276 +    {
277 +      if (GTK_IS_SCROLLBAR (range))
278 +        delta = pow (adj->page_size, 2.0 / 3.0);
279 +      else
280 +        delta = adj->step_increment * 2;
281 +
282 +      if (event->direction == GDK_SCROLL_UP ||
283 +          event->direction == GDK_SCROLL_LEFT)
284 +        delta = - delta;
285 +    }
286 +
287    if (range->inverted)
288      delta = - delta;
289
290    return delta;
291  }
292 -
293 +
294  static gboolean
295  gtk_range_scroll_event (GtkWidget      *widget,
296                         GdkEventScroll *event)
297 @@ -2603,7 +2628,7 @@ gtk_range_scroll_event (GtkWidget      *widget,
298        gdouble delta;
299        gboolean handled;
300
301 -      delta = _gtk_range_get_wheel_delta (range, event->direction);
302 +      delta = _gtk_range_get_wheel_delta (range, event);
303
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
308 --- a/gtk/gtkrange.h
309 +++ b/gtk/gtkrange.h
310 @@ -199,8 +199,8 @@ gint                gtk_range_get_round_digits             (GtkRange      *range
311
312
313  /* internal API */
314 -gdouble            _gtk_range_get_wheel_delta              (GtkRange      *range,
315 -                                                            GdkScrollDirection direction);
316 +gdouble            _gtk_range_get_wheel_delta              (GtkRange       *range,
317 +                                                            GdkEventScroll *event);
318
319  void               _gtk_range_set_stop_values              (GtkRange      *range,
320                                                              gdouble       *values,
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)
328  {
329 -  GtkWidget *range;
330 +  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
331 +  gboolean handled = FALSE;
332 +  gdouble delta_x;
333 +  gdouble delta_y;
334
335    g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (widget), FALSE);
336    g_return_val_if_fail (event != NULL, FALSE);
337
338 -  if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
339 -    range = GTK_SCROLLED_WINDOW (widget)->vscrollbar;
340 -  else
341 -    range = GTK_SCROLLED_WINDOW (widget)->hscrollbar;
342 +  if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
343 +    {
344 +      if (delta_x != 0.0 && scrolled_window->hscrollbar &&
345 +          gtk_widget_get_visible (scrolled_window->hscrollbar))
346 +        {
347 +          GtkAdjustment *adj;
348 +          gdouble new_value;
349 +
350 +          adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
351 +
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));
356 +
357 +          gtk_adjustment_set_value (adj, new_value);
358 +
359 +          handled = TRUE;
360 +        }
361 +
362 +      if (delta_y != 0.0 && scrolled_window->vscrollbar &&
363 +          gtk_widget_get_visible (scrolled_window->vscrollbar))
364 +        {
365 +          GtkAdjustment *adj;
366 +          gdouble new_value;
367 +
368 +          adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
369 +
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));
374
375 -  if (range && gtk_widget_get_visible (range))
376 +          gtk_adjustment_set_value (adj, new_value);
377 +
378 +          handled = TRUE;
379 +        }
380 +    }
381 +  else
382      {
383 -      GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
384 -      gdouble delta, new_value;
385 +      GtkWidget *range;
386
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;
390 +      else
391 +        range = scrolled_window->hscrollbar;
392
393 -      new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size);
394 -
395 -      gtk_adjustment_set_value (adj, new_value);
396 +      if (range && gtk_widget_get_visible (range))
397 +        {
398 +          GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
399 +          gdouble delta, new_value;
400
401 -      return TRUE;
402 +          delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event);
403 +
404 +          new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size);
405 +
406 +          gtk_adjustment_set_value (adj, new_value);
407 +
408 +          handled = TRUE;
409 +        }
410      }
411
412 -  return FALSE;
413 +  return handled;
414  }
415
416  static gboolean
417 --
418 1.7.10.2 (Apple Git-33)