Fix 'mono' package typo
[mono-project.git] / bockbuild / mac-sdk / patches / gtk / 0013-GtkScrolledWindow-add-overlay-scrollbars.patch
blob0a9b34c7b4300dc35533babc0141190ce5a5fbfc
1 From b7ce8de6d7b964eef99aa46ee90a09605acdd5ed Mon Sep 17 00:00:00 2001
2 From: Michael Natterer <mitch@gimp.org>
3 Date: Fri, 1 Jun 2012 13:08:26 +0200
4 Subject: [PATCH 13/68] GtkScrolledWindow: add overlay scrollbars
6 based on code from gnome-builder by Christian Hergert.
7 ---
8 gtk/Makefile.am | 4 +
9 gtk/gb-animation.c | 998 +++++++++++++++++++++++++++++++++++++++++++++++
10 gtk/gb-animation.h | 87 +++++
11 gtk/gb-frame-source.c | 134 +++++++
12 gtk/gb-frame-source.h | 32 ++
13 gtk/gtkscrolledwindow.c | 577 +++++++++++++++++++++++++--
14 6 files changed, 1806 insertions(+), 26 deletions(-)
15 create mode 100644 gtk/gb-animation.c
16 create mode 100644 gtk/gb-animation.h
17 create mode 100644 gtk/gb-frame-source.c
18 create mode 100644 gtk/gb-frame-source.h
20 diff --git a/gtk/Makefile.am b/gtk/Makefile.am
21 index 7fbe429..31dfd19 100644
22 --- a/gtk/Makefile.am
23 +++ b/gtk/Makefile.am
24 @@ -361,6 +361,8 @@ gtk_semi_private_h_sources = \
26 # GTK+ header files that don't get installed
27 gtk_private_h_sources = \
28 + gb-animation.h \
29 + gb-frame-source.h \
30 gtkquery.h \
31 gtksearchengine.h \
32 gtksearchenginesimple.h \
33 @@ -411,6 +413,8 @@ gtk_private_h_sources = \
35 # GTK+ C sources to build the library from
36 gtk_base_c_sources = \
37 + gb-animation.c \
38 + gb-frame-source.c \
39 gtkquery.c \
40 gtksearchengine.c \
41 gtksearchenginesimple.c \
42 diff --git a/gtk/gb-animation.c b/gtk/gb-animation.c
43 new file mode 100644
44 index 0000000..9452b4a
45 --- /dev/null
46 +++ b/gtk/gb-animation.c
47 @@ -0,0 +1,998 @@
48 +/* gb-animation.c
49 + *
50 + * Copyright (C) 2010 Christian Hergert <christian@hergert.me>
51 + *
52 + * This library is free software; you can redistribute it and/or
53 + * modify it under the terms of the GNU Lesser General Public
54 + * License as published by the Free Software Foundation; either
55 + * version 2.1 of the License, or (at your option) any later version.
56 + *
57 + * This program is distributed in the hope that it will be useful,
58 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60 + * GNU General Public License for more details.
61 + *
62 + * You should have received a copy of the GNU Lesser General Public icense along with this library; if not, write to the Free Software
63 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
64 + */
66 +#include <glib/gi18n.h>
67 +#include <gobject/gvaluecollector.h>
68 +#include <gtk/gtk.h>
69 +#include <string.h>
71 +#include "gb-animation.h"
72 +#include "gb-frame-source.h"
74 +G_DEFINE_TYPE(GbAnimation, _gb_animation, G_TYPE_INITIALLY_UNOWNED)
76 +typedef gdouble (*AlphaFunc) (gdouble offset);
77 +typedef void (*TweenFunc) (const GValue *begin,
78 + const GValue *end,
79 + GValue *value,
80 + gdouble offset);
82 +typedef struct
84 + gboolean is_child; /* Does GParamSpec belong to parent widget */
85 + GParamSpec *pspec; /* GParamSpec of target property */
86 + GValue begin; /* Begin value in animation */
87 + GValue end; /* End value in animation */
88 +} Tween;
91 +struct _GbAnimationPrivate
93 + gpointer target; /* Target object to animate */
94 + guint64 begin_msec; /* Time in which animation started */
95 + guint duration_msec; /* Duration of animation */
96 + guint mode; /* Tween mode */
97 + guint tween_handler; /* GSource performing tweens */
98 + GArray *tweens; /* Array of tweens to perform */
99 + guint frame_rate; /* The frame-rate to use */
100 + guint frame_count; /* Counter for debugging frames rendered */
104 +enum
106 + PROP_0,
107 + PROP_DURATION,
108 + PROP_FRAME_RATE,
109 + PROP_MODE,
110 + PROP_TARGET,
111 + LAST_PROP
115 +enum
117 + TICK,
118 + LAST_SIGNAL
123 + * Helper macros.
124 + */
125 +#define TIMEVAL_TO_MSEC(t) (((t).tv_sec * 1000UL) + ((t).tv_usec / 1000UL))
126 +#define LAST_FUNDAMENTAL 64
127 +#define TWEEN(type) \
128 + static void \
129 + tween_##type (const GValue *begin, \
130 + const GValue *end, \
131 + GValue *value, \
132 + gdouble offset) \
133 + { \
134 + g##type x = g_value_get_##type(begin); \
135 + g##type y = g_value_get_##type(end); \
136 + g_value_set_##type(value, x + ((y - x) * offset)); \
141 + * Globals.
142 + */
143 +static AlphaFunc gAlphaFuncs[GB_ANIMATION_LAST];
144 +static gboolean gDebug;
145 +static GParamSpec *gParamSpecs[LAST_PROP];
146 +static guint gSignals[LAST_SIGNAL];
147 +static TweenFunc gTweenFuncs[LAST_FUNDAMENTAL];
151 + * Tweeners for basic types.
152 + */
153 +TWEEN(int);
154 +TWEEN(uint);
155 +TWEEN(long);
156 +TWEEN(ulong);
157 +TWEEN(float);
158 +TWEEN(double);
161 +/**
162 + * _gb_animation_alpha_ease_in_cubic:
163 + * @offset: (in): The position within the animation; 0.0 to 1.0.
165 + * An alpha function to transform the offset within the animation.
166 + * @GB_ANIMATION_CUBIC means the valu ewill be transformed into
167 + * cubic acceleration (x * x * x).
168 + */
169 +static gdouble
170 +_gb_animation_alpha_ease_in_cubic (gdouble offset)
172 + return offset * offset * offset;
176 +/**
177 + * _gb_animation_alpha_linear:
178 + * @offset: (in): The position within the animation; 0.0 to 1.0.
180 + * An alpha function to transform the offset within the animation.
181 + * @GB_ANIMATION_LINEAR means no tranformation will be made.
183 + * Returns: @offset.
184 + * Side effects: None.
185 + */
186 +static gdouble
187 +_gb_animation_alpha_linear (gdouble offset)
189 + return offset;
193 +/**
194 + * _gb_animation_alpha_ease_in_quad:
195 + * @offset: (in): The position within the animation; 0.0 to 1.0.
197 + * An alpha function to transform the offset within the animation.
198 + * @GB_ANIMATION_EASE_IN_QUAD means that the value will be transformed
199 + * into a quadratic acceleration.
201 + * Returns: A tranformation of @offset.
202 + * Side effects: None.
203 + */
204 +static gdouble
205 +_gb_animation_alpha_ease_in_quad (gdouble offset)
207 + return offset * offset;
211 +/**
212 + * _gb_animation_alpha_ease_out_quad:
213 + * @offset: (in): The position within the animation; 0.0 to 1.0.
215 + * An alpha function to transform the offset within the animation.
216 + * @GB_ANIMATION_EASE_OUT_QUAD means that the value will be transformed
217 + * into a quadratic deceleration.
219 + * Returns: A tranformation of @offset.
220 + * Side effects: None.
221 + */
222 +static gdouble
223 +_gb_animation_alpha_ease_out_quad (gdouble offset)
225 + return -1.0 * offset * (offset - 2.0);
229 +/**
230 + * _gb_animation_alpha_ease_in_out_quad:
231 + * @offset: (in): The position within the animation; 0.0 to 1.0.
233 + * An alpha function to transform the offset within the animation.
234 + * @GB_ANIMATION_EASE_IN_OUT_QUAD means that the value will be transformed
235 + * into a quadratic acceleration for the first half, and quadratic
236 + * deceleration the second half.
238 + * Returns: A tranformation of @offset.
239 + * Side effects: None.
240 + */
241 +static gdouble
242 +_gb_animation_alpha_ease_in_out_quad (gdouble offset)
244 + offset *= 2.0;
245 + if (offset < 1.0) {
246 + return 0.5 * offset * offset;
248 + offset -= 1.0;
249 + return -0.5 * (offset * (offset - 2.0) - 1.0);
253 +/**
254 + * _gb_animation_load_begin_values:
255 + * @animation: (in): A #GbAnimation.
257 + * Load the begin values for all the properties we are about to
258 + * animate.
260 + * Returns: None.
261 + * Side effects: None.
262 + */
263 +static void
264 +_gb_animation_load_begin_values (GbAnimation *animation)
266 + GbAnimationPrivate *priv;
267 + GtkContainer *container;
268 + Tween *tween;
269 + gint i;
271 + g_return_if_fail(GB_IS_ANIMATION(animation));
273 + priv = animation->priv;
275 + for (i = 0; i < priv->tweens->len; i++) {
276 + tween = &g_array_index(priv->tweens, Tween, i);
277 + g_value_reset(&tween->begin);
278 + if (tween->is_child) {
279 + container = GTK_CONTAINER(gtk_widget_get_parent(priv->target));
280 + gtk_container_child_get_property(container, priv->target,
281 + tween->pspec->name,
282 + &tween->begin);
283 + } else {
284 + g_object_get_property(priv->target, tween->pspec->name,
285 + &tween->begin);
291 +/**
292 + * _gb_animation_unload_begin_values:
293 + * @animation: (in): A #GbAnimation.
295 + * Unloads the begin values for the animation. This might be particularly
296 + * useful once we support pointer types.
298 + * Returns: None.
299 + * Side effects: None.
300 + */
301 +static void
302 +_gb_animation_unload_begin_values (GbAnimation *animation)
304 + GbAnimationPrivate *priv;
305 + Tween *tween;
306 + gint i;
308 + g_return_if_fail(GB_IS_ANIMATION(animation));
310 + priv = animation->priv;
312 + for (i = 0; i < priv->tweens->len; i++) {
313 + tween = &g_array_index(priv->tweens, Tween, i);
314 + g_value_reset(&tween->begin);
319 +/**
320 + * _gb_animation_get_offset:
321 + * @animation: (in): A #GbAnimation.
323 + * Retrieves the position within the animation from 0.0 to 1.0. This
324 + * value is calculated using the msec of the beginning of the animation
325 + * and the current time.
327 + * Returns: The offset of the animation from 0.0 to 1.0.
328 + * Side effects: None.
329 + */
330 +static gdouble
331 +_gb_animation_get_offset (GbAnimation *animation)
333 + GbAnimationPrivate *priv;
334 + GTimeVal now;
335 + guint64 msec;
336 + gdouble offset;
338 + g_return_val_if_fail(GB_IS_ANIMATION(animation), 0.0);
340 + priv = animation->priv;
342 + g_get_current_time(&now);
343 + msec = TIMEVAL_TO_MSEC(now);
344 + offset = (gdouble)(msec - priv->begin_msec)
345 + / (gdouble)priv->duration_msec;
346 + return CLAMP(offset, 0.0, 1.0);
350 +/**
351 + * _gb_animation_update_property:
352 + * @animation: (in): A #GbAnimation.
353 + * @target: (in): A #GObject.
354 + * @tween: (in): a #Tween containing the property.
355 + * @value: (in) The new value for the property.
357 + * Updates the value of a property on an object using @value.
359 + * Returns: None.
360 + * Side effects: The property of @target is updated.
361 + */
362 +static void
363 +_gb_animation_update_property (GbAnimation *animation,
364 + gpointer target,
365 + Tween *tween,
366 + const GValue *value)
368 + g_object_set_property(target, tween->pspec->name, value);
372 +/**
373 + * _gb_animation_update_child_property:
374 + * @animation: (in): A #GbAnimation.
375 + * @target: (in): A #GObject.
376 + * @tween: (in): A #Tween containing the property.
377 + * @value: (in): The new value for the property.
379 + * Updates the value of the parent widget of the target to @value.
381 + * Returns: None.
382 + * Side effects: The property of @target<!-- -->'s parent widget is updated.
383 + */
384 +static void
385 +_gb_animation_update_child_property (GbAnimation *animation,
386 + gpointer target,
387 + Tween *tween,
388 + const GValue *value)
390 + GtkWidget *parent = gtk_widget_get_parent(GTK_WIDGET(target));
391 + gtk_container_child_set_property(GTK_CONTAINER(parent), target,
392 + tween->pspec->name, value);
396 +/**
397 + * _gb_animation_get_value_at_offset:
398 + * @animation: (in): A #GbAnimation.
399 + * @offset: (in): The offset in the animation from 0.0 to 1.0.
400 + * @tween: (in): A #Tween containing the property.
401 + * @value: (out): A #GValue in which to store the property.
403 + * Retrieves a value for a particular position within the animation.
405 + * Returns: None.
406 + * Side effects: None.
407 + */
408 +static void
409 +_gb_animation_get_value_at_offset (GbAnimation *animation,
410 + gdouble offset,
411 + Tween *tween,
412 + GValue *value)
414 + g_return_if_fail(GB_IS_ANIMATION(animation));
415 + g_return_if_fail(offset >= 0.0);
416 + g_return_if_fail(offset <= 1.0);
417 + g_return_if_fail(tween != NULL);
418 + g_return_if_fail(value != NULL);
419 + g_return_if_fail(value->g_type == tween->pspec->value_type);
421 + if (value->g_type < LAST_FUNDAMENTAL) {
422 + /*
423 + * If you hit the following assertion, you need to add a function
424 + * to create the new value at the given offset.
425 + */
426 + g_assert(gTweenFuncs[value->g_type]);
427 + gTweenFuncs[value->g_type](&tween->begin, &tween->end, value, offset);
428 + } else {
429 + /*
430 + * TODO: Support complex transitions.
431 + */
432 + if (offset >= 1.0) {
433 + g_value_copy(&tween->end, value);
439 +/**
440 + * _gb_animation_tick:
441 + * @animation: (in): A #GbAnimation.
443 + * Moves the object properties to the next position in the animation.
445 + * Returns: %TRUE if the animation has not completed; otherwise %FALSE.
446 + * Side effects: None.
447 + */
448 +static gboolean
449 +_gb_animation_tick (GbAnimation *animation)
451 + GbAnimationPrivate *priv;
452 + GdkWindow *window;
453 + gdouble offset;
454 + gdouble alpha;
455 + GValue value = { 0 };
456 + Tween *tween;
457 + gint i;
459 + g_return_val_if_fail(GB_IS_ANIMATION(animation), FALSE);
461 + priv = animation->priv;
463 + priv->frame_count++;
464 + offset = _gb_animation_get_offset(animation);
465 + alpha = gAlphaFuncs[priv->mode](offset);
467 + /*
468 + * Update property values.
469 + */
470 + for (i = 0; i < priv->tweens->len; i++) {
471 + tween = &g_array_index(priv->tweens, Tween, i);
472 + g_value_init(&value, tween->pspec->value_type);
473 + _gb_animation_get_value_at_offset(animation, alpha, tween, &value);
474 + if (!tween->is_child) {
475 + _gb_animation_update_property(animation, priv->target,
476 + tween, &value);
477 + } else {
478 + _gb_animation_update_child_property(animation, priv->target,
479 + tween, &value);
481 + g_value_unset(&value);
484 + /*
485 + * Notify anyone interested in the tick signal.
486 + */
487 + g_signal_emit(animation, gSignals[TICK], 0);
489 + /*
490 + * Flush any outstanding events to the graphics server (in the case of X).
491 + */
492 + if (GTK_IS_WIDGET(priv->target)) {
493 + if ((window = gtk_widget_get_window(GTK_WIDGET(priv->target)))) {
494 + gdk_window_flush(window);
498 + return (offset < 1.0);
502 +/**
503 + * _gb_animation_timeout:
504 + * @data: (in): A #GbAnimation.
506 + * Timeout from the main loop to move to the next step of the animation.
508 + * Returns: %TRUE until the animation has completed; otherwise %FALSE.
509 + * Side effects: None.
510 + */
511 +static gboolean
512 +_gb_animation_timeout (gpointer data)
514 + GbAnimation *animation = (GbAnimation *)data;
515 + gboolean ret;
517 + if (!(ret = _gb_animation_tick(animation))) {
518 + _gb_animation_stop(animation);
521 + return ret;
525 +/**
526 + * _gb_animation_start:
527 + * @animation: (in): A #GbAnimation.
529 + * Start the animation. When the animation stops, the internal reference will
530 + * be dropped and the animation may be finalized.
532 + * Returns: None.
533 + * Side effects: None.
534 + */
535 +void
536 +_gb_animation_start (GbAnimation *animation)
538 + GbAnimationPrivate *priv;
539 + GTimeVal now;
541 + g_return_if_fail(GB_IS_ANIMATION(animation));
542 + g_return_if_fail(!animation->priv->tween_handler);
544 + priv = animation->priv;
546 + g_get_current_time(&now);
547 + g_object_ref_sink(animation);
548 + _gb_animation_load_begin_values(animation);
550 + priv->begin_msec = TIMEVAL_TO_MSEC(now);
551 + priv->tween_handler = _gb_frame_source_add(priv->frame_rate,
552 + _gb_animation_timeout,
553 + animation);
557 +/**
558 + * _gb_animation_stop:
559 + * @animation: (in): A #GbAnimation.
561 + * Stops a running animation. The internal reference to the animation is
562 + * dropped and therefore may cause the object to finalize.
564 + * Returns: None.
565 + * Side effects: None.
566 + */
567 +void
568 +_gb_animation_stop (GbAnimation *animation)
570 + GbAnimationPrivate *priv;
572 + g_return_if_fail(GB_IS_ANIMATION(animation));
574 + priv = animation->priv;
576 + if (priv->tween_handler) {
577 + g_source_remove(priv->tween_handler);
578 + priv->tween_handler = 0;
579 + _gb_animation_unload_begin_values(animation);
580 + g_object_unref(animation);
585 +/**
586 + * _gb_animation_add_property:
587 + * @animation: (in): A #GbAnimation.
588 + * @pspec: (in): A #ParamSpec of @target or a #GtkWidget<!-- -->'s parent.
589 + * @value: (in): The new value for the property at the end of the animation.
591 + * Adds a new property to the set of properties to be animated during the
592 + * lifetime of the animation.
594 + * Returns: None.
595 + * Side effects: None.
596 + */
597 +void
598 +_gb_animation_add_property (GbAnimation *animation,
599 + GParamSpec *pspec,
600 + const GValue *value)
602 + GbAnimationPrivate *priv;
603 + Tween tween = { 0 };
604 + GType type;
606 + g_return_if_fail(GB_IS_ANIMATION(animation));
607 + g_return_if_fail(pspec != NULL);
608 + g_return_if_fail(value != NULL);
609 + g_return_if_fail(value->g_type);
610 + g_return_if_fail(animation->priv->target);
611 + g_return_if_fail(!animation->priv->tween_handler);
613 + priv = animation->priv;
615 + type = G_TYPE_FROM_INSTANCE(priv->target);
616 + tween.is_child = !g_type_is_a(type, pspec->owner_type);
617 + if (tween.is_child) {
618 + if (!GTK_IS_WIDGET(priv->target)) {
619 + g_critical("Cannot locate property %s in class %s",
620 + pspec->name, g_type_name(type));
621 + return;
625 + tween.pspec = g_param_spec_ref(pspec);
626 + g_value_init(&tween.begin, pspec->value_type);
627 + g_value_init(&tween.end, pspec->value_type);
628 + g_value_copy(value, &tween.end);
629 + g_array_append_val(priv->tweens, tween);
633 +/**
634 + * _gb_animation_dispose:
635 + * @object: (in): A #GbAnimation.
637 + * Releases any object references the animation contains.
639 + * Returns: None.
640 + * Side effects: None.
641 + */
642 +static void
643 +_gb_animation_dispose (GObject *object)
645 + GbAnimationPrivate *priv = GB_ANIMATION(object)->priv;
646 + gpointer instance;
648 + if ((instance = priv->target)) {
649 + priv->target = NULL;
650 + g_object_unref(instance);
653 + G_OBJECT_CLASS(_gb_animation_parent_class)->dispose(object);
657 +/**
658 + * _gb_animation_finalize:
659 + * @object: (in): A #GbAnimation.
661 + * Finalizes the object and releases any resources allocated.
663 + * Returns: None.
664 + * Side effects: None.
665 + */
666 +static void
667 +_gb_animation_finalize (GObject *object)
669 + GbAnimationPrivate *priv = GB_ANIMATION(object)->priv;
670 + Tween *tween;
671 + gint i;
673 + for (i = 0; i < priv->tweens->len; i++) {
674 + tween = &g_array_index(priv->tweens, Tween, i);
675 + g_value_unset(&tween->begin);
676 + g_value_unset(&tween->end);
677 + g_param_spec_unref(tween->pspec);
680 + g_array_unref(priv->tweens);
682 + if (gDebug) {
683 + g_print("Rendered %d frames in %d msec animation.\n",
684 + priv->frame_count, priv->duration_msec);
687 + G_OBJECT_CLASS(_gb_animation_parent_class)->finalize(object);
691 +/**
692 + * _gb_animation_set_property:
693 + * @object: (in): A #GObject.
694 + * @prop_id: (in): The property identifier.
695 + * @value: (in): The given property.
696 + * @pspec: (in): A #ParamSpec.
698 + * Set a given #GObject property.
699 + */
700 +static void
701 +_gb_animation_set_property (GObject *object,
702 + guint prop_id,
703 + const GValue *value,
704 + GParamSpec *pspec)
706 + GbAnimation *animation = GB_ANIMATION(object);
708 + switch (prop_id) {
709 + case PROP_DURATION:
710 + animation->priv->duration_msec = g_value_get_uint(value);
711 + break;
712 + case PROP_FRAME_RATE:
713 + animation->priv->frame_rate = g_value_get_uint(value);
714 + break;
715 + case PROP_MODE:
716 + animation->priv->mode = g_value_get_enum(value);
717 + break;
718 + case PROP_TARGET:
719 + animation->priv->target = g_value_dup_object(value);
720 + break;
721 + default:
722 + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
727 +/**
728 + * _gb_animation_class_init:
729 + * @klass: (in): A #GbAnimationClass.
731 + * Initializes the GObjectClass.
733 + * Returns: None.
734 + * Side effects: Properties, signals, and vtables are initialized.
735 + */
736 +static void
737 +_gb_animation_class_init (GbAnimationClass *klass)
739 + GObjectClass *object_class;
741 + gDebug = !!g_getenv("GB_ANIMATION_DEBUG");
743 + object_class = G_OBJECT_CLASS(klass);
744 + object_class->dispose = _gb_animation_dispose;
745 + object_class->finalize = _gb_animation_finalize;
746 + object_class->set_property = _gb_animation_set_property;
747 + g_type_class_add_private(object_class, sizeof(GbAnimationPrivate));
749 + /**
750 + * GbAnimation:duration:
752 + * The "duration" property is the total number of milliseconds that the
753 + * animation should run before being completed.
754 + */
755 + gParamSpecs[PROP_DURATION] =
756 + g_param_spec_uint("duration",
757 + _("Duration"),
758 + _("The duration of the animation"),
759 + 0,
760 + G_MAXUINT,
761 + 250,
762 + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
763 + g_object_class_install_property(object_class, PROP_DURATION,
764 + gParamSpecs[PROP_DURATION]);
766 + /**
767 + * GbAnimation:mode:
769 + * The "mode" property is the Alpha function that should be used to
770 + * determine the offset within the animation based on the current
771 + * offset in the animations duration.
772 + */
773 + gParamSpecs[PROP_MODE] =
774 + g_param_spec_enum("mode",
775 + _("Mode"),
776 + _("The animation mode"),
777 + GB_TYPE_ANIMATION_MODE,
778 + GB_ANIMATION_LINEAR,
779 + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
780 + g_object_class_install_property(object_class, PROP_MODE,
781 + gParamSpecs[PROP_MODE]);
783 + /**
784 + * GbAnimation:target:
786 + * The "target" property is the #GObject that should have it's properties
787 + * animated.
788 + */
789 + gParamSpecs[PROP_TARGET] =
790 + g_param_spec_object("target",
791 + _("Target"),
792 + _("The target of the animation"),
793 + G_TYPE_OBJECT,
794 + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
795 + g_object_class_install_property(object_class, PROP_TARGET,
796 + gParamSpecs[PROP_TARGET]);
798 + /**
799 + * GbAnimation:frame-rate:
801 + * The "frame-rate" is the number of frames that the animation should
802 + * try to perform per-second. The default is 60 frames-per-second.
803 + */
804 + gParamSpecs[PROP_FRAME_RATE] =
805 + g_param_spec_uint("frame-rate",
806 + _("Frame Rate"),
807 + _("The number of frames per second."),
808 + 1,
809 + G_MAXUINT,
810 + 60,
811 + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
812 + g_object_class_install_property(object_class, PROP_FRAME_RATE,
813 + gParamSpecs[PROP_FRAME_RATE]);
815 + /**
816 + * GbAnimation::tick:
818 + * The "tick" signal is emitted on each frame in the animation.
819 + */
820 + gSignals[TICK] = g_signal_new("tick",
821 + GB_TYPE_ANIMATION,
822 + G_SIGNAL_RUN_FIRST,
823 + 0,
824 + NULL,
825 + NULL,
826 + g_cclosure_marshal_VOID__VOID,
827 + G_TYPE_NONE,
828 + 0);
830 +#define SET_ALPHA(_T, _t) \
831 + gAlphaFuncs[GB_ANIMATION_##_T] = _gb_animation_alpha_##_t
833 + SET_ALPHA(LINEAR, linear);
834 + SET_ALPHA(EASE_IN_QUAD, ease_in_quad);
835 + SET_ALPHA(EASE_OUT_QUAD, ease_out_quad);
836 + SET_ALPHA(EASE_IN_OUT_QUAD, ease_in_out_quad);
837 + SET_ALPHA(EASE_IN_CUBIC, ease_in_cubic);
839 +#define SET_TWEEN(_T, _t) \
840 + G_STMT_START { \
841 + guint idx = G_TYPE_##_T; \
842 + gTweenFuncs[idx] = tween_##_t; \
843 + } G_STMT_END
845 + SET_TWEEN(INT, int);
846 + SET_TWEEN(UINT, uint);
847 + SET_TWEEN(LONG, long);
848 + SET_TWEEN(ULONG, ulong);
849 + SET_TWEEN(FLOAT, float);
850 + SET_TWEEN(DOUBLE, double);
854 +/**
855 + * _gb_animation_init:
856 + * @animation: (in): A #GbAnimation.
858 + * Initializes the #GbAnimation instance.
860 + * Returns: None.
861 + * Side effects: Everything.
862 + */
863 +static void
864 +_gb_animation_init (GbAnimation *animation)
866 + GbAnimationPrivate *priv;
868 + priv = G_TYPE_INSTANCE_GET_PRIVATE(animation, GB_TYPE_ANIMATION,
869 + GbAnimationPrivate);
870 + animation->priv = priv;
872 + priv->duration_msec = 250;
873 + priv->frame_rate = 60;
874 + priv->mode = GB_ANIMATION_LINEAR;
875 + priv->tweens = g_array_new(FALSE, FALSE, sizeof(Tween));
879 +/**
880 + * _gb_animation_mode_get_type:
882 + * Retrieves the GType for #GbAnimationMode.
884 + * Returns: A GType.
885 + * Side effects: GType registered on first call.
886 + */
887 +GType
888 +_gb_animation_mode_get_type (void)
890 + static GType type_id = 0;
891 + static const GEnumValue values[] = {
892 + { GB_ANIMATION_LINEAR, "GB_ANIMATION_LINEAR", "LINEAR" },
893 + { GB_ANIMATION_EASE_IN_QUAD, "GB_ANIMATION_EASE_IN_QUAD", "EASE_IN_QUAD" },
894 + { GB_ANIMATION_EASE_IN_OUT_QUAD, "GB_ANIMATION_EASE_IN_OUT_QUAD", "EASE_IN_OUT_QUAD" },
895 + { GB_ANIMATION_EASE_OUT_QUAD, "GB_ANIMATION_EASE_OUT_QUAD", "EASE_OUT_QUAD" },
896 + { GB_ANIMATION_EASE_IN_CUBIC, "GB_ANIMATION_EASE_IN_CUBIC", "EASE_IN_CUBIC" },
897 + { 0 }
898 + };
900 + if (G_UNLIKELY(!type_id)) {
901 + type_id = g_enum_register_static("GbAnimationMode", values);
903 + return type_id;
906 +/**
907 + * _gb_object_animatev:
908 + * Returns: (transfer none): A #GbAnimation.
909 + */
910 +GbAnimation*
911 +_gb_object_animatev (gpointer object,
912 + GbAnimationMode mode,
913 + guint duration_msec,
914 + guint frame_rate,
915 + const gchar *first_property,
916 + va_list args)
918 + GbAnimation *animation;
919 + GObjectClass *klass;
920 + GObjectClass *pklass;
921 + const gchar *name;
922 + GParamSpec *pspec;
923 + GtkWidget *parent;
924 + GValue value = { 0 };
925 + gchar *error = NULL;
926 + GType type;
927 + GType ptype;
929 + g_return_val_if_fail(first_property != NULL, NULL);
930 + g_return_val_if_fail(mode < GB_ANIMATION_LAST, NULL);
932 + name = first_property;
933 + type = G_TYPE_FROM_INSTANCE(object);
934 + klass = G_OBJECT_GET_CLASS(object);
935 + animation = g_object_new(GB_TYPE_ANIMATION,
936 + "duration", duration_msec,
937 + "frame-rate", frame_rate ? frame_rate : 60,
938 + "mode", mode,
939 + "target", object,
940 + NULL);
942 + do {
943 + /*
944 + * First check for the property on the object. If that does not exist
945 + * then check if the object has a parent and look at its child
946 + * properties (if its a GtkWidget).
947 + */
948 + if (!(pspec = g_object_class_find_property(klass, name))) {
949 + if (!g_type_is_a(type, GTK_TYPE_WIDGET)) {
950 + g_critical("Failed to find property %s in %s",
951 + name, g_type_name(type));
952 + goto failure;
954 + if (!(parent = gtk_widget_get_parent(object))) {
955 + g_critical("Failed to find property %s in %s",
956 + name, g_type_name(type));
957 + goto failure;
959 + pklass = G_OBJECT_GET_CLASS(parent);
960 + ptype = G_TYPE_FROM_INSTANCE(parent);
961 + if (!(pspec = gtk_container_class_find_child_property(pklass, name))) {
962 + g_critical("Failed to find property %s in %s or parent %s",
963 + name, g_type_name(type), g_type_name(ptype));
964 + goto failure;
968 + g_value_init(&value, pspec->value_type);
969 + G_VALUE_COLLECT(&value, args, 0, &error);
970 + if (error != NULL) {
971 + g_critical("Failed to retrieve va_list value: %s", error);
972 + g_free(error);
973 + goto failure;
976 + _gb_animation_add_property(animation, pspec, &value);
977 + g_value_unset(&value);
978 + } while ((name = va_arg(args, const gchar *)));
980 + _gb_animation_start(animation);
982 + return animation;
984 +failure:
985 + g_object_ref_sink(animation);
986 + g_object_unref(animation);
987 + return NULL;
990 +/**
991 + * _gb_object_animate:
992 + * @object: (in): A #GObject.
993 + * @mode: (in): The animation mode.
994 + * @duration_msec: (in): The duration in milliseconds.
995 + * @first_property: (in): The first property to animate.
997 + * Animates the properties of @object. The can be set in a similar
998 + * manner to g_object_set(). They will be animated from their current
999 + * value to the target value over the time period.
1001 + * Return value: (transfer none): A #GbAnimation.
1002 + * Side effects: None.
1003 + */
1004 +GbAnimation*
1005 +_gb_object_animate (gpointer object,
1006 + GbAnimationMode mode,
1007 + guint duration_msec,
1008 + const gchar *first_property,
1009 + ...)
1011 + GbAnimation *animation;
1012 + va_list args;
1014 + va_start(args, first_property);
1015 + animation = _gb_object_animatev(object, mode, duration_msec, 0,
1016 + first_property, args);
1017 + va_end(args);
1018 + return animation;
1021 +/**
1022 + * _gb_object_animate_full:
1024 + * Return value: (transfer none): A #GbAnimation.
1025 + */
1026 +GbAnimation*
1027 +_gb_object_animate_full (gpointer object,
1028 + GbAnimationMode mode,
1029 + guint duration_msec,
1030 + guint frame_rate,
1031 + GDestroyNotify notify,
1032 + gpointer notify_data,
1033 + const gchar *first_property,
1034 + ...)
1036 + GbAnimation *animation;
1037 + va_list args;
1039 + va_start(args, first_property);
1040 + animation = _gb_object_animatev(object, mode, duration_msec,
1041 + frame_rate, first_property, args);
1042 + va_end(args);
1043 + g_object_weak_ref(G_OBJECT(animation), (GWeakNotify)notify, notify_data);
1044 + return animation;
1046 diff --git a/gtk/gb-animation.h b/gtk/gb-animation.h
1047 new file mode 100644
1048 index 0000000..bf9268d
1049 --- /dev/null
1050 +++ b/gtk/gb-animation.h
1051 @@ -0,0 +1,87 @@
1052 +/* gb-animation.h
1054 + * Copyright (C) 2010 Christian Hergert <chris@dronelabs.com>
1056 + * This program is free software: you can redistribute it and/or modify
1057 + * it under the terms of the GNU General Public License as published by
1058 + * the Free Software Foundation, either version 3 of the License, or
1059 + * (at your option) any later version.
1061 + * This program is distributed in the hope that it will be useful,
1062 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1063 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1064 + * GNU General Public License for more details.
1066 + * You should have received a copy of the GNU General Public License
1067 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
1068 + */
1070 +#ifndef GB_ANIMATION_H
1071 +#define GB_ANIMATION_H
1073 +#include <glib-object.h>
1075 +G_BEGIN_DECLS
1077 +#define GB_TYPE_ANIMATION (_gb_animation_get_type())
1078 +#define GB_TYPE_ANIMATION_MODE (_gb_animation_mode_get_type())
1079 +#define GB_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_ANIMATION, GbAnimation))
1080 +#define GB_ANIMATION_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_ANIMATION, GbAnimation const))
1081 +#define GB_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GB_TYPE_ANIMATION, GbAnimationClass))
1082 +#define GB_IS_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GB_TYPE_ANIMATION))
1083 +#define GB_IS_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GB_TYPE_ANIMATION))
1084 +#define GB_ANIMATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GB_TYPE_ANIMATION, GbAnimationClass))
1086 +typedef struct _GbAnimation GbAnimation;
1087 +typedef struct _GbAnimationClass GbAnimationClass;
1088 +typedef struct _GbAnimationPrivate GbAnimationPrivate;
1089 +typedef enum _GbAnimationMode GbAnimationMode;
1091 +enum _GbAnimationMode
1093 + GB_ANIMATION_LINEAR,
1094 + GB_ANIMATION_EASE_IN_QUAD,
1095 + GB_ANIMATION_EASE_OUT_QUAD,
1096 + GB_ANIMATION_EASE_IN_OUT_QUAD,
1097 + GB_ANIMATION_EASE_IN_CUBIC,
1099 + GB_ANIMATION_LAST
1102 +struct _GbAnimation
1104 + GInitiallyUnowned parent;
1106 + /*< private >*/
1107 + GbAnimationPrivate *priv;
1110 +struct _GbAnimationClass
1112 + GInitiallyUnownedClass parent_class;
1115 +GType _gb_animation_get_type (void) G_GNUC_CONST;
1116 +GType _gb_animation_mode_get_type (void) G_GNUC_CONST;
1117 +void _gb_animation_start (GbAnimation *animation);
1118 +void _gb_animation_stop (GbAnimation *animation);
1119 +void _gb_animation_add_property (GbAnimation *animation,
1120 + GParamSpec *pspec,
1121 + const GValue *value);
1122 +GbAnimation* _gb_object_animate (gpointer object,
1123 + GbAnimationMode mode,
1124 + guint duration_msec,
1125 + const gchar *first_property,
1126 + ...) G_GNUC_NULL_TERMINATED;
1127 +GbAnimation* _gb_object_animate_full (gpointer object,
1128 + GbAnimationMode mode,
1129 + guint duration_msec,
1130 + guint frame_rate,
1131 + GDestroyNotify notify,
1132 + gpointer notify_data,
1133 + const gchar *first_property,
1134 + ...) G_GNUC_NULL_TERMINATED;
1136 +G_END_DECLS
1138 +#endif /* GB_ANIMATION_H */
1139 diff --git a/gtk/gb-frame-source.c b/gtk/gb-frame-source.c
1140 new file mode 100644
1141 index 0000000..be04c1b
1142 --- /dev/null
1143 +++ b/gtk/gb-frame-source.c
1144 @@ -0,0 +1,134 @@
1146 + * Based upon code from Clutter:
1148 + * Authored By Neil Roberts <neil@linux.intel.com>
1150 + * Copyright (C) 2009 Intel Corporation.
1151 + * Copyright (C) 2012 Christian Hergert.
1153 + * This library is free software; you can redistribute it and/or
1154 + * modify it under the terms of the GNU Lesser General Public
1155 + * License as published by the Free Software Foundation; either
1156 + * version 2 of the License, or (at your option) any later version.
1158 + * This library is distributed in the hope that it will be useful,
1159 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1160 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1161 + * Lesser General Public License for more details.
1163 + * You should have received a copy of the GNU Lesser General Public
1164 + * License along with this library. If not, see <http://www.gnu.org/licenses/>.
1165 + */
1167 +#include "gb-frame-source.h"
1169 +typedef struct
1171 + GSource parent;
1172 + guint fps;
1173 + guint frame_count;
1174 + gint64 start_time;
1175 +} GbFrameSource;
1177 +static gboolean
1178 +gb_frame_source_prepare (GSource *source,
1179 + gint *timeout_)
1181 + GbFrameSource *fsource = (GbFrameSource *)source;
1182 + gint64 current_time;
1183 + guint elapsed_time;
1184 + guint new_frame_num;
1185 + guint frame_time;
1187 + current_time = g_source_get_time(source) / 1000;
1188 + elapsed_time = current_time - fsource->start_time;
1189 + new_frame_num = elapsed_time * fsource->fps / 1000;
1191 + /* If time has gone backwards or the time since the last frame is
1192 + * greater than the two frames worth then reset the time and do a
1193 + * frame now */
1194 + if (new_frame_num < fsource->frame_count ||
1195 + new_frame_num - fsource->frame_count > 2) {
1196 + /* Get the frame time rounded up to the nearest ms */
1197 + frame_time = (1000 + fsource->fps - 1) / fsource->fps;
1199 + /* Reset the start time */
1200 + fsource->start_time = current_time;
1202 + /* Move the start time as if one whole frame has elapsed */
1203 + fsource->start_time -= frame_time;
1204 + fsource->frame_count = 0;
1205 + *timeout_ = 0;
1206 + return TRUE;
1207 + } else if (new_frame_num > fsource->frame_count) {
1208 + *timeout_ = 0;
1209 + return TRUE;
1210 + } else {
1211 + *timeout_ = (fsource->frame_count + 1) * 1000 / fsource->fps - elapsed_time;
1212 + return FALSE;
1216 +static gboolean
1217 +gb_frame_source_check (GSource *source)
1219 + gint timeout_;
1220 + return gb_frame_source_prepare(source, &timeout_);
1223 +static gboolean
1224 +gb_frame_source_dispatch (GSource *source,
1225 + GSourceFunc source_func,
1226 + gpointer user_data)
1228 + GbFrameSource *fsource = (GbFrameSource *)source;
1229 + gboolean ret;
1231 + if ((ret = source_func(user_data)))
1232 + fsource->frame_count++;
1233 + return ret;
1236 +static GSourceFuncs source_funcs = {
1237 + gb_frame_source_prepare,
1238 + gb_frame_source_check,
1239 + gb_frame_source_dispatch,
1242 +/**
1243 + * gb_frame_source_add:
1244 + * @frames_per_sec: (in): Target frames per second.
1245 + * @callback: (in) (scope notified): A #GSourceFunc to execute.
1246 + * @user_data: (in): User data for @callback.
1248 + * Creates a new frame source that will execute when the timeout interval
1249 + * for the source has elapsed. The timing will try to synchronize based
1250 + * on the end time of the animation.
1252 + * Returns: A source id that can be removed with g_source_remove().
1253 + */
1254 +guint
1255 +_gb_frame_source_add (guint frames_per_sec,
1256 + GSourceFunc callback,
1257 + gpointer user_data)
1259 + GbFrameSource *fsource;
1260 + GSource *source;
1261 + guint ret;
1263 + g_return_val_if_fail(frames_per_sec > 0, 0);
1264 + g_return_val_if_fail(frames_per_sec < 120, 0);
1266 + source = g_source_new(&source_funcs, sizeof(GbFrameSource));
1267 + fsource = (GbFrameSource *)source;
1268 + fsource->fps = frames_per_sec;
1269 + fsource->frame_count = 0;
1270 + fsource->start_time = g_get_monotonic_time() / 1000;
1271 + g_source_set_callback(source, callback, user_data, NULL);
1272 + g_source_set_name(source, "GbFrameSource");
1274 + ret = g_source_attach(source, NULL);
1275 + g_source_unref(source);
1277 + return ret;
1279 diff --git a/gtk/gb-frame-source.h b/gtk/gb-frame-source.h
1280 new file mode 100644
1281 index 0000000..502d86e
1282 --- /dev/null
1283 +++ b/gtk/gb-frame-source.h
1284 @@ -0,0 +1,32 @@
1285 +/* gb-frame-source.h
1287 + * Copyright (C) 2012 Christian Hergert <chris@dronelabs.com>
1289 + * This program is free software: you can redistribute it and/or modify
1290 + * it under the terms of the GNU General Public License as published by
1291 + * the Free Software Foundation, either version 3 of the License, or
1292 + * (at your option) any later version.
1294 + * This program is distributed in the hope that it will be useful,
1295 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1296 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1297 + * GNU General Public License for more details.
1299 + * You should have received a copy of the GNU General Public License
1300 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
1301 + */
1303 +#ifndef GB_FRAME_SOURCE_H
1304 +#define GB_FRAME_SOURCE_H
1306 +#include <glib.h>
1308 +G_BEGIN_DECLS
1310 +guint _gb_frame_source_add (guint frames_per_sec,
1311 + GSourceFunc callback,
1312 + gpointer user_data);
1314 +G_END_DECLS
1316 +#endif /* GB_FRAME_SOURCE_H */
1317 diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
1318 index 821981f..77d485f 100644
1319 --- a/gtk/gtkscrolledwindow.c
1320 +++ b/gtk/gtkscrolledwindow.c
1321 @@ -32,6 +32,7 @@
1322 #include "gtkscrolledwindow.h"
1323 #include "gtkwindow.h"
1324 #include "gtkprivate.h"
1325 +#include "gb-animation.h"
1326 #include "gtkintl.h"
1327 #include "gtkmain.h"
1328 #include "gtkdnd.h"
1329 @@ -111,6 +112,17 @@ typedef struct {
1331 gdouble unclamped_hadj_value;
1332 gdouble unclamped_vadj_value;
1334 + GtkAdjustment *opacity;
1335 + GbAnimation *opacity_anim;
1337 + gint sb_min_height;
1338 + gint sb_padding;
1339 + gint sb_radius;
1340 + gint sb_width;
1341 + gboolean sb_fading_in;
1342 + gint sb_fade_out_delay;
1343 + guint sb_fade_out_id;
1344 } GtkScrolledWindowPrivate;
1346 #define GTK_SCROLLED_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCROLLED_WINDOW, GtkScrolledWindowPrivate))
1347 @@ -206,10 +218,21 @@ static gboolean _gtk_scrolled_window_set_adjustment_value (GtkScrolledWindo
1348 gboolean allow_overshooting,
1349 gboolean snap_to_border);
1351 +static void gtk_scrolled_window_cancel_animation (GtkScrolledWindow *scrolled_window);
1352 +static void gtk_scrolled_window_start_fade_in_animation (GtkScrolledWindow *scrolled_window);
1353 +static void gtk_scrolled_window_start_fade_out_animation (GtkScrolledWindow *scrolled_window);
1354 +static gboolean gtk_scrolled_window_child_expose (GtkWidget *widget,
1355 + GdkEventExpose *eevent,
1356 + GtkScrolledWindow *scrolled_window);
1357 +static void gtk_scrolled_window_expose_scrollbars (GtkAdjustment *adj,
1358 + GtkScrolledWindow *scrolled_window);
1360 static guint signals[LAST_SIGNAL] = {0};
1362 G_DEFINE_TYPE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
1364 +static gboolean overlay_scrollbars = TRUE;
1366 static void
1367 add_scroll_binding (GtkBindingSet *binding_set,
1368 guint keyval,
1369 @@ -444,6 +467,8 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
1370 static void
1371 gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
1373 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1375 gtk_widget_set_has_window (GTK_WIDGET (scrolled_window), FALSE);
1376 gtk_widget_set_can_focus (GTK_WIDGET (scrolled_window), TRUE);
1378 @@ -462,6 +487,24 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
1379 gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE);
1380 gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE);
1383 + if (overlay_scrollbars)
1385 + priv->opacity = g_object_new (GTK_TYPE_ADJUSTMENT,
1386 + "lower", 0.0,
1387 + "upper", 0.5,
1388 + "value", 0.0,
1389 + NULL);
1390 + priv->sb_min_height = 20;
1391 + priv->sb_padding = 2;
1392 + priv->sb_radius = 3;
1393 + priv->sb_width = 6;
1394 + priv->sb_fade_out_delay = 1000;
1396 + g_signal_connect (priv->opacity, "value-changed",
1397 + G_CALLBACK (gtk_scrolled_window_expose_scrollbars),
1398 + scrolled_window);
1403 @@ -541,6 +584,17 @@ gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window,
1404 g_signal_handlers_disconnect_by_func (old_adjustment,
1405 gtk_scrolled_window_adjustment_changed,
1406 scrolled_window);
1408 + if (overlay_scrollbars)
1410 + g_signal_handlers_disconnect_by_func (old_adjustment,
1411 + gtk_scrolled_window_adjustment_value_changed,
1412 + scrolled_window);
1413 + g_signal_handlers_disconnect_by_func (old_adjustment,
1414 + gtk_scrolled_window_expose_scrollbars,
1415 + scrolled_window);
1418 gtk_range_set_adjustment (GTK_RANGE (scrolled_window->hscrollbar),
1419 hadjustment);
1421 @@ -556,10 +610,24 @@ gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window,
1422 gtk_scrolled_window_adjustment_changed (hadjustment, scrolled_window);
1423 gtk_scrolled_window_adjustment_value_changed (hadjustment, scrolled_window);
1425 + if (overlay_scrollbars)
1427 + g_signal_connect (hadjustment, "value-changed",
1428 + G_CALLBACK (gtk_scrolled_window_adjustment_value_changed),
1429 + scrolled_window);
1431 + g_signal_connect (hadjustment, "changed",
1432 + G_CALLBACK (gtk_scrolled_window_expose_scrollbars),
1433 + scrolled_window);
1434 + g_signal_connect (hadjustment, "value-changed",
1435 + G_CALLBACK (gtk_scrolled_window_expose_scrollbars),
1436 + scrolled_window);
1439 if (bin->child)
1440 gtk_widget_set_scroll_adjustments (bin->child,
1441 - gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1442 - gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)));
1443 + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1444 + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)));
1446 g_object_notify (G_OBJECT (scrolled_window), "hadjustment");
1448 @@ -607,6 +675,17 @@ gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window,
1449 g_signal_handlers_disconnect_by_func (old_adjustment,
1450 gtk_scrolled_window_adjustment_changed,
1451 scrolled_window);
1453 + if (overlay_scrollbars)
1455 + g_signal_handlers_disconnect_by_func (old_adjustment,
1456 + gtk_scrolled_window_adjustment_value_changed,
1457 + scrolled_window);
1458 + g_signal_handlers_disconnect_by_func (old_adjustment,
1459 + gtk_scrolled_window_expose_scrollbars,
1460 + scrolled_window);
1463 gtk_range_set_adjustment (GTK_RANGE (scrolled_window->vscrollbar),
1464 vadjustment);
1466 @@ -622,10 +701,25 @@ gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window,
1467 gtk_scrolled_window_adjustment_changed (vadjustment, scrolled_window);
1468 gtk_scrolled_window_adjustment_value_changed (vadjustment, scrolled_window);
1470 + if (overlay_scrollbars)
1472 + g_signal_connect (vadjustment,
1473 + "value-changed",
1474 + G_CALLBACK (gtk_scrolled_window_adjustment_value_changed),
1475 + scrolled_window);
1477 + g_signal_connect (vadjustment, "changed",
1478 + G_CALLBACK (gtk_scrolled_window_expose_scrollbars),
1479 + scrolled_window);
1480 + g_signal_connect (vadjustment, "value-changed",
1481 + G_CALLBACK (gtk_scrolled_window_expose_scrollbars),
1482 + scrolled_window);
1485 if (bin->child)
1486 gtk_widget_set_scroll_adjustments (bin->child,
1487 - gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1488 - gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)));
1489 + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1490 + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)));
1492 g_object_notify (G_OBJECT (scrolled_window), "vadjustment");
1494 @@ -1073,11 +1167,24 @@ gtk_scrolled_window_destroy (GtkObject *object)
1495 GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (object);
1496 GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1498 + gtk_scrolled_window_cancel_animation (scrolled_window);
1500 if (scrolled_window->hscrollbar)
1502 g_signal_handlers_disconnect_by_func (gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1503 gtk_scrolled_window_adjustment_changed,
1504 scrolled_window);
1506 + if (overlay_scrollbars)
1508 + g_signal_handlers_disconnect_by_func (gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1509 + gtk_scrolled_window_adjustment_value_changed,
1510 + scrolled_window);
1511 + g_signal_handlers_disconnect_by_func (gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1512 + gtk_scrolled_window_expose_scrollbars,
1513 + scrolled_window);
1516 gtk_widget_unparent (scrolled_window->hscrollbar);
1517 gtk_widget_destroy (scrolled_window->hscrollbar);
1518 g_object_unref (scrolled_window->hscrollbar);
1519 @@ -1088,6 +1195,17 @@ gtk_scrolled_window_destroy (GtkObject *object)
1520 g_signal_handlers_disconnect_by_func (gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)),
1521 gtk_scrolled_window_adjustment_changed,
1522 scrolled_window);
1524 + if (overlay_scrollbars)
1526 + g_signal_handlers_disconnect_by_func (gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)),
1527 + gtk_scrolled_window_adjustment_value_changed,
1528 + scrolled_window);
1529 + g_signal_handlers_disconnect_by_func (gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)),
1530 + gtk_scrolled_window_expose_scrollbars,
1531 + scrolled_window);
1534 gtk_widget_unparent (scrolled_window->vscrollbar);
1535 gtk_widget_destroy (scrolled_window->vscrollbar);
1536 g_object_unref (scrolled_window->vscrollbar);
1537 @@ -1515,7 +1633,7 @@ gtk_scrolled_window_size_request (GtkWidget *widget,
1539 if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER)
1540 requisition->width += child_requisition.width;
1541 - else
1542 + else if (! overlay_scrollbars)
1544 GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE);
1546 @@ -1530,7 +1648,7 @@ gtk_scrolled_window_size_request (GtkWidget *widget,
1548 if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER)
1549 requisition->height += child_requisition.height;
1550 - else
1551 + else if (! overlay_scrollbars)
1553 GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE);
1555 @@ -1544,20 +1662,23 @@ gtk_scrolled_window_size_request (GtkWidget *widget,
1559 - if (scrolled_window->hscrollbar_policy == GTK_POLICY_AUTOMATIC ||
1560 - scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
1561 + if (! overlay_scrollbars)
1563 - requisition->width = MAX (requisition->width, hscrollbar_requisition.width);
1564 - if (!extra_height || scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
1565 - extra_height = scrollbar_spacing + hscrollbar_requisition.height;
1567 + if (scrolled_window->hscrollbar_policy == GTK_POLICY_AUTOMATIC ||
1568 + scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
1570 + requisition->width = MAX (requisition->width, hscrollbar_requisition.width);
1571 + if (!extra_height || scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
1572 + extra_height = scrollbar_spacing + hscrollbar_requisition.height;
1575 - if (scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC ||
1576 - scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
1578 - requisition->height = MAX (requisition->height, vscrollbar_requisition.height);
1579 - if (!extra_height || scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
1580 - extra_width = scrollbar_spacing + vscrollbar_requisition.width;
1581 + if (scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC ||
1582 + scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
1584 + requisition->height = MAX (requisition->height, vscrollbar_requisition.height);
1585 + if (!extra_height || scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
1586 + extra_width = scrollbar_spacing + vscrollbar_requisition.width;
1590 requisition->width += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_width);
1591 @@ -1598,6 +1719,9 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget,
1592 allocation->width = MAX (1, (gint)widget->allocation.width - allocation->x * 2);
1593 allocation->height = MAX (1, (gint)widget->allocation.height - allocation->y * 2);
1595 + if (overlay_scrollbars)
1596 + return;
1598 if (scrolled_window->vscrollbar_visible)
1600 GtkRequisition vscrollbar_requisition;
1601 @@ -1754,6 +1878,9 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
1602 scrolled_window = GTK_SCROLLED_WINDOW (widget);
1603 bin = GTK_BIN (scrolled_window);
1605 + if (overlay_scrollbars)
1606 + gtk_scrolled_window_expose_scrollbars (NULL, scrolled_window);
1608 scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window);
1609 gtk_widget_style_get (widget, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL);
1611 @@ -1812,7 +1939,7 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
1612 gtk_scrolled_window_relative_allocation (widget, &relative_allocation);
1615 - if (scrolled_window->hscrollbar_visible)
1616 + if (!overlay_scrollbars && scrolled_window->hscrollbar_visible)
1618 GtkRequisition hscrollbar_requisition;
1619 gtk_widget_get_child_requisition (scrolled_window->hscrollbar,
1620 @@ -1860,7 +1987,7 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget,
1621 else if (gtk_widget_get_visible (scrolled_window->hscrollbar))
1622 gtk_widget_hide (scrolled_window->hscrollbar);
1624 - if (scrolled_window->vscrollbar_visible)
1625 + if (!overlay_scrollbars && scrolled_window->vscrollbar_visible)
1627 GtkRequisition vscrollbar_requisition;
1628 if (!gtk_widget_get_visible (scrolled_window->vscrollbar))
1629 @@ -1930,7 +2057,7 @@ gtk_scrolled_window_scroll_event (GtkWidget *widget,
1630 if (gdk_event_get_scroll_deltas ((GdkEvent *) event, &delta_x, &delta_y))
1632 if (delta_x != 0.0 && scrolled_window->hscrollbar &&
1633 - gtk_widget_get_visible (scrolled_window->hscrollbar))
1634 + (overlay_scrollbars || gtk_widget_get_visible (scrolled_window->hscrollbar)))
1636 GtkAdjustment *adj;
1637 gdouble new_value;
1638 @@ -1948,7 +2075,7 @@ gtk_scrolled_window_scroll_event (GtkWidget *widget,
1641 if (delta_y != 0.0 && scrolled_window->vscrollbar &&
1642 - gtk_widget_get_visible (scrolled_window->vscrollbar))
1643 + (overlay_scrollbars || gtk_widget_get_visible (scrolled_window->vscrollbar)))
1645 GtkAdjustment *adj;
1646 gdouble new_value;
1647 @@ -1974,7 +2101,7 @@ gtk_scrolled_window_scroll_event (GtkWidget *widget,
1648 else
1649 range = scrolled_window->hscrollbar;
1651 - if (range && gtk_widget_get_visible (range))
1652 + if (range && (overlay_scrollbars || gtk_widget_get_visible (range)))
1654 GtkAdjustment *adj = GTK_RANGE (range)->adjustment;
1655 gdouble delta, new_value;
1656 @@ -2614,6 +2741,9 @@ gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
1657 gtk_widget_queue_resize (GTK_WIDGET (scrolled_win));
1661 + if (overlay_scrollbars)
1662 + gtk_scrolled_window_start_fade_in_animation (scrolled_win);
1665 static void
1666 @@ -2634,6 +2764,9 @@ gtk_scrolled_window_adjustment_value_changed (GtkAdjustment *adjustment,
1667 else if (scrolled_window->hscrollbar &&
1668 adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)))
1669 priv->unclamped_hadj_value = gtk_adjustment_get_value (adjustment);
1671 + if (overlay_scrollbars)
1672 + gtk_scrolled_window_start_fade_in_animation (scrolled_window);
1675 static void
1676 @@ -2658,10 +2791,17 @@ gtk_scrolled_window_add (GtkContainer *container,
1678 /* this is a temporary message */
1679 if (!gtk_widget_set_scroll_adjustments (child,
1680 - gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1681 - gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar))))
1682 + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
1683 + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar))))
1684 g_warning ("gtk_scrolled_window_add(): cannot add non scrollable widget "
1685 "use gtk_scrolled_window_add_with_viewport() instead");
1687 + if (overlay_scrollbars)
1689 + g_signal_connect_after (child, "expose-event",
1690 + G_CALLBACK (gtk_scrolled_window_child_expose),
1691 + container);
1695 static void
1696 @@ -2671,7 +2811,14 @@ gtk_scrolled_window_remove (GtkContainer *container,
1697 g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container));
1698 g_return_if_fail (child != NULL);
1699 g_return_if_fail (GTK_BIN (container)->child == child);
1702 + if (overlay_scrollbars)
1704 + g_signal_handlers_disconnect_by_func (child,
1705 + gtk_scrolled_window_child_expose,
1706 + container);
1709 gtk_widget_set_scroll_adjustments (child, NULL, NULL);
1711 /* chain parent class handler to remove child */
1712 @@ -2871,5 +3018,383 @@ gtk_scrolled_window_grab_notify (GtkWidget *widget,
1716 +static void
1717 +gtk_scrolled_window_rounded_rectangle (cairo_t *cr,
1718 + gint x,
1719 + gint y,
1720 + gint width,
1721 + gint height,
1722 + gint x_radius,
1723 + gint y_radius)
1725 + gint x1, x2;
1726 + gint y1, y2;
1727 + gint xr1, xr2;
1728 + gint yr1, yr2;
1730 + x1 = x;
1731 + x2 = x1 + width;
1732 + y1 = y;
1733 + y2 = y1 + height;
1735 + x_radius = MIN (x_radius, width / 2.0);
1736 + y_radius = MIN (y_radius, height / 2.0);
1738 + xr1 = x_radius;
1739 + xr2 = x_radius / 2.0;
1740 + yr1 = y_radius;
1741 + yr2 = y_radius / 2.0;
1743 + cairo_move_to (cr, x1 + xr1, y1);
1744 + cairo_line_to (cr, x2 - xr1, y1);
1745 + cairo_curve_to (cr, x2 - xr2, y1, x2, y1 + yr2, x2, y1 + yr1);
1746 + cairo_line_to (cr, x2, y2 - yr1);
1747 + cairo_curve_to (cr, x2, y2 - yr2, x2 - xr2, y2, x2 - xr1, y2);
1748 + cairo_line_to (cr, x1 + xr1, y2);
1749 + cairo_curve_to (cr, x1 + xr2, y2, x1, y2 - yr2, x1, y2 - yr1);
1750 + cairo_line_to (cr, x1, y1 + yr1);
1751 + cairo_curve_to (cr, x1, y1 + yr2, x1 + xr2, y1, x1 + xr1, y1);
1752 + cairo_close_path (cr);
1755 +static void
1756 +gtk_scrolled_window_get_child_scroll_areas (GtkScrolledWindow *scrolled_window,
1757 + GtkWidget *child,
1758 + GdkWindow *child_window,
1759 + GdkRectangle *vbar_rect,
1760 + GdkRectangle *vslider_rect,
1761 + GdkRectangle *hbar_rect,
1762 + GdkRectangle *hslider_rect)
1764 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1765 + GtkAdjustment *adj;
1766 + GtkAllocation allocation;
1767 + gdouble lower;
1768 + gdouble page_size;
1769 + gdouble upper;
1770 + gdouble value_h = 0.0;
1771 + gdouble value_v = 0.0;
1772 + gdouble ratio;
1773 + gdouble width;
1774 + gdouble height;
1775 + gdouble x;
1776 + gdouble y;
1777 + gint window_width;
1778 + gint window_height;
1779 + gint viewport_width;
1780 + gint viewport_height;
1782 + window_width = gdk_window_get_width (child_window);
1783 + window_height = gdk_window_get_height (child_window);
1785 + gtk_widget_get_allocation (child, &allocation);
1787 + viewport_width = MIN (window_width, allocation.width);
1788 + viewport_height = MIN (window_height, allocation.height);
1790 + if (scrolled_window->vscrollbar)
1792 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
1794 + value_v = gtk_adjustment_get_value (adj);
1797 + if (scrolled_window->hscrollbar)
1799 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
1801 + value_h = gtk_adjustment_get_value (adj);
1804 + if ((vbar_rect || vslider_rect) && scrolled_window->vscrollbar)
1806 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
1808 + g_object_get (adj,
1809 + "lower", &lower,
1810 + "upper", &upper,
1811 + "page-size", &page_size,
1812 + NULL);
1814 + ratio = page_size / (upper - lower);
1815 + if (ratio < 1.0)
1817 + height = ratio * (viewport_height - (2 * priv->sb_padding));
1818 + height = MAX (height, 20);
1819 + height = MIN (height, viewport_height - (2 * priv->sb_padding));
1821 + ratio = (value_v - lower) / (upper - page_size - lower);
1822 + y = ratio * (viewport_height - (2 * priv->sb_padding) - height) + priv->sb_padding;
1823 + x = viewport_width - priv->sb_width - priv->sb_padding;
1825 + if (window_width > allocation.width)
1826 + x += value_h;
1828 + if (window_height > allocation.height)
1829 + y += value_v;
1831 + if (vbar_rect)
1833 + vbar_rect->x = x - priv->sb_padding;
1834 + vbar_rect->y = 0;
1835 + vbar_rect->width = priv->sb_width + 2 * priv->sb_padding;
1836 + vbar_rect->height = viewport_height;
1839 + if (vslider_rect)
1841 + vslider_rect->x = x;
1842 + vslider_rect->y = y;
1843 + vslider_rect->width = priv->sb_width;
1844 + vslider_rect->height = height;
1847 + else
1849 + if (vbar_rect)
1851 + vbar_rect->x = 0;
1852 + vbar_rect->y = 0;
1853 + vbar_rect->width = 0;
1854 + vbar_rect->height = 0;
1857 + if (vslider_rect)
1859 + vslider_rect->x = 0;
1860 + vslider_rect->y = 0;
1861 + vslider_rect->width = 0;
1862 + vslider_rect->height = 0;
1867 + if ((hbar_rect || hslider_rect) && scrolled_window->hscrollbar)
1869 + adj = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
1871 + g_object_get (adj,
1872 + "lower", &lower,
1873 + "upper", &upper,
1874 + "page-size", &page_size,
1875 + NULL);
1877 + ratio = page_size / (upper - lower);
1878 + if (ratio < 1.0)
1880 + width = ratio * (viewport_width - (2 * priv->sb_padding));
1881 + width = MAX (width, 20);
1882 + width = MIN (width, viewport_width - (2 * priv->sb_padding));
1884 + ratio = (value_h - lower) / (upper - page_size - lower);
1885 + x = ratio * (viewport_width - (2 * priv->sb_padding) - width) + priv->sb_padding;
1886 + y = viewport_height - priv->sb_width - priv->sb_padding;
1888 + if (window_width > allocation.width)
1889 + x += value_h;
1891 + if (window_height > allocation.height)
1892 + y += value_v;
1894 + if (hbar_rect)
1896 + hbar_rect->x = 0;
1897 + hbar_rect->y = y - priv->sb_padding;
1898 + hbar_rect->width = viewport_width;
1899 + hbar_rect->height = priv->sb_width + 2 * priv->sb_padding;
1902 + if (hslider_rect)
1904 + hslider_rect->x = x;
1905 + hslider_rect->y = y;
1906 + hslider_rect->width = width;
1907 + hslider_rect->height = priv->sb_width;
1910 + else
1912 + if (hbar_rect)
1914 + hbar_rect->x = 0;
1915 + hbar_rect->y = 0;
1916 + hbar_rect->width = 0;
1917 + hbar_rect->height = 0;
1920 + if (hslider_rect)
1922 + hslider_rect->x = 0;
1923 + hslider_rect->y = 0;
1924 + hslider_rect->width = 0;
1925 + hslider_rect->height = 0;
1931 +static gboolean
1932 +gtk_scrolled_window_child_expose (GtkWidget *widget,
1933 + GdkEventExpose *eevent,
1934 + GtkScrolledWindow *scrolled_window)
1936 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1937 + GdkRectangle vbar_rect;
1938 + GdkRectangle vslider_rect;
1939 + GdkRectangle hbar_rect;
1940 + GdkRectangle hslider_rect;
1941 + cairo_t *cr;
1943 + cr = gdk_cairo_create (eevent->window);
1944 + gdk_cairo_region (cr, eevent->region);
1945 + cairo_clip (cr);
1947 + gtk_scrolled_window_get_child_scroll_areas (scrolled_window,
1948 + gtk_bin_get_child (GTK_BIN (scrolled_window)),
1949 + eevent->window,
1950 + &vbar_rect, &vslider_rect,
1951 + &hbar_rect, &hslider_rect);
1953 + if (TRUE)
1955 + if (scrolled_window->vscrollbar && vbar_rect.width > 0)
1956 + gdk_cairo_rectangle (cr, &vbar_rect);
1958 + if (scrolled_window->hscrollbar && hbar_rect.width > 0)
1959 + gdk_cairo_rectangle (cr, &hbar_rect);
1961 + cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
1962 + cairo_fill (cr);
1965 + if (scrolled_window->vscrollbar && vslider_rect.width > 0)
1966 + gtk_scrolled_window_rounded_rectangle (cr,
1967 + vslider_rect.x,
1968 + vslider_rect.y,
1969 + vslider_rect.width,
1970 + vslider_rect.height,
1971 + priv->sb_radius,
1972 + priv->sb_radius);
1974 + if (scrolled_window->hscrollbar && hslider_rect.width > 0)
1975 + gtk_scrolled_window_rounded_rectangle (cr,
1976 + hslider_rect.x,
1977 + hslider_rect.y,
1978 + hslider_rect.width,
1979 + hslider_rect.height,
1980 + priv->sb_radius,
1981 + priv->sb_radius);
1983 + cairo_set_source_rgba (cr, 0, 0, 0, gtk_adjustment_get_value (priv->opacity));
1984 + cairo_fill (cr);
1986 + cairo_destroy (cr);
1988 + return FALSE;
1991 +static void
1992 +gtk_scrolled_window_cancel_animation (GtkScrolledWindow *scrolled_window)
1994 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
1995 + GbAnimation *anim = priv->opacity_anim;
1997 + if (anim)
1999 + priv->opacity_anim = NULL;
2000 + g_object_remove_weak_pointer (G_OBJECT (anim),
2001 + (gpointer *) &priv->opacity_anim);
2002 + _gb_animation_stop (anim);
2005 + if (priv->sb_fade_out_id)
2007 + g_source_remove (priv->sb_fade_out_id);
2008 + priv->sb_fade_out_id = 0;
2011 + priv->sb_fading_in = FALSE;
2014 +static gboolean
2015 +gtk_scrolled_window_fade_out_timeout (GtkScrolledWindow *scrolled_window)
2017 + gtk_scrolled_window_start_fade_out_animation (scrolled_window);
2019 + return FALSE;
2022 +static void
2023 +gtk_scrolled_window_start_fade_in_animation (GtkScrolledWindow *scrolled_window)
2025 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
2026 + gdouble upper;
2028 + if (priv->sb_fading_in)
2029 + return;
2031 + gtk_scrolled_window_cancel_animation (scrolled_window);
2033 + priv->sb_fading_in = TRUE;
2035 + upper = gtk_adjustment_get_upper (priv->opacity);
2036 + priv->opacity_anim = _gb_object_animate (priv->opacity,
2037 + GB_ANIMATION_EASE_OUT_QUAD,
2038 + 100,
2039 + "value", upper,
2040 + NULL);
2041 + g_object_add_weak_pointer (G_OBJECT (priv->opacity_anim),
2042 + (gpointer *) &priv->opacity_anim);
2044 + priv->sb_fade_out_id =
2045 + gdk_threads_add_timeout (priv->sb_fade_out_delay,
2046 + (GSourceFunc) gtk_scrolled_window_fade_out_timeout,
2047 + scrolled_window);
2050 +static void
2051 +gtk_scrolled_window_start_fade_out_animation (GtkScrolledWindow *scrolled_window)
2053 + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window);
2055 + gtk_scrolled_window_cancel_animation (scrolled_window);
2057 + priv->opacity_anim = _gb_object_animate (priv->opacity,
2058 + GB_ANIMATION_EASE_IN_QUAD,
2059 + 300,
2060 + "value", 0.0,
2061 + NULL);
2062 + g_object_add_weak_pointer (G_OBJECT (priv->opacity_anim),
2063 + (gpointer *) &priv->opacity_anim);
2066 +static void
2067 +gtk_scrolled_window_expose_scrollbars (GtkAdjustment *adj,
2068 + GtkScrolledWindow *scrolled_window)
2070 + GtkWidget *child = gtk_bin_get_child (GTK_BIN (scrolled_window));
2072 + if (child && gtk_widget_get_visible (child))
2074 + GtkAllocation alloc;
2076 + gtk_widget_get_allocation (child, &alloc);
2078 + if (scrolled_window->vscrollbar)
2079 + gtk_widget_queue_draw_area (child,
2080 + alloc.width - 20,
2081 + 0,
2082 + 20,
2083 + alloc.height);
2085 + if (scrolled_window->hscrollbar)
2086 + gtk_widget_queue_draw_area (child,
2087 + 0,
2088 + alloc.height - 20,
2089 + alloc.width,
2090 + 20);
2094 #define __GTK_SCROLLED_WINDOW_C__
2095 #include "gtkaliasdef.c"
2097 1.7.10.2 (Apple Git-33)