Transfer the Mac SDK bockbuild profiles & resources inside the Mono repository.
[mono.git] / bockbuild / mac-sdk / patches / gtk / 0014-gtk-add-event-handling-to-GtkScrolledWindow-s-overla.patch
1 From 713b51c19644653815b8ff1cd629d706f1074043 Mon Sep 17 00:00:00 2001
2 From: Michael Natterer <mitch@gimp.org>
3 Date: Tue, 10 Jul 2012 14:33:45 +0200
4 Subject: [PATCH 14/68] gtk: add event handling to GtkScrolledWindow's overlay
5  scrollbars
6
7 ---
8  gtk/gtkscrolledwindow.c |  438 +++++++++++++++++++++++++++++++++++++++++++----
9  1 file changed, 403 insertions(+), 35 deletions(-)
10
11 diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
12 index 77d485f..70de6ec 100644
13 --- a/gtk/gtkscrolledwindow.c
14 +++ b/gtk/gtkscrolledwindow.c
15 @@ -84,6 +84,10 @@
16  #define OVERSHOOT_INVERSE_ACCELERATION 0.003
17  #define RELEASE_EVENT_TIMEOUT 1000
18
19 +/* Overlay scrollbars */
20 +#define SCROLL_INTERVAL_INITIAL 300
21 +#define SCROLL_INTERVAL_REPEAT 100
22 +
23  typedef struct {
24    gboolean window_placement_set;
25    GtkCornerType real_window_placement;
26 @@ -123,6 +127,19 @@ typedef struct {
27    gboolean       sb_fading_in;
28    gint           sb_fade_out_delay;
29    guint          sb_fade_out_id;
30 +
31 +  gboolean       sb_hovering;
32 +  gboolean       sb_pointer_grabbed;
33 +  gboolean       sb_grab_vscroll;
34 +  gboolean       sb_grab_hscroll;
35 +  gboolean       sb_drag_slider;
36 +  gboolean       sb_visible;
37 +
38 +  gint           sb_grab_offset_x;
39 +  gint           sb_grab_offset_y;
40 +
41 +  gint           sb_scroll_direction;
42 +  guint          sb_scroll_timeout_id;
43  } GtkScrolledWindowPrivate;
44
45  #define GTK_SCROLLED_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCROLLED_WINDOW, GtkScrolledWindowPrivate))
46 @@ -219,8 +236,24 @@ static gboolean _gtk_scrolled_window_set_adjustment_value      (GtkScrolledWindo
47                                                                  gboolean           snap_to_border);
48
49  static void gtk_scrolled_window_cancel_animation         (GtkScrolledWindow *scrolled_window);
50 +static void gtk_scrolled_window_start_fade_out_timeout (GtkScrolledWindow *scrolled_window);
51 +static void gtk_scrolled_window_stop_fade_out_timeout (GtkScrolledWindow *scrolled_window);
52  static void gtk_scrolled_window_start_fade_in_animation  (GtkScrolledWindow *scrolled_window);
53  static void gtk_scrolled_window_start_fade_out_animation (GtkScrolledWindow *scrolled_window);
54 +static gboolean
55 +           gtk_scrolled_window_over_child_scroll_areas (GtkScrolledWindow *scrolled_window,
56 +                                                        GdkEvent          *event,
57 +                                                        gint               x,
58 +                                                        gint               y,
59 +                                                        gboolean          *over_vscroll,
60 +                                                        gboolean          *over_hscroll);
61 +static void gtk_scrolled_window_get_child_scroll_areas (GtkScrolledWindow *scrolled_window,
62 +                                                        GtkWidget         *child,
63 +                                                        GdkWindow         *child_window,
64 +                                                        GdkRectangle      *vbar_rect,
65 +                                                        GdkRectangle      *vslider_rect,
66 +                                                        GdkRectangle      *hbar_rect,
67 +                                                        GdkRectangle      *hslider_rect);
68  static gboolean gtk_scrolled_window_child_expose (GtkWidget         *widget,
69                                                    GdkEventExpose    *eevent,
70                                                    GtkScrolledWindow *scrolled_window);
71 @@ -2385,8 +2418,8 @@ gtk_scrolled_window_calculate_velocity (GtkScrolledWindow *scrolled_window,
72  }
73
74  static gboolean
75 -gtk_scrolled_window_captured_button_release (GtkWidget *widget,
76 -                                             GdkEvent  *event)
77 +gtk_scrolled_window_captured_button_release_kinetic (GtkWidget *widget,
78 +                                                     GdkEvent  *event)
79  {
80    GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
81    GtkScrolledWindowPrivate *priv;
82 @@ -2462,8 +2495,8 @@ gtk_scrolled_window_captured_button_release (GtkWidget *widget,
83  }
84
85  static gboolean
86 -gtk_scrolled_window_captured_motion_notify (GtkWidget *widget,
87 -                                            GdkEvent  *event)
88 +gtk_scrolled_window_captured_motion_notify_kinetic (GtkWidget *widget,
89 +                                                    GdkEvent  *event)
90  {
91    GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
92    GtkScrolledWindowPrivate *priv;
93 @@ -2554,8 +2587,8 @@ gtk_scrolled_window_captured_motion_notify (GtkWidget *widget,
94  }
95
96  static gboolean
97 -gtk_scrolled_window_captured_button_press (GtkWidget *widget,
98 -                                           GdkEvent  *event)
99 +gtk_scrolled_window_captured_button_press_kinetic (GtkWidget *widget,
100 +                                                   GdkEvent  *event)
101  {
102    GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
103    GtkScrolledWindowPrivate *priv;
104 @@ -2633,29 +2666,283 @@ gtk_scrolled_window_captured_button_press (GtkWidget *widget,
105      return FALSE;
106  }
107
108 +static void
109 +gtk_scrolled_window_scroll_step (GtkScrolledWindow *scrolled_window)
110 +{
111 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
112 +  GtkAdjustment *adj;
113 +  gdouble value;
114 +
115 +  if (priv->sb_grab_vscroll)
116 +    {
117 +      adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
118 +    }
119 +  else if (priv->sb_grab_hscroll)
120 +    {
121 +      adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
122 +    }
123 +
124 +  value = adj->value + (priv->sb_scroll_direction * adj->page_size);
125 +  value = CLAMP (value, adj->lower, adj->upper - adj->page_size);
126 +
127 +  gtk_adjustment_set_value (adj, value);
128 +}
129 +
130 +static gboolean
131 +gtk_scrolled_window_scroll_step_timeout (gpointer data)
132 +{
133 +  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (data);
134 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
135 +
136 +  gtk_scrolled_window_scroll_step (scrolled_window);
137 +
138 +  g_source_remove (priv->sb_scroll_timeout_id);
139 +
140 +  priv->sb_scroll_timeout_id =
141 +    gdk_threads_add_timeout (SCROLL_INTERVAL_REPEAT,
142 +                             gtk_scrolled_window_scroll_step_timeout,
143 +                             scrolled_window);
144 +
145 +  return FALSE;
146 +}
147 +
148 +static gboolean
149 +gtk_scrolled_window_captured_button_press_scrollbar (GtkWidget *widget,
150 +                                                     GdkEvent  *event)
151 +{
152 +  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
153 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
154 +  GdkEventButton *bevent = (GdkEventButton *) event;
155 +
156 +  if (bevent->button != 1)
157 +    return FALSE;
158 +
159 +  if (gtk_scrolled_window_over_child_scroll_areas (scrolled_window, event,
160 +                                                   bevent->x, bevent->y,
161 +                                                   &priv->sb_grab_vscroll,
162 +                                                   &priv->sb_grab_hscroll))
163 +    {
164 +      GdkRectangle vbar_rect;
165 +      GdkRectangle vslider_rect;
166 +      GdkRectangle hbar_rect;
167 +      GdkRectangle hslider_rect;
168 +
169 +      priv->sb_pointer_grabbed = TRUE;
170 +      gtk_grab_add (widget);
171 +
172 +      gtk_scrolled_window_get_child_scroll_areas (scrolled_window,
173 +                                                  gtk_bin_get_child (GTK_BIN (widget)),
174 +                                                  bevent->window,
175 +                                                  &vbar_rect, &vslider_rect,
176 +                                                  &hbar_rect, &hslider_rect);
177 +
178 +      if (priv->sb_grab_vscroll)
179 +        {
180 +          /* we consider the entire width of the scrollbar clickable */
181 +          vslider_rect.x = vbar_rect.x;
182 +          vslider_rect.width = vbar_rect.width;
183 +
184 +          if (bevent->x >= vslider_rect.x &&
185 +              bevent->x < (vslider_rect.x + vslider_rect.width) &&
186 +              bevent->y >= vslider_rect.y &&
187 +              bevent->y < (vslider_rect.y + vslider_rect.height))
188 +            {
189 +              priv->sb_drag_slider = TRUE;
190 +              priv->sb_grab_offset_y = bevent->y - vslider_rect.y;
191 +            }
192 +          else
193 +            {
194 +              priv->sb_drag_slider = FALSE;
195 +              priv->sb_grab_offset_y = bevent->y - vbar_rect.y;
196 +
197 +              if (bevent->y < vslider_rect.y)
198 +                priv->sb_scroll_direction = -1;
199 +              else
200 +                priv->sb_scroll_direction = 1;
201 +            }
202 +        }
203 +      else if (priv->sb_grab_hscroll)
204 +        {
205 +          /* we consider the entire height of the scrollbar clickable */
206 +          hslider_rect.y = hbar_rect.y;
207 +          hslider_rect.height = hbar_rect.height;
208 +
209 +          if (bevent->x >= hslider_rect.x &&
210 +              bevent->x < (hslider_rect.x + hslider_rect.width) &&
211 +              bevent->y >= hslider_rect.y &&
212 +              bevent->y < (hslider_rect.y + hslider_rect.height))
213 +            {
214 +              priv->sb_drag_slider = TRUE;
215 +              priv->sb_grab_offset_x = bevent->x - hslider_rect.x;
216 +            }
217 +          else
218 +            {
219 +              priv->sb_drag_slider = FALSE;
220 +              priv->sb_grab_offset_x = bevent->x - hbar_rect.x;
221 +
222 +              if (bevent->x < hslider_rect.x)
223 +                priv->sb_scroll_direction = -1;
224 +              else
225 +                priv->sb_scroll_direction = 1;
226 +            }
227 +        }
228 +
229 +      if ((priv->sb_grab_vscroll || priv->sb_grab_hscroll) &&
230 +          !priv->sb_drag_slider)
231 +        {
232 +          gtk_scrolled_window_scroll_step (scrolled_window);
233 +
234 +          priv->sb_scroll_timeout_id =
235 +            gdk_threads_add_timeout (SCROLL_INTERVAL_INITIAL,
236 +                                     gtk_scrolled_window_scroll_step_timeout,
237 +                                     scrolled_window);
238 +        }
239 +
240 +      return TRUE;
241 +    }
242 +
243 +  return FALSE;
244 +}
245 +
246 +static gboolean
247 +gtk_scrolled_window_captured_button_release_scrollbar (GtkWidget *widget,
248 +                                                       GdkEvent  *event)
249 +{
250 +  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
251 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
252 +  GdkEventButton *bevent = (GdkEventButton *) event;
253 +
254 +  if (bevent->button != 1)
255 +    return FALSE;
256 +
257 +  gtk_grab_remove (widget);
258 +  priv->sb_pointer_grabbed = FALSE;
259 +
260 +  if (priv->sb_scroll_timeout_id)
261 +    {
262 +      g_source_remove (priv->sb_scroll_timeout_id);
263 +      priv->sb_scroll_timeout_id = 0;
264 +    }
265 +
266 +  return TRUE;
267 +}
268 +
269 +static gboolean
270 +gtk_scrolled_window_captured_motion_notify_scrollbar (GtkWidget *widget,
271 +                                                      GdkEvent  *event)
272 +{
273 +  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
274 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
275 +  GdkEventMotion *mevent = (GdkEventMotion *) event;
276 +
277 +  if (priv->sb_pointer_grabbed)
278 +    {
279 +      if (priv->sb_drag_slider)
280 +        {
281 +          GdkRectangle vbar_rect;
282 +          GdkRectangle vslider_rect;
283 +          GdkRectangle hbar_rect;
284 +          GdkRectangle hslider_rect;
285 +          GtkAdjustment *adj;
286 +          gint pos;
287 +          gint visible_range;
288 +          gdouble value;
289 +
290 +          gtk_scrolled_window_get_child_scroll_areas (scrolled_window,
291 +                                                      gtk_bin_get_child (GTK_BIN (widget)),
292 +                                                      mevent->window,
293 +                                                      &vbar_rect, &vslider_rect,
294 +                                                      &hbar_rect, &hslider_rect);
295 +
296 +          if (priv->sb_grab_vscroll)
297 +            {
298 +              adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
299 +              pos = mevent->y - priv->sb_grab_offset_y - vbar_rect.y;
300 +              visible_range = vbar_rect.height - vslider_rect.height;
301 +            }
302 +          else if (priv->sb_grab_hscroll)
303 +            {
304 +              adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
305 +              pos = mevent->x - priv->sb_grab_offset_x - hbar_rect.x;
306 +              visible_range = hbar_rect.width - hslider_rect.width;
307 +            }
308 +
309 +          pos = CLAMP (pos, 0, visible_range);
310 +
311 +          value = (adj->upper - adj->page_size - adj->lower) * pos / visible_range;
312 +
313 +          gtk_adjustment_set_value (adj, value);
314 +        }
315 +
316 +      return TRUE;
317 +    }
318 +  else
319 +    {
320 +      if (gtk_scrolled_window_over_child_scroll_areas (scrolled_window, event,
321 +                                                       mevent->x, mevent->y,
322 +                                                       NULL, NULL))
323 +        {
324 +          priv->sb_hovering = TRUE;
325 +          priv->sb_visible = TRUE;
326 +
327 +          gtk_scrolled_window_start_fade_in_animation (scrolled_window);
328 +          gtk_scrolled_window_stop_fade_out_timeout (scrolled_window);
329 +
330 +          /* needed when entering the scrollbar */
331 +          gtk_scrolled_window_expose_scrollbars (NULL, scrolled_window);
332 +
333 +          return TRUE;
334 +        }
335 +
336 +      priv->sb_hovering = FALSE;
337 +
338 +      if (priv->sb_visible || gtk_adjustment_get_value (priv->opacity) > 0.0)
339 +        {
340 +          /* keep visible scrollbars visible while the mouse is moving */
341 +          gtk_scrolled_window_start_fade_in_animation (scrolled_window);
342 +          gtk_scrolled_window_stop_fade_out_timeout (scrolled_window);
343 +          gtk_scrolled_window_start_fade_out_timeout (scrolled_window);
344 +        }
345 +
346 +      return FALSE;
347 +    }
348 +}
349 +
350  static gboolean
351  gtk_scrolled_window_captured_event (GtkWidget *widget,
352                                      GdkEvent  *event)
353  {
354 -  gboolean retval = FALSE;
355 +  GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
356    GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (widget);
357 +  gboolean retval = FALSE;
358
359    switch (event->type)
360      {
361      case GDK_BUTTON_PRESS:
362 -      retval = gtk_scrolled_window_captured_button_press (widget, event);
363 +      retval = gtk_scrolled_window_captured_button_press_scrollbar (widget, event);
364 +      if (!retval)
365 +        retval = gtk_scrolled_window_captured_button_press_kinetic (widget, event);
366        break;
367      case GDK_BUTTON_RELEASE:
368 -      if (priv->pointer_grabbed)
369 -        retval = gtk_scrolled_window_captured_button_release (widget, event);
370 +      if (priv->sb_pointer_grabbed)
371 +        retval = gtk_scrolled_window_captured_button_release_scrollbar (widget, event);
372 +      else if (priv->pointer_grabbed)
373 +        retval = gtk_scrolled_window_captured_button_release_kinetic (widget, event);
374        else
375          priv->last_button_event_valid = FALSE;
376        break;
377      case GDK_MOTION_NOTIFY:
378 -      if (priv->pointer_grabbed)
379 -        retval = gtk_scrolled_window_captured_motion_notify (widget, event);
380 +      if (priv->sb_pointer_grabbed || !priv->pointer_grabbed)
381 +        retval = gtk_scrolled_window_captured_motion_notify_scrollbar (widget, event);
382 +      else if (priv->pointer_grabbed)
383 +        retval = gtk_scrolled_window_captured_motion_notify_kinetic (widget, event);
384        break;
385      case GDK_LEAVE_NOTIFY:
386 +      if (!priv->in_drag && !priv->sb_pointer_grabbed)
387 +        {
388 +          gtk_scrolled_window_start_fade_out_timeout (scrolled_window);
389 +          priv->sb_hovering = FALSE;
390 +        }
391      case GDK_ENTER_NOTIFY:
392        if (priv->in_drag &&
393            event->crossing.mode != GDK_CROSSING_GRAB)
394 @@ -3016,6 +3303,17 @@ gtk_scrolled_window_grab_notify (GtkWidget *widget,
395
396        priv->last_button_event_valid = FALSE;
397      }
398 +
399 +  if (priv->sb_pointer_grabbed && !was_grabbed)
400 +    {
401 +      priv->sb_pointer_grabbed = FALSE;
402 +
403 +      if (priv->sb_scroll_timeout_id)
404 +        {
405 +          g_source_remove (priv->sb_scroll_timeout_id);
406 +          priv->sb_scroll_timeout_id = 0;
407 +        }
408 +    }
409  }
410
411  static void
412 @@ -3057,6 +3355,56 @@ gtk_scrolled_window_rounded_rectangle (cairo_t *cr,
413    cairo_close_path (cr);
414  }
415
416 +static gboolean
417 +gtk_scrolled_window_over_child_scroll_areas (GtkScrolledWindow *scrolled_window,
418 +                                             GdkEvent          *event,
419 +                                             gint               x,
420 +                                             gint               y,
421 +                                             gboolean          *over_vscroll,
422 +                                             gboolean          *over_hscroll)
423 +{
424 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
425 +  GtkWidget *child;
426 +  GdkRectangle vbar_rect;
427 +  GdkRectangle hbar_rect;
428 +  gboolean over_v = FALSE;
429 +  gboolean over_h = FALSE;
430 +
431 +  child = gtk_bin_get_child (GTK_BIN (scrolled_window));
432 +  if (!child)
433 +    return FALSE;
434 +
435 +  if (gtk_get_event_widget (event) != child)
436 +    return FALSE;
437 +
438 +  if (gtk_adjustment_get_value (priv->opacity) == 0.0)
439 +    return FALSE;
440 +
441 +  gtk_scrolled_window_get_child_scroll_areas (scrolled_window,
442 +                                              child,
443 +                                              ((GdkEventAny *) event)->window,
444 +                                              &vbar_rect, NULL,
445 +                                              &hbar_rect, NULL);
446 +
447 +  if (vbar_rect.width > 0 &&
448 +      x >= vbar_rect.x && x < (vbar_rect.x + vbar_rect.width) &&
449 +      y >= vbar_rect.y && y < (vbar_rect.y + vbar_rect.height))
450 +    {
451 +      over_v = TRUE;
452 +    }
453 +  else if (hbar_rect.width > 0 &&
454 +           x >= hbar_rect.x && x < (hbar_rect.x + hbar_rect.width) &&
455 +           y >= hbar_rect.y && y < (hbar_rect.y + hbar_rect.height))
456 +    {
457 +      over_h = TRUE;
458 +    }
459 +
460 +  if (over_vscroll) *over_vscroll = over_v;
461 +  if (over_hscroll) *over_hscroll = over_h;
462 +
463 +  return over_v || over_h;
464 +}
465 +
466  static void
467  gtk_scrolled_window_get_child_scroll_areas (GtkScrolledWindow *scrolled_window,
468                                              GtkWidget         *child,
469 @@ -3083,6 +3431,8 @@ gtk_scrolled_window_get_child_scroll_areas (GtkScrolledWindow *scrolled_window,
470     gint window_height;
471     gint viewport_width;
472     gint viewport_height;
473 +   gint offset_x = 0;
474 +   gint offset_y = 0;
475
476     window_width = gdk_window_get_width (child_window);
477     window_height = gdk_window_get_height (child_window);
478 @@ -3106,6 +3456,12 @@ gtk_scrolled_window_get_child_scroll_areas (GtkScrolledWindow *scrolled_window,
479         value_h = gtk_adjustment_get_value (adj);
480       }
481
482 +   if (window_width > allocation.width)
483 +     offset_x = value_h;
484 +
485 +   if (window_height > allocation.height)
486 +     offset_y = value_v;
487 +
488     if ((vbar_rect || vslider_rect) && scrolled_window->vscrollbar)
489       {
490         adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
491 @@ -3127,16 +3483,13 @@ gtk_scrolled_window_get_child_scroll_areas (GtkScrolledWindow *scrolled_window,
492             y = ratio * (viewport_height - (2 * priv->sb_padding) - height) + priv->sb_padding;
493             x = viewport_width - priv->sb_width - priv->sb_padding;
494
495 -           if (window_width > allocation.width)
496 -             x += value_h;
497 -
498 -           if (window_height > allocation.height)
499 -             y += value_v;
500 +           x += offset_x;
501 +           y += offset_y;
502
503             if (vbar_rect)
504               {
505                 vbar_rect->x = x - priv->sb_padding;
506 -               vbar_rect->y = 0;
507 +               vbar_rect->y = offset_y;
508                 vbar_rect->width = priv->sb_width + 2 * priv->sb_padding;
509                 vbar_rect->height = viewport_height;
510               }
511 @@ -3190,15 +3543,12 @@ gtk_scrolled_window_get_child_scroll_areas (GtkScrolledWindow *scrolled_window,
512             x = ratio * (viewport_width - (2 * priv->sb_padding) - width) + priv->sb_padding;
513             y = viewport_height - priv->sb_width - priv->sb_padding;
514
515 -           if (window_width > allocation.width)
516 -             x += value_h;
517 -
518 -           if (window_height > allocation.height)
519 -             y += value_v;
520 +           x += offset_x;
521 +           y += offset_y;
522
523             if (hbar_rect)
524               {
525 -               hbar_rect->x = 0;
526 +               hbar_rect->x = offset_x;
527                 hbar_rect->y = y - priv->sb_padding;
528                 hbar_rect->width = viewport_width;
529                 hbar_rect->height = priv->sb_width + 2 * priv->sb_padding;
530 @@ -3255,7 +3605,7 @@ gtk_scrolled_window_child_expose (GtkWidget         *widget,
531                                                 &vbar_rect, &vslider_rect,
532                                                 &hbar_rect, &hslider_rect);
533
534 -   if (TRUE)
535 +   if (priv->sb_visible)
536       {
537         if (scrolled_window->vscrollbar && vbar_rect.width > 0)
538           gdk_cairo_rectangle (cr, &vbar_rect);
539 @@ -3263,7 +3613,7 @@ gtk_scrolled_window_child_expose (GtkWidget         *widget,
540         if (scrolled_window->hscrollbar && hbar_rect.width > 0)
541           gdk_cairo_rectangle (cr, &hbar_rect);
542
543 -       cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
544 +       cairo_set_source_rgba (cr, 0, 0, 0, gtk_adjustment_get_value (priv->opacity) / 2.0);
545         cairo_fill (cr);
546       }
547
548 @@ -3307,11 +3657,7 @@ gtk_scrolled_window_cancel_animation (GtkScrolledWindow *scrolled_window)
549        _gb_animation_stop (anim);
550      }
551
552 -  if (priv->sb_fade_out_id)
553 -    {
554 -      g_source_remove (priv->sb_fade_out_id);
555 -      priv->sb_fade_out_id = 0;
556 -    }
557 +  gtk_scrolled_window_stop_fade_out_timeout (scrolled_window);
558
559    priv->sb_fading_in = FALSE;
560  }
561 @@ -3325,6 +3671,30 @@ gtk_scrolled_window_fade_out_timeout (GtkScrolledWindow *scrolled_window)
562  }
563
564  static void
565 +gtk_scrolled_window_start_fade_out_timeout (GtkScrolledWindow *scrolled_window)
566 +{
567 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
568 +
569 +  if (! priv->sb_fade_out_id)
570 +    priv->sb_fade_out_id =
571 +      gdk_threads_add_timeout (priv->sb_fade_out_delay,
572 +                               (GSourceFunc) gtk_scrolled_window_fade_out_timeout,
573 +                               scrolled_window);
574 +}
575 +
576 +static void
577 +gtk_scrolled_window_stop_fade_out_timeout (GtkScrolledWindow *scrolled_window)
578 +{
579 +  GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
580 +
581 +  if (priv->sb_fade_out_id)
582 +    {
583 +      g_source_remove (priv->sb_fade_out_id);
584 +      priv->sb_fade_out_id = 0;
585 +    }
586 +}
587 +
588 +static void
589  gtk_scrolled_window_start_fade_in_animation (GtkScrolledWindow *scrolled_window)
590  {
591    GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
592 @@ -3336,6 +3706,7 @@ gtk_scrolled_window_start_fade_in_animation (GtkScrolledWindow *scrolled_window)
593    gtk_scrolled_window_cancel_animation (scrolled_window);
594
595    priv->sb_fading_in = TRUE;
596 +  priv->sb_visible = priv->sb_hovering;
597
598    upper = gtk_adjustment_get_upper (priv->opacity);
599    priv->opacity_anim = _gb_object_animate (priv->opacity,
600 @@ -3346,10 +3717,7 @@ gtk_scrolled_window_start_fade_in_animation (GtkScrolledWindow *scrolled_window)
601    g_object_add_weak_pointer (G_OBJECT (priv->opacity_anim),
602                               (gpointer *) &priv->opacity_anim);
603
604 -  priv->sb_fade_out_id =
605 -    gdk_threads_add_timeout (priv->sb_fade_out_delay,
606 -                             (GSourceFunc) gtk_scrolled_window_fade_out_timeout,
607 -                             scrolled_window);
608 +  gtk_scrolled_window_start_fade_out_timeout (scrolled_window);
609  }
610
611  static void
612 --
613 1.7.10.2 (Apple Git-33)