Merge lp:~cimi/overlay-scrollbar/new-thumb-functionalities into lp:overlay-scrollbar

Proposed by Andrea Cimitan
Status: Merged
Merged at revision: 311
Proposed branch: lp:~cimi/overlay-scrollbar/new-thumb-functionalities
Merge into: lp:overlay-scrollbar
Diff against target: 4177 lines (+1568/-1308)
5 files modified
os/Makefile.am (+1/-1)
os/os-bar.c (+454/-355)
os/os-private.h (+63/-53)
os/os-scrollbar.c (+1008/-866)
os/os-thumb.c (+42/-33)
To merge this branch: bzr merge lp:~cimi/overlay-scrollbar/new-thumb-functionalities
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+79140@code.launchpad.net

Description of the change

Big changes... are you really sure you want to review that? :-)

To post a comment you must log in.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

I do :)

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

From an usability point of view I'd reduce the value of TIMEOUT_THUMB_SHOW to 50ms. It seems better here.

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

Marco, I'm thinking about increasing it to 150 :-) Please notice that the timeout is not respected when the thumb is touching the screen edge.

Anyway, the branch is still in progress :-) Not ready for review (see the "Status"!)

Revision history for this message
Ted Gould (ted) wrote :

In general, I'm a little uncomfortable with all the bit twittling for the state variable. I think that you should put that into its own function. Two reasons, it's easy to mess up. And it seems to be likely someplace you'll want to put a g_debug() statement when things are going wrong.

Also, the diffs would be a lot smaller if the name changes weren't included with the logic changes. I think next time you should split those out into two different merge requests.

