Merge lp:~cimi/overlay-scrollbar/animated-thumb-fade-out into lp:overlay-scrollbar

Proposed by Andrea Cimitan
Status: Merged
Merged at revision: 193
Proposed branch: lp:~cimi/overlay-scrollbar/animated-thumb-fade-out
Merge into: lp:overlay-scrollbar
Diff against target: 305 lines (+176/-13)
1 file modified
os/os-thumb.c (+176/-13)
To merge this branch: bzr merge lp:~cimi/overlay-scrollbar/animated-thumb-fade-out
Reviewer Review Type Date Requested Status
Kalle Valo (community) Approve
Ayatana Scrollbar Team Pending
Review via email: mp+56372@code.launchpad.net

Description of the change

as in the bugreport, add a fade-out animation

To post a comment you must log in.
Revision history for this message
Kalle Valo (kvalo) wrote :

Good looking code and didn't find anything wrong.

review: Approve
194. By Andrea Cimitan

Added few comments, try to avoid useless calls ("faster code is code that doesn't execute").

Revision history for this message
Kalle Valo (kvalo) wrote :

Update looks good as well.

review: Approve
195. By Andrea Cimitan

stop the animation on leave-notify only if there's an active timeout

Revision history for this message
Loïc Molinari (loic.molinari) wrote :

Why not using the end animation callback of OsAnimation instead of testing if weight is equal to 1.0 in os_thumb_fade_out_cb()?

The comment in os_thumb_button_release_event() says that "priv->source_id should be always != 0". I guess you meant "== 0" here, otherwise I think you should remove the source from the mainloop first. In any case, adding a debug assert "OS_DCHECK (priv->source_id == 0);" would be very useful there to make sure it's really the case.

Apart from that, looks good to me too.

Revision history for this message
Andrea Cimitan (cimi) wrote :

Because the end animation fallback iirc is called also when you stop the animation (that's why I've chosen to do in that way... but maybe was late the previous night, let me check :-) )

196. By Andrea Cimitan

fixed comment

Revision history for this message
Andrea Cimitan (cimi) wrote :

exactly: os_animation_stop () calls the end_func, so if I put a gtk_widget_hide there, this will be called everytime I stop the fade-out (so if the widget is 90% opaque, it will be hidden), and I don't want it to stop everytime, but only if weight == 1.0f.
Yeah, I could write a complex end_func just to check the opacity of the window, but it's more expensive, isn't it?

Revision history for this message
Loïc Molinari (loic.molinari) wrote :

I get it. Actually I see no good reason for stop to call the end callback. Maybe we should remove it. What do you think?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'os/os-thumb.c'
2--- os/os-thumb.c 2011-04-04 16:25:26 +0000
3+++ os/os-thumb.c 2011-04-05 16:01:57 +0000
4@@ -25,15 +25,28 @@
5 #endif /* HAVE_CONFIG_H */
6
7 #include "os-private.h"
8+#include "math.h"
9+
10+/* Rate of the fade-out */
11+#define RATE_FADE_OUT 30
12+
13+/* Duration of the fade-out */
14+#define DURATION_FADE_OUT 2000
15+
16+/* Timeout before the fade-out */
17+#define TIMEOUT_FADE_OUT 250
18
19 struct _OsThumbPrivate {
20 GtkOrientation orientation;
21 GtkWidget *grabbed_widget;
22+ OsAnimation *animation;
23 gboolean button_press_event;
24+ gboolean enter_notify_event;
25 gboolean motion_notify_event;
26 gboolean can_rgba;
27 gint pointer_x;
28 gint pointer_y;
29+ guint32 source_id;
30 };
31
32 enum {
33@@ -42,10 +55,14 @@
34 LAST_ARG
35 };
36
37+static void os_thumb_fade_out_cb (gfloat weight, gpointer user_data);
38+static gboolean os_thumb_timeout_fade_out_cb (gpointer user_data);
39 static gboolean os_thumb_button_press_event (GtkWidget *widget, GdkEventButton *event);
40 static gboolean os_thumb_button_release_event (GtkWidget *widget, GdkEventButton *event);
41 static void os_thumb_composited_changed (GtkWidget *widget);
42+static gboolean os_thumb_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event);
43 static gboolean os_thumb_expose (GtkWidget *widget, GdkEventExpose *event);
44+static gboolean os_thumb_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event);
45 static gboolean os_thumb_motion_notify_event (GtkWidget *widget, GdkEventMotion *event);
46 static void os_thumb_map (GtkWidget *widget);
47 static void os_thumb_screen_changed (GtkWidget *widget, GdkScreen *old_screen);
48@@ -83,6 +100,43 @@
49 cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
50 }
51
52+static void
53+os_thumb_fade_out_cb (gfloat weight,
54+ gpointer user_data)
55+{
56+ OsThumb *thumb;
57+ OsThumbPrivate *priv;
58+
59+ thumb = OS_THUMB (user_data);
60+
61+ priv = thumb->priv;
62+
63+ if (weight < 1.0f)
64+ gtk_window_set_opacity (GTK_WINDOW (thumb), fabs (weight - 1.0f));
65+ else
66+ {
67+ /* Animation ended. */
68+ priv->source_id = 0;
69+
70+ gtk_widget_hide (GTK_WIDGET (thumb));
71+ }
72+}
73+
74+static gboolean
75+os_thumb_timeout_fade_out_cb (gpointer user_data)
76+{
77+ OsThumb *thumb;
78+ OsThumbPrivate *priv;
79+
80+ thumb = OS_THUMB (user_data);
81+
82+ priv = thumb->priv;
83+
84+ os_animation_start (priv->animation);
85+
86+ return FALSE;
87+}
88+
89 /* Type definition. */
90
91 G_DEFINE_TYPE (OsThumb, os_thumb, GTK_TYPE_WINDOW);
92@@ -99,7 +153,9 @@
93 widget_class->button_press_event = os_thumb_button_press_event;
94 widget_class->button_release_event = os_thumb_button_release_event;
95 widget_class->composited_changed = os_thumb_composited_changed;
96+ widget_class->enter_notify_event = os_thumb_enter_notify_event;
97 widget_class->expose_event = os_thumb_expose;
98+ widget_class->leave_notify_event = os_thumb_leave_notify_event;
99 widget_class->map = os_thumb_map;
100 widget_class->motion_notify_event = os_thumb_motion_notify_event;
101 widget_class->screen_changed = os_thumb_screen_changed;
102@@ -134,6 +190,10 @@
103
104 priv->can_rgba = FALSE;
105
106+ priv->source_id = 0;
107+ priv->animation = os_animation_new (RATE_FADE_OUT, DURATION_FADE_OUT,
108+ os_thumb_fade_out_cb, NULL, thumb);
109+
110 gtk_window_set_skip_pager_hint (GTK_WINDOW (thumb), TRUE);
111 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (thumb), TRUE);
112 /* gtk_window_set_has_resize_grip (GTK_WINDOW (thumb), FALSE); */
113@@ -143,7 +203,7 @@
114 gtk_widget_set_app_paintable (GTK_WIDGET (thumb), TRUE);
115 gtk_widget_add_events (GTK_WIDGET (thumb), GDK_BUTTON_PRESS_MASK |
116 GDK_BUTTON_RELEASE_MASK |
117- GDK_BUTTON_MOTION_MASK |
118+ GDK_POINTER_MOTION_MASK |
119 GDK_POINTER_MOTION_HINT_MASK);
120
121 os_thumb_screen_changed (GTK_WIDGET (thumb), NULL);
122@@ -153,6 +213,24 @@
123 static void
124 os_thumb_dispose (GObject *object)
125 {
126+ OsThumb *thumb;
127+ OsThumbPrivate *priv;
128+
129+ thumb = OS_THUMB (object);
130+ priv = thumb->priv;
131+
132+ if (priv->source_id != 0)
133+ {
134+ g_source_remove (priv->source_id);
135+ priv->source_id = 0;
136+ }
137+
138+ if (priv->animation != NULL)
139+ {
140+ g_object_unref (priv->animation);
141+ priv->animation = NULL;
142+ }
143+
144 G_OBJECT_CLASS (os_thumb_parent_class)->dispose (object);
145 }
146
147@@ -167,16 +245,27 @@
148 os_thumb_button_press_event (GtkWidget *widget,
149 GdkEventButton *event)
150 {
151+ OsThumb *thumb;
152+ OsThumbPrivate *priv;
153+
154+ thumb = OS_THUMB (widget);
155+ priv = thumb->priv;
156+
157+ /* Stop the animation on user interaction,
158+ * the button_press_event. */
159+ if (priv->source_id != 0)
160+ {
161+ g_source_remove (priv->source_id);
162+ priv->source_id = 0;
163+
164+ os_animation_stop (priv->animation);
165+ gtk_window_set_opacity (GTK_WINDOW (widget), 1.0f);
166+ }
167+
168 if (event->type == GDK_BUTTON_PRESS)
169 {
170 if (event->button == 1)
171 {
172- OsThumb *thumb;
173- OsThumbPrivate *priv;
174-
175- thumb = OS_THUMB (widget);
176- priv = thumb->priv;
177-
178 gtk_grab_add (widget);
179
180 priv->pointer_x = event->x;
181@@ -196,16 +285,26 @@
182 os_thumb_button_release_event (GtkWidget *widget,
183 GdkEventButton *event)
184 {
185+ OsThumb *thumb;
186+ OsThumbPrivate *priv;
187+
188+ thumb = OS_THUMB (widget);
189+ priv = thumb->priv;
190+
191+ /* priv->source_id should be always 0 here,
192+ * because it's set to 0 in both motion_notify_event
193+ * and button_press_event.
194+ * Add the fade-out timeout only if the pointer is inside,
195+ * so if priv->enter_notify_event is TRUE. */
196+ if (priv->enter_notify_event)
197+ priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,
198+ os_thumb_timeout_fade_out_cb,
199+ thumb);
200+
201 if (event->type == GDK_BUTTON_RELEASE)
202 {
203 if (event->button == 1)
204 {
205- OsThumb *thumb;
206- OsThumbPrivate *priv;
207-
208- thumb = OS_THUMB (widget);
209- priv = thumb->priv;
210-
211 gtk_grab_remove (widget);
212
213 priv->button_press_event = FALSE;
214@@ -245,6 +344,21 @@
215 }
216
217 static gboolean
218+os_thumb_enter_notify_event (GtkWidget *widget,
219+ GdkEventCrossing *event)
220+{
221+ OsThumb *thumb;
222+ OsThumbPrivate *priv;
223+
224+ thumb = OS_THUMB (widget);
225+ priv = thumb->priv;
226+
227+ priv->enter_notify_event = TRUE;
228+
229+ return FALSE;
230+}
231+
232+static gboolean
233 os_thumb_expose (GtkWidget *widget,
234 GdkEventExpose *event)
235 {
236@@ -451,6 +565,36 @@
237 return FALSE;
238 }
239
240+static gboolean
241+os_thumb_leave_notify_event (GtkWidget *widget,
242+ GdkEventCrossing *event)
243+{
244+ OsThumb *thumb;
245+ OsThumbPrivate *priv;
246+
247+ thumb = OS_THUMB (widget);
248+ priv = thumb->priv;
249+
250+ priv->enter_notify_event = FALSE;
251+
252+ /* If we exit the thumb when a button is pressed,
253+ * there's no need to stop the animation, it should
254+ * already be stopped.
255+ * Stop it only if priv->button_press_event is FALSE. */
256+ if (!priv->button_press_event)
257+ {
258+ if (priv->source_id != 0)
259+ {
260+ g_source_remove (priv->source_id);
261+ priv->source_id = 0;
262+
263+ os_animation_stop (priv->animation);
264+ }
265+ }
266+
267+ return FALSE;
268+}
269+
270 static void
271 os_thumb_map (GtkWidget *widget)
272 {
273@@ -478,6 +622,24 @@
274 thumb = OS_THUMB (widget);
275 priv = thumb->priv;
276
277+ /* On motion, stop the fade-out. */
278+ if (priv->source_id != 0)
279+ {
280+ g_source_remove (priv->source_id);
281+ priv->source_id = 0;
282+
283+ os_animation_stop (priv->animation);
284+ gtk_window_set_opacity (GTK_WINDOW (widget), 1.0f);
285+ }
286+
287+ /* If you're not dragging, enable the fade-out.
288+ * priv->motion_notify_event is TRUE only on dragging,
289+ * see code few lines below. */
290+ if (!priv->motion_notify_event)
291+ priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,
292+ os_thumb_timeout_fade_out_cb,
293+ thumb);
294+
295 if (priv->button_press_event)
296 {
297 if (!priv->motion_notify_event)
298@@ -513,6 +675,7 @@
299 priv = thumb->priv;
300
301 priv->button_press_event = FALSE;
302+ priv->enter_notify_event = FALSE;
303 priv->motion_notify_event = FALSE;
304
305 if (priv->grabbed_widget != NULL)

Subscribers

People subscribed via source and target branches