Other than that, it was a big diff! :-) I didn't see anything on a general read through.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'os/Makefile.am'
--- os/Makefile.am 2011-10-05 12:24:21 +0000
+++ os/Makefile.am 2011-10-12 17:16:23 +0000
@@ -16,8 +16,8 @@
1616
17source_c = \17source_c = \
18 $(srcdir)/os-animation.c \18 $(srcdir)/os-animation.c \
19 $(srcdir)/os-bar.c \
19 $(srcdir)/os-log.c \20 $(srcdir)/os-log.c \
20 $(srcdir)/os-pager.c \
21 $(srcdir)/os-scrollbar.c \21 $(srcdir)/os-scrollbar.c \
22 $(srcdir)/os-thumb.c \22 $(srcdir)/os-thumb.c \
23 $(srcdir)/os-utils.c23 $(srcdir)/os-utils.c
2424
=== renamed file 'os/os-pager.c' => 'os/os-bar.c'
--- os/os-pager.c 2011-10-05 12:24:21 +0000
+++ os/os-bar.c 2011-10-12 17:16:23 +0000
@@ -29,78 +29,45 @@
29#include <cairo-xlib.h>29#include <cairo-xlib.h>
30#include <gdk/gdkx.h>30#include <gdk/gdkx.h>
3131
32/* Rate of the fade. */
33#define RATE_FADE 30
34
35/* Duration of the fade-in. */32/* Duration of the fade-in. */
36#define DURATION_FADE_IN 20033#define DURATION_FADE_IN 200
3734
38/* Duration of the fade-out. */35/* Duration of the fade-out. */
39#define DURATION_FADE_OUT 40036#define DURATION_FADE_OUT 400
4037
38/* Max duration of the retracting tail. */
39#define MAX_DURATION_TAIL 600
40
41/* Min duration of the retracting tail. */
42#define MIN_DURATION_TAIL 100
43
41#ifdef USE_GTK344#ifdef USE_GTK3
42#define SHAPE_REGION(x) (cairo_region_create_rectangle (x))45#define SHAPE_REGION(x) (cairo_region_create_rectangle (x))
43#else46#else
44#define SHAPE_REGION(x) (gdk_region_rectangle (x))47#define SHAPE_REGION(x) (gdk_region_rectangle (x))
45#endif48#endif
4649
47struct _OsPagerPrivate {50struct _OsBarPrivate {
48 GdkWindow *pager_window;51 GdkRectangle bar_mask;
49 GdkWindow *connection_window;52 GdkRectangle tail_mask; /* In theory not needed, but easier to read. */
53 GdkRectangle allocation;
54 GdkWindow *bar_window;
55 GdkWindow *tail_window;
50 GtkWidget *parent;56 GtkWidget *parent;
51 GdkRectangle mask;57 OsAnimation *state_animation;
52 GdkRectangle connection_mask; /* In theory not needed, but easier to read. */58 OsAnimation *tail_animation;
53 GdkRectangle allocation;
54 OsAnimation *animation;
55 gboolean active;59 gboolean active;
56 gboolean detached;60 gboolean detached;
57 gboolean visible;61 gboolean visible;
58 gfloat weight;62 gfloat weight;
59 gulong handler_id;
60};63};
6164
62static void os_pager_dispose (GObject *object);65static void os_bar_dispose (GObject *object);
63static void os_pager_finalize (GObject *object);66static void os_bar_finalize (GObject *object);
6467
65/* Draw on the connection_window. */68/* Draw on the bar_window. */
66static void69static void
67draw_connection (OsPager *pager)70draw_bar (OsBar *bar)
68{
69#ifdef USE_GTK3
70 GdkRGBA color;
71 GtkStyleContext *style_context;
72#else
73 GdkColor color;
74 GtkStyle *style;
75#endif
76 OsPagerPrivate *priv;
77
78 priv = pager->priv;
79
80#ifdef USE_GTK3
81 style_context = gtk_widget_get_style_context (priv->parent);
82
83 gtk_style_context_get_background_color (style_context, GTK_STATE_FLAG_ACTIVE, &color);
84
85 color.alpha = 1.0;
86
87 gdk_window_set_background_rgba (priv->connection_window, &color);
88#else
89 style = gtk_widget_get_style (priv->parent);
90
91 color = style->bg[GTK_STATE_ACTIVE];
92
93 gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->connection_window), &color, FALSE, TRUE);
94
95 gdk_window_set_background (priv->connection_window, &color);
96#endif
97
98 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
99}
100
101/* Draw on the pager_window. */
102static void
103draw_pager (OsPager *pager)
104{71{
105#ifdef USE_GTK372#ifdef USE_GTK3
106 GdkRGBA c1, c2, color;73 GdkRGBA c1, c2, color;
@@ -109,10 +76,10 @@
109 GdkColor c1, c2, color;76 GdkColor c1, c2, color;
110 GtkStyle *style;77 GtkStyle *style;
111#endif78#endif
112 OsPagerPrivate *priv;79 OsBarPrivate *priv;
113 gfloat weight;80 gfloat weight;
11481
115 priv = pager->priv;82 priv = bar->priv;
11683
117 weight = priv->weight;84 weight = priv->weight;
11885
@@ -135,7 +102,7 @@
135 color.blue = weight * c1.blue + (1.0 - weight) * c2.blue;102 color.blue = weight * c1.blue + (1.0 - weight) * c2.blue;
136 color.alpha = 1.0;103 color.alpha = 1.0;
137104
138 gdk_window_set_background_rgba (priv->pager_window, &color);105 gdk_window_set_background_rgba (priv->bar_window, &color);
139#else106#else
140 style = gtk_widget_get_style (priv->parent);107 style = gtk_widget_get_style (priv->parent);
141108
@@ -154,9 +121,45 @@
154 color.green = weight * c1.green + (1.0 - weight) * c2.green;121 color.green = weight * c1.green + (1.0 - weight) * c2.green;
155 color.blue = weight * c1.blue + (1.0 - weight) * c2.blue;122 color.blue = weight * c1.blue + (1.0 - weight) * c2.blue;
156123
157 gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->pager_window), &color, FALSE, TRUE);124 gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->bar_window), &color, FALSE, TRUE);
158125
159 gdk_window_set_background (priv->pager_window, &color);126 gdk_window_set_background (priv->bar_window, &color);
127#endif
128
129 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
130}
131
132/* Draw on the tail_window. */
133static void
134draw_tail (OsBar *bar)
135{
136#ifdef USE_GTK3
137 GdkRGBA color;
138 GtkStyleContext *style_context;
139#else
140 GdkColor color;
141 GtkStyle *style;
142#endif
143 OsBarPrivate *priv;
144
145 priv = bar->priv;
146
147#ifdef USE_GTK3
148 style_context = gtk_widget_get_style_context (priv->parent);
149
150 gtk_style_context_get_background_color (style_context, GTK_STATE_FLAG_ACTIVE, &color);
151
152 color.alpha = 1.0;
153
154 gdk_window_set_background_rgba (priv->tail_window, &color);
155#else
156 style = gtk_widget_get_style (priv->parent);
157
158 color = style->bg[GTK_STATE_ACTIVE];
159
160 gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->tail_window), &color, FALSE, TRUE);
161
162 gdk_window_set_background (priv->tail_window, &color);
160#endif163#endif
161164
162 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);165 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
@@ -167,35 +170,35 @@
167change_state_cb (gfloat weight,170change_state_cb (gfloat weight,
168 gpointer user_data)171 gpointer user_data)
169{172{
170 OsPager *pager;173 OsBar *bar;
171 OsPagerPrivate *priv;174 OsBarPrivate *priv;
172175
173 pager = OS_PAGER (user_data);176 bar = OS_BAR (user_data);
174177
175 priv = pager->priv;178 priv = bar->priv;
176179
177 priv->weight = weight;180 priv->weight = weight;
178181
179 if (priv->parent == NULL)182 if (priv->parent == NULL)
180 return;183 return;
181184
182 draw_pager (pager);185 draw_bar (bar);
183}186}
184187
185/* Stop function called by the change-state animation. */188/* Stop function called by the change-state animation. */
186static void189static void
187change_state_stop_cb (gpointer user_data)190change_state_stop_cb (gpointer user_data)
188{191{
189 OsPager *pager;192 OsBar *bar;
190 OsPagerPrivate *priv;193 OsBarPrivate *priv;
191194
192 pager = OS_PAGER (user_data);195 bar = OS_BAR (user_data);
193196
194 priv = pager->priv;197 priv = bar->priv;
195198
196 priv->weight = 1.0f;199 priv->weight = 1.0f;
197200
198 draw_pager (pager);201 draw_bar (bar);
199}202}
200203
201/* Callback called when the Gtk+ theme changes. */204/* Callback called when the Gtk+ theme changes. */
@@ -204,19 +207,19 @@
204 GParamSpec* pspec,207 GParamSpec* pspec,
205 gpointer user_data)208 gpointer user_data)
206{209{
207 OsPager *pager;210 OsBar *bar;
208 OsPagerPrivate *priv;211 OsBarPrivate *priv;
209212
210 pager = OS_PAGER (user_data);213 bar = OS_BAR (user_data);
211 priv = pager->priv;214 priv = bar->priv;
212215
213 if (priv->parent == NULL ||216 if (priv->parent == NULL ||
214 priv->pager_window == NULL ||217 priv->bar_window == NULL ||
215 priv->connection_window == NULL)218 priv->tail_window == NULL)
216 return;219 return;
217220
218 draw_connection (pager);221 draw_tail (bar);
219 draw_pager (pager);222 draw_bar (bar);
220}223}
221224
222/* Check if two GdkRectangle are different. */225/* Check if two GdkRectangle are different. */
@@ -232,29 +235,93 @@
232 return FALSE;235 return FALSE;
233}236}
234237
235G_DEFINE_TYPE (OsPager, os_pager, G_TYPE_OBJECT);238/* Callback called by the retract-tail animation. */
236239static void
237static void240retract_tail_cb (gfloat weight,
238os_pager_class_init (OsPagerClass *class)241 gpointer user_data)
242{
243 GdkRectangle tail_mask;
244 OsBar *bar;
245 OsBarPrivate *priv;
246
247 bar = OS_BAR (user_data);
248
249 priv = bar->priv;
250
251 if (priv->parent == NULL)
252 return;
253
254 tail_mask = priv->tail_mask;
255
256 if (priv->allocation.height >= priv->allocation.width)
257 {
258 tail_mask.height = tail_mask.height * (1.0 - weight);
259
260 if (priv->tail_mask.y + priv->tail_mask.height < priv->bar_mask.y + priv->bar_mask.height)
261 tail_mask.y = priv->tail_mask.y + priv->tail_mask.height - tail_mask.height;
262 }
263 else
264 {
265 tail_mask.width = tail_mask.width * (1.0 - weight);
266
267 if (priv->tail_mask.x + priv->tail_mask.width < priv->bar_mask.x + priv->bar_mask.width)
268 tail_mask.x = priv->tail_mask.x + priv->tail_mask.width - tail_mask.width;
269 }
270
271 if (weight < 1.0)
272 gdk_window_shape_combine_region (priv->tail_window,
273 SHAPE_REGION(&tail_mask),
274 0, 0);
275 else
276 {
277 /* Store the new tail_mask and hide the tail_window. */
278 priv->tail_mask = tail_mask;
279 gdk_window_hide (priv->tail_window);
280 }
281}
282
283/* Stop function called by the retract-tail animation. */
284static void
285retract_tail_stop_cb (gpointer user_data)
286{
287 OsBar *bar;
288 OsBarPrivate *priv;
289
290 bar = OS_BAR (user_data);
291
292 priv = bar->priv;
293
294 if (priv->parent == NULL)
295 return;
296
297 gdk_window_shape_combine_region (priv->tail_window,
298 SHAPE_REGION(&priv->tail_mask),
299 0, 0);
300}
301
302G_DEFINE_TYPE (OsBar, os_bar, G_TYPE_OBJECT);
303
304static void
305os_bar_class_init (OsBarClass *class)
239{306{
240 GObjectClass *gobject_class = G_OBJECT_CLASS (class);307 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
241308
242 gobject_class->dispose = os_pager_dispose;309 gobject_class->dispose = os_bar_dispose;
243 gobject_class->finalize = os_pager_finalize;310 gobject_class->finalize = os_bar_finalize;
244311
245 g_type_class_add_private (gobject_class, sizeof (OsPagerPrivate));312 g_type_class_add_private (gobject_class, sizeof (OsBarPrivate));
246}313}
247314
248static void315static void
249os_pager_init (OsPager *pager)316os_bar_init (OsBar *bar)
250{317{
251 GdkRectangle allocation, mask;318 GdkRectangle allocation, mask;
252 OsPagerPrivate *priv;319 OsBarPrivate *priv;
253320
254 pager->priv = G_TYPE_INSTANCE_GET_PRIVATE (pager,321 bar->priv = G_TYPE_INSTANCE_GET_PRIVATE (bar,
255 OS_TYPE_PAGER,322 OS_TYPE_BAR,
256 OsPagerPrivate);323 OsBarPrivate);
257 priv = pager->priv;324 priv = bar->priv;
258325
259 allocation.x = 0;326 allocation.x = 0;
260 allocation.y = 0;327 allocation.y = 0;
@@ -268,8 +335,8 @@
268 mask.width = 1;335 mask.width = 1;
269 mask.height = 1;336 mask.height = 1;
270337
271 priv->connection_mask = mask;338 priv->bar_mask = mask;
272 priv->mask = mask;339 priv->tail_mask = mask;
273340
274 priv->active = FALSE;341 priv->active = FALSE;
275 priv->detached = FALSE;342 priv->detached = FALSE;
@@ -277,217 +344,227 @@
277344
278 priv->weight = 1.0f;345 priv->weight = 1.0f;
279346
280 priv->animation = os_animation_new (RATE_FADE, DURATION_FADE_OUT,347 priv->state_animation = os_animation_new (RATE_ANIMATION, DURATION_FADE_OUT,
281 change_state_cb, NULL, pager);348 change_state_cb, NULL, bar);
282349 priv->tail_animation = os_animation_new (RATE_ANIMATION, MAX_DURATION_TAIL,
283 priv->handler_id = g_signal_connect (gtk_settings_get_default (), "notify::gtk-theme-name",350 retract_tail_cb, NULL, bar);
284 G_CALLBACK (notify_gtk_theme_name_cb), pager);351
285}352 g_signal_connect (gtk_settings_get_default (), "notify::gtk-theme-name",
286353 G_CALLBACK (notify_gtk_theme_name_cb), bar);
287static void354}
288os_pager_dispose (GObject *object)355
289{356static void
290 OsPager *pager;357os_bar_dispose (GObject *object)
291 OsPagerPrivate *priv;358{
292359 OsBar *bar;
293 pager = OS_PAGER (object);360 OsBarPrivate *priv;
294 priv = pager->priv;361
295362 bar = OS_BAR (object);
296 if (priv->animation != NULL)363 priv = bar->priv;
297 {364
298 g_object_unref (priv->animation);365 if (priv->tail_animation != NULL)
299 priv->animation = NULL;366 {
300 }367 g_object_unref (priv->tail_animation);
301368 priv->tail_animation = NULL;
302 if (priv->connection_window != NULL)369 }
303 {370
304 /* From the Gdk documentation:371 if (priv->state_animation != NULL)
305 * "Note that a window will not be destroyed372 {
306 * automatically when its reference count373 g_object_unref (priv->state_animation);
307 * reaches zero. You must call374 priv->state_animation = NULL;
308 * gdk_window_destroy ()375 }
309 * yourself before that happens". */376
310 gdk_window_destroy (priv->connection_window);377 if (priv->tail_window != NULL)
311378 {
312 g_object_unref (priv->connection_window);379 /* From the Gdk documentation:
313 priv->connection_window = NULL;380 * "Note that a window will not be destroyed
314 }381 * automatically when its reference count
315382 * reaches zero. You must call
316 if (priv->pager_window != NULL)383 * gdk_window_destroy ()
317 {384 * yourself before that happens". */
318 /* From the Gdk documentation:385 gdk_window_destroy (priv->tail_window);
319 * "Note that a window will not be destroyed386
320 * automatically when its reference count387 g_object_unref (priv->tail_window);
321 * reaches zero. You must call388 priv->tail_window = NULL;
322 * gdk_window_destroy ()389 }
323 * yourself before that happens". */390
324 gdk_window_destroy (priv->pager_window);391 if (priv->bar_window != NULL)
325392 {
326 g_object_unref (priv->pager_window);393 /* From the Gdk documentation:
327 priv->pager_window = NULL;394 * "Note that a window will not be destroyed
328 }395 * automatically when its reference count
329396 * reaches zero. You must call
330 os_pager_set_parent (pager, NULL);397 * gdk_window_destroy ()
331398 * yourself before that happens". */
332 g_signal_handler_disconnect (gtk_settings_get_default (),399 gdk_window_destroy (priv->bar_window);
333 priv->handler_id);400
334401 g_object_unref (priv->bar_window);
335 G_OBJECT_CLASS (os_pager_parent_class)->dispose (object);402 priv->bar_window = NULL;
336}403 }
337404
338static void405 os_bar_set_parent (bar, NULL);
339os_pager_finalize (GObject *object)406
340{407 G_OBJECT_CLASS (os_bar_parent_class)->dispose (object);
341 G_OBJECT_CLASS (os_pager_parent_class)->finalize (object);408}
409
410static void
411os_bar_finalize (GObject *object)
412{
413 G_OBJECT_CLASS (os_bar_parent_class)->finalize (object);
342}414}
343415
344/* Public functions. */416/* Public functions. */
345417
346/**418/**
347 * os_pager_new:419 * os_bar_new:
348 *420 *
349 * Creates a new #OsPager instance.421 * Creates a new #OsBar instance.
350 *422 *
351 * Returns: the new #OsPager instance.423 * Returns: the new #OsBar instance.
352 **/424 **/
353OsPager*425OsBar*
354os_pager_new (void)426os_bar_new (void)
355{427{
356 return g_object_new (OS_TYPE_PAGER, NULL);428 return g_object_new (OS_TYPE_BAR, NULL);
357}429}
358430
359/* Move a mask on the connection_window, fake movement. */431/* Move a mask on the tail_window, fake movement. */
360static void432static void
361mask_connection (OsPager *pager)433mask_tail (OsBar *bar)
362{434{
363 OsPagerPrivate *priv;435 OsBarPrivate *priv;
364436
365 priv = pager->priv;437 priv = bar->priv;
366438
367 gdk_window_shape_combine_region (priv->connection_window,439 gdk_window_shape_combine_region (priv->tail_window,
368 SHAPE_REGION(&priv->connection_mask),440 SHAPE_REGION(&priv->tail_mask),
369 0, 0);441 0, 0);
370}442}
371443
372/**444/**
373 * os_pager_connect:445 * os_bar_connect:
374 * @pager: a #OsPager446 * @bar: a #OsBar
375 * @mask: a #GdkRectangle with the position and dimension of the connection447 * @mask: a #GdkRectangle with the position and dimension of the tail
376 *448 *
377 * Moves and resizes connection.449 * Moves and resizes tail.
378 **/450 **/
379void451void
380os_pager_connect (OsPager *pager,452os_bar_connect (OsBar *bar,
381 GdkRectangle mask)453 GdkRectangle mask)
382{454{
383 OsPagerPrivate *priv;455 OsBarPrivate *priv;
384456
385 g_return_if_fail (OS_IS_PAGER (pager));457 g_return_if_fail (OS_IS_BAR (bar));
386458
387 priv = pager->priv;459 priv = bar->priv;
388460
389 if (!rectangle_changed (priv->connection_mask, mask))461 if (!os_animation_is_running (priv->tail_animation) &&
390 return;462 !rectangle_changed (priv->tail_mask, mask))
391
392 priv->connection_mask = mask;
393
394 if (priv->parent == NULL)
395 return;
396
397 mask_connection (pager);
398}
399
400/**
401 * os_pager_hide:
402 * @pager: a #OsPager
403 *
404 * Hides the #OsPager.
405 **/
406void
407os_pager_hide (OsPager *pager)
408{
409 OsPagerPrivate *priv;
410
411 g_return_if_fail (OS_IS_PAGER (pager));
412
413 priv = pager->priv;
414
415 priv->visible = FALSE;
416
417 if (priv->parent == NULL)
418 return;463 return;
419464
420 /* If there's an animation currently running, stop it. */465 /* If there's an animation currently running, stop it. */
421 os_animation_stop (priv->animation, change_state_stop_cb);466 os_animation_stop (priv->tail_animation, NULL);
422467
423 gdk_window_hide (priv->connection_window);468 priv->tail_mask = mask;
424 gdk_window_hide (priv->pager_window);469
425}470 if (priv->parent == NULL)
426471 return;
427/* Move a mask on the pager_window, fake movement. */472
473 mask_tail (bar);
474}
475
476/**
477 * os_bar_hide:
478 * @bar: a #OsBar
479 *
480 * Hides the #OsBar.
481 **/
482void
483os_bar_hide (OsBar *bar)
484{
485 OsBarPrivate *priv;
486
487 g_return_if_fail (OS_IS_BAR (bar));
488
489 priv = bar->priv;
490
491 priv->visible = FALSE;
492
493 if (priv->parent == NULL)
494 return;
495
496 /* Immediately hide, then stop animations. */
497 gdk_window_hide (priv->tail_window);
498 gdk_window_hide (priv->bar_window);
499
500 os_animation_stop (priv->tail_animation, retract_tail_stop_cb);
501 os_animation_stop (priv->state_animation, change_state_stop_cb);
502}
503
504/* Move a mask on the bar_window, fake movement. */
428static void505static void
429mask_pager (OsPager *pager)506mask_bar (OsBar *bar)
430{507{
431 OsPagerPrivate *priv;508 OsBarPrivate *priv;
432509
433 priv = pager->priv;510 priv = bar->priv;
434511
435 gdk_window_shape_combine_region (priv->pager_window,512 gdk_window_shape_combine_region (priv->bar_window,
436 SHAPE_REGION(&priv->mask),513 SHAPE_REGION(&priv->bar_mask),
437 0, 0);514 0, 0);
438}515}
439516
440/**517/**
441 * os_pager_move_resize:518 * os_bar_move_resize:
442 * @pager: a #OsPager519 * @bar: a #OsBar
443 * @mask: a #GdkRectangle with the position and dimension of the #OsPager520 * @mask: a #GdkRectangle with the position and dimension of the #OsBar
444 *521 *
445 * Moves and resizes @pager.522 * Moves and resizes @bar.
446 **/523 **/
447void524void
448os_pager_move_resize (OsPager *pager,525os_bar_move_resize (OsBar *bar,
449 GdkRectangle mask)526 GdkRectangle mask)
450{527{
451 OsPagerPrivate *priv;528 OsBarPrivate *priv;
452529
453 g_return_if_fail (OS_IS_PAGER (pager));530 g_return_if_fail (OS_IS_BAR (bar));
454531
455 priv = pager->priv;532 priv = bar->priv;
456533
457 if (!rectangle_changed (priv->mask, mask))534 if (!rectangle_changed (priv->bar_mask, mask))
458 return;535 return;
459536
460 priv->mask = mask;537 priv->bar_mask = mask;
461538
462 if (priv->parent == NULL)539 if (priv->parent == NULL)
463 return;540 return;
464541
465 mask_pager (pager);542 mask_bar (bar);
466}543}
467544
468/**545/**
469 * os_pager_set_active:546 * os_bar_set_active:
470 * @pager: a #OsPager547 * @bar: a #OsBar
471 * @active: whether is active or not548 * @active: whether is active or not
472 * @animation: whether animate it or not549 * @animate: whether animate it or not
473 *550 *
474 * Changes the activity state of @pager.551 * Changes the activity state of @bar.
475 **/552 **/
476void553void
477os_pager_set_active (OsPager *pager,554os_bar_set_active (OsBar *bar,
478 gboolean active,555 gboolean active,
479 gboolean animate)556 gboolean animate)
480{557{
481 OsPagerPrivate *priv;558 OsBarPrivate *priv;
482559
483 g_return_if_fail (OS_IS_PAGER (pager));560 g_return_if_fail (OS_IS_BAR (bar));
484561
485 priv = pager->priv;562 priv = bar->priv;
486563
487 /* Set the state and draw even if there's an animation running, that is564 /* Set the state and draw even if there's a state_animation running, that is
488 * (!animate && os_animation_is_running (priv->animation)). */565 * (!animate && os_animation_is_running (priv->state_animation)). */
489 if ((priv->active != active) ||566 if ((priv->active != active) ||
490 (!animate && os_animation_is_running (priv->animation)))567 (!animate && os_animation_is_running (priv->state_animation)))
491 {568 {
492 gboolean visible;569 gboolean visible;
493570
@@ -496,43 +573,45 @@
496 if (priv->parent == NULL)573 if (priv->parent == NULL)
497 return;574 return;
498575
499 visible = gdk_window_is_visible (priv->pager_window);576 visible = gdk_window_is_visible (priv->bar_window);
500577
501 if (visible)578 if (visible)
502 os_animation_stop (priv->animation, NULL);579 os_animation_stop (priv->state_animation, NULL);
503580
504 if (visible && animate)581 if (visible && animate)
505 {582 {
506 os_animation_set_duration (priv->animation, priv->active ? DURATION_FADE_IN :583 os_animation_set_duration (priv->state_animation, priv->active ? DURATION_FADE_IN :
507 DURATION_FADE_OUT);584 DURATION_FADE_OUT);
508 os_animation_start (priv->animation);585 os_animation_start (priv->state_animation);
509 }586 }
510587
511 if (!visible || !animate)588 if (!visible || !animate)
512 {589 {
513 priv->weight = 1.0f;590 priv->weight = 1.0f;
514591
515 draw_pager (pager);592 draw_bar (bar);
516 }593 }
517 }594 }
518}595}
519596
520/**597/**
521 * os_pager_set_detached:598 * os_bar_set_detached:
522 * @pager: a #OsPager599 * @bar: a #OsBar
523 * @detached: whether the pager is detached or not600 * @detached: whether the bar is detached or not
601 * @animate: whether animate it or not
524 *602 *
525 * Changes the detached state of @pager.603 * Changes the detached state of @bar.
526 **/604 **/
527void605void
528os_pager_set_detached (OsPager *pager,606os_bar_set_detached (OsBar *bar,
529 gboolean detached)607 gboolean detached,
608 gboolean animate)
530{609{
531 OsPagerPrivate *priv;610 OsBarPrivate *priv;
532611
533 g_return_if_fail (OS_IS_PAGER (pager));612 g_return_if_fail (OS_IS_BAR (bar));
534613
535 priv = pager->priv;614 priv = bar->priv;
536615
537 if (priv->detached != detached)616 if (priv->detached != detached)
538 {617 {
@@ -543,27 +622,49 @@
543622
544 if (priv->detached)623 if (priv->detached)
545 {624 {
546 gdk_window_show (priv->connection_window);625 /* If there's a tail animation currently running, stop it. */
547 gdk_window_raise (priv->pager_window);626 os_animation_stop (priv->tail_animation, retract_tail_stop_cb);
627
628 /* No tail connection animation yet. */
629 gdk_window_show (priv->tail_window);
630 gdk_window_raise (priv->bar_window);
631 }
632 else if (animate)
633 {
634 gint32 duration;
635
636 /* The detached state should already stop this. */
637 OS_DCHECK (!os_animation_is_running (priv->tail_animation));
638
639 /* Calculate and set the duration. */
640 if (priv->allocation.height >= priv->allocation.width)
641 duration = MIN_DURATION_TAIL + ((gdouble) priv->tail_mask.height / priv->allocation.height) *
642 (MAX_DURATION_TAIL - MIN_DURATION_TAIL);
643 else
644 duration = MIN_DURATION_TAIL + ((gdouble) priv->tail_mask.width / priv->allocation.width) *
645 (MAX_DURATION_TAIL - MIN_DURATION_TAIL);
646 os_animation_set_duration (priv->tail_animation, duration);
647
648 os_animation_start (priv->tail_animation);
548 }649 }
549 else650 else
550 gdk_window_hide (priv->connection_window);651 gdk_window_hide (priv->tail_window);
551 }652 }
552}653}
553654
554/* Create connection_window and pager_window. */655/* Create tail_window and bar_window. */
555static void656static void
556create_windows (OsPager *pager)657create_windows (OsBar *bar)
557{658{
558 GdkWindowAttr attributes;659 GdkWindowAttr attributes;
559 OsPagerPrivate *priv;660 OsBarPrivate *priv;
560661
561 priv = pager->priv;662 priv = bar->priv;
562663
563 /* Instead reparenting,664 /* Instead reparenting,
564 * which doesn't seem to work well,665 * which doesn't seem to work well,
565 * destroy the two windows. */666 * destroy the two windows. */
566 if (priv->connection_window != NULL)667 if (priv->tail_window != NULL)
567 {668 {
568 /* From the Gdk documentation:669 /* From the Gdk documentation:
569 * "Note that a window will not be destroyed670 * "Note that a window will not be destroyed
@@ -571,13 +672,13 @@
571 * reaches zero. You must call672 * reaches zero. You must call
572 * gdk_window_destroy ()673 * gdk_window_destroy ()
573 * yourself before that happens". */674 * yourself before that happens". */
574 gdk_window_destroy (priv->connection_window);675 gdk_window_destroy (priv->tail_window);
575676
576 g_object_unref (priv->connection_window);677 g_object_unref (priv->tail_window);
577 priv->connection_window = NULL;678 priv->tail_window = NULL;
578 }679 }
579680
580 if (priv->pager_window != NULL)681 if (priv->bar_window != NULL)
581 {682 {
582 /* From the Gdk documentation:683 /* From the Gdk documentation:
583 * "Note that a window will not be destroyed684 * "Note that a window will not be destroyed
@@ -585,10 +686,10 @@
585 * reaches zero. You must call686 * reaches zero. You must call
586 * gdk_window_destroy ()687 * gdk_window_destroy ()
587 * yourself before that happens". */688 * yourself before that happens". */
588 gdk_window_destroy (priv->pager_window);689 gdk_window_destroy (priv->bar_window);
589690
590 g_object_unref (priv->pager_window);691 g_object_unref (priv->bar_window);
591 priv->pager_window = NULL;692 priv->bar_window = NULL;
592 }693 }
593694
594 attributes.event_mask = 0;695 attributes.event_mask = 0;
@@ -601,8 +702,8 @@
601 attributes.colormap = gtk_widget_get_colormap (priv->parent);702 attributes.colormap = gtk_widget_get_colormap (priv->parent);
602#endif703#endif
603704
604 /* connection_window. */705 /* tail_window. */
605 priv->connection_window = gdk_window_new (gtk_widget_get_window (priv->parent),706 priv->tail_window = gdk_window_new (gtk_widget_get_window (priv->parent),
606 &attributes,707 &attributes,
607#ifdef USE_GTK3708#ifdef USE_GTK3
608 GDK_WA_VISUAL);709 GDK_WA_VISUAL);
@@ -610,13 +711,13 @@
610 GDK_WA_VISUAL | GDK_WA_COLORMAP);711 GDK_WA_VISUAL | GDK_WA_COLORMAP);
611#endif712#endif
612713
613 g_object_ref_sink (priv->connection_window);714 g_object_ref_sink (priv->tail_window);
614715
615 gdk_window_set_transient_for (priv->connection_window,716 gdk_window_set_transient_for (priv->tail_window,
616 gtk_widget_get_window (priv->parent));717 gtk_widget_get_window (priv->parent));
617718
618 /* FIXME(Cimi) maybe this is not required with 0 as event mask. */719 /* FIXME(Cimi) maybe this is not required with 0 as event mask. */
619 gdk_window_input_shape_combine_region (priv->connection_window,720 gdk_window_input_shape_combine_region (priv->tail_window,
620#ifdef USE_GTK3721#ifdef USE_GTK3
621 cairo_region_create (),722 cairo_region_create (),
622#else723#else
@@ -624,22 +725,22 @@
624#endif725#endif
625 0, 0);726 0, 0);
626727
627 /* pager_window. */728 /* bar_window. */
628 priv->pager_window = gdk_window_new (gtk_widget_get_window (priv->parent),729 priv->bar_window = gdk_window_new (gtk_widget_get_window (priv->parent),
629 &attributes,730 &attributes,
630#ifdef USE_GTK3731#ifdef USE_GTK3
631 GDK_WA_VISUAL);732 GDK_WA_VISUAL);
632#else733#else
633 GDK_WA_VISUAL | GDK_WA_COLORMAP);734 GDK_WA_VISUAL | GDK_WA_COLORMAP);
634#endif 735#endif
635736
636 g_object_ref_sink (priv->pager_window);737 g_object_ref_sink (priv->bar_window);
637738
638 gdk_window_set_transient_for (priv->pager_window,739 gdk_window_set_transient_for (priv->bar_window,
639 gtk_widget_get_window (priv->parent));740 gtk_widget_get_window (priv->parent));
640741
641 /* FIXME(Cimi) maybe this is not required with 0 as event mask. */742 /* FIXME(Cimi) maybe this is not required with 0 as event mask. */
642 gdk_window_input_shape_combine_region (priv->pager_window,743 gdk_window_input_shape_combine_region (priv->bar_window,
643#ifdef USE_GTK3744#ifdef USE_GTK3
644 cairo_region_create (),745 cairo_region_create (),
645#else746#else
@@ -649,30 +750,30 @@
649}750}
650751
651/**752/**
652 * os_pager_set_parent:753 * os_bar_set_parent:
653 * @pager: a #OsPager754 * @bar: a #OsBar
654 * @parent: a #GtkWidget755 * @parent: a #GtkWidget
655 *756 *
656 * Sets the parent widget757 * Sets the parent widget
657 **/758 **/
658void759void
659os_pager_set_parent (OsPager *pager,760os_bar_set_parent (OsBar *bar,
660 GtkWidget *parent)761 GtkWidget *parent)
661{762{
662 OsPagerPrivate *priv;763 OsBarPrivate *priv;
663764
664 g_return_if_fail (OS_IS_PAGER (pager));765 g_return_if_fail (OS_IS_BAR (bar));
665766
666 priv = pager->priv;767 priv = bar->priv;
667768
668 /* Stop currently running animation. */769 /* Stop currently running animations. */
669 if (priv->animation != NULL)770 if (priv->tail_animation != NULL)
670 os_animation_stop (priv->animation, NULL);771 os_animation_stop (priv->tail_animation, retract_tail_stop_cb);
772 if (priv->state_animation != NULL)
773 os_animation_stop (priv->state_animation, NULL);
671774
672 if (priv->parent != NULL)775 if (priv->parent != NULL)
673 {776 g_object_unref (priv->parent);
674 g_object_unref (priv->parent);
675 }
676777
677 priv->parent = parent;778 priv->parent = parent;
678779
@@ -682,69 +783,67 @@
682783
683 priv->weight = 1.0f;784 priv->weight = 1.0f;
684785
685 create_windows (pager);786 create_windows (bar);
686 draw_connection (pager);787 draw_tail (bar);
687 draw_pager (pager);788 draw_bar (bar);
688 mask_pager (pager);789 mask_bar (bar);
689790
690 gdk_window_move_resize (priv->connection_window,791 gdk_window_move_resize (priv->tail_window,
691 priv->allocation.x,792 priv->allocation.x,
692 priv->allocation.y,793 priv->allocation.y,
693 priv->allocation.width,794 priv->allocation.width,
694 priv->allocation.height);795 priv->allocation.height);
695796
696 gdk_window_move_resize (priv->pager_window,797 gdk_window_move_resize (priv->bar_window,
697 priv->allocation.x,798 priv->allocation.x,
698 priv->allocation.y,799 priv->allocation.y,
699 priv->allocation.width,800 priv->allocation.width,
700 priv->allocation.height);801 priv->allocation.height);
701802
702 if (priv->visible)803 if (priv->visible)
703 {804 gdk_window_show (priv->bar_window);
704 gdk_window_show (priv->pager_window);
705 }
706 }805 }
707}806}
708807
709/**808/**
710 * os_pager_show:809 * os_bar_show:
711 * @pager: a #OsPager810 * @bar: a #OsBar
712 *811 *
713 * Shows @pager.812 * Shows @bar.
714 **/813 **/
715void814void
716os_pager_show (OsPager *pager)815os_bar_show (OsBar *bar)
717{816{
718 OsPagerPrivate *priv;817 OsBarPrivate *priv;
719818
720 g_return_if_fail (OS_IS_PAGER (pager));819 g_return_if_fail (OS_IS_BAR (bar));
721820
722 priv = pager->priv;821 priv = bar->priv;
723822
724 priv->visible = TRUE;823 priv->visible = TRUE;
725824
726 if (priv->parent == NULL)825 if (priv->parent == NULL)
727 return;826 return;
728827
729 gdk_window_show (priv->pager_window);828 gdk_window_show (priv->bar_window);
730}829}
731830
732/**831/**
733 * os_pager_size_allocate:832 * os_bar_size_allocate:
734 * @pager: a #OsPager833 * @bar: a #OsBar
735 * @rectangle: a #GdkRectangle834 * @rectangle: a #GdkRectangle
736 *835 *
737 * Sets the position and dimension of the whole area.836 * Sets the position and dimension of the whole area.
738 **/837 **/
739void838void
740os_pager_size_allocate (OsPager *pager,839os_bar_size_allocate (OsBar *bar,
741 GdkRectangle rectangle)840 GdkRectangle rectangle)
742{841{
743 OsPagerPrivate *priv;842 OsBarPrivate *priv;
744843
745 g_return_if_fail (OS_IS_PAGER (pager));844 g_return_if_fail (OS_IS_BAR (bar));
746845
747 priv = pager->priv;846 priv = bar->priv;
748847
749 if (!rectangle_changed (priv->allocation, rectangle))848 if (!rectangle_changed (priv->allocation, rectangle))
750 return;849 return;
@@ -754,13 +853,13 @@
754 if (priv->parent == NULL)853 if (priv->parent == NULL)
755 return;854 return;
756855
757 gdk_window_move_resize (priv->connection_window,856 gdk_window_move_resize (priv->tail_window,
758 rectangle.x,857 rectangle.x,
759 rectangle.y,858 rectangle.y,
760 rectangle.width,859 rectangle.width,
761 rectangle.height);860 rectangle.height);
762861
763 gdk_window_move_resize (priv->pager_window,862 gdk_window_move_resize (priv->bar_window,
764 rectangle.x,863 rectangle.x,
765 rectangle.y,864 rectangle.y,
766 rectangle.width,865 rectangle.width,
767866
=== modified file 'os/os-private.h'
--- os/os-private.h 2011-10-05 12:24:21 +0000
+++ os/os-private.h 2011-10-12 17:16:23 +0000
@@ -30,7 +30,11 @@
30#pragma GCC visibility push(hidden)30#pragma GCC visibility push(hidden)
31#endif /* __GNUC__ */31#endif /* __GNUC__ */
3232
33/* Rate of the animations (frames per second). */
34#define RATE_ANIMATION 30
35
33/* Size of the thumb in pixels. */36/* Size of the thumb in pixels. */
37#define MIN_THUMB_HEIGHT 35
34#define THUMB_WIDTH 1738#define THUMB_WIDTH 17
35#define THUMB_HEIGHT 6939#define THUMB_HEIGHT 69
3640
@@ -39,14 +43,19 @@
3943
40G_BEGIN_DECLS44G_BEGIN_DECLS
4145
46typedef struct
47{
48 gint x;
49 gint y;
50} OsCoordinate;
51
42typedef enum52typedef enum
43{53{
44 OS_EVENT_NONE = 0,54 OS_EVENT_NONE = 0,
45 OS_EVENT_BUTTON_PRESS = 1,55 OS_EVENT_BUTTON_PRESS = 1,
46 OS_EVENT_ENTER_NOTIFY = 2,56 OS_EVENT_ENTER_NOTIFY = 2,
47 OS_EVENT_MOTION_NOTIFY = 4,57 OS_EVENT_MOTION_NOTIFY = 4
48 OS_EVENT_VALUE_CHANGED = 858} OsEventFlags;
49} OsEvent;
5059
51/* os-log.c */60/* os-log.c */
5261
@@ -150,6 +159,57 @@
150void os_animation_stop (OsAnimation *animation,159void os_animation_stop (OsAnimation *animation,
151 OsAnimationStopFunc stop_func);160 OsAnimationStopFunc stop_func);
152161
162/* os-bar.c */
163
164#define OS_TYPE_BAR (os_bar_get_type ())
165#define OS_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OS_TYPE_BAR, OsBar))
166#define OS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OS_TYPE_BAR, OsBarClass))
167#define OS_IS_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OS_TYPE_BAR))
168#define OS_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OS_TYPE_BAR))
169#define OS_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OS_TYPE_BAR, OsBarClass))
170
171typedef struct _OsBar OsBar;
172typedef struct _OsBarClass OsBarClass;
173typedef struct _OsBarPrivate OsBarPrivate;
174
175struct _OsBar {
176 GObject parent_instance;
177
178 OsBarPrivate *priv;
179};
180
181struct _OsBarClass {
182 GObjectClass parent_class;
183};
184
185GType os_bar_get_type (void) G_GNUC_CONST;
186
187OsBar* os_bar_new (void);
188
189void os_bar_hide (OsBar *bar);
190
191void os_bar_connect (OsBar *bar,
192 GdkRectangle mask);
193
194void os_bar_move_resize (OsBar *bar,
195 GdkRectangle mask);
196
197void os_bar_set_active (OsBar *bar,
198 gboolean active,
199 gboolean animate);
200
201void os_bar_set_detached (OsBar *bar,
202 gboolean detached,
203 gboolean animate);
204
205void os_bar_set_parent (OsBar *bar,
206 GtkWidget *parent);
207
208void os_bar_show (OsBar *bar);
209
210void os_bar_size_allocate (OsBar *bar,
211 GdkRectangle rectangle);
212
153/* os-thumb.c */213/* os-thumb.c */
154214
155#define OS_TYPE_THUMB (os_thumb_get_type ())215#define OS_TYPE_THUMB (os_thumb_get_type ())
@@ -184,56 +244,6 @@
184void os_thumb_set_detached (OsThumb *thumb,244void os_thumb_set_detached (OsThumb *thumb,
185 gboolean detached);245 gboolean detached);
186246
187/* os-pager.c */
188
189#define OS_TYPE_PAGER (os_pager_get_type ())
190#define OS_PAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OS_TYPE_PAGER, OsPager))
191#define OS_PAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OS_TYPE_PAGER, OsPagerClass))
192#define OS_IS_PAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OS_TYPE_PAGER))
193#define OS_IS_PAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OS_TYPE_PAGER))
194#define OS_PAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OS_TYPE_PAGER, OsPagerClass))
195
196typedef struct _OsPager OsPager;
197typedef struct _OsPagerClass OsPagerClass;
198typedef struct _OsPagerPrivate OsPagerPrivate;
199
200struct _OsPager {
201 GObject parent_instance;
202
203 OsPagerPrivate *priv;
204};
205
206struct _OsPagerClass {
207 GObjectClass parent_class;
208};
209
210GType os_pager_get_type (void) G_GNUC_CONST;
211
212OsPager* os_pager_new (void);
213
214void os_pager_hide (OsPager *pager);
215
216void os_pager_connect (OsPager *pager,
217 GdkRectangle mask);
218
219void os_pager_move_resize (OsPager *pager,
220 GdkRectangle mask);
221
222void os_pager_set_active (OsPager *pager,
223 gboolean active,
224 gboolean animate);
225
226void os_pager_set_detached (OsPager *pager,
227 gboolean detached);
228
229void os_pager_set_parent (OsPager *pager,
230 GtkWidget *parent);
231
232void os_pager_show (OsPager *pager);
233
234void os_pager_size_allocate (OsPager *pager,
235 GdkRectangle rectangle);
236
237G_END_DECLS247G_END_DECLS
238248
239#ifdef __GNUC__249#ifdef __GNUC__
240250
=== modified file 'os/os-scrollbar.c'
--- os/os-scrollbar.c 2011-10-05 12:24:21 +0000
+++ os/os-scrollbar.c 2011-10-12 17:16:23 +0000
@@ -34,20 +34,17 @@
34#include <X11/Xutil.h>34#include <X11/Xutil.h>
35#include <X11/extensions/XInput2.h>35#include <X11/extensions/XInput2.h>
3636
37/* Size of the pager in pixels. */37/* Size of the bar in pixels. */
38#define PAGER_SIZE 338#define BAR_SIZE 3
3939
40/* Size of the proximity effect in pixels. */40/* Size of the proximity effect in pixels. */
41#define PROXIMITY_SIZE 3041#define PROXIMITY_SIZE 30
4242
43/* Rate of the paging. */43/* Max duration of the scrolling. */
44#define RATE_PAGING 3044#define MAX_DURATION_SCROLLING 1000
4545
46/* Max duration of the paging. */46/* Min duration of the scrolling. */
47#define MAX_DURATION_PAGING 100047#define MIN_DURATION_SCROLLING 250
48
49/* Min duration of the paging. */
50#define MIN_DURATION_PAGING 250
5148
52/* Timeout assumed for PropertyNotify _NET_ACTIVE_WINDOW event. */49/* Timeout assumed for PropertyNotify _NET_ACTIVE_WINDOW event. */
53#define TIMEOUT_PRESENT_WINDOW 40050#define TIMEOUT_PRESENT_WINDOW 400
@@ -58,6 +55,9 @@
58/* Timeout before hiding in ms, after leaving the thumb. */55/* Timeout before hiding in ms, after leaving the thumb. */
59#define TIMEOUT_THUMB_HIDE 20056#define TIMEOUT_THUMB_HIDE 200
6057
58/* Timeout before showing in ms, after entering the proximity. */
59#define TIMEOUT_THUMB_SHOW 100
60
61/* Timeout before hiding in ms, after leaving the toplevel. */61/* Timeout before hiding in ms, after leaving the toplevel. */
62#define TIMEOUT_TOPLEVEL_HIDE 20062#define TIMEOUT_TOPLEVEL_HIDE 200
6363
@@ -71,48 +71,60 @@
7171
72typedef enum72typedef enum
73{73{
74 OS_STATE_NONE = 0,
75 OS_STATE_CONNECTED = 1,
76 OS_STATE_DETACHED = 2,
77 OS_STATE_FULLSIZE = 4,
78 OS_STATE_INTERNAL = 8,
79 OS_STATE_LOCKED = 16,
80 OS_STATE_RECONNECTING = 32
81} OsStateFlags;
82
83typedef enum
84{
74 OS_STRUT_SIDE_NONE = 0,85 OS_STRUT_SIDE_NONE = 0,
75 OS_STRUT_SIDE_TOP = 1,86 OS_STRUT_SIDE_TOP = 1,
76 OS_STRUT_SIDE_BOTTOM = 2,87 OS_STRUT_SIDE_BOTTOM = 2,
77 OS_STRUT_SIDE_LEFT = 4,88 OS_STRUT_SIDE_LEFT = 4,
78 OS_STRUT_SIDE_RIGHT = 889 OS_STRUT_SIDE_RIGHT = 8
79} OsStrutSide;90} OsStrutSideFlags;
91
92typedef struct
93{
94 gboolean proximity;
95 gboolean running;
96} OsWindowFilter;
8097
81struct _OsScrollbarPrivate98struct _OsScrollbarPrivate
82{99{
83 GdkRectangle overlay;100 GdkRectangle overlay;
84 GdkRectangle slider;101 GdkRectangle slider;
85 GdkRectangle trough;102 GdkRectangle trough;
86 GtkAllocation pager_all;103 GtkAllocation bar_all;
87 GtkAllocation thumb_all;104 GtkAllocation thumb_all;
88 GtkAdjustment *adjustment;105 GtkAdjustment *adjustment;
89 GtkOrientation orientation;106 GtkOrientation orientation;
90 GtkWidget *thumb;107 GtkWidget *thumb;
91 GtkWindowGroup *window_group;108 GtkWindowGroup *window_group;
92 OsAnimation *animation;109 OsAnimation *animation;
93 OsPager *pager;110 OsBar *bar;
111 OsCoordinate pointer;
112 OsCoordinate thumb_win;
113 OsEventFlags event;
114 OsStateFlags state;
94 OsSide side;115 OsSide side;
95 OsEvent event;116 OsWindowFilter filter;
96 gboolean active_window;117 gboolean active_window;
97 gboolean can_deactivate_pager;118 gboolean deactivable_bar;
98 gboolean can_hide;119 gboolean hidable_thumb;
99 gboolean detached_scroll;120 gboolean window_button_press; /* FIXME(Cimi) to replace with X11 input events. */
100 gboolean filter;
101 gboolean fullsize;
102 gboolean internal;
103 gboolean lock_position;
104 gboolean proximity;
105 gboolean toplevel_button_press;
106 gdouble value;121 gdouble value;
107 gint win_x;
108 gint win_y;
109 gint slide_initial_slider_position;122 gint slide_initial_slider_position;
110 gint slide_initial_coordinate;123 gint slide_initial_coordinate;
111 gint pointer_x;
112 gint pointer_y;
113 gint64 present_time;124 gint64 present_time;
114 guint32 source_deactivate_pager_id;125 guint32 source_deactivate_bar_id;
115 guint32 source_hide_thumb_id;126 guint32 source_hide_thumb_id;
127 guint32 source_show_thumb_id;
116 guint32 source_unlock_thumb_id;128 guint32 source_unlock_thumb_id;
117};129};
118130
@@ -159,10 +171,10 @@
159static void os_scrollbar_dispose (GObject *object);171static void os_scrollbar_dispose (GObject *object);
160static void os_scrollbar_finalize (GObject *object);172static void os_scrollbar_finalize (GObject *object);
161173
162/* Calculate pager layout info. */174/* Calculate bar layout info. */
163static void175static void
164calc_layout_pager (OsScrollbar *scrollbar,176calc_layout_bar (OsScrollbar *scrollbar,
165 gdouble adjustment_value)177 gdouble adjustment_value)
166{178{
167 OsScrollbarPrivate *priv;179 OsScrollbarPrivate *priv;
168180
@@ -279,6 +291,23 @@
279 }291 }
280}292}
281293
294/* Calculate the position of the thumb window. */
295static void
296calc_thumb_window_position (OsScrollbar *scrollbar)
297{
298 OsScrollbarPrivate *priv;
299 gint x_pos, y_pos;
300
301 priv = scrollbar->priv;
302
303 /* In reality, I'm storing widget's window, not the toplevel.
304 * Is that the same with gdk_window_get_origin? */
305 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
306
307 priv->thumb_win.x = x_pos + priv->thumb_all.x;
308 priv->thumb_win.y = y_pos + priv->thumb_all.y;
309}
310
282/* Calculate the workarea using _UNITY_NET_WORKAREA_REGION. */311/* Calculate the workarea using _UNITY_NET_WORKAREA_REGION. */
283static void312static void
284calc_workarea (Display *display,313calc_workarea (Display *display,
@@ -327,21 +356,114 @@
327 }356 }
328}357}
329358
330/* Deactivate the pager if it's the case. */359/* Check whether the thumb movement can be considered connected or not. */
331static void360static void
332deactivate_pager (OsScrollbar *scrollbar)361check_connection (OsScrollbar *scrollbar)
333{362{
334 OsScrollbarPrivate *priv;363 OsScrollbarPrivate *priv;
335364 gint x_pos, y_pos;
336 priv = scrollbar->priv;365
337366 priv = scrollbar->priv;
338 if (priv->pager != NULL && priv->can_deactivate_pager)367
339 os_pager_set_active (priv->pager, FALSE, TRUE);368 /* This seems to be required to get proper values. */
340}369 calc_layout_bar (scrollbar, gtk_adjustment_get_value (priv->adjustment));
341370 calc_layout_slider (scrollbar, gtk_adjustment_get_value (priv->adjustment));
342/* Timeout before deactivating the pager. */371
372 gdk_window_get_origin (gtk_widget_get_window (priv->thumb), &x_pos, &y_pos);
373
374 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
375 {
376 if (priv->overlay.height > priv->slider.height)
377 {
378 if (y_pos >= priv->thumb_win.y + priv->overlay.y &&
379 y_pos + priv->slider.height <= priv->thumb_win.y + priv->overlay.y + priv->overlay.height)
380 priv->state |= OS_STATE_CONNECTED;
381 else
382 priv->state &= ~(OS_STATE_CONNECTED);
383 }
384 else
385 {
386 if (y_pos == priv->thumb_win.y + priv->slider.y)
387 priv->state |= OS_STATE_CONNECTED;
388 else
389 priv->state &= ~(OS_STATE_CONNECTED);
390 }
391 }
392 else
393 {
394 if (priv->overlay.width > priv->slider.width)
395 {
396 if (x_pos >= priv->thumb_win.x + priv->overlay.x &&
397 x_pos + priv->slider.width <= priv->thumb_win.x + priv->overlay.x + priv->overlay.width)
398 priv->state |= OS_STATE_CONNECTED;
399 else
400 priv->state &= ~(OS_STATE_CONNECTED);
401 }
402 else
403 {
404 if (x_pos == priv->thumb_win.x + priv->slider.x)
405 priv->state |= OS_STATE_CONNECTED;
406 else
407 priv->state &= ~(OS_STATE_CONNECTED);
408 }
409 }
410}
411
412/* Traduce coordinates into GtkRange values. */
413static gdouble
414coord_to_value (OsScrollbar *scrollbar,
415 gint coord)
416{
417 OsScrollbarPrivate *priv;
418 gdouble frac;
419 gdouble value;
420 gint trough_length;
421 gint slider_length;
422
423 priv = scrollbar->priv;
424
425 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
426 {
427 trough_length = priv->trough.height;
428 slider_length = MAX (priv->slider.height, priv->overlay.height);
429 }
430 else
431 {
432 trough_length = priv->trough.width;
433 slider_length = MAX (priv->slider.width, priv->overlay.width);
434 }
435
436 if (trough_length == slider_length)
437 frac = 1.0;
438 else
439 frac = (MAX (0, coord) / (gdouble) (trough_length - slider_length));
440
441 value = gtk_adjustment_get_lower (priv->adjustment) + frac * (gtk_adjustment_get_upper (priv->adjustment) -
442 gtk_adjustment_get_lower (priv->adjustment) -
443 gtk_adjustment_get_page_size (priv->adjustment));
444
445 value = CLAMP (value,
446 gtk_adjustment_get_lower (priv->adjustment),
447 gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment));
448
449 return value;
450}
451
452/* Deactivate the bar if it's the case. */
453static void
454deactivate_bar (OsScrollbar *scrollbar)
455{
456 OsScrollbarPrivate *priv;
457
458 priv = scrollbar->priv;
459
460 if (priv->bar != NULL && priv->deactivable_bar)
461 os_bar_set_active (priv->bar, FALSE, TRUE);
462}
463
464/* Timeout before deactivating the bar. */
343static gboolean465static gboolean
344deactivate_pager_cb (gpointer user_data)466deactivate_bar_cb (gpointer user_data)
345{467{
346 OsScrollbar *scrollbar;468 OsScrollbar *scrollbar;
347 OsScrollbarPrivate *priv;469 OsScrollbarPrivate *priv;
@@ -351,8 +473,8 @@
351473
352 OS_DCHECK (!priv->active_window);474 OS_DCHECK (!priv->active_window);
353475
354 deactivate_pager (scrollbar);476 deactivate_bar (scrollbar);
355 priv->source_deactivate_pager_id = 0;477 priv->source_deactivate_bar_id = 0;
356478
357 return FALSE;479 return FALSE;
358}480}
@@ -365,7 +487,7 @@
365487
366 priv = scrollbar->priv;488 priv = scrollbar->priv;
367489
368 if (priv->can_hide)490 if (priv->hidable_thumb)
369 gtk_widget_hide (priv->thumb);491 gtk_widget_hide (priv->thumb);
370}492}
371493
@@ -396,9 +518,9 @@
396#endif518#endif
397}519}
398520
399/* Move the pager. */521/* Move the bar. */
400static void522static void
401move_pager (OsScrollbar *scrollbar)523move_bar (OsScrollbar *scrollbar)
402{524{
403 GdkRectangle mask;525 GdkRectangle mask;
404 OsScrollbarPrivate *priv;526 OsScrollbarPrivate *priv;
@@ -409,7 +531,7 @@
409 {531 {
410 mask.x = 0;532 mask.x = 0;
411 mask.y = priv->overlay.y;533 mask.y = priv->overlay.y;
412 mask.width = priv->pager_all.width;534 mask.width = priv->bar_all.width;
413 mask.height = priv->overlay.height;535 mask.height = priv->overlay.height;
414 }536 }
415 else537 else
@@ -417,10 +539,10 @@
417 mask.x = priv->overlay.x;539 mask.x = priv->overlay.x;
418 mask.y = 0;540 mask.y = 0;
419 mask.width = priv->overlay.width;541 mask.width = priv->overlay.width;
420 mask.height = priv->pager_all.height;542 mask.height = priv->bar_all.height;
421 }543 }
422544
423 os_pager_move_resize (priv->pager, mask);545 os_bar_move_resize (priv->bar, mask);
424}546}
425547
426/* Sanitize x coordinate of thumb window. */548/* Sanitize x coordinate of thumb window. */
@@ -481,7 +603,7 @@
481603
482 for (i = 0; i < cairo_region_num_rectangles (struts_region); i++)604 for (i = 0; i < cairo_region_num_rectangles (struts_region); i++)
483 {605 {
484 OsStrutSide strut_side;606 OsStrutSideFlags strut_side;
485 gint count;607 gint count;
486608
487 cairo_region_get_rectangle (struts_region, i, &tmp_rect);609 cairo_region_get_rectangle (struts_region, i, &tmp_rect);
@@ -548,7 +670,7 @@
548 (n_monitor != gdk_screen_get_monitor_at_point (screen, monitor_x + priv->thumb_all.width, y) ||670 (n_monitor != gdk_screen_get_monitor_at_point (screen, monitor_x + priv->thumb_all.width, y) ||
549 monitor_x + priv->thumb_all.width >= screen_width))671 monitor_x + priv->thumb_all.width >= screen_width))
550 {672 {
551 priv->internal = TRUE;673 priv->state |= OS_STATE_INTERNAL;
552 return MAX (x - priv->thumb_all.width, screen_width - priv->thumb_all.width);674 return MAX (x - priv->thumb_all.width, screen_width - priv->thumb_all.width);
553 }675 }
554676
@@ -556,12 +678,12 @@
556 (n_monitor != gdk_screen_get_monitor_at_point (screen, monitor_x - priv->thumb_all.width, y) ||678 (n_monitor != gdk_screen_get_monitor_at_point (screen, monitor_x - priv->thumb_all.width, y) ||
557 monitor_x - priv->thumb_all.width <= screen_x))679 monitor_x - priv->thumb_all.width <= screen_x))
558 {680 {
559 priv->internal = TRUE;681 priv->state |= OS_STATE_INTERNAL;
560 return MAX (x, screen_x);682 return MAX (x, screen_x);
561 }683 }
562684
563 if (priv->orientation == GTK_ORIENTATION_VERTICAL)685 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
564 priv->internal = FALSE;686 priv->state &= ~(OS_STATE_INTERNAL);
565687
566 return x;688 return x;
567}689}
@@ -624,7 +746,7 @@
624746
625 for (i = 0; i < cairo_region_num_rectangles (struts_region); i++)747 for (i = 0; i < cairo_region_num_rectangles (struts_region); i++)
626 {748 {
627 OsStrutSide strut_side;749 OsStrutSideFlags strut_side;
628 gint count;750 gint count;
629751
630 cairo_region_get_rectangle (struts_region, i, &tmp_rect);752 cairo_region_get_rectangle (struts_region, i, &tmp_rect);
@@ -691,7 +813,7 @@
691 (n_monitor != gdk_screen_get_monitor_at_point (screen, x, monitor_y + priv->thumb_all.height) ||813 (n_monitor != gdk_screen_get_monitor_at_point (screen, x, monitor_y + priv->thumb_all.height) ||
692 monitor_y + priv->thumb_all.height >= screen_height))814 monitor_y + priv->thumb_all.height >= screen_height))
693 {815 {
694 priv->internal = TRUE;816 priv->state |= OS_STATE_INTERNAL;
695 return MAX (y - priv->thumb_all.height, screen_height - priv->thumb_all.height);817 return MAX (y - priv->thumb_all.height, screen_height - priv->thumb_all.height);
696 }818 }
697819
@@ -699,12 +821,12 @@
699 (n_monitor != gdk_screen_get_monitor_at_point (screen, x, monitor_y - priv->thumb_all.height) ||821 (n_monitor != gdk_screen_get_monitor_at_point (screen, x, monitor_y - priv->thumb_all.height) ||
700 monitor_y - priv->thumb_all.height <= screen_y))822 monitor_y - priv->thumb_all.height <= screen_y))
701 {823 {
702 priv->internal = TRUE;824 priv->state |= OS_STATE_INTERNAL;
703 return MAX (y, screen_y);825 return MAX (y, screen_y);
704 }826 }
705827
706 if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)828 if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
707 priv->internal = FALSE;829 priv->state &= ~(OS_STATE_INTERNAL);
708830
709 return y;831 return y;
710}832}
@@ -752,10 +874,10 @@
752 swap_thumb (scrollbar, os_thumb_new (priv->orientation));874 swap_thumb (scrollbar, os_thumb_new (priv->orientation));
753}875}
754876
755/* Callback called by the paging animation. */877/* Callback called by the scrolling animation. */
756static void878static void
757paging_cb (gfloat weight,879scrolling_cb (gfloat weight,
758 gpointer user_data)880 gpointer user_data)
759{881{
760 gdouble new_value;882 gdouble new_value;
761 OsScrollbar *scrollbar;883 OsScrollbar *scrollbar;
@@ -779,6 +901,22 @@
779 gtk_adjustment_set_value (priv->adjustment, new_value);901 gtk_adjustment_set_value (priv->adjustment, new_value);
780}902}
781903
904/* End function called by the scrolling animation. */
905static void
906scrolling_end_cb (gpointer user_data)
907{
908 OsScrollbar *scrollbar;
909 OsScrollbarPrivate *priv;
910
911 scrollbar = OS_SCROLLBAR (user_data);
912
913 priv = scrollbar->priv;
914
915 priv->state &= ~(OS_STATE_RECONNECTING);
916
917 check_connection (scrollbar);
918}
919
782/* Swap adjustment pointer. */920/* Swap adjustment pointer. */
783static void921static void
784swap_adjustment (OsScrollbar *scrollbar,922swap_adjustment (OsScrollbar *scrollbar,
@@ -879,8 +1017,8 @@
879 scrollbar = OS_SCROLLBAR (user_data);1017 scrollbar = OS_SCROLLBAR (user_data);
880 priv = scrollbar->priv;1018 priv = scrollbar->priv;
8811019
882 if (priv->can_hide)1020 if (priv->hidable_thumb)
883 priv->lock_position = FALSE;1021 priv->state &= ~(OS_STATE_LOCKED);
8841022
885 priv->source_unlock_thumb_id = 0;1023 priv->source_unlock_thumb_id = 0;
8861024
@@ -899,43 +1037,43 @@
899 scrollbar = OS_SCROLLBAR (user_data);1037 scrollbar = OS_SCROLLBAR (user_data);
900 priv = scrollbar->priv;1038 priv = scrollbar->priv;
9011039
902 /* FIXME(Cimi) we should control each time os_pager_show()/hide()1040 /* FIXME(Cimi) we should control each time os_bar_show ()/hide ()
903 * is called here and in map()/unmap().1041 * is called here and in map ()/unmap ().
904 * We are arbitrary calling that and I'm frightened we should show or keep1042 * We are arbitrary calling that and I'm frightened we should show or keep
905 * hidden a pager that is meant to be hidden/shown.1043 * hidden a bar that is meant to be hidden/shown.
906 * I don't want to see pagers reappearing because1044 * I don't want to see bars reappearing because
907 * of a change in the adjustment of an invisible pager or viceversa. */1045 * of a change in the adjustment of an invisible bar or viceversa. */
908 if (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_lower (adjustment) >1046 if (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_lower (adjustment) >
909 gtk_adjustment_get_page_size (adjustment))1047 gtk_adjustment_get_page_size (adjustment))
910 {1048 {
911 priv->fullsize = FALSE;1049 priv->state &= ~(OS_STATE_FULLSIZE);
912 if (priv->proximity != FALSE)1050 if (priv->filter.proximity)
913 os_pager_show (priv->pager);1051 os_bar_show (priv->bar);
914 }1052 }
915 else1053 else
916 {1054 {
917 priv->fullsize = TRUE;1055 priv->state |= OS_STATE_FULLSIZE;
918 if (priv->proximity != FALSE)1056 if (priv->filter.proximity)
919 {1057 {
920 os_pager_hide (priv->pager);1058 os_bar_hide (priv->bar);
9211059
922 gtk_widget_hide (priv->thumb);1060 gtk_widget_hide (priv->thumb);
923 }1061 }
924 }1062 }
9251063
926 calc_layout_pager (scrollbar, gtk_adjustment_get_value (adjustment));1064 calc_layout_bar (scrollbar, gtk_adjustment_get_value (adjustment));
927 calc_layout_slider (scrollbar, gtk_adjustment_get_value (adjustment));1065 calc_layout_slider (scrollbar, gtk_adjustment_get_value (adjustment));
9281066
929 if (!(priv->event & OS_EVENT_ENTER_NOTIFY) &&1067 if (!(priv->event & OS_EVENT_ENTER_NOTIFY) &&
930 !(priv->event & OS_EVENT_MOTION_NOTIFY))1068 !(priv->event & OS_EVENT_MOTION_NOTIFY))
931 gtk_widget_hide (priv->thumb);1069 gtk_widget_hide (priv->thumb);
9321070
933 move_pager (scrollbar);1071 move_bar (scrollbar);
934}1072}
9351073
936/* Update the visual connection between pager and thumb. */1074/* Update the tail (visual connection) between bar and thumb. */
937static void1075static void
938update_visual_connection (OsScrollbar *scrollbar)1076update_tail (OsScrollbar *scrollbar)
939{1077{
940 OsScrollbarPrivate *priv;1078 OsScrollbarPrivate *priv;
941 gint x_pos, y_pos;1079 gint x_pos, y_pos;
@@ -946,73 +1084,85 @@
9461084
947 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1085 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
948 {1086 {
949 if (priv->win_y + priv->overlay.y >= y_pos + priv->slider.height)1087 if (priv->thumb_win.y + priv->overlay.y >= y_pos + priv->slider.height)
950 {1088 {
951 GdkRectangle mask;1089 GdkRectangle mask;
9521090
953 mask.x = 0;1091 mask.x = 0;
954 mask.y = y_pos + priv->slider.height / 2 - priv->win_y;1092 mask.y = y_pos + priv->slider.height / 2 - priv->thumb_win.y;
955 mask.width = priv->pager_all.width;1093 mask.width = priv->bar_all.width;
956 mask.height = priv->overlay.y - mask.y;1094 mask.height = priv->overlay.y - mask.y;
9571095
958 os_pager_connect (priv->pager, mask);1096 os_bar_connect (priv->bar, mask);
959 os_pager_set_detached (priv->pager, TRUE);1097
9601098 priv->state |= OS_STATE_DETACHED;
1099
1100 os_bar_set_detached (priv->bar, TRUE, FALSE);
961 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);1101 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
962 }1102 }
963 else if (priv->win_y + priv->overlay.y + priv->overlay.height <= y_pos)1103 else if (priv->thumb_win.y + priv->overlay.y + priv->overlay.height <= y_pos)
964 {1104 {
965 GdkRectangle mask;1105 GdkRectangle mask;
9661106
967 mask.x = 0;1107 mask.x = 0;
968 mask.y = priv->overlay.y + priv->overlay.height;1108 mask.y = priv->overlay.y + priv->overlay.height;
969 mask.width = priv->pager_all.width;1109 mask.width = priv->bar_all.width;
970 mask.height = y_pos + priv->slider.height / 2 - priv->win_y - mask.y;1110 mask.height = y_pos + priv->slider.height / 2 - priv->thumb_win.y - mask.y;
9711111
972 os_pager_connect (priv->pager, mask);1112 os_bar_connect (priv->bar, mask);
973 os_pager_set_detached (priv->pager, TRUE);1113
9741114 priv->state |= OS_STATE_DETACHED;
1115
1116 os_bar_set_detached (priv->bar, TRUE, FALSE);
975 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);1117 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
976 }1118 }
977 else 1119 else
978 {1120 {
979 os_pager_set_detached (priv->pager, FALSE);1121 priv->state &= ~(OS_STATE_DETACHED);
1122
1123 os_bar_set_detached (priv->bar, FALSE, FALSE);
980 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);1124 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
981 }1125 }
982 }1126 }
983 else1127 else
984 {1128 {
985 if (priv->win_x + priv->overlay.x >= x_pos + priv->slider.width)1129 if (priv->thumb_win.x + priv->overlay.x >= x_pos + priv->slider.width)
986 {1130 {
987 GdkRectangle mask;1131 GdkRectangle mask;
9881132
989 mask.x = x_pos + priv->slider.width / 2 - priv->win_x;1133 mask.x = x_pos + priv->slider.width / 2 - priv->thumb_win.x;
990 mask.y = 0;1134 mask.y = 0;
991 mask.width = priv->overlay.x - mask.x;1135 mask.width = priv->overlay.x - mask.x;
992 mask.height = priv->pager_all.height;1136 mask.height = priv->bar_all.height;
9931137
994 os_pager_connect (priv->pager, mask);1138 os_bar_connect (priv->bar, mask);
995 os_pager_set_detached (priv->pager, TRUE);1139
9961140 priv->state |= OS_STATE_DETACHED;
1141
1142 os_bar_set_detached (priv->bar, TRUE, FALSE);
997 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);1143 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
998 }1144 }
999 else if (priv->win_x + priv->overlay.x + priv->overlay.width <= x_pos)1145 else if (priv->thumb_win.x + priv->overlay.x + priv->overlay.width <= x_pos)
1000 {1146 {
1001 GdkRectangle mask;1147 GdkRectangle mask;
10021148
1003 mask.x = priv->overlay.x + priv->overlay.width;1149 mask.x = priv->overlay.x + priv->overlay.width;
1004 mask.y = 0;1150 mask.y = 0;
1005 mask.width = x_pos + priv->slider.width / 2 - priv->win_x - mask.x;1151 mask.width = x_pos + priv->slider.width / 2 - priv->thumb_win.x - mask.x;
1006 mask.height = priv->pager_all.height;1152 mask.height = priv->bar_all.height;
10071153
1008 os_pager_connect (priv->pager, mask);1154 os_bar_connect (priv->bar, mask);
1009 os_pager_set_detached (priv->pager, TRUE);1155
10101156 priv->state |= OS_STATE_DETACHED;
1157
1158 os_bar_set_detached (priv->bar, TRUE, FALSE);
1011 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);1159 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
1012 }1160 }
1013 else1161 else
1014 {1162 {
1015 os_pager_set_detached (priv->pager, FALSE);1163 priv->state &= ~(OS_STATE_DETACHED);
1164
1165 os_bar_set_detached (priv->bar, FALSE, FALSE);
1016 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);1166 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
1017 }1167 }
1018 }1168 }
@@ -1028,35 +1178,28 @@
1028 scrollbar = OS_SCROLLBAR (user_data);1178 scrollbar = OS_SCROLLBAR (user_data);
1029 priv = scrollbar->priv;1179 priv = scrollbar->priv;
10301180
1031 calc_layout_pager (scrollbar, gtk_adjustment_get_value (adjustment));1181 calc_layout_bar (scrollbar, gtk_adjustment_get_value (adjustment));
1032 calc_layout_slider (scrollbar, gtk_adjustment_get_value (adjustment));1182 calc_layout_slider (scrollbar, gtk_adjustment_get_value (adjustment));
10331183
1034 if (!(priv->event & OS_EVENT_ENTER_NOTIFY) &&1184 if (!(priv->event & OS_EVENT_ENTER_NOTIFY) &&
1035 !(priv->event & OS_EVENT_MOTION_NOTIFY))1185 !(priv->event & OS_EVENT_MOTION_NOTIFY))
1036 gtk_widget_hide (priv->thumb);1186 gtk_widget_hide (priv->thumb);
10371187
1038 if (gtk_widget_get_mapped (priv->thumb))1188 if (gtk_widget_get_mapped (priv->thumb) &&
1039 {1189 !((priv->event & OS_EVENT_MOTION_NOTIFY) &&
1040 /* If we're dragging the thumb, it can't be detached. */1190 (priv->state & OS_STATE_CONNECTED)))
1041 if (priv->event & OS_EVENT_MOTION_NOTIFY)1191 update_tail (scrollbar);
1042 {
1043 os_pager_set_detached (priv->pager, FALSE);
1044 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
1045 }
1046 else
1047 update_visual_connection (scrollbar);
1048 }
10491192
1050 move_pager (scrollbar);1193 move_bar (scrollbar);
1051}1194}
10521195
1053/* Pager functions. */1196/* Bar functions. */
10541197
1055/* Set the state of the pager checking mouse position. */1198/* Set the state of the bar checking mouse position. */
1056static void1199static void
1057pager_set_state_from_pointer (OsScrollbar *scrollbar,1200bar_set_state_from_pointer (OsScrollbar *scrollbar,
1058 gint x,1201 gint x,
1059 gint y)1202 gint y)
1060{1203{
1061 GtkAllocation allocation;1204 GtkAllocation allocation;
1062 OsScrollbarPrivate *priv;1205 OsScrollbarPrivate *priv;
@@ -1070,13 +1213,13 @@
1070 if ((x > allocation.x && x < allocation.x + allocation.width) &&1213 if ((x > allocation.x && x < allocation.x + allocation.width) &&
1071 (y > allocation.y && y < allocation.y + allocation.height))1214 (y > allocation.y && y < allocation.y + allocation.height))
1072 {1215 {
1073 priv->can_deactivate_pager = FALSE;1216 priv->deactivable_bar = FALSE;
1074 os_pager_set_active (priv->pager, TRUE, TRUE);1217 os_bar_set_active (priv->bar, TRUE, TRUE);
1075 }1218 }
1076 else1219 else
1077 {1220 {
1078 priv->can_deactivate_pager = TRUE;1221 priv->deactivable_bar = TRUE;
1079 os_pager_set_active (priv->pager, FALSE, TRUE);1222 os_bar_set_active (priv->bar, FALSE, TRUE);
1080 }1223 }
1081}1224}
10821225
@@ -1105,16 +1248,16 @@
1105 gdk_screen_get_active_window (gtk_widget_get_screen (GTK_WIDGET (scrollbar))))1248 gdk_screen_get_active_window (gtk_widget_get_screen (GTK_WIDGET (scrollbar))))
1106 {1249 {
1107 /* Stops potential running timeout. */1250 /* Stops potential running timeout. */
1108 if (priv->source_deactivate_pager_id != 0)1251 if (priv->source_deactivate_bar_id != 0)
1109 {1252 {
1110 g_source_remove (priv->source_deactivate_pager_id);1253 g_source_remove (priv->source_deactivate_bar_id);
1111 priv->source_deactivate_pager_id = 0;1254 priv->source_deactivate_bar_id = 0;
1112 }1255 }
11131256
1114 priv->active_window = TRUE;1257 priv->active_window = TRUE;
11151258
1116 priv->can_deactivate_pager = FALSE;1259 priv->deactivable_bar = FALSE;
1117 os_pager_set_active (priv->pager, TRUE, TRUE);1260 os_bar_set_active (priv->bar, TRUE, TRUE);
1118 }1261 }
1119 else if (priv->active_window)1262 else if (priv->active_window)
1120 {1263 {
@@ -1147,13 +1290,13 @@
1147 /* When the window is unfocused,1290 /* When the window is unfocused,
1148 * check the position of the pointer1291 * check the position of the pointer
1149 * and set the state accordingly. */1292 * and set the state accordingly. */
1150 pager_set_state_from_pointer (scrollbar, x, y);1293 bar_set_state_from_pointer (scrollbar, x, y);
1151 }1294 }
1152 else1295 else
1153 {1296 {
1154 /* If the pointer is outside of the window, set it inactive. */1297 /* If the pointer is outside of the window, set it inactive. */
1155 priv->can_deactivate_pager = TRUE;1298 priv->deactivable_bar = TRUE;
1156 os_pager_set_active (priv->pager, FALSE, TRUE);1299 os_bar_set_active (priv->bar, FALSE, TRUE);
1157 }1300 }
11581301
1159 if ((current_time > end_time) && priv->thumb != NULL)1302 if ((current_time > end_time) && priv->thumb != NULL)
@@ -1251,7 +1394,8 @@
1251{1394{
1252 if (event->type == GDK_BUTTON_PRESS)1395 if (event->type == GDK_BUTTON_PRESS)
1253 {1396 {
1254 if (event->button == 1)1397 if (event->button == 1 ||
1398 event->button == 2)
1255 {1399 {
1256 OsScrollbar *scrollbar;1400 OsScrollbar *scrollbar;
1257 OsScrollbarPrivate *priv;1401 OsScrollbarPrivate *priv;
@@ -1268,7 +1412,60 @@
1268 priv->event |= OS_EVENT_BUTTON_PRESS;1412 priv->event |= OS_EVENT_BUTTON_PRESS;
1269 priv->event &= ~(OS_EVENT_MOTION_NOTIFY);1413 priv->event &= ~(OS_EVENT_MOTION_NOTIFY);
12701414
1271 priv->detached_scroll = FALSE;1415 if (event->button == 2)
1416 {
1417 /* Reconnect the thumb with the bar. */
1418 gdouble new_value;
1419 gint c, delta;
1420 gint32 duration;
1421
1422 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1423 {
1424 priv->slide_initial_slider_position = event->y_root - priv->thumb_win.y - event->y;
1425 priv->slide_initial_coordinate = event->y_root;
1426
1427 delta = event->y_root - priv->slide_initial_coordinate;
1428 }
1429 else
1430 {
1431 priv->slide_initial_slider_position = event->x_root - priv->thumb_win.x - event->x;
1432 priv->slide_initial_coordinate = event->x_root;
1433
1434 delta = event->x_root - priv->slide_initial_coordinate;
1435 }
1436
1437 c = priv->slide_initial_slider_position + delta;
1438
1439 /* If a scrolling animation is running,
1440 * stop it and add the new value. */
1441 os_animation_stop (priv->animation, NULL);
1442
1443 new_value = coord_to_value (scrollbar, c);
1444
1445 /* Only start the animation if needed. */
1446 if (new_value != gtk_adjustment_get_value (priv->adjustment))
1447 {
1448 priv->state |= OS_STATE_RECONNECTING;
1449
1450 priv->value = new_value;
1451
1452 /* Calculate and set the duration. */
1453 if (priv->value > gtk_adjustment_get_value (priv->adjustment))
1454 duration = MIN_DURATION_SCROLLING + ((priv->value - gtk_adjustment_get_value (priv->adjustment)) /
1455 (gtk_adjustment_get_upper (priv->adjustment) -
1456 gtk_adjustment_get_lower (priv->adjustment))) *
1457 (MAX_DURATION_SCROLLING - MIN_DURATION_SCROLLING);
1458 else
1459 duration = MIN_DURATION_SCROLLING + ((gtk_adjustment_get_value (priv->adjustment) - priv->value) /
1460 (gtk_adjustment_get_upper (priv->adjustment) -
1461 gtk_adjustment_get_lower (priv->adjustment))) *
1462 (MAX_DURATION_SCROLLING - MIN_DURATION_SCROLLING);
1463 os_animation_set_duration (priv->animation, duration);
1464
1465 /* Start the scrolling animation. */
1466 os_animation_start (priv->animation);
1467 }
1468 }
12721469
1273 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1470 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1274 {1471 {
@@ -1281,8 +1478,8 @@
1281 priv->slide_initial_coordinate = event->x_root;1478 priv->slide_initial_coordinate = event->x_root;
1282 }1479 }
12831480
1284 priv->pointer_x = event->x;1481 priv->pointer.x = event->x;
1285 priv->pointer_y = event->y;1482 priv->pointer.y = event->y;
1286 }1483 }
1287 }1484 }
12881485
@@ -1299,7 +1496,7 @@
12991496
1300 priv = scrollbar->priv;1497 priv = scrollbar->priv;
13011498
1302 /* If a paging animation is running,1499 /* If a scrolling animation is running,
1303 * stop it and add the new value. */1500 * stop it and add the new value. */
1304 if (os_animation_is_running (priv->animation))1501 if (os_animation_is_running (priv->animation))
1305 {1502 {
@@ -1314,13 +1511,17 @@
1314 gtk_adjustment_get_lower (priv->adjustment),1511 gtk_adjustment_get_lower (priv->adjustment),
1315 gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment));1512 gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment));
13161513
1514 /* There's no need to do start a new animation. */
1515 if (priv->value == gtk_adjustment_get_value (priv->adjustment))
1516 return;
1517
1317 /* Calculate and set the duration. */1518 /* Calculate and set the duration. */
1318 duration = MIN_DURATION_PAGING + ((priv->value - gtk_adjustment_get_value (priv->adjustment)) /1519 duration = MIN_DURATION_SCROLLING + ((priv->value - gtk_adjustment_get_value (priv->adjustment)) /
1319 gtk_adjustment_get_page_increment (priv->adjustment)) *1520 gtk_adjustment_get_page_increment (priv->adjustment)) *
1320 (MAX_DURATION_PAGING - MIN_DURATION_PAGING);1521 (MAX_DURATION_SCROLLING - MIN_DURATION_SCROLLING);
1321 os_animation_set_duration (priv->animation, duration);1522 os_animation_set_duration (priv->animation, duration);
13221523
1323 /* Start the paging animation. */1524 /* Start the scrolling animation. */
1324 os_animation_start (priv->animation);1525 os_animation_start (priv->animation);
1325}1526}
13261527
@@ -1334,7 +1535,7 @@
13341535
1335 priv = scrollbar->priv;1536 priv = scrollbar->priv;
13361537
1337 /* If a paging animation is running,1538 /* If a scrolling animation is running,
1338 * stop it and subtract the new value. */1539 * stop it and subtract the new value. */
1339 if (os_animation_is_running (priv->animation))1540 if (os_animation_is_running (priv->animation))
1340 {1541 {
@@ -1349,13 +1550,17 @@
1349 gtk_adjustment_get_lower (priv->adjustment),1550 gtk_adjustment_get_lower (priv->adjustment),
1350 gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment));1551 gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment));
13511552
1553 /* There's no need to do start a new animation. */
1554 if (priv->value == gtk_adjustment_get_value (priv->adjustment))
1555 return;
1556
1352 /* Calculate and set the duration. */1557 /* Calculate and set the duration. */
1353 duration = MIN_DURATION_PAGING + ((gtk_adjustment_get_value (priv->adjustment) - priv->value) /1558 duration = MIN_DURATION_SCROLLING + ((gtk_adjustment_get_value (priv->adjustment) - priv->value) /
1354 gtk_adjustment_get_page_increment (priv->adjustment)) *1559 gtk_adjustment_get_page_increment (priv->adjustment)) *
1355 (MAX_DURATION_PAGING - MIN_DURATION_PAGING);1560 (MAX_DURATION_SCROLLING - MIN_DURATION_SCROLLING);
1356 os_animation_set_duration (priv->animation, duration);1561 os_animation_set_duration (priv->animation, duration);
13571562
1358 /* Start the paging animation. */1563 /* Start the scrolling animation. */
1359 os_animation_start (priv->animation);1564 os_animation_start (priv->animation);
1360}1565}
13611566
@@ -1366,7 +1571,8 @@
1366{1571{
1367 if (event->type == GDK_BUTTON_RELEASE)1572 if (event->type == GDK_BUTTON_RELEASE)
1368 {1573 {
1369 if (event->button == 1)1574 if (event->button == 1 ||
1575 event->button == 2)
1370 {1576 {
1371 OsScrollbar *scrollbar;1577 OsScrollbar *scrollbar;
1372 OsScrollbarPrivate *priv;1578 OsScrollbarPrivate *priv;
@@ -1376,24 +1582,23 @@
13761582
1377 gtk_window_set_transient_for (GTK_WINDOW (widget), NULL);1583 gtk_window_set_transient_for (GTK_WINDOW (widget), NULL);
13781584
1379 if (!(priv->event & OS_EVENT_MOTION_NOTIFY) && !priv->detached_scroll)1585 if (event->button == 1 &&
1586 !(priv->event & OS_EVENT_MOTION_NOTIFY))
1380 {1587 {
1381 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1588 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1382 {1589 {
1383 if (priv->pointer_y < priv->slider.height / 2)1590 if (priv->pointer.y < priv->slider.height / 2)
1384 page_up (scrollbar);1591 page_up (scrollbar);
1385 else1592 else
1386 page_down (scrollbar);1593 page_down (scrollbar);
1387 }1594 }
1388 else1595 else
1389 {1596 {
1390 if (priv->pointer_x < priv->slider.width / 2)1597 if (priv->pointer.x < priv->slider.width / 2)
1391 page_up (scrollbar);1598 page_up (scrollbar);
1392 else1599 else
1393 page_down (scrollbar);1600 page_down (scrollbar);
1394 }1601 }
1395
1396 priv->event |= OS_EVENT_VALUE_CHANGED;
1397 }1602 }
13981603
1399 priv->event &= ~(OS_EVENT_BUTTON_PRESS | OS_EVENT_MOTION_NOTIFY);1604 priv->event &= ~(OS_EVENT_BUTTON_PRESS | OS_EVENT_MOTION_NOTIFY);
@@ -1416,11 +1621,11 @@
14161621
1417 priv->event |= OS_EVENT_ENTER_NOTIFY;1622 priv->event |= OS_EVENT_ENTER_NOTIFY;
14181623
1419 priv->can_deactivate_pager = FALSE;1624 priv->deactivable_bar = FALSE;
1420 priv->can_hide = FALSE;1625 priv->hidable_thumb = FALSE;
14211626
1422 if (priv->internal)1627 if (priv->state & OS_STATE_INTERNAL)
1423 priv->lock_position = TRUE;1628 priv->state |= OS_STATE_LOCKED;
14241629
1425 return FALSE;1630 return FALSE;
1426}1631}
@@ -1440,20 +1645,20 @@
1440 * not interacting with the thumb. */1645 * not interacting with the thumb. */
1441 if (!(priv->event & OS_EVENT_BUTTON_PRESS))1646 if (!(priv->event & OS_EVENT_BUTTON_PRESS))
1442 {1647 {
1443 /* Never deactivate the pager in an active window. */1648 /* Never deactivate the bar in an active window. */
1444 if (!priv->active_window)1649 if (!priv->active_window)
1445 {1650 {
1446 priv->can_deactivate_pager = TRUE;1651 priv->deactivable_bar = TRUE;
14471652
1448 if (priv->source_deactivate_pager_id != 0)1653 if (priv->source_deactivate_bar_id != 0)
1449 g_source_remove (priv->source_deactivate_pager_id);1654 g_source_remove (priv->source_deactivate_bar_id);
14501655
1451 priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_THUMB_HIDE,1656 priv->source_deactivate_bar_id = g_timeout_add (TIMEOUT_THUMB_HIDE,
1452 deactivate_pager_cb,1657 deactivate_bar_cb,
1453 scrollbar);1658 scrollbar);
1454 }1659 }
14551660
1456 priv->can_hide = TRUE;1661 priv->hidable_thumb = TRUE;
14571662
1458 if (priv->source_hide_thumb_id != 0)1663 if (priv->source_hide_thumb_id != 0)
1459 g_source_remove (priv->source_hide_thumb_id);1664 g_source_remove (priv->source_hide_thumb_id);
@@ -1481,9 +1686,9 @@
1481 scrollbar = OS_SCROLLBAR (user_data);1686 scrollbar = OS_SCROLLBAR (user_data);
1482 priv = scrollbar->priv;1687 priv = scrollbar->priv;
14831688
1484 /* Immediately set the pager to be active. */1689 /* Immediately set the bar to be active. */
1485 priv->can_deactivate_pager = FALSE;1690 priv->deactivable_bar = FALSE;
1486 os_pager_set_active (priv->pager, TRUE, FALSE);1691 os_bar_set_active (priv->bar, TRUE, FALSE);
14871692
1488 xid = GDK_WINDOW_XID (gtk_widget_get_window (widget));1693 xid = GDK_WINDOW_XID (gtk_widget_get_window (widget));
1489 xid_parent = GDK_WINDOW_XID (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (scrollbar))));1694 xid_parent = GDK_WINDOW_XID (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (scrollbar))));
@@ -1542,46 +1747,6 @@
1542 }1747 }
1543}1748}
15441749
1545/* Traduce coordinates into GtkRange values. */
1546static gdouble
1547coord_to_value (OsScrollbar *scrollbar,
1548 gint coord)
1549{
1550 OsScrollbarPrivate *priv;
1551 gdouble frac;
1552 gdouble value;
1553 gint trough_length;
1554 gint slider_length;
1555
1556 priv = scrollbar->priv;
1557
1558 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1559 {
1560 trough_length = priv->trough.height;
1561 slider_length = MAX (priv->slider.height, priv->overlay.height);
1562 }
1563 else
1564 {
1565 trough_length = priv->trough.width;
1566 slider_length = MAX (priv->slider.width, priv->overlay.width);
1567 }
1568
1569 if (trough_length == slider_length)
1570 frac = 1.0;
1571 else
1572 frac = (MAX (0, coord) / (gdouble) (trough_length - slider_length));
1573
1574 value = gtk_adjustment_get_lower (priv->adjustment) + frac * (gtk_adjustment_get_upper (priv->adjustment) -
1575 gtk_adjustment_get_lower (priv->adjustment) -
1576 gtk_adjustment_get_page_size (priv->adjustment));
1577
1578 value = CLAMP (value,
1579 gtk_adjustment_get_lower (priv->adjustment),
1580 gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment));
1581
1582 return value;
1583}
1584
1585/* From pointer movement, set adjustment value. */1750/* From pointer movement, set adjustment value. */
1586static void1751static void
1587capture_movement (OsScrollbar *scrollbar,1752capture_movement (OsScrollbar *scrollbar,
@@ -1622,184 +1787,214 @@
1622 {1787 {
1623 gint x, y;1788 gint x, y;
16241789
1625 /* Thumb and pager are detached.1790 /* Use tolerance at the first calls to this motion notify event. */
1626 * Detached scroll: keep the thumb detached during the scroll,1791 if (!(priv->event & OS_EVENT_MOTION_NOTIFY) &&
1627 * update the visual connection when reaching an edge. */1792 abs (priv->pointer.x - event->x) <= TOLERANCE_MOTION &&
1628 if (priv->event & OS_EVENT_VALUE_CHANGED)1793 abs (priv->pointer.y - event->y) <= TOLERANCE_MOTION)
1629 {1794 return FALSE;
1630 /* Return if the mouse movement is small. */1795
1631 if (abs (priv->pointer_x - event->x) <= TOLERANCE_MOTION &&1796 if (!(priv->event & OS_EVENT_MOTION_NOTIFY))
1632 abs (priv->pointer_y - event->y) <= TOLERANCE_MOTION)1797 {
1633 return FALSE;1798 /* Check if we can consider the thumb movement connected with the overlay. */
16341799 check_connection (scrollbar);
1635 priv->detached_scroll = TRUE;1800
16361801 priv->event |= OS_EVENT_MOTION_NOTIFY;
1637 /* Stop the paging animation if it's running. */1802 }
1638 os_animation_stop (priv->animation, NULL);1803
1804 /* Before stopping the animation,
1805 * check if it's reconnecting.
1806 * In this case we need to update the slide values
1807 * with the current position. */
1808 if (os_animation_is_running (priv->animation))
1809 {
1810 if (priv->state & OS_STATE_RECONNECTING)
1811 {
1812 /* It's a reconnecting animation. */
1813 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1814 {
1815 priv->slide_initial_slider_position = MIN (priv->slider.y, priv->overlay.y);
1816 priv->slide_initial_coordinate = event->y_root;
1817 }
1818 else
1819 {
1820 priv->slide_initial_slider_position = MIN (priv->slider.x, priv->overlay.x);
1821 priv->slide_initial_coordinate = event->x_root;
1822 }
1823 }
1824 else
1825 {
1826 /* Stop the paging animation now. */
1827 os_animation_stop (priv->animation, NULL);
1828 }
1829 }
1830
1831 /* Behave differently when the thumb is connected or not. */
1832 if (priv->state & OS_STATE_CONNECTED)
1833 {
1834 /* This is a connected scroll,
1835 * the thumb movement is kept in sync with the overlay. */
1836
1837 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1838 {
1839 if (priv->overlay.height > priv->slider.height)
1840 {
1841 /* Limit x and y within the overlay. */
1842 x = priv->thumb_win.x;
1843 y = CLAMP (event->y_root - priv->pointer.y,
1844 priv->thumb_win.y + priv->overlay.y,
1845 priv->thumb_win.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
1846 }
1847 else
1848 {
1849 x = priv->thumb_win.x;
1850 y = priv->thumb_win.y + priv->slider.y;
1851 }
1852 }
1853 else
1854 {
1855 if (priv->overlay.width > priv->slider.width)
1856 {
1857 /* Limit x and y within the overlay. */
1858 x = CLAMP (event->x_root - priv->pointer.x,
1859 priv->thumb_win.x + priv->overlay.x,
1860 priv->thumb_win.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
1861 y = priv->thumb_win.y;
1862 }
1863 else
1864 {
1865 x = priv->thumb_win.x + priv->slider.x;
1866 y = priv->thumb_win.y;
1867 }
1868 }
1869
1870 /* There's no need to stop animations,
1871 * since the reconnecting animation should not have
1872 * state OS_STATE_CONNECTED, unless it's ended.
1873 * Just capture the movement and change adjustment's value (scroll). */
1874 capture_movement (scrollbar, event->x_root, event->y_root);
1875 }
1876 else
1877 {
1878 /* This is a fine scroll, works subtly different.
1879 * It has to take care of reconnection,
1880 * and scrolling is not allowed when hitting an edge. */
16391881
1640 /* Limit x and y within the allocation. */1882 /* Limit x and y within the allocation. */
1641 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1883 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1642 {1884 {
1643 x = priv->win_x;1885 x = priv->thumb_win.x;
1644 y = CLAMP (event->y_root - priv->pointer_y,1886 y = CLAMP (event->y_root - priv->pointer.y,
1645 priv->win_y,1887 priv->thumb_win.y,
1646 priv->win_y + priv->thumb_all.height - priv->slider.height);1888 priv->thumb_win.y + priv->thumb_all.height - priv->slider.height);
1647 }1889 }
1648 else1890 else
1649 {1891 {
1650 x = CLAMP (event->x_root - priv->pointer_x,1892 x = CLAMP (event->x_root - priv->pointer.x,
1651 priv->win_x,1893 priv->thumb_win.x,
1652 priv->win_x + priv->thumb_all.width - priv->slider.width);1894 priv->thumb_win.x + priv->thumb_all.width - priv->slider.width);
1653 y = priv->win_y;1895 y = priv->thumb_win.y;
1654 }1896 }
16551897
1656 /* Fine scroll while detached,1898 /* Fine scroll while detached,
1657 * do not scroll when hitting an edge. */1899 * do not scroll when hitting an edge. */
1658 if ((priv->orientation == GTK_ORIENTATION_VERTICAL &&1900 if ((priv->orientation == GTK_ORIENTATION_VERTICAL &&
1659 y > priv->win_y &&1901 y > priv->thumb_win.y &&
1660 y < priv->win_y + priv->thumb_all.height - priv->slider.height) ||1902 y < priv->thumb_win.y + priv->thumb_all.height - priv->slider.height) ||
1661 (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&1903 (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
1662 x > priv->win_x &&1904 x > priv->thumb_win.x &&
1663 x < priv->win_x + priv->thumb_all.width - priv->slider.width))1905 x < priv->thumb_win.x + priv->thumb_all.width - priv->slider.width))
1664 capture_movement (scrollbar, event->x_root, event->y_root);1906 {
16651907 /* Stop the animation now.
1666 move_thumb (scrollbar, x, y);1908 * Only the reconnecting animation can be running now,
16671909 * because the paging animations were stop before. */
1668 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1910 os_animation_stop (priv->animation, NULL);
1669 {1911
1670 if (gtk_adjustment_get_value (priv->adjustment) == 0)1912 /* Capture the movement and change adjustment's value (scroll). */
1671 {1913 capture_movement (scrollbar, event->x_root, event->y_root);
1672 update_visual_connection (scrollbar); 1914 }
16731915 else if (!os_animation_is_running (priv->animation) &&
1674 if (priv->overlay.height > priv->slider.height)1916 !(priv->state & OS_STATE_DETACHED))
1675 {1917 {
1676 priv->slide_initial_slider_position = 0;1918 /* Animate scrolling till reaches the edge. */
1677 priv->slide_initial_coordinate = MAX (event->y_root, priv->win_y + priv->pointer_y);1919 if ((priv->orientation == GTK_ORIENTATION_VERTICAL && y <= priv->thumb_win.y) ||
1678 }1920 (priv->orientation == GTK_ORIENTATION_HORIZONTAL && x <= priv->thumb_win.x))
1679 else1921 priv->value = gtk_adjustment_get_lower (priv->adjustment);
1680 {1922 else
1681 priv->slide_initial_slider_position = 0;1923 priv->value = gtk_adjustment_get_upper (priv->adjustment) -
1682 priv->slide_initial_coordinate = event->y_root;1924 gtk_adjustment_get_page_size (priv->adjustment);
1683 }1925
1684 }1926 /* Proceed with the reconnection only if needed. */
1685 else if (priv->overlay.y + priv->overlay.height >= priv->trough.height)1927 if (priv->value != gtk_adjustment_get_value (priv->adjustment))
1686 {1928 {
1687 update_visual_connection (scrollbar);1929 /* If the thumb is not detached, proceed with reconnection. */
16881930 priv->state |= OS_STATE_RECONNECTING;
1689 if (priv->overlay.height > priv->slider.height)1931
1690 {1932 os_animation_set_duration (priv->animation, MIN_DURATION_SCROLLING);
1691 priv->slide_initial_slider_position = priv->trough.height - priv->overlay.height;1933
1692 priv->slide_initial_coordinate = MAX (event->y_root, priv->win_y + priv->pointer_y);1934 /* Start the scrolling animation. */
1693 }1935 os_animation_start (priv->animation);
1694 else1936 }
1695 {1937 }
1696 priv->slide_initial_slider_position = priv->trough.height - priv->slider.height;1938 }
1697 priv->slide_initial_coordinate = event->y_root;1939
1698 }1940 /* Move the thumb window. */
1699 }
1700 }
1701 else
1702 {
1703 if (gtk_adjustment_get_value (priv->adjustment) == 0)
1704 {
1705 update_visual_connection (scrollbar);
1706
1707 if (priv->overlay.width > priv->slider.width)
1708 {
1709 priv->slide_initial_slider_position = 0;
1710 priv->slide_initial_coordinate = MAX (event->x_root, priv->win_x + priv->pointer_x);
1711 }
1712 else
1713 {
1714 priv->slide_initial_slider_position = 0;
1715 priv->slide_initial_coordinate = event->x_root;
1716 }
1717 }
1718 else if (priv->overlay.x + priv->overlay.width >= priv->trough.width)
1719 {
1720 update_visual_connection (scrollbar);
1721
1722 if (priv->overlay.width > priv->slider.width)
1723 {
1724 priv->slide_initial_slider_position = priv->trough.width - priv->overlay.width;
1725 priv->slide_initial_coordinate = MAX (event->x_root, priv->win_x + priv->pointer_x);
1726 }
1727 else
1728 {
1729 priv->slide_initial_slider_position = priv->trough.width - priv->slider.width;
1730 priv->slide_initial_coordinate = event->x_root;
1731 }
1732 }
1733 }
1734
1735 return FALSE;
1736 }
1737
1738 OS_DCHECK (!priv->detached_scroll);
1739
1740 /* Thumb and pager are connected.
1741 * Normal scroll: keep the thumb in sync with the pager,
1742 * do not update the visual connection. */
1743 priv->event |= OS_EVENT_MOTION_NOTIFY;
1744
1745 capture_movement (scrollbar, event->x_root, event->y_root);
1746
1747 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1748 {
1749 if (priv->overlay.height > priv->slider.height)
1750 {
1751 /* Limit x and y within the overlay. */
1752 x = priv->win_x;
1753 y = CLAMP (event->y_root - priv->pointer_y,
1754 priv->win_y + priv->overlay.y,
1755 priv->win_y + priv->overlay.y + priv->overlay.height - priv->slider.height);
1756
1757 if (gtk_adjustment_get_value (priv->adjustment) == 0)
1758 {
1759 priv->slide_initial_slider_position = 0;
1760 priv->slide_initial_coordinate = MAX (event->y_root, priv->win_y + priv->pointer_y);
1761 }
1762 else if (priv->overlay.y + priv->overlay.height >= priv->trough.height)
1763 {
1764 priv->slide_initial_slider_position = priv->trough.height - priv->overlay.height;
1765 priv->slide_initial_coordinate = MAX (event->y_root, priv->win_y + priv->pointer_y);
1766 }
1767 }
1768 else
1769 {
1770 x = priv->win_x;
1771 y = priv->win_y + priv->slider.y;
1772 }
1773 }
1774 else
1775 {
1776 if (priv->overlay.width > priv->slider.width)
1777 {
1778 /* Limit x and y within the overlay. */
1779 x = CLAMP (event->x_root - priv->pointer_x,
1780 priv->win_x + priv->overlay.x,
1781 priv->win_x + priv->overlay.x + priv->overlay.width - priv->slider.width);
1782 y = priv->win_y;
1783
1784 if (gtk_adjustment_get_value (priv->adjustment) == 0)
1785 {
1786 priv->slide_initial_slider_position = 0;
1787 priv->slide_initial_coordinate = MAX (event->x_root, priv->win_x + priv->pointer_x);
1788 }
1789 else if (priv->overlay.x + priv->overlay.width >= priv->trough.width)
1790 {
1791 priv->slide_initial_slider_position = priv->trough.width - priv->overlay.width;
1792 priv->slide_initial_coordinate = MAX (event->x_root, priv->win_x + priv->pointer_x);
1793 }
1794 }
1795 else
1796 {
1797 x = priv->win_x + priv->slider.x;
1798 y = priv->win_y;
1799 }
1800 }
1801
1802 move_thumb (scrollbar, x, y);1941 move_thumb (scrollbar, x, y);
1942
1943 /* Adjust slide values in some special situations,
1944 * update the tail if the thumb is detached and
1945 * check if the movement changed the thumb state to connected. */
1946 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1947 {
1948 if (gtk_adjustment_get_value (priv->adjustment) <= gtk_adjustment_get_lower (priv->adjustment))
1949 {
1950 if (priv->state & OS_STATE_DETACHED)
1951 update_tail (scrollbar);
1952
1953 if (!(priv->state & OS_STATE_CONNECTED))
1954 check_connection (scrollbar);
1955
1956 priv->slide_initial_slider_position = 0;
1957 priv->slide_initial_coordinate = MAX (event->y_root, priv->thumb_win.y + priv->pointer.y);
1958 }
1959 else if (priv->overlay.y + priv->overlay.height >= priv->trough.height)
1960 {
1961 if (priv->state & OS_STATE_DETACHED)
1962 update_tail (scrollbar);
1963
1964 if (!(priv->state & OS_STATE_CONNECTED))
1965 check_connection (scrollbar);
1966
1967 priv->slide_initial_slider_position = priv->trough.height - MAX (priv->overlay.height, priv->slider.height);
1968 priv->slide_initial_coordinate = MIN (event->y_root, (priv->thumb_win.y + priv->trough.height -
1969 priv->slider.height + priv->pointer.y));
1970 }
1971 }
1972 else
1973 {
1974 if (gtk_adjustment_get_value (priv->adjustment) <= gtk_adjustment_get_lower (priv->adjustment))
1975 {
1976 if (priv->state & OS_STATE_DETACHED)
1977 update_tail (scrollbar);
1978
1979 if (!(priv->state & OS_STATE_CONNECTED))
1980 check_connection (scrollbar);
1981
1982 priv->slide_initial_slider_position = 0;
1983 priv->slide_initial_coordinate = MAX (event->x_root, priv->thumb_win.x + priv->pointer.x);
1984 }
1985 else if (priv->overlay.x + priv->overlay.width >= priv->trough.width)
1986 {
1987 if (priv->state & OS_STATE_DETACHED)
1988 update_tail (scrollbar);
1989
1990 if (!(priv->state & OS_STATE_CONNECTED))
1991 check_connection (scrollbar);
1992
1993 priv->slide_initial_slider_position = priv->trough.width - MAX (priv->overlay.width, priv->slider.width);
1994 priv->slide_initial_coordinate = MIN (event->x_root, (priv->thumb_win.x + priv->trough.width -
1995 priv->slider.width + priv->pointer.x));
1996 }
1997 }
1803 }1998 }
18041999
1805 return FALSE;2000 return FALSE;
@@ -1836,11 +2031,9 @@
1836 scrollbar = OS_SCROLLBAR (user_data);2031 scrollbar = OS_SCROLLBAR (user_data);
1837 priv = scrollbar->priv;2032 priv = scrollbar->priv;
18382033
1839 /* Stop the paging animation if it's running. */2034 /* Stop the scrolling animation if it's running. */
1840 os_animation_stop (priv->animation, NULL);2035 os_animation_stop (priv->animation, NULL);
18412036
1842 priv->event |= OS_EVENT_VALUE_CHANGED;
1843
1844 delta = get_wheel_delta (scrollbar, event->direction);2037 delta = get_wheel_delta (scrollbar, event->direction);
18452038
1846 gtk_adjustment_set_value (priv->adjustment,2039 gtk_adjustment_set_value (priv->adjustment,
@@ -1849,6 +2042,25 @@
1849 (gtk_adjustment_get_upper (priv->adjustment) -2042 (gtk_adjustment_get_upper (priv->adjustment) -
1850 gtk_adjustment_get_page_size (priv->adjustment))));2043 gtk_adjustment_get_page_size (priv->adjustment))));
18512044
2045 /* Deal with simultaneous events. */
2046 if (priv->event & OS_EVENT_BUTTON_PRESS)
2047 {
2048 priv->event &= ~(OS_EVENT_MOTION_NOTIFY);
2049
2050 /* we need to update the slide values
2051 * with the current position. */
2052 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
2053 {
2054 priv->slide_initial_slider_position = MIN (priv->slider.y, priv->overlay.y);
2055 priv->slide_initial_coordinate = event->y_root;
2056 }
2057 else
2058 {
2059 priv->slide_initial_slider_position = MIN (priv->slider.x, priv->overlay.x);
2060 priv->slide_initial_coordinate = event->x_root;
2061 }
2062 }
2063
1852 return FALSE;2064 return FALSE;
1853}2065}
18542066
@@ -1863,31 +2075,28 @@
1863 priv = scrollbar->priv;2075 priv = scrollbar->priv;
18642076
1865 priv->event = OS_EVENT_NONE;2077 priv->event = OS_EVENT_NONE;
18662078 priv->hidable_thumb = TRUE;
1867 priv->detached_scroll = FALSE;2079
18682080 /* Remove running hide timeout, if there is one. */
1869 os_pager_set_detached (priv->pager, FALSE);2081 if (priv->source_hide_thumb_id != 0)
2082 {
2083 g_source_remove (priv->source_hide_thumb_id);
2084 priv->source_hide_thumb_id = 0;
2085 }
2086
2087 /* This could hardly still be running,
2088 * but it is not impossible. */
2089 if (priv->source_show_thumb_id != 0)
2090 {
2091 g_source_remove (priv->source_show_thumb_id);
2092 priv->source_show_thumb_id = 0;
2093 }
2094
2095 os_bar_set_detached (priv->bar, FALSE, TRUE);
1870}2096}
18712097
1872/* Toplevel functions. */2098/* Toplevel functions. */
18732099
1874/* Store the position of the toplevel window. */
1875static void
1876store_toplevel_position (OsScrollbar *scrollbar)
1877{
1878 OsScrollbarPrivate *priv;
1879 gint x_pos, y_pos;
1880
1881 priv = scrollbar->priv;
1882
1883 /* In reality, I'm storing widget's window, not the toplevel.
1884 * Is that the same with gdk_window_get_origin? */
1885 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
1886
1887 priv->win_x = x_pos + priv->thumb_all.x;
1888 priv->win_y = y_pos + priv->thumb_all.y;
1889}
1890
1891static gboolean2100static gboolean
1892toplevel_configure_event_cb (GtkWidget *widget,2101toplevel_configure_event_cb (GtkWidget *widget,
1893 GdkEventConfigure *event,2102 GdkEventConfigure *event,
@@ -1902,7 +2111,7 @@
1902 * and the configure-event happens after2111 * and the configure-event happens after
1903 * the PropertyNotify _NET_ACTIVE_WINDOW event,2112 * the PropertyNotify _NET_ACTIVE_WINDOW event,
1904 * see if the mouse pointer is over this window, if TRUE,2113 * see if the mouse pointer is over this window, if TRUE,
1905 * proceed with pager_set_state_from_pointer. */2114 * proceed with bar_set_state_from_pointer (). */
1906 if (!is_insensitive (scrollbar) &&2115 if (!is_insensitive (scrollbar) &&
1907 (current_time > end_time) &&2116 (current_time > end_time) &&
1908 gtk_widget_get_mapped (GTK_WIDGET (scrollbar)))2117 gtk_widget_get_mapped (GTK_WIDGET (scrollbar)))
@@ -1932,34 +2141,67 @@
1932 /* When the window is resized (maximize/restore),2141 /* When the window is resized (maximize/restore),
1933 * check the position of the pointer2142 * check the position of the pointer
1934 * and set the state accordingly. */2143 * and set the state accordingly. */
1935 pager_set_state_from_pointer (scrollbar, x, y);2144 bar_set_state_from_pointer (scrollbar, x, y);
1936 }2145 }
1937 }2146 }
1938 else2147 else
1939 {2148 {
1940 priv->can_deactivate_pager = FALSE;2149 priv->deactivable_bar = FALSE;
1941 os_pager_set_active (priv->pager, TRUE, TRUE);2150 os_bar_set_active (priv->bar, TRUE, TRUE);
1942 }2151 }
1943 }2152 }
19442153
1945 if (current_time > end_time)2154 if (current_time > end_time)
1946 gtk_widget_hide (priv->thumb);2155 gtk_widget_hide (priv->thumb);
19472156
1948 priv->lock_position = FALSE;2157 priv->state &= ~(OS_STATE_LOCKED);
19492158
1950 calc_layout_pager (scrollbar, gtk_adjustment_get_value (priv->adjustment));2159 calc_layout_bar (scrollbar, gtk_adjustment_get_value (priv->adjustment));
1951 calc_layout_slider (scrollbar, gtk_adjustment_get_value (priv->adjustment));2160 calc_layout_slider (scrollbar, gtk_adjustment_get_value (priv->adjustment));
19522161
1953 store_toplevel_position (scrollbar);2162 calc_thumb_window_position (scrollbar);
19542163
1955 return FALSE;2164 return FALSE;
1956}2165}
19572166
2167/* widget's window functions. */
2168
2169/* Move the thumb in the proximity area. */
2170static void
2171adjust_thumb_position (OsScrollbar *scrollbar,
2172 gdouble event_x,
2173 gdouble event_y)
2174{
2175 OsScrollbarPrivate *priv;
2176 gint x, y, x_pos, y_pos;
2177
2178 priv = scrollbar->priv;
2179
2180 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2181
2182 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
2183 {
2184 x = priv->thumb_all.x;
2185 y = CLAMP (event_y - priv->slider.height / 2,
2186 priv->thumb_all.y,
2187 priv->thumb_all.y + priv->thumb_all.height - priv->slider.height);
2188 }
2189 else
2190 {
2191 x = CLAMP (event_x - priv->slider.width / 2,
2192 priv->thumb_all.x,
2193 priv->thumb_all.x + priv->thumb_all.width - priv->slider.width);
2194 y = priv->thumb_all.y;
2195 }
2196
2197 move_thumb (scrollbar, x_pos + x, y_pos + y);
2198}
2199
1958/* Checks if the pointer is in the proximity area. */2200/* Checks if the pointer is in the proximity area. */
1959static gboolean2201static gboolean
1960check_proximity (OsScrollbar *scrollbar,2202check_proximity (OsScrollbar *scrollbar,
1961 gint x,2203 gint x,
1962 gint y)2204 gint y)
1963{2205{
1964 OsScrollbarPrivate *priv;2206 OsScrollbarPrivate *priv;
19652207
@@ -1968,28 +2210,28 @@
1968 switch (priv->side)2210 switch (priv->side)
1969 {2211 {
1970 case OS_SIDE_RIGHT:2212 case OS_SIDE_RIGHT:
1971 return (x >= priv->pager_all.x + priv->pager_all.width - PROXIMITY_SIZE &&2213 return (x >= priv->bar_all.x + priv->bar_all.width - PROXIMITY_SIZE &&
1972 x <= priv->pager_all.x + priv->pager_all.width) &&2214 x <= priv->bar_all.x + priv->bar_all.width) &&
1973 (y >= priv->pager_all.y + priv->overlay.y &&2215 (y >= priv->bar_all.y &&
1974 y <= priv->pager_all.y + priv->overlay.y + priv->overlay.height);2216 y <= priv->bar_all.y + priv->bar_all.height);
1975 break;2217 break;
1976 case OS_SIDE_BOTTOM:2218 case OS_SIDE_BOTTOM:
1977 return (y >= priv->pager_all.y + priv->pager_all.height - PROXIMITY_SIZE &&2219 return (y >= priv->bar_all.y + priv->bar_all.height - PROXIMITY_SIZE &&
1978 y <= priv->pager_all.y + priv->pager_all.height) &&2220 y <= priv->bar_all.y + priv->bar_all.height) &&
1979 (x >= priv->pager_all.x + priv->overlay.x &&2221 (x >= priv->bar_all.x &&
1980 x <= priv->pager_all.x + priv->overlay.x + priv->overlay.width);2222 x <= priv->bar_all.x + priv->bar_all.width);
1981 break;2223 break;
1982 case OS_SIDE_LEFT:2224 case OS_SIDE_LEFT:
1983 return (x <= priv->pager_all.x + priv->pager_all.width + PROXIMITY_SIZE &&2225 return (x <= priv->bar_all.x + priv->bar_all.width + PROXIMITY_SIZE &&
1984 x >= priv->pager_all.x) &&2226 x >= priv->bar_all.x) &&
1985 (y >= priv->pager_all.y + priv->overlay.y &&2227 (y >= priv->bar_all.y &&
1986 y <= priv->pager_all.y + priv->overlay.y + priv->overlay.height);2228 y <= priv->bar_all.y + priv->bar_all.height);
1987 break;2229 break;
1988 case OS_SIDE_TOP:2230 case OS_SIDE_TOP:
1989 return (y <= priv->pager_all.y + priv->pager_all.height + PROXIMITY_SIZE &&2231 return (y <= priv->bar_all.y + priv->bar_all.height + PROXIMITY_SIZE &&
1990 y >= priv->pager_all.y) &&2232 y >= priv->bar_all.y) &&
1991 (x >= priv->pager_all.x + priv->overlay.x &&2233 (x >= priv->bar_all.x &&
1992 x <= priv->pager_all.x + priv->overlay.x + priv->overlay.width);2234 x <= priv->bar_all.x + priv->bar_all.width);
1993 break;2235 break;
1994 default:2236 default:
1995 break;2237 break;
@@ -1998,6 +2240,64 @@
1998 return FALSE;2240 return FALSE;
1999}2241}
20002242
2243/* Callback that shows the thumb if it's the case. */
2244static gboolean
2245show_thumb_cb (gpointer user_data)
2246{
2247 OsScrollbar *scrollbar;
2248 OsScrollbarPrivate *priv;
2249
2250 scrollbar = OS_SCROLLBAR (user_data);
2251 priv = scrollbar->priv;
2252
2253 if (!priv->hidable_thumb)
2254 {
2255 gtk_widget_show (priv->thumb);
2256
2257 update_tail (scrollbar);
2258 }
2259
2260 priv->source_show_thumb_id = 0;
2261
2262 return FALSE;
2263}
2264
2265/* Adds a timeout to reveal the thumb. */
2266static void
2267show_thumb (OsScrollbar *scrollbar)
2268{
2269 OsScrollbarPrivate *priv;
2270
2271 priv = scrollbar->priv;
2272
2273 /* Just update the tail if the thumb is already mapped. */
2274 if (gtk_widget_get_mapped (priv->thumb))
2275 {
2276 update_tail (scrollbar);
2277 return;
2278 }
2279
2280 if (priv->state & OS_STATE_INTERNAL)
2281 {
2282 /* If the scrollbar is close to one edge of the screen,
2283 * show it immediately, ignoring the timeout,
2284 * to preserve Fitts' law. */
2285 if (priv->source_show_thumb_id != 0)
2286 {
2287 g_source_remove (priv->source_show_thumb_id);
2288 priv->source_show_thumb_id = 0;
2289 }
2290
2291 gtk_widget_show (priv->thumb);
2292
2293 update_tail (scrollbar);
2294 }
2295 else if (priv->source_show_thumb_id == 0)
2296 priv->source_show_thumb_id = g_timeout_add (TIMEOUT_THUMB_SHOW,
2297 show_thumb_cb,
2298 scrollbar);
2299}
2300
2001/* Filter function applied to the toplevel window. */2301/* Filter function applied to the toplevel window. */
2002#ifdef USE_GTK32302#ifdef USE_GTK3
2003typedef enum2303typedef enum
@@ -2025,10 +2325,10 @@
20252325
2026 xev = gdkxevent;2326 xev = gdkxevent;
20272327
2028 g_return_val_if_fail (OS_IS_PAGER (priv->pager), GDK_FILTER_CONTINUE);2328 g_return_val_if_fail (OS_IS_BAR (priv->bar), GDK_FILTER_CONTINUE);
2029 g_return_val_if_fail (OS_IS_THUMB (priv->thumb), GDK_FILTER_CONTINUE);2329 g_return_val_if_fail (OS_IS_THUMB (priv->thumb), GDK_FILTER_CONTINUE);
20302330
2031 if (!priv->fullsize)2331 if (!(priv->state & OS_STATE_FULLSIZE))
2032 {2332 {
2033 OsXEvent os_xevent;2333 OsXEvent os_xevent;
2034 gdouble event_x, event_y;2334 gdouble event_x, event_y;
@@ -2092,101 +2392,72 @@
20922392
2093 if (os_xevent == OS_XEVENT_BUTTON_PRESS)2393 if (os_xevent == OS_XEVENT_BUTTON_PRESS)
2094 {2394 {
2095 priv->toplevel_button_press = TRUE;2395 priv->window_button_press = TRUE;
2396
2397 if (priv->source_show_thumb_id != 0)
2398 {
2399 g_source_remove (priv->source_show_thumb_id);
2400 priv->source_show_thumb_id = 0;
2401 }
2402
2096 gtk_widget_hide (priv->thumb);2403 gtk_widget_hide (priv->thumb);
2097 }2404 }
20982405
2099 if (priv->toplevel_button_press && os_xevent == OS_XEVENT_BUTTON_RELEASE)2406 if (priv->window_button_press && os_xevent == OS_XEVENT_BUTTON_RELEASE)
2100 {2407 {
2101 priv->toplevel_button_press = FALSE;2408 priv->window_button_press = FALSE;
21022409
2103 /* Proximity area. */2410 /* Proximity area. */
2104 if (priv->orientation == GTK_ORIENTATION_VERTICAL)2411 if (check_proximity (scrollbar, event_x, event_y))
2105 {2412 {
2106 if (check_proximity (scrollbar, event_x, event_y))2413 priv->hidable_thumb = FALSE;
2107 {2414
2108 priv->can_hide = FALSE;2415 if (priv->state & OS_STATE_LOCKED)
21092416 return GDK_FILTER_CONTINUE;
2110 if (priv->lock_position)2417
2111 return GDK_FILTER_CONTINUE;2418 adjust_thumb_position (scrollbar, event_x, event_y);
21122419
2113 if (priv->overlay.height > priv->slider.height)2420 gtk_widget_show (priv->thumb);
2114 {2421
2115 gint x, y, x_pos, y_pos;2422 update_tail (scrollbar);
2116
2117 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2118
2119 x = priv->thumb_all.x;
2120 y = CLAMP (event_y - priv->slider.height / 2,
2121 priv->thumb_all.y + priv->overlay.y,
2122 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
2123
2124 move_thumb (scrollbar, x_pos + x, y_pos + y);
2125 }
2126 else
2127 {
2128 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
2129 }
2130
2131 gtk_widget_show (priv->thumb);
2132 }
2133 }
2134 else
2135 {
2136 if (check_proximity (scrollbar, event_x, event_y))
2137 {
2138 priv->can_hide = FALSE;
2139
2140 if (priv->lock_position)
2141 return GDK_FILTER_CONTINUE;
2142
2143 if (priv->overlay.width > priv->slider.width)
2144 {
2145 gint x, y, x_pos, y_pos;
2146
2147 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2148
2149 x = CLAMP (event_x - priv->slider.width / 2,
2150 priv->thumb_all.x + priv->overlay.x,
2151 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
2152 y = priv->thumb_all.y;
2153
2154 move_thumb (scrollbar, x_pos + x, y_pos + y);
2155 }
2156 else
2157 {
2158 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
2159 }
2160
2161 gtk_widget_show (priv->thumb);
2162 }
2163 }2423 }
2164 }2424 }
21652425
2166 if (os_xevent == OS_XEVENT_LEAVE)2426 if (os_xevent == OS_XEVENT_LEAVE)
2167 {2427 {
2168 /* Never deactivate the pager in an active window. */2428 priv->window_button_press = FALSE;
2429
2430 /* Never deactivate the bar in an active window. */
2169 if (!priv->active_window)2431 if (!priv->active_window)
2170 {2432 {
2171 priv->can_deactivate_pager = TRUE;2433 priv->deactivable_bar = TRUE;
21722434
2173 if (priv->source_deactivate_pager_id != 0)2435 if (priv->source_deactivate_bar_id != 0)
2174 g_source_remove (priv->source_deactivate_pager_id);2436 g_source_remove (priv->source_deactivate_bar_id);
21752437
2176 priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,2438 priv->source_deactivate_bar_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
2177 deactivate_pager_cb,2439 deactivate_bar_cb,
2178 scrollbar);2440 scrollbar);
2179 }2441 }
21802442
2181 priv->toplevel_button_press = FALSE;2443 if (gtk_widget_get_mapped (priv->thumb) &&
2182 priv->can_hide = TRUE;2444 !(priv->event & OS_EVENT_BUTTON_PRESS))
21832445 {
2184 if (priv->source_hide_thumb_id != 0)2446 priv->hidable_thumb = TRUE;
2185 g_source_remove (priv->source_hide_thumb_id);2447
21862448 if (priv->source_hide_thumb_id != 0)
2187 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,2449 g_source_remove (priv->source_hide_thumb_id);
2188 hide_thumb_cb,2450
2189 scrollbar);2451 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
2452 hide_thumb_cb,
2453 scrollbar);
2454 }
2455
2456 if (priv->source_show_thumb_id != 0)
2457 {
2458 g_source_remove (priv->source_show_thumb_id);
2459 priv->source_show_thumb_id = 0;
2460 }
21902461
2191 if (priv->source_unlock_thumb_id != 0)2462 if (priv->source_unlock_thumb_id != 0)
2192 g_source_remove (priv->source_unlock_thumb_id);2463 g_source_remove (priv->source_unlock_thumb_id);
@@ -2197,107 +2468,47 @@
2197 }2468 }
21982469
2199 /* Get the motion_notify_event trough XEvent. */2470 /* Get the motion_notify_event trough XEvent. */
2200 if (!priv->toplevel_button_press && os_xevent == OS_XEVENT_MOTION)2471 if (!priv->window_button_press && os_xevent == OS_XEVENT_MOTION)
2201 {2472 {
2202 /* React to motion_notify_event2473 /* React to motion_notify_event
2203 * and set the state accordingly. */2474 * and set the state accordingly. */
2204 if (!is_insensitive (scrollbar) && !priv->active_window)2475 if (!is_insensitive (scrollbar) && !priv->active_window)
2205 pager_set_state_from_pointer (scrollbar, event_x, event_y);2476 bar_set_state_from_pointer (scrollbar, event_x, event_y);
22062477
2207 /* Proximity area. */2478 /* Proximity area. */
2208 if (priv->orientation == GTK_ORIENTATION_VERTICAL)2479 if (check_proximity (scrollbar, event_x, event_y))
2209 {2480 {
2210 if (check_proximity (scrollbar, event_x, event_y))2481 priv->hidable_thumb = FALSE;
2211 {2482
2212 priv->can_hide = FALSE;2483 if (priv->source_hide_thumb_id != 0)
22132484 {
2214 if (priv->source_hide_thumb_id != 0)2485 g_source_remove (priv->source_hide_thumb_id);
2215 {2486 priv->source_hide_thumb_id = 0;
2216 g_source_remove (priv->source_hide_thumb_id);2487 }
2217 priv->source_hide_thumb_id = 0;2488
2218 }2489 if (priv->state & OS_STATE_LOCKED)
22192490 return GDK_FILTER_CONTINUE;
2220 if (priv->lock_position)2491
2221 return GDK_FILTER_CONTINUE;2492 adjust_thumb_position (scrollbar, event_x, event_y);
22222493
2223 if (priv->overlay.height > priv->slider.height)2494 show_thumb (scrollbar);
2224 {
2225 gint x, y, x_pos, y_pos;
2226
2227 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2228
2229 x = priv->thumb_all.x;
2230 y = CLAMP (event_y - priv->slider.height / 2,
2231 priv->thumb_all.y + priv->overlay.y,
2232 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
2233
2234 move_thumb (scrollbar, x_pos + x, y_pos + y);
2235 }
2236 else
2237 {
2238 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
2239 }
2240
2241 os_pager_set_detached (priv->pager, FALSE);
2242 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
2243 gtk_widget_show (priv->thumb);
2244 }
2245 else
2246 {
2247 priv->can_hide = TRUE;
2248 priv->lock_position = FALSE;
2249
2250 if (gtk_widget_get_mapped (priv->thumb) &&
2251 priv->source_hide_thumb_id == 0)
2252 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_PROXIMITY_HIDE,
2253 hide_thumb_cb,
2254 scrollbar);
2255 }
2256 }2495 }
2257 else2496 else
2258 {2497 {
2259 if (check_proximity (scrollbar, event_x, event_y))2498 priv->state &= ~(OS_STATE_LOCKED);
2499
2500 if (priv->source_show_thumb_id != 0)
2260 {2501 {
2261 priv->can_hide = FALSE;2502 g_source_remove (priv->source_show_thumb_id);
22622503 priv->source_show_thumb_id = 0;
2263 if (priv->source_hide_thumb_id != 0)
2264 {
2265 g_source_remove (priv->source_hide_thumb_id);
2266 priv->source_hide_thumb_id = 0;
2267 }
2268
2269 if (priv->lock_position)
2270 return GDK_FILTER_CONTINUE;
2271
2272 if (priv->overlay.width > priv->slider.width)
2273 {
2274 gint x, y, x_pos, y_pos;
2275
2276 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2277
2278 x = CLAMP (event_x - priv->slider.width / 2,
2279 priv->thumb_all.x + priv->overlay.x,
2280 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
2281 y = priv->thumb_all.y;
2282
2283 move_thumb (scrollbar, x_pos + x, y_pos + y);
2284 }
2285 else
2286 {
2287 move_thumb (scrollbar, priv->win_x + priv->slider.x, priv->win_y);
2288 }
2289
2290 os_pager_set_detached (priv->pager, FALSE);
2291 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
2292 gtk_widget_show (priv->thumb);
2293 }2504 }
2294 else2505
2506 if (gtk_widget_get_mapped (priv->thumb) &&
2507 !(priv->event & OS_EVENT_BUTTON_PRESS))
2295 {2508 {
2296 priv->can_hide = TRUE;2509 priv->hidable_thumb = TRUE;
2297 priv->lock_position = FALSE;
22982510
2299 if (gtk_widget_get_mapped (priv->thumb) &&2511 if (priv->source_hide_thumb_id == 0)
2300 priv->source_hide_thumb_id == 0)
2301 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_PROXIMITY_HIDE,2512 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_PROXIMITY_HIDE,
2302 hide_thumb_cb,2513 hide_thumb_cb,
2303 scrollbar);2514 scrollbar);
@@ -2325,120 +2536,79 @@
23252536
2326 xev = gdkxevent;2537 xev = gdkxevent;
23272538
2328 g_return_val_if_fail (OS_IS_PAGER (priv->pager), GDK_FILTER_CONTINUE);2539 g_return_val_if_fail (OS_IS_BAR (priv->bar), GDK_FILTER_CONTINUE);
2329 g_return_val_if_fail (OS_IS_THUMB (priv->thumb), GDK_FILTER_CONTINUE);2540 g_return_val_if_fail (OS_IS_THUMB (priv->thumb), GDK_FILTER_CONTINUE);
23302541
2331 if (!priv->fullsize)2542 if (!(priv->state & OS_STATE_FULLSIZE))
2332 {2543 {
2333 if (xev->type == ButtonPress)2544 if (xev->type == ButtonPress)
2334 {2545 {
2335 priv->toplevel_button_press = TRUE;2546 priv->window_button_press = TRUE;
2547
2548 if (priv->source_show_thumb_id != 0)
2549 {
2550 g_source_remove (priv->source_show_thumb_id);
2551 priv->source_show_thumb_id = 0;
2552 }
2553
2336 gtk_widget_hide (priv->thumb);2554 gtk_widget_hide (priv->thumb);
2337 }2555 }
23382556
2339 if (priv->toplevel_button_press && xev->type == ButtonRelease)2557 if (priv->window_button_press && xev->type == ButtonRelease)
2340 {2558 {
2341 priv->toplevel_button_press = FALSE;2559 priv->window_button_press = FALSE;
23422560
2343 /* Proximity area. */2561 /* Proximity area. */
2344 if (priv->orientation == GTK_ORIENTATION_VERTICAL)2562 if (check_proximity (scrollbar, xev->xbutton.x, xev->xbutton.y))
2345 {2563 {
2346 if (check_proximity (scrollbar, xev->xbutton.x, xev->xbutton.y))2564 priv->hidable_thumb = FALSE;
2347 {2565
2348 priv->can_hide = FALSE;2566 if (priv->state & OS_STATE_LOCKED)
23492567 return GDK_FILTER_CONTINUE;
2350 if (priv->source_hide_thumb_id != 0)2568
2351 {2569 adjust_thumb_position (scrollbar, xev->xbutton.x, xev->xbutton.y);
2352 g_source_remove (priv->source_hide_thumb_id);2570
2353 priv->source_hide_thumb_id = 0;2571 gtk_widget_show (priv->thumb);
2354 }2572
23552573 update_tail (scrollbar);
2356 if (priv->lock_position)
2357 return GDK_FILTER_CONTINUE;
2358
2359 if (priv->overlay.height > priv->slider.height)
2360 {
2361 gint x, y, x_pos, y_pos;
2362
2363 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2364
2365 x = priv->thumb_all.x;
2366 y = CLAMP (xev->xbutton.y - priv->slider.height / 2,
2367 priv->thumb_all.y + priv->overlay.y,
2368 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
2369
2370 move_thumb (scrollbar, x_pos + x, y_pos + y);
2371 }
2372 else
2373 {
2374 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
2375 }
2376
2377 gtk_widget_show (priv->thumb);
2378 }
2379 }
2380 else
2381 {
2382 if (check_proximity (scrollbar, xev->xbutton.x, xev->xbutton.y))
2383 {
2384 priv->can_hide = FALSE;
2385
2386 if (priv->source_hide_thumb_id != 0)
2387 {
2388 g_source_remove (priv->source_hide_thumb_id);
2389 priv->source_hide_thumb_id = 0;
2390 }
2391
2392 if (priv->lock_position)
2393 return GDK_FILTER_CONTINUE;
2394
2395 if (priv->overlay.width > priv->slider.width)
2396 {
2397 gint x, y, x_pos, y_pos;
2398
2399 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2400
2401 x = CLAMP (xev->xbutton.x - priv->slider.width / 2,
2402 priv->thumb_all.x + priv->overlay.x,
2403 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
2404 y = priv->thumb_all.y;
2405
2406 move_thumb (scrollbar, x_pos + x, y_pos + y);
2407 }
2408 else
2409 {
2410 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
2411 }
2412
2413 gtk_widget_show (priv->thumb);
2414 }
2415 }2574 }
2416 }2575 }
24172576
2418 if (xev->type == LeaveNotify)2577 if (xev->type == LeaveNotify)
2419 {2578 {
2420 /* Never deactivate the pager in an active window. */2579 priv->window_button_press = FALSE;
2580
2581 /* Never deactivate the bar in an active window. */
2421 if (!priv->active_window)2582 if (!priv->active_window)
2422 {2583 {
2423 priv->can_deactivate_pager = TRUE;2584 priv->deactivable_bar = TRUE;
24242585
2425 if (priv->source_deactivate_pager_id != 0)2586 if (priv->source_deactivate_bar_id != 0)
2426 g_source_remove (priv->source_deactivate_pager_id);2587 g_source_remove (priv->source_deactivate_bar_id);
24272588
2428 priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,2589 priv->source_deactivate_bar_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
2429 deactivate_pager_cb,2590 deactivate_bar_cb,
2430 scrollbar);2591 scrollbar);
2431 }2592 }
24322593
2433 priv->toplevel_button_press = FALSE;2594 if (gtk_widget_get_mapped (priv->thumb) &&
2434 priv->can_hide = TRUE;2595 !(priv->event & OS_EVENT_BUTTON_PRESS))
24352596 {
2436 if (priv->source_hide_thumb_id != 0)2597 priv->hidable_thumb = TRUE;
2437 g_source_remove (priv->source_hide_thumb_id);2598
24382599 if (priv->source_hide_thumb_id != 0)
2439 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,2600 g_source_remove (priv->source_hide_thumb_id);
2440 hide_thumb_cb,2601
2441 scrollbar);2602 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
2603 hide_thumb_cb,
2604 scrollbar);
2605 }
2606
2607 if (priv->source_show_thumb_id != 0)
2608 {
2609 g_source_remove (priv->source_show_thumb_id);
2610 priv->source_show_thumb_id = 0;
2611 }
24422612
2443 if (priv->source_unlock_thumb_id != 0)2613 if (priv->source_unlock_thumb_id != 0)
2444 g_source_remove (priv->source_unlock_thumb_id);2614 g_source_remove (priv->source_unlock_thumb_id);
@@ -2449,95 +2619,47 @@
2449 }2619 }
24502620
2451 /* Get the motion_notify_event trough XEvent. */2621 /* Get the motion_notify_event trough XEvent. */
2452 if (!priv->toplevel_button_press && xev->type == MotionNotify)2622 if (!priv->window_button_press && xev->type == MotionNotify)
2453 {2623 {
2454 /* React to motion_notify_event2624 /* React to motion_notify_event
2455 * and set the state accordingly. */2625 * and set the state accordingly. */
2456 if (!is_insensitive (scrollbar) && !priv->active_window)2626 if (!is_insensitive (scrollbar) && !priv->active_window)
2457 pager_set_state_from_pointer (scrollbar, xev->xmotion.x, xev->xmotion.y);2627 bar_set_state_from_pointer (scrollbar, xev->xmotion.x, xev->xmotion.y);
24582628
2459 /* Proximity area. */2629 /* Proximity area. */
2460 if (priv->orientation == GTK_ORIENTATION_VERTICAL)2630 if (check_proximity (scrollbar, xev->xmotion.x, xev->xmotion.y))
2461 {2631 {
2462 if (check_proximity (scrollbar, xev->xmotion.x, xev->xmotion.y))2632 priv->hidable_thumb = FALSE;
2463 {2633
2464 priv->can_hide = FALSE;2634 if (priv->source_hide_thumb_id != 0)
24652635 {
2466 if (priv->lock_position)2636 g_source_remove (priv->source_hide_thumb_id);
2467 return GDK_FILTER_CONTINUE;2637 priv->source_hide_thumb_id = 0;
24682638 }
2469 if (priv->overlay.height > priv->slider.height)2639
2470 {2640 if (priv->state & OS_STATE_LOCKED)
2471 gint x, y, x_pos, y_pos;2641 return GDK_FILTER_CONTINUE;
24722642
2473 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);2643 adjust_thumb_position (scrollbar, xev->xmotion.x, xev->xmotion.y);
24742644
2475 x = priv->thumb_all.x;2645 show_thumb (scrollbar);
2476 y = CLAMP (xev->xmotion.y - priv->slider.height / 2,
2477 priv->thumb_all.y + priv->overlay.y,
2478 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
2479
2480 move_thumb (scrollbar, x_pos + x, y_pos + y);
2481 }
2482 else
2483 {
2484 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
2485 }
2486
2487 os_pager_set_detached (priv->pager, FALSE);
2488 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
2489 gtk_widget_show (priv->thumb);
2490 }
2491 else
2492 {
2493 priv->can_hide = TRUE;
2494 priv->lock_position = FALSE;
2495
2496 if (gtk_widget_get_mapped (priv->thumb) &&
2497 priv->source_hide_thumb_id == 0)
2498 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_PROXIMITY_HIDE,
2499 hide_thumb_cb,
2500 scrollbar);
2501 }
2502 }2646 }
2503 else2647 else
2504 {2648 {
2505 if (check_proximity (scrollbar, xev->xmotion.x, xev->xmotion.y))2649 priv->state &= ~(OS_STATE_LOCKED);
2650
2651 if (priv->source_show_thumb_id != 0)
2506 {2652 {
2507 priv->can_hide = FALSE;2653 g_source_remove (priv->source_show_thumb_id);
25082654 priv->source_show_thumb_id = 0;
2509 if (priv->lock_position)
2510 return GDK_FILTER_CONTINUE;
2511
2512 if (priv->overlay.width > priv->slider.width)
2513 {
2514 gint x, y, x_pos, y_pos;
2515
2516 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
2517
2518 x = CLAMP (xev->xmotion.x - priv->slider.width / 2,
2519 priv->thumb_all.x + priv->overlay.x,
2520 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
2521 y = priv->thumb_all.y;
2522
2523 move_thumb (scrollbar, x_pos + x, y_pos + y);
2524 }
2525 else
2526 {
2527 move_thumb (scrollbar, priv->win_x + priv->slider.x, priv->win_y);
2528 }
2529
2530 os_pager_set_detached (priv->pager, FALSE);
2531 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
2532 gtk_widget_show (priv->thumb);
2533 }2655 }
2534 else2656
2657 if (gtk_widget_get_mapped (priv->thumb) &&
2658 !(priv->event & OS_EVENT_BUTTON_PRESS))
2535 {2659 {
2536 priv->can_hide = TRUE;2660 priv->hidable_thumb = TRUE;
2537 priv->lock_position = FALSE;
25382661
2539 if (gtk_widget_get_mapped (priv->thumb) &&2662 if (priv->source_hide_thumb_id == 0)
2540 priv->source_hide_thumb_id == 0)
2541 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_PROXIMITY_HIDE,2663 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_PROXIMITY_HIDE,
2542 hide_thumb_cb,2664 hide_thumb_cb,
2543 scrollbar);2665 scrollbar);
@@ -2550,6 +2672,44 @@
2550}2672}
2551#endif2673#endif
25522674
2675/* Add the window filter function. */
2676static void
2677add_window_filter (OsScrollbar *scrollbar)
2678{
2679 OsScrollbarPrivate *priv;
2680
2681 priv = scrollbar->priv;
2682
2683 /* Don't add duplicated filters. */
2684 if (!priv->filter.running &&
2685 gtk_widget_get_realized (GTK_WIDGET (scrollbar)))
2686 {
2687 priv->filter.running = TRUE;
2688 gdk_window_add_filter (gtk_widget_get_window (GTK_WIDGET (scrollbar)),
2689 window_filter_func,
2690 scrollbar);
2691 }
2692}
2693
2694/* Remove the window filter function. */
2695static void
2696remove_window_filter (OsScrollbar *scrollbar)
2697{
2698 OsScrollbarPrivate *priv;
2699
2700 priv = scrollbar->priv;
2701
2702 /* Remove only if the filter is running. */
2703 if (priv->filter.running &&
2704 gtk_widget_get_realized (GTK_WIDGET (scrollbar)))
2705 {
2706 priv->filter.running = FALSE;
2707 gdk_window_remove_filter (gtk_widget_get_window (GTK_WIDGET (scrollbar)),
2708 window_filter_func,
2709 scrollbar);
2710 }
2711}
2712
2553G_DEFINE_TYPE (OsScrollbar, os_scrollbar, GTK_TYPE_SCROLLBAR);2713G_DEFINE_TYPE (OsScrollbar, os_scrollbar, GTK_TYPE_SCROLLBAR);
25542714
2555static void2715static void
@@ -2634,27 +2794,34 @@
26342794
2635 priv->event = OS_EVENT_NONE;2795 priv->event = OS_EVENT_NONE;
26362796
2797 priv->state = OS_STATE_NONE;
2798
2799 priv->side = OS_SIDE_RIGHT;
2800
2801 priv->filter.proximity = FALSE;
2802 priv->filter.running = FALSE;
2803
2637 priv->active_window = FALSE;2804 priv->active_window = FALSE;
2638 priv->can_deactivate_pager = TRUE;2805 priv->deactivable_bar = TRUE;
2639 priv->can_hide = TRUE;2806 priv->hidable_thumb = TRUE;
2640 priv->detached_scroll = FALSE;2807 priv->window_button_press = FALSE;
2641 priv->filter = FALSE;2808
2642 priv->fullsize = FALSE;2809 priv->pointer.x = 0;
2643 priv->internal = FALSE;2810 priv->pointer.y = 0;
2644 priv->lock_position = FALSE;2811 priv->thumb_win.x = 0;
2645 priv->proximity = FALSE;2812 priv->thumb_win.y = 0;
2646 priv->toplevel_button_press = FALSE;2813
2647 priv->side = OS_SIDE_RIGHT;2814 priv->source_deactivate_bar_id = 0;
2648 priv->source_deactivate_pager_id = 0;
2649 priv->source_hide_thumb_id = 0;2815 priv->source_hide_thumb_id = 0;
2816 priv->source_show_thumb_id = 0;
2650 priv->source_unlock_thumb_id = 0;2817 priv->source_unlock_thumb_id = 0;
26512818
2652 priv->pager = os_pager_new ();2819 priv->bar = os_bar_new ();
26532820
2654 priv->window_group = gtk_window_group_new ();2821 priv->window_group = gtk_window_group_new ();
26552822
2656 priv->animation = os_animation_new (RATE_PAGING, MAX_DURATION_PAGING,2823 priv->animation = os_animation_new (RATE_ANIMATION, MAX_DURATION_SCROLLING,
2657 paging_cb, NULL, scrollbar);2824 scrolling_cb, scrolling_end_cb, scrollbar);
2658 priv->value = 0;2825 priv->value = 0;
26592826
2660 g_signal_connect (G_OBJECT (scrollbar), "notify::adjustment",2827 g_signal_connect (G_OBJECT (scrollbar), "notify::adjustment",
@@ -2673,10 +2840,10 @@
2673 scrollbar = OS_SCROLLBAR (object);2840 scrollbar = OS_SCROLLBAR (object);
2674 priv = scrollbar->priv;2841 priv = scrollbar->priv;
26752842
2676 if (priv->source_deactivate_pager_id != 0)2843 if (priv->source_deactivate_bar_id != 0)
2677 {2844 {
2678 g_source_remove (priv->source_deactivate_pager_id);2845 g_source_remove (priv->source_deactivate_bar_id);
2679 priv->source_deactivate_pager_id = 0;2846 priv->source_deactivate_bar_id = 0;
2680 }2847 }
26812848
2682 if (priv->source_hide_thumb_id != 0)2849 if (priv->source_hide_thumb_id != 0)
@@ -2711,10 +2878,10 @@
2711 priv->animation = NULL;2878 priv->animation = NULL;
2712 }2879 }
27132880
2714 if (priv->pager != NULL)2881 if (priv->bar != NULL)
2715 {2882 {
2716 g_object_unref (priv->pager);2883 g_object_unref (priv->bar);
2717 priv->pager = NULL;2884 priv->bar = NULL;
2718 }2885 }
27192886
2720 if (priv->window_group != NULL)2887 if (priv->window_group != NULL)
@@ -2767,8 +2934,7 @@
2767 *minimal_width = *natural_width = 0;2934 *minimal_width = *natural_width = 0;
2768 else2935 else
2769 {2936 {
2770 /* Smaller than 35 pixels the thumb looks weird. */2937 *minimal_width = MIN_THUMB_HEIGHT;
2771 *minimal_width = 35;
2772 *natural_width = THUMB_HEIGHT;2938 *natural_width = THUMB_HEIGHT;
2773 }2939 }
2774}2940}
@@ -2788,8 +2954,7 @@
2788 *minimal_height = *natural_height = 0;2954 *minimal_height = *natural_height = 0;
2789 else2955 else
2790 {2956 {
2791 /* Smaller than 35 pixels the thumb looks weird. */2957 *minimal_height = MIN_THUMB_HEIGHT;
2792 *minimal_height = 35;
2793 *natural_height = THUMB_HEIGHT;2958 *natural_height = THUMB_HEIGHT;
2794 }2959 }
2795}2960}
@@ -2823,10 +2988,10 @@
2823 gdk_screen_get_active_window (gtk_widget_get_screen (widget)))2988 gdk_screen_get_active_window (gtk_widget_get_screen (widget)))
2824 {2989 {
2825 /* Stops potential running timeout. */2990 /* Stops potential running timeout. */
2826 if (priv->source_deactivate_pager_id != 0)2991 if (priv->source_deactivate_bar_id != 0)
2827 {2992 {
2828 g_source_remove (priv->source_deactivate_pager_id);2993 g_source_remove (priv->source_deactivate_bar_id);
2829 priv->source_deactivate_pager_id = 0;2994 priv->source_deactivate_bar_id = 0;
2830 }2995 }
28312996
2832 priv->active_window = TRUE;2997 priv->active_window = TRUE;
@@ -2846,29 +3011,24 @@
2846 * for example when switching notebook page,3011 * for example when switching notebook page,
2847 * check the position of the pointer3012 * check the position of the pointer
2848 * and set the state accordingly. */3013 * and set the state accordingly. */
2849 pager_set_state_from_pointer (scrollbar, x, y);3014 bar_set_state_from_pointer (scrollbar, x, y);
2850 }3015 }
2851 else3016 else
2852 {3017 {
2853 /* On map-event of an active window,3018 /* On map-event of an active window,
2854 * the pager should be active. */3019 * the bar should be active. */
2855 priv->can_deactivate_pager = FALSE;3020 priv->deactivable_bar = FALSE;
2856 os_pager_set_active (priv->pager, TRUE, FALSE);3021 os_bar_set_active (priv->bar, TRUE, FALSE);
2857 }3022 }
2858 }3023 }
28593024
2860 if (priv->fullsize == FALSE)3025 if (!(priv->state & OS_STATE_FULLSIZE))
2861 os_pager_show (priv->pager);3026 os_bar_show (priv->bar);
28623027
2863 if (!is_insensitive (scrollbar))3028 if (!is_insensitive (scrollbar))
2864 {3029 {
2865 priv->proximity = TRUE;3030 priv->filter.proximity = TRUE;
28663031 add_window_filter (scrollbar);
2867 if (gtk_widget_get_realized (widget) && priv->filter == FALSE)
2868 {
2869 priv->filter = TRUE;
2870 gdk_window_add_filter (gtk_widget_get_window (widget), window_filter_func, scrollbar);
2871 }
2872 }3032 }
2873}3033}
28743034
@@ -2889,20 +3049,17 @@
2889 gdk_window_get_events (gtk_widget_get_window (widget)) |3049 gdk_window_get_events (gtk_widget_get_window (widget)) |
2890 GDK_POINTER_MOTION_MASK);3050 GDK_POINTER_MOTION_MASK);
28913051
2892 if (priv->filter == FALSE && priv->proximity == TRUE)3052 if (priv->filter.proximity)
2893 {3053 add_window_filter (scrollbar);
2894 priv->filter = TRUE;
2895 gdk_window_add_filter (gtk_widget_get_window (widget), window_filter_func, scrollbar);
2896 }
28973054
2898 g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)), "configure-event",3055 g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)), "configure-event",
2899 G_CALLBACK (toplevel_configure_event_cb), scrollbar);3056 G_CALLBACK (toplevel_configure_event_cb), scrollbar);
29003057
2901 calc_layout_pager (scrollbar, gtk_adjustment_get_value (priv->adjustment));3058 calc_layout_bar (scrollbar, gtk_adjustment_get_value (priv->adjustment));
29023059
2903 os_pager_set_parent (priv->pager, widget);3060 os_bar_set_parent (priv->bar, widget);
29043061
2905 store_toplevel_position (scrollbar);3062 calc_thumb_window_position (scrollbar);
2906}3063}
29073064
2908static void3065static void
@@ -2965,7 +3122,7 @@
2965 scrollbar = OS_SCROLLBAR (widget);3122 scrollbar = OS_SCROLLBAR (widget);
2966 priv = scrollbar->priv;3123 priv = scrollbar->priv;
29673124
2968 /* Get the side, then move thumb and pager accordingly. */3125 /* Get the side, then move thumb and bar accordingly. */
2969 retrieve_side (scrollbar);3126 retrieve_side (scrollbar);
29703127
2971 priv->trough.x = allocation->x;3128 priv->trough.x = allocation->x;
@@ -2973,7 +3130,7 @@
2973 priv->trough.width = allocation->width;3130 priv->trough.width = allocation->width;
2974 priv->trough.height = allocation->height;3131 priv->trough.height = allocation->height;
29753132
2976 priv->pager_all = *allocation;3133 priv->bar_all = *allocation;
2977 priv->thumb_all = *allocation;3134 priv->thumb_all = *allocation;
29783135
2979 if (priv->orientation == GTK_ORIENTATION_VERTICAL)3136 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
@@ -2986,16 +3143,16 @@
2986 }3143 }
29873144
2988 if (priv->side == OS_SIDE_RIGHT)3145 if (priv->side == OS_SIDE_RIGHT)
2989 priv->pager_all.x = allocation->x - PAGER_SIZE;3146 priv->bar_all.x = allocation->x - BAR_SIZE;
29903147
2991 priv->pager_all.width = PAGER_SIZE;3148 priv->bar_all.width = BAR_SIZE;
29923149
2993 priv->thumb_all.width = THUMB_WIDTH;3150 priv->thumb_all.width = THUMB_WIDTH;
29943151
2995 if (priv->side == OS_SIDE_RIGHT)3152 if (priv->side == OS_SIDE_RIGHT)
2996 priv->thumb_all.x = allocation->x - priv->pager_all.width;3153 priv->thumb_all.x = allocation->x - priv->bar_all.width;
2997 else3154 else
2998 priv->thumb_all.x = allocation->x + priv->pager_all.width - priv->thumb_all.width;3155 priv->thumb_all.x = allocation->x + priv->bar_all.width - priv->thumb_all.width;
29993156
3000 allocation->width = 0;3157 allocation->width = 0;
3001 }3158 }
@@ -3009,32 +3166,32 @@
3009 }3166 }
30103167
3011 if (priv->side == OS_SIDE_BOTTOM)3168 if (priv->side == OS_SIDE_BOTTOM)
3012 priv->pager_all.y = allocation->y - PAGER_SIZE;3169 priv->bar_all.y = allocation->y - BAR_SIZE;
30133170
3014 priv->pager_all.height = PAGER_SIZE;3171 priv->bar_all.height = BAR_SIZE;
30153172
3016 priv->thumb_all.height = THUMB_WIDTH;3173 priv->thumb_all.height = THUMB_WIDTH;
30173174
3018 if (priv->side == OS_SIDE_BOTTOM)3175 if (priv->side == OS_SIDE_BOTTOM)
3019 priv->thumb_all.y = allocation->y - priv->pager_all.height;3176 priv->thumb_all.y = allocation->y - priv->bar_all.height;
3020 else3177 else
3021 priv->thumb_all.y = allocation->y + priv->pager_all.height - priv->thumb_all.height;3178 priv->thumb_all.y = allocation->y + priv->bar_all.height - priv->thumb_all.height;
30223179
3023 allocation->height = 0;3180 allocation->height = 0;
3024 }3181 }
30253182
3026 if (priv->adjustment != NULL)3183 if (priv->adjustment != NULL)
3027 {3184 {
3028 calc_layout_pager (scrollbar, gtk_adjustment_get_value (priv->adjustment));3185 calc_layout_bar (scrollbar, gtk_adjustment_get_value (priv->adjustment));
3029 calc_layout_slider (scrollbar, gtk_adjustment_get_value (priv->adjustment));3186 calc_layout_slider (scrollbar, gtk_adjustment_get_value (priv->adjustment));
3030 }3187 }
30313188
3032 os_pager_size_allocate (priv->pager, priv->pager_all);3189 os_bar_size_allocate (priv->bar, priv->bar_all);
30333190
3034 move_pager (scrollbar);3191 move_bar (scrollbar);
30353192
3036 if (gtk_widget_get_realized (widget))3193 if (gtk_widget_get_realized (widget))
3037 store_toplevel_position (scrollbar);3194 calc_thumb_window_position (scrollbar);
30383195
3039 gtk_widget_set_allocation (widget, allocation);3196 gtk_widget_set_allocation (widget, allocation);
3040}3197}
@@ -3047,15 +3204,10 @@
30473204
3048 priv = scrollbar->priv;3205 priv = scrollbar->priv;
30493206
3050 priv->proximity = FALSE;3207 priv->filter.proximity = FALSE;
30513208 remove_window_filter (scrollbar);
3052 if (gtk_widget_get_realized (GTK_WIDGET (scrollbar)) && priv->filter == TRUE)3209
3053 {3210 os_bar_set_active (priv->bar, FALSE, FALSE);
3054 priv->filter = FALSE;
3055 gdk_window_remove_filter (gtk_widget_get_window (GTK_WIDGET (scrollbar)), window_filter_func, scrollbar);
3056 }
3057
3058 os_pager_set_active (priv->pager, FALSE, FALSE);
30593211
3060 gtk_widget_hide (priv->thumb);3212 gtk_widget_hide (priv->thumb);
3061}3213}
@@ -3068,16 +3220,11 @@
30683220
3069 priv = scrollbar->priv;3221 priv = scrollbar->priv;
30703222
3071 priv->proximity = TRUE;3223 priv->filter.proximity = TRUE;
30723224 add_window_filter (scrollbar);
3073 if (gtk_widget_get_realized (GTK_WIDGET (scrollbar)) && priv->filter == FALSE)
3074 {
3075 priv->filter = TRUE;
3076 gdk_window_add_filter (gtk_widget_get_window (GTK_WIDGET (scrollbar)), window_filter_func, scrollbar);
3077 }
30783225
3079 if (priv->active_window)3226 if (priv->active_window)
3080 os_pager_set_active (priv->pager, TRUE, FALSE);3227 os_bar_set_active (priv->bar, TRUE, FALSE);
3081 else3228 else
3082 {3229 {
3083 gint x, y;3230 gint x, y;
@@ -3087,7 +3234,7 @@
3087 /* When the window is unfocused,3234 /* When the window is unfocused,
3088 * check the position of the pointer3235 * check the position of the pointer
3089 * and set the state accordingly. */3236 * and set the state accordingly. */
3090 pager_set_state_from_pointer (scrollbar, x, y);3237 bar_set_state_from_pointer (scrollbar, x, y);
3091 }3238 }
3092}3239}
30933240
@@ -3150,17 +3297,12 @@
31503297
3151 GTK_WIDGET_CLASS (g_type_class_peek (GTK_TYPE_WIDGET))->unmap (widget);3298 GTK_WIDGET_CLASS (g_type_class_peek (GTK_TYPE_WIDGET))->unmap (widget);
31523299
3153 priv->proximity = FALSE;3300 os_bar_hide (priv->bar);
3154
3155 os_pager_hide (priv->pager);
31563301
3157 gtk_widget_hide (priv->thumb);3302 gtk_widget_hide (priv->thumb);
31583303
3159 if (gtk_widget_get_realized (widget) && priv->filter == TRUE)3304 priv->filter.proximity = FALSE;
3160 {3305 remove_window_filter (scrollbar);
3161 priv->filter = FALSE;
3162 gdk_window_remove_filter (gtk_widget_get_window (widget), window_filter_func, scrollbar);
3163 }
3164}3306}
31653307
3166static void3308static void
@@ -3172,17 +3314,17 @@
3172 scrollbar = OS_SCROLLBAR (widget);3314 scrollbar = OS_SCROLLBAR (widget);
3173 priv = scrollbar->priv;3315 priv = scrollbar->priv;
31743316
3175 os_pager_hide (priv->pager);3317 os_bar_hide (priv->bar);
31763318
3177 gtk_widget_hide (priv->thumb);3319 gtk_widget_hide (priv->thumb);
31783320
3179 priv->filter = FALSE;3321 priv->filter.running = FALSE;
3180 gdk_window_remove_filter (gtk_widget_get_window (widget), window_filter_func, scrollbar);3322 gdk_window_remove_filter (gtk_widget_get_window (widget), window_filter_func, scrollbar);
31813323
3182 g_signal_handlers_disconnect_by_func (G_OBJECT (gtk_widget_get_toplevel (widget)),3324 g_signal_handlers_disconnect_by_func (G_OBJECT (gtk_widget_get_toplevel (widget)),
3183 G_CALLBACK (toplevel_configure_event_cb), scrollbar);3325 G_CALLBACK (toplevel_configure_event_cb), scrollbar);
31843326
3185 os_pager_set_parent (priv->pager, NULL);3327 os_bar_set_parent (priv->bar, NULL);
31863328
3187 GTK_WIDGET_CLASS (g_type_class_peek (GTK_TYPE_WIDGET))->unrealize (widget);3329 GTK_WIDGET_CLASS (g_type_class_peek (GTK_TYPE_WIDGET))->unrealize (widget);
3188}3330}
31893331
=== modified file 'os/os-thumb.c'
--- os/os-thumb.c 2011-10-05 12:24:21 +0000
+++ os/os-thumb.c 2011-10-12 17:16:23 +0000
@@ -29,9 +29,6 @@
29#include <math.h>29#include <math.h>
30#include <stdlib.h>30#include <stdlib.h>
3131
32/* Rate of the fade-out. */
33#define RATE_FADE_OUT 30
34
35/* Duration of the fade-out. */32/* Duration of the fade-out. */
36#define DURATION_FADE_OUT 200033#define DURATION_FADE_OUT 2000
3734
@@ -57,14 +54,12 @@
57 GtkOrientation orientation;54 GtkOrientation orientation;
58 GtkWidget *grabbed_widget;55 GtkWidget *grabbed_widget;
59 OsAnimation *animation;56 OsAnimation *animation;
60 OsEvent event;57 OsCoordinate pointer;
61 gboolean can_rgba;58 OsCoordinate pointer_root;
59 OsEventFlags event;
60 gboolean rgba;
62 gboolean detached;61 gboolean detached;
63 gboolean use_tolerance;62 gboolean tolerance;
64 gint pointer_x;
65 gint pointer_y;
66 gint pointer_x_root;
67 gint pointer_y_root;
68 guint32 source_id;63 guint32 source_id;
69};64};
7065
@@ -192,12 +187,17 @@
192187
193 priv->event = OS_EVENT_NONE;188 priv->event = OS_EVENT_NONE;
194189
195 priv->can_rgba = FALSE;190 priv->pointer.x = 0;
191 priv->pointer.y = 0;
192 priv->pointer_root.x = 0;
193 priv->pointer_root.y = 0;
194
195 priv->rgba = FALSE;
196 priv->detached = FALSE;196 priv->detached = FALSE;
197 priv->use_tolerance = FALSE;197 priv->tolerance = FALSE;
198198
199 priv->source_id = 0;199 priv->source_id = 0;
200 priv->animation = os_animation_new (RATE_FADE_OUT, DURATION_FADE_OUT,200 priv->animation = os_animation_new (RATE_ANIMATION, DURATION_FADE_OUT,
201 fade_out_cb, NULL, thumb);201 fade_out_cb, NULL, thumb);
202202
203 gtk_window_set_skip_pager_hint (GTK_WINDOW (thumb), TRUE);203 gtk_window_set_skip_pager_hint (GTK_WINDOW (thumb), TRUE);
@@ -237,19 +237,20 @@
237237
238 if (event->type == GDK_BUTTON_PRESS)238 if (event->type == GDK_BUTTON_PRESS)
239 {239 {
240 if (event->button == 1)240 if (event->button == 1 ||
241 event->button == 2)
241 {242 {
242 gtk_grab_add (widget);243 gtk_grab_add (widget);
243244
244 priv->pointer_x = event->x;245 priv->pointer.x = event->x;
245 priv->pointer_y = event->y;246 priv->pointer.y = event->y;
246 priv->pointer_x_root = event->x_root;247 priv->pointer_root.x = event->x_root;
247 priv->pointer_y_root = event->y_root;248 priv->pointer_root.y = event->y_root;
248249
249 priv->event |= OS_EVENT_BUTTON_PRESS;250 priv->event |= OS_EVENT_BUTTON_PRESS;
250 priv->event &= ~(OS_EVENT_MOTION_NOTIFY);251 priv->event &= ~(OS_EVENT_MOTION_NOTIFY);
251252
252 priv->use_tolerance = TRUE;253 priv->tolerance = TRUE;
253254
254 gtk_widget_queue_draw (widget);255 gtk_widget_queue_draw (widget);
255 }256 }
@@ -273,7 +274,8 @@
273274
274 if (event->type == GDK_BUTTON_RELEASE)275 if (event->type == GDK_BUTTON_RELEASE)
275 {276 {
276 if (event->button == 1)277 if (event->button == 1 ||
278 event->button == 2)
277 {279 {
278 gtk_grab_remove (widget);280 gtk_grab_remove (widget);
279281
@@ -295,7 +297,7 @@
295 thumb = OS_THUMB (widget);297 thumb = OS_THUMB (widget);
296 priv = thumb->priv;298 priv = thumb->priv;
297299
298 priv->can_rgba = FALSE;300 priv->rgba = FALSE;
299301
300 if (gdk_screen_is_composited (gtk_widget_get_screen (widget)))302 if (gdk_screen_is_composited (gtk_widget_get_screen (widget)))
301 {303 {
@@ -313,7 +315,7 @@
313 if (gdk_visual_get_depth (visual) == 32 && (red_mask == 0xff0000 &&315 if (gdk_visual_get_depth (visual) == 32 && (red_mask == 0xff0000 &&
314 green_mask == 0x00ff00 &&316 green_mask == 0x00ff00 &&
315 blue_mask == 0x0000ff)) 317 blue_mask == 0x0000ff))
316 priv->can_rgba = TRUE;318 priv->rgba = TRUE;
317 }319 }
318320
319 gtk_widget_queue_draw (widget);321 gtk_widget_queue_draw (widget);
@@ -631,7 +633,7 @@
631 thumb = OS_THUMB (widget);633 thumb = OS_THUMB (widget);
632 priv = thumb->priv;634 priv = thumb->priv;
633635
634 radius = priv->can_rgba ? THUMB_RADIUS : 0;636 radius = priv->rgba ? THUMB_RADIUS : 0;
635637
636#ifdef USE_GTK3638#ifdef USE_GTK3
637 width = gtk_widget_get_allocated_width (widget);639 width = gtk_widget_get_allocated_width (widget);
@@ -690,8 +692,8 @@
690 if ((priv->event & OS_EVENT_BUTTON_PRESS) &&692 if ((priv->event & OS_EVENT_BUTTON_PRESS) &&
691 !(priv->event & OS_EVENT_MOTION_NOTIFY))693 !(priv->event & OS_EVENT_MOTION_NOTIFY))
692 {694 {
693 if ((priv->orientation == GTK_ORIENTATION_VERTICAL && (priv->pointer_y < height / 2)) ||695 if ((priv->orientation == GTK_ORIENTATION_VERTICAL && (priv->pointer.y < height / 2)) ||
694 (priv->orientation == GTK_ORIENTATION_HORIZONTAL && (priv->pointer_x < width / 2)))696 (priv->orientation == GTK_ORIENTATION_HORIZONTAL && (priv->pointer.x < width / 2)))
695 {697 {
696 pattern_add_gdk_rgba_stop (pat, 0.0, &bg_arrow_down, 0.6);698 pattern_add_gdk_rgba_stop (pat, 0.0, &bg_arrow_down, 0.6);
697 pattern_add_gdk_rgba_stop (pat, 0.49, &bg_arrow_down, 0.1);699 pattern_add_gdk_rgba_stop (pat, 0.49, &bg_arrow_down, 0.1);
@@ -850,7 +852,7 @@
850 os_animation_stop (priv->animation, NULL);852 os_animation_stop (priv->animation, NULL);
851 }853 }
852854
853 priv->use_tolerance = FALSE;855 priv->tolerance = FALSE;
854856
855 return FALSE;857 return FALSE;
856}858}
@@ -906,11 +908,11 @@
906 * see code few lines below. */908 * see code few lines below. */
907 if (!(priv->event & OS_EVENT_MOTION_NOTIFY))909 if (!(priv->event & OS_EVENT_MOTION_NOTIFY))
908 {910 {
909 if (!priv->use_tolerance ||911 if (!priv->tolerance ||
910 (abs (priv->pointer_x - event->x) > TOLERANCE_FADE ||912 (abs (priv->pointer.x - event->x) > TOLERANCE_FADE ||
911 abs (priv->pointer_y - event->y) > TOLERANCE_FADE))913 abs (priv->pointer.y - event->y) > TOLERANCE_FADE))
912 {914 {
913 priv->use_tolerance = FALSE;915 priv->tolerance = FALSE;
914 priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,916 priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,
915 timeout_fade_out_cb,917 timeout_fade_out_cb,
916 thumb);918 thumb);
@@ -920,8 +922,8 @@
920 if (priv->event & OS_EVENT_BUTTON_PRESS &&922 if (priv->event & OS_EVENT_BUTTON_PRESS &&
921 !(priv->event & OS_EVENT_MOTION_NOTIFY))923 !(priv->event & OS_EVENT_MOTION_NOTIFY))
922 {924 {
923 if (abs (priv->pointer_x_root - event->x_root) <= TOLERANCE_MOTION &&925 if (abs (priv->pointer_root.x - event->x_root) <= TOLERANCE_MOTION &&
924 abs (priv->pointer_y_root - event->y_root) <= TOLERANCE_MOTION)926 abs (priv->pointer_root.y - event->y_root) <= TOLERANCE_MOTION)
925 return FALSE;927 return FALSE;
926928
927 priv->event |= OS_EVENT_MOTION_NOTIFY;929 priv->event |= OS_EVENT_MOTION_NOTIFY;
@@ -977,6 +979,13 @@
977 /* If started, stop the fade-out. */979 /* If started, stop the fade-out. */
978 os_animation_stop (priv->animation, fade_out_stop_cb);980 os_animation_stop (priv->animation, fade_out_stop_cb);
979981
982 if (priv->event & OS_EVENT_MOTION_NOTIFY)
983 {
984 priv->event &= ~(OS_EVENT_MOTION_NOTIFY);
985
986 gtk_widget_queue_draw (widget);
987 }
988
980 return FALSE;989 return FALSE;
981}990}
982991
@@ -991,7 +1000,7 @@
9911000
992 priv->event = OS_EVENT_NONE;1001 priv->event = OS_EVENT_NONE;
9931002
994 priv->use_tolerance = FALSE;1003 priv->tolerance = FALSE;
9951004
996 if (priv->grabbed_widget != NULL && gtk_widget_get_mapped (priv->grabbed_widget))1005 if (priv->grabbed_widget != NULL && gtk_widget_get_mapped (priv->grabbed_widget))
997 gtk_grab_add (priv->grabbed_widget);1006 gtk_grab_add (priv->grabbed_widget);

Subscribers

People subscribed via source and target branches