Merge lp:~cimi/overlay-scrollbar/0.2-refactoring into lp:overlay-scrollbar

Proposed by Andrea Cimitan
Status: Merged
Approved by: Ted Gould
Approved revision: 239
Merged at revision: 238
Proposed branch: lp:~cimi/overlay-scrollbar/0.2-refactoring
Merge into: lp:overlay-scrollbar
Diff against target: 2609 lines (+955/-960)
4 files modified
os/os-animation.c (+33/-37)
os/os-pager.c (+184/-192)
os/os-scrollbar.c (+626/-618)
os/os-thumb.c (+112/-113)
To merge this branch: bzr merge lp:~cimi/overlay-scrollbar/0.2-refactoring
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+61454@code.launchpad.net

Description of the change

Functions moved, comments, etc etc...

........(compiles) :D

To post a comment you must log in.
239. By Andrea Cimitan

Renamed xevent into xev to save space

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

Wow, major reshuffle. Kinda hard to trace everything in the diff, but I couldn't find anything unexpected.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'os/os-animation.c'
--- os/os-animation.c 2011-04-04 16:17:15 +0000
+++ os/os-animation.c 2011-05-18 18:39:29 +0000
@@ -37,45 +37,9 @@
37 guint32 source_id;37 guint32 source_id;
38};38};
3939
40static gboolean os_animation_update_cb (gpointer user_data);
41static void os_animation_dispose (GObject* object);40static void os_animation_dispose (GObject* object);
42static void os_animation_finalize (GObject* object);41static void os_animation_finalize (GObject* object);
4342
44/* Private functions. */
45
46static gboolean
47os_animation_update_cb (gpointer user_data)
48{
49 OsAnimation *animation = OS_ANIMATION (user_data);
50 OsAnimationPrivate *priv = animation->priv;
51 const gint64 current_time = g_get_monotonic_time ();
52 const gint64 end_time = priv->start_time + priv->duration;
53
54 if (current_time < end_time)
55 {
56 /* On-going animation. */
57 const gfloat diff_time = current_time - priv->start_time;
58 const gfloat weight = diff_time / priv->duration;
59
60 priv->update_func (weight, priv->user_data);
61
62 return TRUE;
63 }
64 else
65 {
66 /* Animation ended. */
67 priv->update_func (1.0f, priv->user_data);
68 priv->source_id = 0;
69
70 if (priv->end_func != NULL)
71 priv->end_func (priv->user_data);
72
73 return FALSE;
74 }
75}
76
77/* Type definition. */
78
79G_DEFINE_TYPE (OsAnimation, os_animation, G_TYPE_OBJECT);43G_DEFINE_TYPE (OsAnimation, os_animation, G_TYPE_OBJECT);
8044
81static void45static void
@@ -189,6 +153,38 @@
189 priv->duration = (gint64) duration * G_GINT64_CONSTANT (1000);153 priv->duration = (gint64) duration * G_GINT64_CONSTANT (1000);
190}154}
191155
156/* callback called by the animation */
157static gboolean
158update_cb (gpointer user_data)
159{
160 OsAnimation *animation = OS_ANIMATION (user_data);
161 OsAnimationPrivate *priv = animation->priv;
162 const gint64 current_time = g_get_monotonic_time ();
163 const gint64 end_time = priv->start_time + priv->duration;
164
165 if (current_time < end_time)
166 {
167 /* On-going animation. */
168 const gfloat diff_time = current_time - priv->start_time;
169 const gfloat weight = diff_time / priv->duration;
170
171 priv->update_func (weight, priv->user_data);
172
173 return TRUE;
174 }
175 else
176 {
177 /* Animation ended. */
178 priv->update_func (1.0f, priv->user_data);
179 priv->source_id = 0;
180
181 if (priv->end_func != NULL)
182 priv->end_func (priv->user_data);
183
184 return FALSE;
185 }
186}
187
192/**188/**
193 * os_animation_start:189 * os_animation_start:
194 * @animation: a #OsAnimation190 * @animation: a #OsAnimation
@@ -207,7 +203,7 @@
207 if (priv->source_id == 0)203 if (priv->source_id == 0)
208 {204 {
209 priv->start_time = g_get_monotonic_time ();205 priv->start_time = g_get_monotonic_time ();
210 priv->source_id = g_timeout_add (priv->rate, os_animation_update_cb, animation);206 priv->source_id = g_timeout_add (priv->rate, update_cb, animation);
211 }207 }
212}208}
213209
214210
=== modified file 'os/os-pager.c'
--- os/os-pager.c 2011-05-12 23:39:33 +0000
+++ os/os-pager.c 2011-05-18 18:39:29 +0000
@@ -49,135 +49,40 @@
49 gboolean detached;49 gboolean detached;
50 gboolean visible;50 gboolean visible;
51 gfloat weight;51 gfloat weight;
52 gint width;
53 gint height;
54 gulong handler_id;52 gulong handler_id;
55};53};
5654
57static gboolean rectangle_changed (GdkRectangle rectangle1, GdkRectangle rectangle2);
58static void os_pager_dispose (GObject *object);55static void os_pager_dispose (GObject *object);
59static void os_pager_finalize (GObject *object);56static void os_pager_finalize (GObject *object);
60static void os_pager_change_state_cb (gfloat weight, gpointer user_data);
61static void os_pager_create (OsPager *pager);
62static void os_pager_draw (OsPager *pager);
63static void os_pager_draw_connection (OsPager *pager);
64static void os_pager_mask (OsPager *pager);
65static void os_pager_notify_gtk_theme_name_cb (GObject *object, GParamSpec* pspec, gpointer user_data);
6657
67/* Private functions */58/* Private functions */
6859
69static gboolean60/* draw on the connection_window */
70rectangle_changed (GdkRectangle rectangle1,61static void
71 GdkRectangle rectangle2)62draw_connection (OsPager *pager)
72{63{
73 if (rectangle1.x != rectangle2.x) return TRUE;64 GdkColor color;
74 if (rectangle1.y != rectangle2.y) return TRUE;65 OsPagerPrivate *priv;
75 if (rectangle1.width != rectangle2.width) return TRUE;66
76 if (rectangle1.height != rectangle2.height) return TRUE;67 priv = pager->priv;
7768
78 return FALSE;69 /* 0.6 is taken from os_thumb_expose. */
79}70 color.red = 65535 * 0.6;
8071 color.green = 65535 * 0.6;
81/* Create a pager. */72 color.blue = 65535 * 0.6;
82static void73
83os_pager_create (OsPager *pager)74 gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->connection_window), &color, FALSE, TRUE);
84{75
85 GdkWindowAttr attributes;76 gdk_window_set_background (priv->connection_window, &color);
86 OsPagerPrivate *priv;77
8778 gdk_window_clear (priv->connection_window);
88 priv = pager->priv;79
8980 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
90 /* Instead reparenting,81}
91 * which doesn't seem to work well,82
92 * destroy the two windows. */83/* draw on the pager_window */
93 if (priv->connection_window != NULL)84static void
94 {85draw_pager (OsPager *pager)
95 /* From the Gdk documentation:
96 * "Note that a window will not be destroyed
97 * automatically when its reference count
98 * reaches zero. You must call
99 * gdk_window_destroy ()
100 * yourself before that happens". */
101 gdk_window_destroy (priv->connection_window);
102
103 g_object_unref (priv->connection_window);
104 priv->connection_window = NULL;
105 }
106
107 if (priv->pager_window != NULL)
108 {
109 /* From the Gdk documentation:
110 * "Note that a window will not be destroyed
111 * automatically when its reference count
112 * reaches zero. You must call
113 * gdk_window_destroy ()
114 * yourself before that happens". */
115 gdk_window_destroy (priv->pager_window);
116
117 g_object_unref (priv->pager_window);
118 priv->pager_window = NULL;
119 }
120
121 attributes.width = priv->allocation.width;
122 attributes.height = priv->allocation.height;
123 attributes.wclass = GDK_INPUT_OUTPUT;
124 attributes.window_type = GDK_WINDOW_CHILD;
125 attributes.visual = gtk_widget_get_visual (priv->parent);
126 attributes.colormap = gtk_widget_get_colormap (priv->parent);
127
128 /* connection_window */
129 priv->connection_window = gdk_window_new (gtk_widget_get_window (priv->parent),
130 &attributes,
131 GDK_WA_VISUAL | GDK_WA_COLORMAP);
132
133 g_object_ref_sink (priv->connection_window);
134
135 gdk_window_set_transient_for (priv->connection_window,
136 gtk_widget_get_window (priv->parent));
137
138 gdk_window_input_shape_combine_region (priv->connection_window,
139 gdk_region_new (),
140 0, 0);
141
142 /* pager_window */
143 priv->pager_window = gdk_window_new (gtk_widget_get_window (priv->parent),
144 &attributes,
145 GDK_WA_VISUAL | GDK_WA_COLORMAP);
146
147 g_object_ref_sink (priv->pager_window);
148
149 /* stay above the connection_window */
150 gdk_window_set_transient_for (priv->pager_window,
151 priv->connection_window);
152
153 gdk_window_input_shape_combine_region (priv->pager_window,
154 gdk_region_new (),
155 0, 0);
156}
157
158static void
159os_pager_change_state_cb (gfloat weight,
160 gpointer user_data)
161{
162 OsPager *pager;
163 OsPagerPrivate *priv;
164
165 pager = OS_PAGER (user_data);
166
167 priv = pager->priv;
168
169 priv->weight = weight;
170
171 if (priv->parent == NULL)
172 return;
173
174 os_pager_draw_connection (pager);
175 os_pager_draw (pager);
176}
177
178/* Draw on the pager_window. */
179static void
180os_pager_draw (OsPager *pager)
181{86{
182 GdkColor c1, c2, color;87 GdkColor c1, c2, color;
183 GtkStyle *style;88 GtkStyle *style;
@@ -214,63 +119,32 @@
214 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);119 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
215}120}
216121
217/* Draw on the connection_window. */122/* callback called by the change-state animation */
218static void123static void
219os_pager_draw_connection (OsPager *pager)124change_state_cb (gfloat weight,
220{125 gpointer user_data)
221 GdkColor color;126{
222 OsPagerPrivate *priv;127 OsPager *pager;
223128 OsPagerPrivate *priv;
224 priv = pager->priv;129
225130 pager = OS_PAGER (user_data);
226 /* 0.6 is taken from os_thumb_expose. */131
227 color.red = 65535 * 0.6;132 priv = pager->priv;
228 color.green = 65535 * 0.6;133
229 color.blue = 65535 * 0.6;134 priv->weight = weight;
230135
231 gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->connection_window), &color, FALSE, TRUE);136 if (priv->parent == NULL)
232137 return;
233 gdk_window_set_background (priv->connection_window, &color);138
234139 draw_connection (pager);
235 gdk_window_clear (priv->connection_window);140 draw_pager (pager);
236141}
237 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);142
238}143/* callback called when the Gtk+ theme changes */
239144static void
240/* Mask the pager_window. */145notify_gtk_theme_name_cb (GObject* gobject,
241static void146 GParamSpec* pspec,
242os_pager_mask (OsPager *pager)147 gpointer user_data)
243{
244 OsPagerPrivate *priv;
245
246 priv = pager->priv;
247
248 gdk_window_shape_combine_region (priv->pager_window,
249 gdk_region_rectangle (&priv->mask),
250 0, 0);
251
252 gdk_window_clear (priv->pager_window);
253}
254
255/* Mask the connection_window. */
256static void
257os_pager_mask_connection (OsPager *pager)
258{
259 OsPagerPrivate *priv;
260
261 priv = pager->priv;
262
263 gdk_window_shape_combine_region (priv->connection_window,
264 gdk_region_rectangle (&priv->connection_mask),
265 0, 0);
266
267 gdk_window_clear (priv->connection_window);
268}
269
270static void
271os_pager_notify_gtk_theme_name_cb (GObject* gobject,
272 GParamSpec* pspec,
273 gpointer user_data)
274{148{
275 OsPager *pager;149 OsPager *pager;
276 OsPagerPrivate *priv;150 OsPagerPrivate *priv;
@@ -283,11 +157,22 @@
283 priv->connection_window == NULL)157 priv->connection_window == NULL)
284 return;158 return;
285159
286 os_pager_draw_connection (pager);160 draw_connection (pager);
287 os_pager_draw (pager);161 draw_pager (pager);
288}162}
289163
290/* Type definition. */164/* check if two GdkRectangle are different */
165static gboolean
166rectangle_changed (GdkRectangle rectangle1,
167 GdkRectangle rectangle2)
168{
169 if (rectangle1.x != rectangle2.x) return TRUE;
170 if (rectangle1.y != rectangle2.y) return TRUE;
171 if (rectangle1.width != rectangle2.width) return TRUE;
172 if (rectangle1.height != rectangle2.height) return TRUE;
173
174 return FALSE;
175}
291176
292G_DEFINE_TYPE (OsPager, os_pager, G_TYPE_OBJECT);177G_DEFINE_TYPE (OsPager, os_pager, G_TYPE_OBJECT);
293178
@@ -335,10 +220,10 @@
335 priv->weight = 1.0f;220 priv->weight = 1.0f;
336221
337 priv->animation = os_animation_new (RATE_FADE, DURATION_FADE_OUT,222 priv->animation = os_animation_new (RATE_FADE, DURATION_FADE_OUT,
338 os_pager_change_state_cb, NULL, pager);223 change_state_cb, NULL, pager);
339224
340 priv->handler_id = g_signal_connect (gtk_settings_get_default (), "notify::gtk-theme-name",225 priv->handler_id = g_signal_connect (gtk_settings_get_default (), "notify::gtk-theme-name",
341 G_CALLBACK (os_pager_notify_gtk_theme_name_cb), pager);226 G_CALLBACK (notify_gtk_theme_name_cb), pager);
342}227}
343228
344static void229static void
@@ -413,6 +298,21 @@
413 return g_object_new (OS_TYPE_PAGER, NULL);298 return g_object_new (OS_TYPE_PAGER, NULL);
414}299}
415300
301/* move a mask on the connection_window, fake movement */
302static void
303mask_connection (OsPager *pager)
304{
305 OsPagerPrivate *priv;
306
307 priv = pager->priv;
308
309 gdk_window_shape_combine_region (priv->connection_window,
310 gdk_region_rectangle (&priv->connection_mask),
311 0, 0);
312
313 gdk_window_clear (priv->connection_window);
314}
315
416/**316/**
417 * os_pager_connect:317 * os_pager_connect:
418 * @pager: a #OsPager318 * @pager: a #OsPager
@@ -438,7 +338,7 @@
438 if (priv->parent == NULL)338 if (priv->parent == NULL)
439 return;339 return;
440340
441 os_pager_mask_connection (pager);341 mask_connection (pager);
442}342}
443343
444/**344/**
@@ -468,6 +368,21 @@
468 gdk_window_hide (priv->pager_window);368 gdk_window_hide (priv->pager_window);
469}369}
470370
371/* move a mask on the pager_window, fake movement */
372static void
373mask_pager (OsPager *pager)
374{
375 OsPagerPrivate *priv;
376
377 priv = pager->priv;
378
379 gdk_window_shape_combine_region (priv->pager_window,
380 gdk_region_rectangle (&priv->mask),
381 0, 0);
382
383 gdk_window_clear (priv->pager_window);
384}
385
471/**386/**
472 * os_pager_move_resize:387 * os_pager_move_resize:
473 * @pager: a #OsPager388 * @pager: a #OsPager
@@ -493,7 +408,7 @@
493 if (priv->parent == NULL)408 if (priv->parent == NULL)
494 return;409 return;
495410
496 os_pager_mask (pager);411 mask_pager (pager);
497}412}
498413
499/**414/**
@@ -534,7 +449,7 @@
534 {449 {
535 priv->weight = 1.0f;450 priv->weight = 1.0f;
536451
537 os_pager_draw (pager);452 draw_pager (pager);
538 }453 }
539 }454 }
540}455}
@@ -574,6 +489,83 @@
574 }489 }
575}490}
576491
492/* create connection_window and pager_window */
493static void
494create_windows (OsPager *pager)
495{
496 GdkWindowAttr attributes;
497 OsPagerPrivate *priv;
498
499 priv = pager->priv;
500
501 /* Instead reparenting,
502 * which doesn't seem to work well,
503 * destroy the two windows. */
504 if (priv->connection_window != NULL)
505 {
506 /* From the Gdk documentation:
507 * "Note that a window will not be destroyed
508 * automatically when its reference count
509 * reaches zero. You must call
510 * gdk_window_destroy ()
511 * yourself before that happens". */
512 gdk_window_destroy (priv->connection_window);
513
514 g_object_unref (priv->connection_window);
515 priv->connection_window = NULL;
516 }
517
518 if (priv->pager_window != NULL)
519 {
520 /* From the Gdk documentation:
521 * "Note that a window will not be destroyed
522 * automatically when its reference count
523 * reaches zero. You must call
524 * gdk_window_destroy ()
525 * yourself before that happens". */
526 gdk_window_destroy (priv->pager_window);
527
528 g_object_unref (priv->pager_window);
529 priv->pager_window = NULL;
530 }
531
532 attributes.width = priv->allocation.width;
533 attributes.height = priv->allocation.height;
534 attributes.wclass = GDK_INPUT_OUTPUT;
535 attributes.window_type = GDK_WINDOW_CHILD;
536 attributes.visual = gtk_widget_get_visual (priv->parent);
537 attributes.colormap = gtk_widget_get_colormap (priv->parent);
538
539 /* connection_window */
540 priv->connection_window = gdk_window_new (gtk_widget_get_window (priv->parent),
541 &attributes,
542 GDK_WA_VISUAL | GDK_WA_COLORMAP);
543
544 g_object_ref_sink (priv->connection_window);
545
546 gdk_window_set_transient_for (priv->connection_window,
547 gtk_widget_get_window (priv->parent));
548
549 gdk_window_input_shape_combine_region (priv->connection_window,
550 gdk_region_new (),
551 0, 0);
552
553 /* pager_window */
554 priv->pager_window = gdk_window_new (gtk_widget_get_window (priv->parent),
555 &attributes,
556 GDK_WA_VISUAL | GDK_WA_COLORMAP);
557
558 g_object_ref_sink (priv->pager_window);
559
560 /* stay above the connection_window */
561 gdk_window_set_transient_for (priv->pager_window,
562 priv->connection_window);
563
564 gdk_window_input_shape_combine_region (priv->pager_window,
565 gdk_region_new (),
566 0, 0);
567}
568
577/**569/**
578 * os_pager_set_parent:570 * os_pager_set_parent:
579 * @pager: a #OsPager571 * @pager: a #OsPager
@@ -608,10 +600,10 @@
608600
609 priv->weight = 1.0f;601 priv->weight = 1.0f;
610602
611 os_pager_create (pager);603 create_windows (pager);
612 os_pager_draw_connection (pager);604 draw_connection (pager);
613 os_pager_draw (pager);605 draw_pager (pager);
614 os_pager_mask (pager);606 mask_pager (pager);
615607
616 gdk_window_move_resize (priv->connection_window,608 gdk_window_move_resize (priv->connection_window,
617 priv->allocation.x,609 priv->allocation.x,
618610
=== modified file 'os/os-scrollbar.c'
--- os/os-scrollbar.c 2011-05-17 20:54:31 +0000
+++ os/os-scrollbar.c 2011-05-18 18:39:29 +0000
@@ -65,12 +65,12 @@
65 gboolean active_window;65 gboolean active_window;
66 gboolean can_deactivate_pager;66 gboolean can_deactivate_pager;
67 gboolean can_hide;67 gboolean can_hide;
68 gboolean toplevel_button_press;
69 gboolean filter;68 gboolean filter;
70 gboolean fullsize;69 gboolean fullsize;
71 gboolean internal;70 gboolean internal;
72 gboolean lock_position;71 gboolean lock_position;
73 gboolean proximity;72 gboolean proximity;
73 gboolean toplevel_button_press;
74 gint win_x;74 gint win_x;
75 gint win_y;75 gint win_y;
76 gint slide_initial_slider_position;76 gint slide_initial_slider_position;
@@ -86,7 +86,20 @@
86static Atom net_active_window_atom = None;86static Atom net_active_window_atom = None;
87static GList *os_root_list = NULL;87static GList *os_root_list = NULL;
8888
89static void swap_adjustment (OsScrollbar *scrollbar, GtkAdjustment *adjustment);
90static void swap_thumb (OsScrollbar *scrollbar, GtkWidget *thumb);
91static void adjustment_changed_cb (GtkAdjustment *adjustment, gpointer user_data);
92static void adjustment_value_changed_cb (GtkAdjustment *adjustment, gpointer user_data);
93static gboolean thumb_button_press_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data);
94static gboolean thumb_button_release_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data);
95static gboolean thumb_enter_notify_event_cb (GtkWidget *widget, GdkEventCrossing *event, gpointer user_data);
96static gboolean thumb_leave_notify_event_cb (GtkWidget *widget, GdkEventCrossing *event, gpointer user_data);
97static void thumb_map_cb (GtkWidget *widget, gpointer user_data);
98static gboolean thumb_motion_notify_event_cb (GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
99static gboolean thumb_scroll_event_cb (GtkWidget *widget, GdkEventScroll *event, gpointer user_data);
100static void thumb_unmap_cb (GtkWidget *widget, gpointer user_data);
89static gboolean os_scrollbar_expose_event (GtkWidget *widget, GdkEventExpose *event);101static gboolean os_scrollbar_expose_event (GtkWidget *widget, GdkEventExpose *event);
102
90static void os_scrollbar_grab_notify (GtkWidget *widget, gboolean was_grabbed);103static void os_scrollbar_grab_notify (GtkWidget *widget, gboolean was_grabbed);
91static void os_scrollbar_hide (GtkWidget *widget);104static void os_scrollbar_hide (GtkWidget *widget);
92static void os_scrollbar_map (GtkWidget *widget);105static void os_scrollbar_map (GtkWidget *widget);
@@ -98,98 +111,13 @@
98static void os_scrollbar_unrealize (GtkWidget *widget);111static void os_scrollbar_unrealize (GtkWidget *widget);
99static void os_scrollbar_dispose (GObject *object);112static void os_scrollbar_dispose (GObject *object);
100static void os_scrollbar_finalize (GObject *object);113static void os_scrollbar_finalize (GObject *object);
101static void os_scrollbar_calc_layout_pager (OsScrollbar *scrollbar, gdouble adjustment_value);
102static void os_scrollbar_calc_layout_slider (OsScrollbar *scrollbar, gdouble adjustment_value);
103static gdouble os_scrollbar_coord_to_value (OsScrollbar *scrollbar, gint coord);
104static void os_scrollbar_deactivate_pager (OsScrollbar *scrollbar);
105static gboolean os_scrollbar_deactivate_pager_cb (gpointer user_data);
106static gdouble os_scrollbar_get_wheel_delta (OsScrollbar *scrollbar, GdkScrollDirection direction);
107static void os_scrollbar_hide_thumb (OsScrollbar *scrollbar);
108static gboolean os_scrollbar_hide_thumb_cb (gpointer user_data);
109static gboolean os_scrollbar_unlock_thumb_cb (gpointer user_data);
110static void os_scrollbar_move (OsScrollbar *scrollbar, gint mouse_x, gint mouse_y);
111static void os_scrollbar_move_thumb (OsScrollbar *scrollbar, gint x, gint y);
112static void os_scrollbar_notify_adjustment_cb (GObject *object, gpointer user_data);
113static void os_scrollbar_notify_orientation_cb (GObject *object, gpointer user_data);
114static gint os_scrollbar_sanitize_x (OsScrollbar *scrollbar, gint x, gint y);
115static gint os_scrollbar_sanitize_y (OsScrollbar *scrollbar, gint x, gint y);
116static void os_scrollbar_store_window_position (OsScrollbar *scrollbar);
117static void os_scrollbar_swap_adjustment (OsScrollbar *scrollbar, GtkAdjustment *adjustment);
118static void os_scrollbar_swap_thumb (OsScrollbar *scrollbar, GtkWidget *thumb);
119static gboolean thumb_button_press_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data);
120static gboolean thumb_button_release_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data);
121static gboolean thumb_enter_notify_event_cb (GtkWidget *widget, GdkEventCrossing *event, gpointer user_data);
122static gboolean thumb_leave_notify_event_cb (GtkWidget *widget, GdkEventCrossing *event, gpointer user_data);
123static void thumb_map_cb (GtkWidget *widget, gpointer user_data);
124static gboolean thumb_motion_notify_event_cb (GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
125static gboolean thumb_scroll_event_cb (GtkWidget *widget, GdkEventScroll *event, gpointer user_data);
126static void thumb_unmap_cb (GtkWidget *widget, gpointer user_data);
127static void pager_move (OsScrollbar *scrollbar);
128static void pager_set_state_from_pointer (OsScrollbar *scrollbar, gint x, gint y);
129static void adjustment_changed_cb (GtkAdjustment *adjustment, gpointer user_data);
130static void adjustment_value_changed_cb (GtkAdjustment *adjustment, gpointer user_data);
131static GdkFilterReturn root_filter_func (GdkXEvent *gdkxevent, GdkEvent *event, gpointer user_data);
132static void root_gfunc (gpointer data, gpointer user_data);
133static gboolean toplevel_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, gpointer user_data);
134static GdkFilterReturn toplevel_filter_func (GdkXEvent *gdkxevent, GdkEvent *event, gpointer user_data);
135114
136/* Private functions. */115/* Private functions. */
137116
138/* Present a X11 window. */117/* calculate pager layout info */
139static void118static void
140os_present_window_with_timestamp (Screen *screen,119calc_layout_pager (OsScrollbar *scrollbar,
141 gint xid,120 gdouble adjustment_value)
142 guint32 timestamp)
143{
144 Display *display;
145 Window root;
146 XEvent xev;
147
148 if (timestamp == 0)
149 g_warning ("Received a timestamp of 0; window activation may not "
150 "function properly.\n");
151
152 display = DisplayOfScreen (screen);
153 root = RootWindowOfScreen (screen);
154
155 xev.xclient.type = ClientMessage;
156 xev.xclient.serial = 0;
157 xev.xclient.send_event = True;
158 xev.xclient.display = display;
159 xev.xclient.window = xid;
160 xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_ACTIVE_WINDOW");
161 xev.xclient.format = 32;
162 xev.xclient.data.l[0] = 1;
163 xev.xclient.data.l[1] = timestamp;
164 xev.xclient.data.l[2] = 0;
165 xev.xclient.data.l[3] = 0;
166 xev.xclient.data.l[4] = 0;
167
168 gdk_error_trap_push ();
169
170 XSendEvent (display, root, False,
171 SubstructureRedirectMask | SubstructureNotifyMask,
172 &xev);
173
174 gdk_flush ();
175
176 gdk_error_trap_pop ();
177}
178
179/* Present a GDK window. */
180static void
181os_present_gdk_window_with_timestamp (GtkWidget *widget,
182 guint32 timestamp)
183{
184 os_present_window_with_timestamp (GDK_SCREEN_XSCREEN (gtk_widget_get_screen (widget)),
185 GDK_WINDOW_XID (gtk_widget_get_window (widget)),
186 timestamp);
187}
188
189/* Calculate layout and store info. */
190static void
191os_scrollbar_calc_layout_pager (OsScrollbar *scrollbar,
192 gdouble adjustment_value)
193{121{
194 OsScrollbarPrivate *priv;122 OsScrollbarPrivate *priv;
195123
@@ -261,10 +189,10 @@
261 }189 }
262}190}
263191
264/* Calculate OsScrollbar layout and store info. */192/* calculate slider (thumb) layout info */
265static void193static void
266os_scrollbar_calc_layout_slider (OsScrollbar *scrollbar,194calc_layout_slider (OsScrollbar *scrollbar,
267 gdouble adjustment_value)195 gdouble adjustment_value)
268{196{
269 OsScrollbarPrivate *priv;197 OsScrollbarPrivate *priv;
270198
@@ -316,51 +244,9 @@
316 }244 }
317}245}
318246
319/* Traduce pixels into proper values. */247/* deactivate the pager if it's the case */
320static gdouble
321os_scrollbar_coord_to_value (OsScrollbar *scrollbar,
322 gint coord)
323{
324 OsScrollbarPrivate *priv;
325 gdouble frac;
326 gdouble value;
327 gint trough_length;
328 gint trough_start;
329 gint slider_length;
330
331 priv = scrollbar->priv;
332
333 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
334 {
335 trough_length = priv->trough.height;
336 trough_start = priv->trough.y;
337 slider_length = MAX (priv->slider.height, priv->overlay.height);
338 }
339 else
340 {
341 trough_length = priv->trough.width;
342 trough_start = priv->trough.y;
343 slider_length = MAX (priv->slider.width, priv->overlay.width);
344 }
345
346 if (trough_length == slider_length)
347 frac = 1.0;
348 else
349 frac = (MAX (0, coord - trough_start) /
350 (gdouble) (trough_length - slider_length));
351
352 value = priv->adjustment->lower + frac * (priv->adjustment->upper -
353 priv->adjustment->lower -
354 priv->adjustment->page_size);
355
356 value = CLAMP (value, priv->adjustment->lower, priv->adjustment->upper - priv->adjustment->page_size);
357
358 return value;
359}
360
361/* Deactivate pager if it's ok to make it inactive. */
362static void248static void
363os_scrollbar_deactivate_pager (OsScrollbar *scrollbar)249deactivate_pager (OsScrollbar *scrollbar)
364{250{
365 OsScrollbarPrivate *priv;251 OsScrollbarPrivate *priv;
366252
@@ -370,8 +256,9 @@
370 os_pager_set_active (OS_PAGER (priv->pager), FALSE);256 os_pager_set_active (OS_PAGER (priv->pager), FALSE);
371}257}
372258
259/* timeout before deactivating the pager */
373static gboolean260static gboolean
374os_scrollbar_deactivate_pager_cb (gpointer user_data)261deactivate_pager_cb (gpointer user_data)
375{262{
376 OsScrollbar *scrollbar;263 OsScrollbar *scrollbar;
377 OsScrollbarPrivate *priv;264 OsScrollbarPrivate *priv;
@@ -381,33 +268,15 @@
381268
382 OS_DCHECK (!priv->active_window);269 OS_DCHECK (!priv->active_window);
383270
384 os_scrollbar_deactivate_pager (scrollbar);271 deactivate_pager (scrollbar);
385 priv->source_deactivate_pager_id = 0;272 priv->source_deactivate_pager_id = 0;
386273
387 return FALSE;274 return FALSE;
388}275}
389276
390static gdouble277/* hide the thumb if it's the case */
391os_scrollbar_get_wheel_delta (OsScrollbar *scrollbar,
392 GdkScrollDirection direction)
393{
394 OsScrollbarPrivate *priv;
395 gdouble delta;
396
397 priv = scrollbar->priv;
398
399 delta = pow (priv->adjustment->page_size, 2.0 / 3.0);
400
401 if (direction == GDK_SCROLL_UP ||
402 direction == GDK_SCROLL_LEFT)
403 delta = - delta;
404
405 return delta;
406}
407
408/* Hide if it's ok to hide. */
409static void278static void
410os_scrollbar_hide_thumb (OsScrollbar *scrollbar)279hide_thumb (OsScrollbar *scrollbar)
411{280{
412 OsScrollbarPrivate *priv;281 OsScrollbarPrivate *priv;
413282
@@ -420,8 +289,9 @@
420 }289 }
421}290}
422291
292/* timeout before hiding the thumb */
423static gboolean293static gboolean
424os_scrollbar_hide_thumb_cb (gpointer user_data)294hide_thumb_cb (gpointer user_data)
425{295{
426 OsScrollbar *scrollbar;296 OsScrollbar *scrollbar;
427 OsScrollbarPrivate *priv;297 OsScrollbarPrivate *priv;
@@ -429,97 +299,44 @@
429 scrollbar = OS_SCROLLBAR (user_data);299 scrollbar = OS_SCROLLBAR (user_data);
430 priv = scrollbar->priv;300 priv = scrollbar->priv;
431301
432 os_scrollbar_hide_thumb (scrollbar);302 hide_thumb (scrollbar);
433 priv->source_hide_thumb_id = 0;303 priv->source_hide_thumb_id = 0;
434304
435 return FALSE;305 return FALSE;
436}306}
437307
438static gboolean308/* move the pager */
439os_scrollbar_unlock_thumb_cb (gpointer user_data)
440{
441 OsScrollbar *scrollbar;
442 OsScrollbarPrivate *priv;
443
444 scrollbar = OS_SCROLLBAR (user_data);
445 priv = scrollbar->priv;
446
447 if (priv->can_hide)
448 priv->lock_position = FALSE;
449
450 priv->source_unlock_thumb_id = 0;
451
452 return FALSE;
453}
454
455static void309static void
456os_scrollbar_move (OsScrollbar *scrollbar,310move_pager (OsScrollbar *scrollbar)
457 gint mouse_x,
458 gint mouse_y)
459{311{
312 GdkRectangle mask;
460 OsScrollbarPrivate *priv;313 OsScrollbarPrivate *priv;
461 gint delta;
462 gint c;
463 gdouble new_value;
464314
465 priv = scrollbar->priv;315 priv = scrollbar->priv;
466316
467 if (priv->orientation == GTK_ORIENTATION_VERTICAL)317 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
468 delta = mouse_y - priv->slide_initial_coordinate;318 {
319 mask.x = 0;
320 mask.y = priv->overlay.y;
321 mask.width = DEFAULT_PAGER_WIDTH;
322 mask.height = priv->overlay.height;
323 }
469 else324 else
470 delta = mouse_x - priv->slide_initial_coordinate;325 {
471326 mask.x = priv->overlay.x;
472 c = priv->slide_initial_slider_position + delta;327 mask.y = 0;
473328 mask.width = priv->overlay.width;
474 new_value = os_scrollbar_coord_to_value (scrollbar, c);329 mask.height = DEFAULT_PAGER_WIDTH;
475330 }
476 gtk_adjustment_set_value (priv->adjustment, new_value);331
477}332 os_pager_move_resize (OS_PAGER (priv->pager), mask);
478333}
479static void334
480os_scrollbar_move_thumb (OsScrollbar *scrollbar,335/* sanitize x coordinate of thumb window */
481 gint x,
482 gint y)
483{
484 OsScrollbarPrivate *priv;
485
486 priv = scrollbar->priv;
487
488 gtk_window_move (GTK_WINDOW (priv->thumb),
489 os_scrollbar_sanitize_x (scrollbar, x, y),
490 os_scrollbar_sanitize_y (scrollbar, x, y));
491}
492
493static void
494os_scrollbar_notify_adjustment_cb (GObject *object,
495 gpointer user_data)
496{
497 OsScrollbar *scrollbar;
498
499 scrollbar = OS_SCROLLBAR (object);
500
501 os_scrollbar_swap_adjustment (scrollbar, gtk_range_get_adjustment (GTK_RANGE (object)));
502}
503
504static void
505os_scrollbar_notify_orientation_cb (GObject *object,
506 gpointer user_data)
507{
508 OsScrollbar *scrollbar;
509 OsScrollbarPrivate *priv;
510
511 scrollbar = OS_SCROLLBAR (object);
512 priv = scrollbar->priv;
513
514 priv->orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (object));
515
516 os_scrollbar_swap_thumb (scrollbar, os_thumb_new (priv->orientation));
517}
518
519static gint336static gint
520os_scrollbar_sanitize_x (OsScrollbar *scrollbar,337sanitize_x (OsScrollbar *scrollbar,
521 gint x,338 gint x,
522 gint y)339 gint y)
523{340{
524 GdkRectangle rect;341 GdkRectangle rect;
525 OsScrollbarPrivate *priv;342 OsScrollbarPrivate *priv;
@@ -550,10 +367,11 @@
550 return x;367 return x;
551}368}
552369
370/* sanitize y coordinate of thumb window */
553static gint371static gint
554os_scrollbar_sanitize_y (OsScrollbar *scrollbar,372sanitize_y (OsScrollbar *scrollbar,
555 gint x,373 gint x,
556 gint y)374 gint y)
557{375{
558 GdkRectangle rect;376 GdkRectangle rect;
559 OsScrollbarPrivate *priv;377 OsScrollbarPrivate *priv;
@@ -584,33 +402,53 @@
584 return y;402 return y;
585}403}
586404
587/* Store scrollbar window position. */405/* move the thumb window */
588static void406static void
589os_scrollbar_store_window_position (OsScrollbar *scrollbar)407move_thumb (OsScrollbar *scrollbar,
590{408 gint x,
591 OsScrollbarPrivate *priv;409 gint y)
592 gint win_x, win_y;410{
593411 OsScrollbarPrivate *priv;
594 priv = scrollbar->priv;412
595413 priv = scrollbar->priv;
596 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &win_x, &win_y);414
597415 gtk_window_move (GTK_WINDOW (priv->thumb),
598 if (priv->orientation == GTK_ORIENTATION_VERTICAL)416 sanitize_x (scrollbar, x, y),
599 {417 sanitize_y (scrollbar, x, y));
600 priv->win_x = win_x + priv->thumb_all.x;418}
601 priv->win_y = win_y + priv->thumb_all.y;419
602 }420/* callback called when the adjustment changes */
603 else421static void
604 {422notify_adjustment_cb (GObject *object,
605 priv->win_x = win_x + priv->thumb_all.x;423 gpointer user_data)
606 priv->win_y = win_y + priv->thumb_all.y;424{
607 }425 OsScrollbar *scrollbar;
608}426
609427 scrollbar = OS_SCROLLBAR (object);
610/* Swap the adjustment pointer. */428
611static void429 swap_adjustment (scrollbar, gtk_range_get_adjustment (GTK_RANGE (object)));
612os_scrollbar_swap_adjustment (OsScrollbar *scrollbar,430}
613 GtkAdjustment *adjustment)431
432/* callback called when the orientation changes */
433static void
434notify_orientation_cb (GObject *object,
435 gpointer user_data)
436{
437 OsScrollbar *scrollbar;
438 OsScrollbarPrivate *priv;
439
440 scrollbar = OS_SCROLLBAR (object);
441 priv = scrollbar->priv;
442
443 priv->orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (object));
444
445 swap_thumb (scrollbar, os_thumb_new (priv->orientation));
446}
447
448/* swap adjustment pointer */
449static void
450swap_adjustment (OsScrollbar *scrollbar,
451 GtkAdjustment *adjustment)
614{452{
615 OsScrollbarPrivate *priv;453 OsScrollbarPrivate *priv;
616454
@@ -639,10 +477,10 @@
639 }477 }
640}478}
641479
642/* Swap the thumb pointer. */480/* swap thumb pointer */
643static void481static void
644os_scrollbar_swap_thumb (OsScrollbar *scrollbar,482swap_thumb (OsScrollbar *scrollbar,
645 GtkWidget *thumb)483 GtkWidget *thumb)
646{484{
647 OsScrollbarPrivate *priv;485 OsScrollbarPrivate *priv;
648486
@@ -697,6 +535,353 @@
697 }535 }
698}536}
699537
538/* timeout before unlocking the thumb */
539static gboolean
540unlock_thumb_cb (gpointer user_data)
541{
542 OsScrollbar *scrollbar;
543 OsScrollbarPrivate *priv;
544
545 scrollbar = OS_SCROLLBAR (user_data);
546 priv = scrollbar->priv;
547
548 if (priv->can_hide)
549 priv->lock_position = FALSE;
550
551 priv->source_unlock_thumb_id = 0;
552
553 return FALSE;
554}
555
556/* adjustment functions */
557
558static void
559adjustment_changed_cb (GtkAdjustment *adjustment,
560 gpointer user_data)
561{
562 OsScrollbar *scrollbar;
563 OsScrollbarPrivate *priv;
564
565 scrollbar = OS_SCROLLBAR (user_data);
566 priv = scrollbar->priv;
567
568 /* FIXME(Cimi) we should control each time os_pager_show()/hide()
569 * is called here and in map()/unmap().
570 * We are arbitrary calling that and I'm frightened we should show or keep
571 * hidden a pager that is meant to be hidden/shown.
572 * I don't want to see pagers reappearing because
573 * of a change in the adjustment of an invisible pager or viceversa. */
574 if ((adjustment->upper - adjustment->lower) > adjustment->page_size)
575 {
576 priv->fullsize = FALSE;
577 if (priv->proximity != FALSE)
578 os_pager_show (OS_PAGER (priv->pager));
579 }
580 else
581 {
582 priv->fullsize = TRUE;
583 if (priv->proximity != FALSE)
584 {
585 os_pager_hide (OS_PAGER (priv->pager));
586
587 gtk_widget_hide (priv->thumb);
588 }
589 }
590
591 calc_layout_pager (scrollbar, adjustment->value);
592 calc_layout_slider (scrollbar, adjustment->value);
593
594 if (!priv->motion_notify_event && !priv->enter_notify_event)
595 gtk_widget_hide (GTK_WIDGET (priv->thumb));
596
597 move_pager (scrollbar);
598}
599
600static void
601adjustment_value_changed_cb (GtkAdjustment *adjustment,
602 gpointer user_data)
603{
604 OsScrollbar *scrollbar;
605 OsScrollbarPrivate *priv;
606
607 scrollbar = OS_SCROLLBAR (user_data);
608 priv = scrollbar->priv;
609
610 calc_layout_pager (scrollbar, adjustment->value);
611 calc_layout_slider (scrollbar, adjustment->value);
612
613 if (!priv->motion_notify_event && !priv->enter_notify_event)
614 gtk_widget_hide (GTK_WIDGET (priv->thumb));
615
616 if (gtk_widget_get_mapped (GTK_WIDGET (priv->thumb)))
617 {
618 /* if we're dragging the thumb, it can't be detached. */
619 if (priv->motion_notify_event)
620 {
621 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
622 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
623 }
624 else
625 {
626 gint x_pos, y_pos;
627 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (priv->thumb)), &x_pos, &y_pos);
628
629 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
630 {
631 if (priv->win_y + priv->overlay.y > y_pos + priv->slider.height)
632 {
633 GdkRectangle mask;
634
635 mask.x = 0;
636 mask.y = y_pos + priv->slider.height / 2 - priv->win_y;
637 mask.width = DEFAULT_PAGER_WIDTH;
638 mask.height = priv->overlay.y - mask.y;
639
640 os_pager_connect (OS_PAGER (priv->pager), mask);
641 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
642
643 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
644 }
645 else if (priv->win_y + priv->overlay.y + priv->overlay.height < y_pos)
646 {
647 GdkRectangle mask;
648
649 mask.x = 0;
650 mask.y = priv->overlay.y + priv->overlay.height;
651 mask.width = DEFAULT_PAGER_WIDTH;
652 mask.height = y_pos + priv->slider.height / 2 - priv->win_y - mask.y;
653
654 os_pager_connect (OS_PAGER (priv->pager), mask);
655 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
656
657 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
658 }
659 else
660 {
661 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
662 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
663 }
664 }
665 else
666 {
667 if (priv->win_x + priv->overlay.x > x_pos + priv->slider.width)
668 {
669 GdkRectangle mask;
670
671 mask.x = x_pos + priv->slider.width / 2 - priv->win_x;
672 mask.y = 0;
673 mask.width = priv->overlay.x - mask.x;
674 mask.height = DEFAULT_PAGER_WIDTH;
675
676 os_pager_connect (OS_PAGER (priv->pager), mask);
677 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
678
679 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
680 }
681 else if (priv->win_x + priv->overlay.x + priv->overlay.width < x_pos)
682 {
683 GdkRectangle mask;
684
685 mask.x = priv->overlay.y + priv->overlay.height;
686 mask.y = 0;
687 mask.width = x_pos + priv->slider.width / 2 - priv->win_x - mask.x;
688 mask.height = DEFAULT_PAGER_WIDTH;
689
690 os_pager_connect (OS_PAGER (priv->pager), mask);
691 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
692 }
693 else
694 {
695 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
696 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
697 }
698 }
699 }
700 }
701
702 move_pager (scrollbar);
703}
704
705/* pager functions */
706
707/* set the state of the pager checking mouse position */
708static void
709pager_set_state_from_pointer (OsScrollbar *scrollbar,
710 gint x,
711 gint y)
712{
713 GtkAllocation allocation;
714 OsScrollbarPrivate *priv;
715
716 priv = scrollbar->priv;
717
718 OS_DCHECK (!priv->active_window);
719
720 gtk_widget_get_allocation (gtk_widget_get_parent (GTK_WIDGET (scrollbar)), &allocation);
721
722 if ((x > allocation.x && x < allocation.x + allocation.width) &&
723 (y > allocation.y && y < allocation.y + allocation.height))
724 {
725 priv->can_deactivate_pager = FALSE;
726 os_pager_set_active (OS_PAGER (priv->pager), TRUE);
727 }
728 else
729 {
730 priv->can_deactivate_pager = TRUE;
731 os_pager_set_active (OS_PAGER (priv->pager), FALSE);
732 }
733}
734
735/* root window functions */
736
737/* react on active window changes */
738static void
739root_gfunc (gpointer data,
740 gpointer user_data)
741{
742 OsScrollbar *scrollbar;
743 OsScrollbarPrivate *priv;
744
745 scrollbar = OS_SCROLLBAR (data);
746 priv = scrollbar->priv;
747
748 OS_DCHECK (scrollbar != NULL);
749
750 if (gtk_widget_get_mapped (GTK_WIDGET (scrollbar)))
751 {
752 if (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (scrollbar))) ==
753 gdk_screen_get_active_window (gtk_widget_get_screen (GTK_WIDGET (scrollbar))))
754 {
755 /* stops potential running timeout. */
756 if (priv->source_deactivate_pager_id != 0)
757 {
758 g_source_remove (priv->source_deactivate_pager_id);
759 priv->source_deactivate_pager_id = 0;
760 }
761
762 priv->active_window = TRUE;
763
764 priv->can_deactivate_pager = FALSE;
765 os_pager_set_active (OS_PAGER (priv->pager), TRUE);
766 }
767 else if (priv->active_window)
768 {
769 GdkWindow *parent;
770 GdkWindow *window;
771 const gint64 current_time = g_get_monotonic_time ();
772 const gint64 end_time = priv->present_time + TIMEOUT_PRESENT_WINDOW * 1000;
773
774 priv->active_window = FALSE;
775
776 /* loop through parent windows until it reaches
777 * either an unknown GdkWindow (NULL),
778 * or the toplevel window. */
779 window = gtk_widget_get_window (GTK_WIDGET (scrollbar));
780 parent = gdk_window_at_pointer (NULL, NULL);
781 while (parent != NULL)
782 {
783 if (window == parent)
784 break;
785
786 parent = gdk_window_get_parent (parent);
787 }
788
789 if (parent != NULL)
790 {
791 gint x, y;
792
793 gdk_window_get_pointer (window, &x, &y, NULL);
794
795 /* when the window is unfocused,
796 * check the position of the pointer
797 * and set the state accordingly. */
798 pager_set_state_from_pointer (scrollbar, x, y);
799 }
800 else
801 {
802 /* if the pointer is outside of the window, set it inactive. */
803 priv->can_deactivate_pager = TRUE;
804 os_pager_set_active (OS_PAGER (priv->pager), FALSE);
805 }
806
807 if ((current_time > end_time) && priv->thumb != NULL)
808 gtk_widget_hide (priv->thumb);
809 }
810 }
811}
812
813/* filter function applied to the root window */
814static GdkFilterReturn
815root_filter_func (GdkXEvent *gdkxevent,
816 GdkEvent *event,
817 gpointer user_data)
818{
819 XEvent* xev;
820
821 xev = gdkxevent;
822
823 if (xev->xany.type == PropertyNotify &&
824 xev->xproperty.atom == net_active_window_atom)
825 {
826 g_list_foreach (os_root_list, root_gfunc, NULL);
827 }
828
829 return GDK_FILTER_CONTINUE;
830}
831
832/* thumb functions */
833
834/* present a X11 window */
835static void
836present_window_with_timestamp (Screen *screen,
837 gint xid,
838 guint32 timestamp)
839{
840 Display *display;
841 Window root;
842 XEvent xev;
843
844 if (timestamp == 0)
845 g_warning ("Received a timestamp of 0; window activation may not "
846 "function properly.\n");
847
848 display = DisplayOfScreen (screen);
849 root = RootWindowOfScreen (screen);
850
851 xev.xclient.type = ClientMessage;
852 xev.xclient.serial = 0;
853 xev.xclient.send_event = True;
854 xev.xclient.display = display;
855 xev.xclient.window = xid;
856 xev.xclient.message_type = gdk_x11_get_xatom_by_name ("_NET_ACTIVE_WINDOW");
857 xev.xclient.format = 32;
858 xev.xclient.data.l[0] = 1;
859 xev.xclient.data.l[1] = timestamp;
860 xev.xclient.data.l[2] = 0;
861 xev.xclient.data.l[3] = 0;
862 xev.xclient.data.l[4] = 0;
863
864 gdk_error_trap_push ();
865
866 XSendEvent (display, root, False,
867 SubstructureRedirectMask | SubstructureNotifyMask,
868 &xev);
869
870 gdk_flush ();
871
872 gdk_error_trap_pop ();
873}
874
875/* present a Gdk window */
876static void
877present_gdk_window_with_timestamp (GtkWidget *widget,
878 guint32 timestamp)
879{
880 present_window_with_timestamp (GDK_SCREEN_XSCREEN (gtk_widget_get_screen (widget)),
881 GDK_WINDOW_XID (gtk_widget_get_window (widget)),
882 timestamp);
883}
884
700static gboolean885static gboolean
701thumb_button_press_event_cb (GtkWidget *widget,886thumb_button_press_event_cb (GtkWidget *widget,
702 GdkEventButton *event,887 GdkEventButton *event,
@@ -716,7 +901,7 @@
716 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (scrollbar))));901 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (scrollbar))));
717902
718 priv->present_time = g_get_monotonic_time ();903 priv->present_time = g_get_monotonic_time ();
719 os_present_gdk_window_with_timestamp (GTK_WIDGET (scrollbar), event->time);904 present_gdk_window_with_timestamp (GTK_WIDGET (scrollbar), event->time);
720905
721 priv->button_press_event = TRUE;906 priv->button_press_event = TRUE;
722 priv->motion_notify_event = FALSE;907 priv->motion_notify_event = FALSE;
@@ -830,7 +1015,7 @@
830 g_source_remove (priv->source_deactivate_pager_id);1015 g_source_remove (priv->source_deactivate_pager_id);
8311016
832 priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_THUMB_HIDE,1017 priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_THUMB_HIDE,
833 os_scrollbar_deactivate_pager_cb,1018 deactivate_pager_cb,
834 scrollbar);1019 scrollbar);
835 }1020 }
8361021
@@ -840,7 +1025,7 @@
840 g_source_remove (priv->source_hide_thumb_id);1025 g_source_remove (priv->source_hide_thumb_id);
8411026
842 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_THUMB_HIDE,1027 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_THUMB_HIDE,
843 os_scrollbar_hide_thumb_cb,1028 hide_thumb_cb,
844 scrollbar);1029 scrollbar);
845 }1030 }
8461031
@@ -916,6 +1101,73 @@
916 }1101 }
917}1102}
9181103
1104/* traduce coordinates into GtkRange values */
1105static gdouble
1106coord_to_value (OsScrollbar *scrollbar,
1107 gint coord)
1108{
1109 OsScrollbarPrivate *priv;
1110 gdouble frac;
1111 gdouble value;
1112 gint trough_length;
1113 gint trough_start;
1114 gint slider_length;
1115
1116 priv = scrollbar->priv;
1117
1118 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1119 {
1120 trough_length = priv->trough.height;
1121 trough_start = priv->trough.y;
1122 slider_length = MAX (priv->slider.height, priv->overlay.height);
1123 }
1124 else
1125 {
1126 trough_length = priv->trough.width;
1127 trough_start = priv->trough.y;
1128 slider_length = MAX (priv->slider.width, priv->overlay.width);
1129 }
1130
1131 if (trough_length == slider_length)
1132 frac = 1.0;
1133 else
1134 frac = (MAX (0, coord - trough_start) /
1135 (gdouble) (trough_length - slider_length));
1136
1137 value = priv->adjustment->lower + frac * (priv->adjustment->upper -
1138 priv->adjustment->lower -
1139 priv->adjustment->page_size);
1140
1141 value = CLAMP (value, priv->adjustment->lower, priv->adjustment->upper - priv->adjustment->page_size);
1142
1143 return value;
1144}
1145
1146/* from pointer movement, set GtkRange value */
1147static void
1148capture_movement (OsScrollbar *scrollbar,
1149 gint mouse_x,
1150 gint mouse_y)
1151{
1152 OsScrollbarPrivate *priv;
1153 gint delta;
1154 gint c;
1155 gdouble new_value;
1156
1157 priv = scrollbar->priv;
1158
1159 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1160 delta = mouse_y - priv->slide_initial_coordinate;
1161 else
1162 delta = mouse_x - priv->slide_initial_coordinate;
1163
1164 c = priv->slide_initial_slider_position + delta;
1165
1166 new_value = coord_to_value (scrollbar, c);
1167
1168 gtk_adjustment_set_value (priv->adjustment, new_value);
1169}
1170
919static gboolean1171static gboolean
920thumb_motion_notify_event_cb (GtkWidget *widget,1172thumb_motion_notify_event_cb (GtkWidget *widget,
921 GdkEventMotion *event,1173 GdkEventMotion *event,
@@ -945,13 +1197,14 @@
945 priv->slide_initial_coordinate = event->x_root;1197 priv->slide_initial_coordinate = event->x_root;
946 }1198 }
9471199
948 os_scrollbar_move (scrollbar, event->x_root, event->y_root);1200 /* FIXME(Cimi) seems useless. */
1201 capture_movement (scrollbar, event->x_root, event->y_root);
949 priv->value_changed_event = FALSE;1202 priv->value_changed_event = FALSE;
950 }1203 }
9511204
952 priv->motion_notify_event = TRUE;1205 priv->motion_notify_event = TRUE;
9531206
954 os_scrollbar_move (scrollbar, event->x_root, event->y_root);1207 capture_movement (scrollbar, event->x_root, event->y_root);
9551208
956 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1209 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
957 {1210 {
@@ -1006,12 +1259,31 @@
1006 }1259 }
1007 }1260 }
10081261
1009 os_scrollbar_move_thumb (scrollbar, x, y);1262 move_thumb (scrollbar, x, y);
1010 }1263 }
10111264
1012 return FALSE;1265 return FALSE;
1013}1266}
10141267
1268/* mouse wheel delta */
1269static gdouble
1270get_wheel_delta (OsScrollbar *scrollbar,
1271 GdkScrollDirection direction)
1272{
1273 OsScrollbarPrivate *priv;
1274 gdouble delta;
1275
1276 priv = scrollbar->priv;
1277
1278 delta = pow (priv->adjustment->page_size, 2.0 / 3.0);
1279
1280 if (direction == GDK_SCROLL_UP ||
1281 direction == GDK_SCROLL_LEFT)
1282 delta = - delta;
1283
1284 return delta;
1285}
1286
1015static gboolean1287static gboolean
1016thumb_scroll_event_cb (GtkWidget *widget,1288thumb_scroll_event_cb (GtkWidget *widget,
1017 GdkEventScroll *event,1289 GdkEventScroll *event,
@@ -1026,7 +1298,7 @@
10261298
1027 priv->value_changed_event = TRUE;1299 priv->value_changed_event = TRUE;
10281300
1029 delta = os_scrollbar_get_wheel_delta (scrollbar, event->direction);1301 delta = get_wheel_delta (scrollbar, event->direction);
10301302
1031 gtk_adjustment_set_value (priv->adjustment,1303 gtk_adjustment_set_value (priv->adjustment,
1032 CLAMP (priv->adjustment->value + delta,1304 CLAMP (priv->adjustment->value + delta,
@@ -1054,297 +1326,30 @@
1054 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);1326 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
1055}1327}
10561328
1057/* Move the pager to the right position. */1329/* toplevel functions */
1330
1331/* store the position of the toplevel window */
1058static void1332static void
1059pager_move (OsScrollbar *scrollbar)1333store_toplevel_position (OsScrollbar *scrollbar)
1060{1334{
1061 GdkRectangle mask;
1062 OsScrollbarPrivate *priv;1335 OsScrollbarPrivate *priv;
1336 gint win_x, win_y;
10631337
1064 priv = scrollbar->priv;1338 priv = scrollbar->priv;
10651339
1340 /* In reality, I'm storing widget's window, not the toplevel.
1341 * Is that the same with gdk_window_get_origin? */
1342 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &win_x, &win_y);
1343
1066 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1344 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1067 {1345 {
1068 mask.x = 0;1346 priv->win_x = win_x + priv->thumb_all.x;
1069 mask.y = priv->overlay.y;1347 priv->win_y = win_y + priv->thumb_all.y;
1070 mask.width = DEFAULT_PAGER_WIDTH;1348 }
1071 mask.height = priv->overlay.height;1349 else
1072 }1350 {
1073 else1351 priv->win_x = win_x + priv->thumb_all.x;
1074 {1352 priv->win_y = win_y + priv->thumb_all.y;
1075 mask.x = priv->overlay.x;
1076 mask.y = 0;
1077 mask.width = priv->overlay.width;
1078 mask.height = DEFAULT_PAGER_WIDTH;
1079 }
1080
1081 os_pager_move_resize (OS_PAGER (priv->pager), mask);
1082}
1083
1084static void
1085pager_set_state_from_pointer (OsScrollbar *scrollbar,
1086 gint x,
1087 gint y)
1088{
1089 GtkAllocation allocation;
1090 OsScrollbarPrivate *priv;
1091
1092 priv = scrollbar->priv;
1093
1094 OS_DCHECK (!priv->active_window);
1095
1096 gtk_widget_get_allocation (gtk_widget_get_parent (GTK_WIDGET (scrollbar)), &allocation);
1097
1098 if ((x > allocation.x && x < allocation.x + allocation.width) &&
1099 (y > allocation.y && y < allocation.y + allocation.height))
1100 {
1101 priv->can_deactivate_pager = FALSE;
1102 os_pager_set_active (OS_PAGER (priv->pager), TRUE);
1103 }
1104 else
1105 {
1106 priv->can_deactivate_pager = TRUE;
1107 os_pager_set_active (OS_PAGER (priv->pager), FALSE);
1108 }
1109}
1110
1111static void
1112adjustment_changed_cb (GtkAdjustment *adjustment,
1113 gpointer user_data)
1114{
1115 OsScrollbar *scrollbar;
1116 OsScrollbarPrivate *priv;
1117
1118 scrollbar = OS_SCROLLBAR (user_data);
1119 priv = scrollbar->priv;
1120
1121 /* FIXME(Cimi) we should control each time os_pager_show()/hide()
1122 * is called here and in map()/unmap().
1123 * We are arbitrary calling that and I'm frightened we should show or keep
1124 * hidden a pager that is meant to be hidden/shown.
1125 * I don't want to see pagers reappearing because
1126 * of a change in the adjustment of an invisible pager or viceversa. */
1127 if ((adjustment->upper - adjustment->lower) > adjustment->page_size)
1128 {
1129 priv->fullsize = FALSE;
1130 if (priv->proximity != FALSE)
1131 os_pager_show (OS_PAGER (priv->pager));
1132 }
1133 else
1134 {
1135 priv->fullsize = TRUE;
1136 if (priv->proximity != FALSE)
1137 {
1138 os_pager_hide (OS_PAGER (priv->pager));
1139
1140 gtk_widget_hide (priv->thumb);
1141 }
1142 }
1143
1144 os_scrollbar_calc_layout_pager (scrollbar, adjustment->value);
1145 os_scrollbar_calc_layout_slider (scrollbar, adjustment->value);
1146
1147 if (!priv->motion_notify_event && !priv->enter_notify_event)
1148 gtk_widget_hide (GTK_WIDGET (priv->thumb));
1149
1150 pager_move (scrollbar);
1151}
1152
1153static void
1154adjustment_value_changed_cb (GtkAdjustment *adjustment,
1155 gpointer user_data)
1156{
1157 OsScrollbar *scrollbar;
1158 OsScrollbarPrivate *priv;
1159
1160 scrollbar = OS_SCROLLBAR (user_data);
1161 priv = scrollbar->priv;
1162
1163 os_scrollbar_calc_layout_pager (scrollbar, adjustment->value);
1164 os_scrollbar_calc_layout_slider (scrollbar, adjustment->value);
1165
1166 if (!priv->motion_notify_event && !priv->enter_notify_event)
1167 gtk_widget_hide (GTK_WIDGET (priv->thumb));
1168
1169 if (gtk_widget_get_mapped (GTK_WIDGET (priv->thumb)))
1170 {
1171 /* if we're dragging the thumb, it can't be detached. */
1172 if (priv->motion_notify_event)
1173 {
1174 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
1175 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
1176 }
1177 else
1178 {
1179 gint x_pos, y_pos;
1180 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (priv->thumb)), &x_pos, &y_pos);
1181
1182 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1183 {
1184 if (priv->win_y + priv->overlay.y > y_pos + priv->slider.height)
1185 {
1186 GdkRectangle mask;
1187
1188 mask.x = 0;
1189 mask.y = y_pos + priv->slider.height / 2 - priv->win_y;
1190 mask.width = DEFAULT_PAGER_WIDTH;
1191 mask.height = priv->overlay.y - mask.y;
1192
1193 os_pager_connect (OS_PAGER (priv->pager), mask);
1194 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
1195
1196 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
1197 }
1198 else if (priv->win_y + priv->overlay.y + priv->overlay.height < y_pos)
1199 {
1200 GdkRectangle mask;
1201
1202 mask.x = 0;
1203 mask.y = priv->overlay.y + priv->overlay.height;
1204 mask.width = DEFAULT_PAGER_WIDTH;
1205 mask.height = y_pos + priv->slider.height / 2 - priv->win_y - mask.y;
1206
1207 os_pager_connect (OS_PAGER (priv->pager), mask);
1208 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
1209
1210 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
1211 }
1212 else
1213 {
1214 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
1215 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
1216 }
1217 }
1218 else
1219 {
1220 if (priv->win_x + priv->overlay.x > x_pos + priv->slider.width)
1221 {
1222 GdkRectangle mask;
1223
1224 mask.x = x_pos + priv->slider.width / 2 - priv->win_x;
1225 mask.y = 0;
1226 mask.width = priv->overlay.x - mask.x;
1227 mask.height = DEFAULT_PAGER_WIDTH;
1228
1229 os_pager_connect (OS_PAGER (priv->pager), mask);
1230 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
1231
1232 os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
1233 }
1234 else if (priv->win_x + priv->overlay.x + priv->overlay.width < x_pos)
1235 {
1236 GdkRectangle mask;
1237
1238 mask.x = priv->overlay.y + priv->overlay.height;
1239 mask.y = 0;
1240 mask.width = x_pos + priv->slider.width / 2 - priv->win_x - mask.x;
1241 mask.height = DEFAULT_PAGER_WIDTH;
1242
1243 os_pager_connect (OS_PAGER (priv->pager), mask);
1244 os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
1245 }
1246 else
1247 {
1248 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
1249 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
1250 }
1251 }
1252 }
1253 }
1254
1255 pager_move (scrollbar);
1256}
1257
1258static GdkFilterReturn
1259root_filter_func (GdkXEvent *gdkxevent,
1260 GdkEvent *event,
1261 gpointer user_data)
1262{
1263 XEvent* xevent;
1264
1265 xevent = gdkxevent;
1266
1267 if (xevent->xany.type == PropertyNotify &&
1268 xevent->xproperty.atom == net_active_window_atom)
1269 {
1270 g_list_foreach (os_root_list, root_gfunc, NULL);
1271 }
1272
1273 return GDK_FILTER_CONTINUE;
1274}
1275
1276static void
1277root_gfunc (gpointer data,
1278 gpointer user_data)
1279{
1280 OsScrollbar *scrollbar;
1281 OsScrollbarPrivate *priv;
1282
1283 scrollbar = OS_SCROLLBAR (data);
1284 priv = scrollbar->priv;
1285
1286 OS_DCHECK (scrollbar != NULL);
1287
1288 if (gtk_widget_get_mapped (GTK_WIDGET (scrollbar)))
1289 {
1290 if (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (scrollbar))) ==
1291 gdk_screen_get_active_window (gtk_widget_get_screen (GTK_WIDGET (scrollbar))))
1292 {
1293 /* stops potential running timeout. */
1294 if (priv->source_deactivate_pager_id != 0)
1295 {
1296 g_source_remove (priv->source_deactivate_pager_id);
1297 priv->source_deactivate_pager_id = 0;
1298 }
1299
1300 priv->active_window = TRUE;
1301
1302 priv->can_deactivate_pager = FALSE;
1303 os_pager_set_active (OS_PAGER (priv->pager), TRUE);
1304 }
1305 else if (priv->active_window)
1306 {
1307 GdkWindow *parent;
1308 GdkWindow *window;
1309 const gint64 current_time = g_get_monotonic_time ();
1310 const gint64 end_time = priv->present_time + TIMEOUT_PRESENT_WINDOW * 1000;
1311
1312 priv->active_window = FALSE;
1313
1314 /* loop through parent windows until it reaches
1315 * either an unknown GdkWindow (NULL),
1316 * or the toplevel window. */
1317 window = gtk_widget_get_window (GTK_WIDGET (scrollbar));
1318 parent = gdk_window_at_pointer (NULL, NULL);
1319 while (parent != NULL)
1320 {
1321 if (window == parent)
1322 break;
1323
1324 parent = gdk_window_get_parent (parent);
1325 }
1326
1327 if (parent != NULL)
1328 {
1329 gint x, y;
1330
1331 gdk_window_get_pointer (window, &x, &y, NULL);
1332
1333 /* when the window is unfocused,
1334 * check the position of the pointer
1335 * and set the state accordingly. */
1336 pager_set_state_from_pointer (scrollbar, x, y);
1337 }
1338 else
1339 {
1340 /* if the pointer is outside of the window, set it inactive. */
1341 priv->can_deactivate_pager = TRUE;
1342 os_pager_set_active (OS_PAGER (priv->pager), FALSE);
1343 }
1344
1345 if ((current_time > end_time) && priv->thumb != NULL)
1346 gtk_widget_hide (priv->thumb);
1347 }
1348 }1353 }
1349}1354}
13501355
@@ -1405,15 +1410,15 @@
14051410
1406 priv->lock_position = FALSE;1411 priv->lock_position = FALSE;
14071412
1408 os_scrollbar_calc_layout_pager (scrollbar, priv->adjustment->value);1413 calc_layout_pager (scrollbar, priv->adjustment->value);
1409 os_scrollbar_calc_layout_slider (scrollbar, priv->adjustment->value);1414 calc_layout_slider (scrollbar, priv->adjustment->value);
14101415
1411 os_scrollbar_store_window_position (scrollbar);1416 store_toplevel_position (scrollbar);
14121417
1413 return FALSE;1418 return FALSE;
1414}1419}
14151420
1416/* Add a filter to the toplevel GdkWindow, to activate proximity effect. */1421/* filter function applied to the toplevel window */
1417static GdkFilterReturn1422static GdkFilterReturn
1418toplevel_filter_func (GdkXEvent *gdkxevent,1423toplevel_filter_func (GdkXEvent *gdkxevent,
1419 GdkEvent *event,1424 GdkEvent *event,
@@ -1421,37 +1426,37 @@
1421{1426{
1422 OsScrollbar *scrollbar;1427 OsScrollbar *scrollbar;
1423 OsScrollbarPrivate *priv;1428 OsScrollbarPrivate *priv;
1424 XEvent *xevent;1429 XEvent *xev;
14251430
1426 g_return_val_if_fail (OS_SCROLLBAR (user_data), GDK_FILTER_CONTINUE);1431 g_return_val_if_fail (OS_SCROLLBAR (user_data), GDK_FILTER_CONTINUE);
14271432
1428 scrollbar = OS_SCROLLBAR (user_data);1433 scrollbar = OS_SCROLLBAR (user_data);
14291434
1430 priv = scrollbar->priv;1435 priv = scrollbar->priv;
1431 xevent = gdkxevent;1436 xev = gdkxevent;
14321437
1433 g_return_val_if_fail (priv->pager != NULL, GDK_FILTER_CONTINUE);1438 g_return_val_if_fail (priv->pager != NULL, GDK_FILTER_CONTINUE);
1434 g_return_val_if_fail (priv->thumb != NULL, GDK_FILTER_CONTINUE);1439 g_return_val_if_fail (priv->thumb != NULL, GDK_FILTER_CONTINUE);
14351440
1436 if (!priv->fullsize)1441 if (!priv->fullsize)
1437 {1442 {
1438 if (xevent->type == ButtonPress)1443 if (xev->type == ButtonPress)
1439 {1444 {
1440 priv->toplevel_button_press = TRUE;1445 priv->toplevel_button_press = TRUE;
1441 gtk_widget_hide (priv->thumb);1446 gtk_widget_hide (priv->thumb);
1442 }1447 }
14431448
1444 if (priv->toplevel_button_press && xevent->type == ButtonRelease)1449 if (priv->toplevel_button_press && xev->type == ButtonRelease)
1445 {1450 {
1446 priv->toplevel_button_press = FALSE;1451 priv->toplevel_button_press = FALSE;
14471452
1448 /* proximity area */1453 /* proximity area */
1449 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1454 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1450 {1455 {
1451 if ((priv->thumb_all.x - xevent->xbutton.x <= PROXIMITY_WIDTH &&1456 if ((priv->thumb_all.x - xev->xbutton.x <= PROXIMITY_WIDTH &&
1452 priv->thumb_all.x - xevent->xbutton.x >= 0) &&1457 priv->thumb_all.x - xev->xbutton.x >= 0) &&
1453 (xevent->xbutton.y >= priv->thumb_all.y + priv->overlay.y &&1458 (xev->xbutton.y >= priv->thumb_all.y + priv->overlay.y &&
1454 xevent->xbutton.y <= priv->thumb_all.y + priv->overlay.y + priv->overlay.height))1459 xev->xbutton.y <= priv->thumb_all.y + priv->overlay.y + priv->overlay.height))
1455 {1460 {
1456 priv->can_hide = FALSE;1461 priv->can_hide = FALSE;
14571462
@@ -1465,15 +1470,15 @@
1465 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);1470 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
14661471
1467 x = priv->thumb_all.x;1472 x = priv->thumb_all.x;
1468 y = CLAMP (xevent->xbutton.y - priv->slider.height / 2,1473 y = CLAMP (xev->xbutton.y - priv->slider.height / 2,
1469 priv->thumb_all.y + priv->overlay.y,1474 priv->thumb_all.y + priv->overlay.y,
1470 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);1475 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
14711476
1472 os_scrollbar_move_thumb (scrollbar, x_pos + x, y_pos + y);1477 move_thumb (scrollbar, x_pos + x, y_pos + y);
1473 }1478 }
1474 else1479 else
1475 {1480 {
1476 os_scrollbar_move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);1481 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
1477 }1482 }
14781483
1479 gtk_widget_show (GTK_WIDGET (priv->thumb));1484 gtk_widget_show (GTK_WIDGET (priv->thumb));
@@ -1481,10 +1486,10 @@
1481 }1486 }
1482 else1487 else
1483 {1488 {
1484 if ((priv->thumb_all.y - xevent->xbutton.y <= PROXIMITY_WIDTH &&1489 if ((priv->thumb_all.y - xev->xbutton.y <= PROXIMITY_WIDTH &&
1485 priv->thumb_all.y - xevent->xbutton.y >= 0) &&1490 priv->thumb_all.y - xev->xbutton.y >= 0) &&
1486 (xevent->xbutton.x >= priv->thumb_all.x + priv->overlay.x &&1491 (xev->xbutton.x >= priv->thumb_all.x + priv->overlay.x &&
1487 xevent->xbutton.x <= priv->thumb_all.x + priv->overlay.x + priv->overlay.width))1492 xev->xbutton.x <= priv->thumb_all.x + priv->overlay.x + priv->overlay.width))
1488 {1493 {
1489 priv->can_hide = FALSE;1494 priv->can_hide = FALSE;
14901495
@@ -1497,16 +1502,16 @@
14971502
1498 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);1503 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
14991504
1500 x = CLAMP (xevent->xbutton.x - priv->slider.width / 2,1505 x = CLAMP (xev->xbutton.x - priv->slider.width / 2,
1501 priv->thumb_all.x + priv->overlay.x,1506 priv->thumb_all.x + priv->overlay.x,
1502 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);1507 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
1503 y = priv->thumb_all.y;1508 y = priv->thumb_all.y;
15041509
1505 os_scrollbar_move_thumb (scrollbar, x_pos + x, y_pos + y);1510 move_thumb (scrollbar, x_pos + x, y_pos + y);
1506 }1511 }
1507 else1512 else
1508 {1513 {
1509 os_scrollbar_move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);1514 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
1510 }1515 }
15111516
1512 gtk_widget_show (GTK_WIDGET (priv->thumb));1517 gtk_widget_show (GTK_WIDGET (priv->thumb));
@@ -1520,10 +1525,10 @@
1520 * this call checks the pointer after the scroll-event,1525 * this call checks the pointer after the scroll-event,
1521 * since it enters the window,1526 * since it enters the window,
1522 * then sets the state accordingly. */1527 * then sets the state accordingly. */
1523 if (!priv->active_window && xevent->type == EnterNotify)1528 if (!priv->active_window && xev->type == EnterNotify)
1524 pager_set_state_from_pointer (scrollbar, xevent->xcrossing.x, xevent->xcrossing.y);1529 pager_set_state_from_pointer (scrollbar, xev->xcrossing.x, xev->xcrossing.y);
15251530
1526 if (xevent->type == LeaveNotify)1531 if (xev->type == LeaveNotify)
1527 {1532 {
1528 /* never deactivate the pager in an active window. */1533 /* never deactivate the pager in an active window. */
1529 if (!priv->active_window)1534 if (!priv->active_window)
@@ -1534,7 +1539,7 @@
1534 g_source_remove (priv->source_deactivate_pager_id);1539 g_source_remove (priv->source_deactivate_pager_id);
15351540
1536 priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,1541 priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
1537 os_scrollbar_deactivate_pager_cb,1542 deactivate_pager_cb,
1538 scrollbar);1543 scrollbar);
1539 }1544 }
15401545
@@ -1545,32 +1550,32 @@
1545 g_source_remove (priv->source_hide_thumb_id);1550 g_source_remove (priv->source_hide_thumb_id);
15461551
1547 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,1552 priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
1548 os_scrollbar_hide_thumb_cb,1553 hide_thumb_cb,
1549 scrollbar);1554 scrollbar);
15501555
1551 if (priv->source_unlock_thumb_id != 0)1556 if (priv->source_unlock_thumb_id != 0)
1552 g_source_remove (priv->source_unlock_thumb_id);1557 g_source_remove (priv->source_unlock_thumb_id);
15531558
1554 priv->source_unlock_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,1559 priv->source_unlock_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
1555 os_scrollbar_unlock_thumb_cb,1560 unlock_thumb_cb,
1556 scrollbar);1561 scrollbar);
1557 }1562 }
15581563
1559 /* get the motion_notify_event trough XEvent */1564 /* get the motion_notify_event trough XEvent */
1560 if (!priv->toplevel_button_press && xevent->type == MotionNotify)1565 if (!priv->toplevel_button_press && xev->type == MotionNotify)
1561 {1566 {
1562 /* react to motion_notify_event1567 /* react to motion_notify_event
1563 * and set the state accordingly. */1568 * and set the state accordingly. */
1564 if (!priv->active_window)1569 if (!priv->active_window)
1565 pager_set_state_from_pointer (scrollbar, xevent->xmotion.x, xevent->xmotion.y);1570 pager_set_state_from_pointer (scrollbar, xev->xmotion.x, xev->xmotion.y);
15661571
1567 /* proximity area */1572 /* proximity area */
1568 if (priv->orientation == GTK_ORIENTATION_VERTICAL)1573 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
1569 {1574 {
1570 if ((priv->thumb_all.x - xevent->xmotion.x <= PROXIMITY_WIDTH &&1575 if ((priv->thumb_all.x - xev->xmotion.x <= PROXIMITY_WIDTH &&
1571 priv->thumb_all.x - xevent->xmotion.x >= 0) &&1576 priv->thumb_all.x - xev->xmotion.x >= 0) &&
1572 (xevent->xmotion.y >= priv->thumb_all.y + priv->overlay.y &&1577 (xev->xmotion.y >= priv->thumb_all.y + priv->overlay.y &&
1573 xevent->xmotion.y <= priv->thumb_all.y + priv->overlay.y + priv->overlay.height))1578 xev->xmotion.y <= priv->thumb_all.y + priv->overlay.y + priv->overlay.height))
1574 {1579 {
1575 priv->can_hide = FALSE;1580 priv->can_hide = FALSE;
15761581
@@ -1584,15 +1589,15 @@
1584 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);1589 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
15851590
1586 x = priv->thumb_all.x;1591 x = priv->thumb_all.x;
1587 y = CLAMP (xevent->xmotion.y - priv->slider.height / 2,1592 y = CLAMP (xev->xmotion.y - priv->slider.height / 2,
1588 priv->thumb_all.y + priv->overlay.y,1593 priv->thumb_all.y + priv->overlay.y,
1589 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);1594 priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
15901595
1591 os_scrollbar_move_thumb (scrollbar, x_pos + x, y_pos + y);1596 move_thumb (scrollbar, x_pos + x, y_pos + y);
1592 }1597 }
1593 else1598 else
1594 {1599 {
1595 os_scrollbar_move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);1600 move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
1596 }1601 }
15971602
1598 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);1603 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
@@ -1603,15 +1608,15 @@
1603 {1608 {
1604 priv->can_hide = TRUE;1609 priv->can_hide = TRUE;
1605 priv->lock_position = FALSE;1610 priv->lock_position = FALSE;
1606 os_scrollbar_hide_thumb (scrollbar);1611 hide_thumb (scrollbar);
1607 }1612 }
1608 }1613 }
1609 else1614 else
1610 {1615 {
1611 if ((priv->thumb_all.y - xevent->xmotion.y <= PROXIMITY_WIDTH &&1616 if ((priv->thumb_all.y - xev->xmotion.y <= PROXIMITY_WIDTH &&
1612 priv->thumb_all.y - xevent->xmotion.y >= 0) &&1617 priv->thumb_all.y - xev->xmotion.y >= 0) &&
1613 (xevent->xmotion.x >= priv->thumb_all.x + priv->overlay.x &&1618 (xev->xmotion.x >= priv->thumb_all.x + priv->overlay.x &&
1614 xevent->xmotion.x <= priv->thumb_all.x + priv->overlay.x + priv->overlay.width))1619 xev->xmotion.x <= priv->thumb_all.x + priv->overlay.x + priv->overlay.width))
1615 {1620 {
1616 priv->can_hide = FALSE;1621 priv->can_hide = FALSE;
16171622
@@ -1624,16 +1629,16 @@
16241629
1625 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);1630 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
16261631
1627 x = CLAMP (xevent->xmotion.x - priv->slider.width / 2,1632 x = CLAMP (xev->xmotion.x - priv->slider.width / 2,
1628 priv->thumb_all.x + priv->overlay.x,1633 priv->thumb_all.x + priv->overlay.x,
1629 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);1634 priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
1630 y = priv->thumb_all.y;1635 y = priv->thumb_all.y;
16311636
1632 os_scrollbar_move_thumb (scrollbar, x_pos + x, y_pos + y);1637 move_thumb (scrollbar, x_pos + x, y_pos + y);
1633 }1638 }
1634 else1639 else
1635 {1640 {
1636 os_scrollbar_move_thumb (scrollbar, priv->win_x + priv->slider.x, priv->win_y);1641 move_thumb (scrollbar, priv->win_x + priv->slider.x, priv->win_y);
1637 }1642 }
16381643
1639 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);1644 os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
@@ -1644,7 +1649,7 @@
1644 {1649 {
1645 priv->can_hide = TRUE;1650 priv->can_hide = TRUE;
1646 priv->lock_position = FALSE;1651 priv->lock_position = FALSE;
1647 os_scrollbar_hide_thumb (scrollbar);1652 hide_thumb (scrollbar);
1648 }1653 }
1649 }1654 }
1650 }1655 }
@@ -1653,8 +1658,6 @@
1653 return GDK_FILTER_CONTINUE;1658 return GDK_FILTER_CONTINUE;
1654}1659}
16551660
1656/* Type definition. */
1657
1658G_DEFINE_TYPE (OsScrollbar, os_scrollbar, GTK_TYPE_SCROLLBAR);1661G_DEFINE_TYPE (OsScrollbar, os_scrollbar, GTK_TYPE_SCROLLBAR);
16591662
1660static void1663static void
@@ -1717,6 +1720,11 @@
1717 os_root_list = g_list_append (os_root_list, scrollbar);1720 os_root_list = g_list_append (os_root_list, scrollbar);
1718 }1721 }
17191722
1723 priv->button_press_event = FALSE;
1724 priv->enter_notify_event = FALSE;
1725 priv->motion_notify_event = FALSE;
1726 priv->value_changed_event = FALSE;
1727
1720 priv->active_window = FALSE;1728 priv->active_window = FALSE;
1721 priv->can_deactivate_pager = TRUE;1729 priv->can_deactivate_pager = TRUE;
1722 priv->can_hide = TRUE;1730 priv->can_hide = TRUE;
@@ -1733,10 +1741,10 @@
1733 priv->pager = os_pager_new ();1741 priv->pager = os_pager_new ();
17341742
1735 g_signal_connect (G_OBJECT (scrollbar), "notify::adjustment",1743 g_signal_connect (G_OBJECT (scrollbar), "notify::adjustment",
1736 G_CALLBACK (os_scrollbar_notify_adjustment_cb), NULL);1744 G_CALLBACK (notify_adjustment_cb), NULL);
17371745
1738 g_signal_connect (G_OBJECT (scrollbar), "notify::orientation",1746 g_signal_connect (G_OBJECT (scrollbar), "notify::orientation",
1739 G_CALLBACK (os_scrollbar_notify_orientation_cb), NULL);1747 G_CALLBACK (notify_orientation_cb), NULL);
1740}1748}
17411749
1742static void1750static void
@@ -1778,8 +1786,8 @@
1778 priv->pager = NULL;1786 priv->pager = NULL;
1779 }1787 }
17801788
1781 os_scrollbar_swap_adjustment (scrollbar, NULL);1789 swap_adjustment (scrollbar, NULL);
1782 os_scrollbar_swap_thumb (scrollbar, NULL);1790 swap_thumb (scrollbar, NULL);
17831791
1784 G_OBJECT_CLASS (os_scrollbar_parent_class)->dispose (object);1792 G_OBJECT_CLASS (os_scrollbar_parent_class)->dispose (object);
1785}1793}
@@ -1892,11 +1900,11 @@
1892 g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)), "configure-event",1900 g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)), "configure-event",
1893 G_CALLBACK (toplevel_configure_event_cb), scrollbar);1901 G_CALLBACK (toplevel_configure_event_cb), scrollbar);
18941902
1895 os_scrollbar_calc_layout_pager (scrollbar, priv->adjustment->value);1903 calc_layout_pager (scrollbar, priv->adjustment->value);
18961904
1897 os_pager_set_parent (OS_PAGER (priv->pager), widget);1905 os_pager_set_parent (OS_PAGER (priv->pager), widget);
18981906
1899 os_scrollbar_store_window_position (scrollbar);1907 store_toplevel_position (scrollbar);
1900}1908}
19011909
1902static void1910static void
@@ -1955,16 +1963,16 @@
19551963
1956 if (priv->adjustment != NULL)1964 if (priv->adjustment != NULL)
1957 {1965 {
1958 os_scrollbar_calc_layout_pager (scrollbar, priv->adjustment->value);1966 calc_layout_pager (scrollbar, priv->adjustment->value);
1959 os_scrollbar_calc_layout_slider (scrollbar, priv->adjustment->value);1967 calc_layout_slider (scrollbar, priv->adjustment->value);
1960 }1968 }
19611969
1962 os_pager_size_allocate (OS_PAGER (priv->pager), rect);1970 os_pager_size_allocate (OS_PAGER (priv->pager), rect);
19631971
1964 pager_move (scrollbar);1972 move_pager (scrollbar);
19651973
1966 if (gtk_widget_get_realized (widget))1974 if (gtk_widget_get_realized (widget))
1967 os_scrollbar_store_window_position (scrollbar);1975 store_toplevel_position (scrollbar);
19681976
1969 widget->allocation = *allocation;1977 widget->allocation = *allocation;
1970}1978}
19711979
=== modified file 'os/os-thumb.c'
--- os/os-thumb.c 2011-05-17 22:10:53 +0000
+++ os/os-thumb.c 2011-05-18 18:39:29 +0000
@@ -50,8 +50,8 @@
50 gboolean button_press_event;50 gboolean button_press_event;
51 gboolean motion_notify_event;51 gboolean motion_notify_event;
52 gboolean can_rgba;52 gboolean can_rgba;
53 gboolean detached;
53 gboolean use_tolerance;54 gboolean use_tolerance;
54 gboolean detached;
55 gint pointer_x;55 gint pointer_x;
56 gint pointer_y;56 gint pointer_y;
57 guint32 source_id;57 guint32 source_id;
@@ -63,8 +63,6 @@
63 LAST_ARG63 LAST_ARG
64};64};
6565
66static void os_thumb_fade_out_cb (gfloat weight, gpointer user_data);
67static gboolean os_thumb_timeout_fade_out_cb (gpointer user_data);
68static gboolean os_thumb_button_press_event (GtkWidget *widget, GdkEventButton *event);66static gboolean os_thumb_button_press_event (GtkWidget *widget, GdkEventButton *event);
69static gboolean os_thumb_button_release_event (GtkWidget *widget, GdkEventButton *event);67static gboolean os_thumb_button_release_event (GtkWidget *widget, GdkEventButton *event);
70static void os_thumb_composited_changed (GtkWidget *widget);68static void os_thumb_composited_changed (GtkWidget *widget);
@@ -81,61 +79,12 @@
81static void os_thumb_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);79static void os_thumb_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
82static void os_thumb_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);80static void os_thumb_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
8381
84/* Private functions. */82/* Private functions */
8583
86/* Draw an arror. */84/* callback called by the fade-out animation */
87static void85static void
88os_cairo_draw_arrow (cairo_t *cr,86fade_out_cb (gfloat weight,
89 gdouble x,87 gpointer user_data)
90 gdouble y,
91 gdouble width,
92 gdouble height)
93{
94 cairo_save (cr);
95
96 cairo_translate (cr, x, y);
97 cairo_move_to (cr, -width / 2, -height / 2);
98 cairo_line_to (cr, 0, height / 2);
99 cairo_line_to (cr, width / 2, -height / 2);
100 cairo_close_path (cr);
101
102 cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 0.75);
103 cairo_fill_preserve (cr);
104
105 cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 1.0);
106 cairo_stroke (cr);
107
108 cairo_restore (cr);
109}
110
111/* Draw a rounded rectangle. */
112static void
113os_cairo_draw_rounded_rect (cairo_t *cr,
114 gdouble x,
115 gdouble y,
116 gdouble width,
117 gdouble height,
118 gdouble radius)
119{
120 if (radius < 1)
121 {
122 cairo_rectangle (cr, x, y, width, height);
123 return;
124 }
125
126 radius = MIN (radius, MIN (width / 2.0, height / 2.0));
127
128 cairo_move_to (cr, x + radius, y);
129
130 cairo_arc (cr, x + width - radius, y + radius, radius, G_PI * 1.5, G_PI * 2);
131 cairo_arc (cr, x + width - radius, y + height - radius, radius, 0, G_PI * 0.5);
132 cairo_arc (cr, x + radius, y + height - radius, radius, G_PI * 0.5, G_PI);
133 cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
134}
135
136static void
137os_thumb_fade_out_cb (gfloat weight,
138 gpointer user_data)
139{88{
140 OsThumb *thumb;89 OsThumb *thumb;
14190
@@ -147,8 +96,9 @@
147 gtk_widget_hide (GTK_WIDGET (thumb));96 gtk_widget_hide (GTK_WIDGET (thumb));
148}97}
14998
99/* timeout before starting the fade-out animation */
150static gboolean100static gboolean
151os_thumb_timeout_fade_out_cb (gpointer user_data)101timeout_fade_out_cb (gpointer user_data)
152{102{
153 OsThumb *thumb;103 OsThumb *thumb;
154 OsThumbPrivate *priv;104 OsThumbPrivate *priv;
@@ -163,8 +113,6 @@
163 return FALSE;113 return FALSE;
164}114}
165115
166/* Type definition. */
167
168G_DEFINE_TYPE (OsThumb, os_thumb, GTK_TYPE_WINDOW);116G_DEFINE_TYPE (OsThumb, os_thumb, GTK_TYPE_WINDOW);
169117
170static void118static void
@@ -214,16 +162,19 @@
214 OsThumbPrivate);162 OsThumbPrivate);
215 priv = thumb->priv;163 priv = thumb->priv;
216164
165 priv->button_press_event = FALSE;
166 priv->motion_notify_event = FALSE;
167
217 priv->can_rgba = FALSE;168 priv->can_rgba = FALSE;
218 priv->detached = FALSE;169 priv->detached = FALSE;
170 priv->use_tolerance = FALSE;
219171
220 priv->source_id = 0;172 priv->source_id = 0;
221 priv->animation = os_animation_new (RATE_FADE_OUT, DURATION_FADE_OUT,173 priv->animation = os_animation_new (RATE_FADE_OUT, DURATION_FADE_OUT,
222 os_thumb_fade_out_cb, NULL, thumb);174 fade_out_cb, NULL, thumb);
223175
224 gtk_window_set_skip_pager_hint (GTK_WINDOW (thumb), TRUE);176 gtk_window_set_skip_pager_hint (GTK_WINDOW (thumb), TRUE);
225 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (thumb), TRUE);177 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (thumb), TRUE);
226 /* gtk_window_set_has_resize_grip (GTK_WINDOW (thumb), FALSE); */
227 gtk_window_set_decorated (GTK_WINDOW (thumb), FALSE);178 gtk_window_set_decorated (GTK_WINDOW (thumb), FALSE);
228 gtk_window_set_focus_on_map (GTK_WINDOW (thumb), FALSE);179 gtk_window_set_focus_on_map (GTK_WINDOW (thumb), FALSE);
229 gtk_window_set_accept_focus (GTK_WINDOW (thumb), FALSE);180 gtk_window_set_accept_focus (GTK_WINDOW (thumb), FALSE);
@@ -237,43 +188,6 @@
237 os_thumb_composited_changed (GTK_WIDGET (thumb));188 os_thumb_composited_changed (GTK_WIDGET (thumb));
238}189}
239190
240static void
241os_thumb_dispose (GObject *object)
242{
243 OsThumb *thumb;
244 OsThumbPrivate *priv;
245
246 thumb = OS_THUMB (object);
247 priv = thumb->priv;
248
249 if (priv->source_id != 0)
250 {
251 g_source_remove (priv->source_id);
252 priv->source_id = 0;
253 }
254
255 if (priv->animation != NULL)
256 {
257 g_object_unref (priv->animation);
258 priv->animation = NULL;
259 }
260
261 if (priv->grabbed_widget != NULL)
262 {
263 g_object_unref (priv->grabbed_widget);
264 priv->grabbed_widget = NULL;
265 }
266
267 G_OBJECT_CLASS (os_thumb_parent_class)->dispose (object);
268}
269
270static void
271os_thumb_finalize (GObject *object)
272{
273 G_OBJECT_CLASS (os_thumb_parent_class)->finalize (object);
274}
275
276
277static gboolean191static gboolean
278os_thumb_button_press_event (GtkWidget *widget,192os_thumb_button_press_event (GtkWidget *widget,
279 GdkEventButton *event)193 GdkEventButton *event)
@@ -371,6 +285,56 @@
371 gtk_widget_queue_draw (widget);285 gtk_widget_queue_draw (widget);
372}286}
373287
288/* draw an arrow using cairo */
289static void
290draw_arrow (cairo_t *cr,
291 gdouble x,
292 gdouble y,
293 gdouble width,
294 gdouble height)
295{
296 cairo_save (cr);
297
298 cairo_translate (cr, x, y);
299 cairo_move_to (cr, -width / 2, -height / 2);
300 cairo_line_to (cr, 0, height / 2);
301 cairo_line_to (cr, width / 2, -height / 2);
302 cairo_close_path (cr);
303
304 cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 0.75);
305 cairo_fill_preserve (cr);
306
307 cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 1.0);
308 cairo_stroke (cr);
309
310 cairo_restore (cr);
311}
312
313/* draw a rounded rectangle using cairo */
314static void
315draw_round_rect (cairo_t *cr,
316 gdouble x,
317 gdouble y,
318 gdouble width,
319 gdouble height,
320 gdouble radius)
321{
322 radius = MIN (radius, MIN (width / 2.0, height / 2.0));
323
324 if (radius < 1)
325 {
326 cairo_rectangle (cr, x, y, width, height);
327 return;
328 }
329
330 cairo_move_to (cr, x + radius, y);
331
332 cairo_arc (cr, x + width - radius, y + radius, radius, G_PI * 1.5, G_PI * 2);
333 cairo_arc (cr, x + width - radius, y + height - radius, radius, 0, G_PI * 0.5);
334 cairo_arc (cr, x + radius, y + height - radius, radius, G_PI * 0.5, G_PI);
335 cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
336}
337
374static gboolean338static gboolean
375os_thumb_expose (GtkWidget *widget,339os_thumb_expose (GtkWidget *widget,
376 GdkEventExpose *event)340 GdkEventExpose *event)
@@ -413,7 +377,7 @@
413 cairo_set_line_width (cr, 1);377 cairo_set_line_width (cr, 1);
414 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);378 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
415379
416 os_cairo_draw_rounded_rect (cr, x, y, width, height, radius);380 draw_round_rect (cr, x, y, width, height, radius);
417381
418 if (priv->orientation == GTK_ORIENTATION_VERTICAL)382 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
419 pat = cairo_pattern_create_linear (x, y, width + x, y);383 pat = cairo_pattern_create_linear (x, y, width + x, y);
@@ -426,7 +390,7 @@
426 cairo_pattern_destroy (pat);390 cairo_pattern_destroy (pat);
427 cairo_fill (cr);391 cairo_fill (cr);
428392
429 os_cairo_draw_rounded_rect (cr, x, y, width, height, radius);393 draw_round_rect (cr, x, y, width, height, radius);
430394
431 if (priv->orientation == GTK_ORIENTATION_VERTICAL)395 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
432 pat = cairo_pattern_create_linear (x, y, x, height + y);396 pat = cairo_pattern_create_linear (x, y, x, height + y);
@@ -461,7 +425,6 @@
461 cairo_set_source (cr, pat);425 cairo_set_source (cr, pat);
462 cairo_pattern_destroy (pat);426 cairo_pattern_destroy (pat);
463427
464
465 if (priv->motion_notify_event)428 if (priv->motion_notify_event)
466 {429 {
467 cairo_fill_preserve (cr);430 cairo_fill_preserve (cr);
@@ -472,7 +435,7 @@
472 cairo_fill (cr);435 cairo_fill (cr);
473436
474 cairo_set_line_width (cr, 2.0);437 cairo_set_line_width (cr, 2.0);
475 os_cairo_draw_rounded_rect (cr, x + 0.5, y + 0.5, width - 1, height - 1, radius - 1);438 draw_round_rect (cr, x + 0.5, y + 0.5, width - 1, height - 1, radius - 1);
476 if (!priv->detached)439 if (!priv->detached)
477 cairo_set_source_rgba (cr, style->bg[GTK_STATE_SELECTED].red/65535.0,440 cairo_set_source_rgba (cr, style->bg[GTK_STATE_SELECTED].red/65535.0,
478 style->bg[GTK_STATE_SELECTED].green/65535.0,441 style->bg[GTK_STATE_SELECTED].green/65535.0,
@@ -482,15 +445,15 @@
482 cairo_stroke (cr);445 cairo_stroke (cr);
483446
484 cairo_set_line_width (cr, 1.0);447 cairo_set_line_width (cr, 1.0);
485 os_cairo_draw_rounded_rect (cr, x + 1, y + 1, width - 2, height - 2, radius - 1);448 draw_round_rect (cr, x + 1, y + 1, width - 2, height - 2, radius - 1);
486 cairo_set_source_rgba (cr, 0.1, 0.1, 0.1, 0.1);449 cairo_set_source_rgba (cr, 0.1, 0.1, 0.1, 0.1);
487 cairo_stroke (cr);450 cairo_stroke (cr);
488451
489 os_cairo_draw_rounded_rect (cr, x + 2, y + 2, width - 4, height - 4, radius - 3);452 draw_round_rect (cr, x + 2, y + 2, width - 4, height - 4, radius - 3);
490 cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, 0.5);453 cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, 0.5);
491 cairo_stroke (cr);454 cairo_stroke (cr);
492455
493 os_cairo_draw_rounded_rect (cr, x + 3, y + 3, width - 6, height - 6, radius - 4);456 draw_round_rect (cr, x + 3, y + 3, width - 6, height - 6, radius - 4);
494 cairo_set_source_rgba (cr, 1, 1, 1, 0.2);457 cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
495 cairo_stroke (cr);458 cairo_stroke (cr);
496459
@@ -525,14 +488,14 @@
525 cairo_save (cr);488 cairo_save (cr);
526 cairo_translate (cr, 8.5, 8.5);489 cairo_translate (cr, 8.5, 8.5);
527 cairo_rotate (cr, G_PI); 490 cairo_rotate (cr, G_PI);
528 os_cairo_draw_arrow (cr, 0.5, 0, 4, 3);491 draw_arrow (cr, 0.5, 0, 4, 3);
529 cairo_restore (cr);492 cairo_restore (cr);
530493
531 /* direction DOWN. */494 /* direction DOWN. */
532 cairo_save (cr);495 cairo_save (cr);
533 cairo_translate (cr, 8.5, height - 8.5);496 cairo_translate (cr, 8.5, height - 8.5);
534 cairo_rotate (cr, 0);497 cairo_rotate (cr, 0);
535 os_cairo_draw_arrow (cr, -0.5, 0, 4, 3);498 draw_arrow (cr, -0.5, 0, 4, 3);
536 cairo_restore (cr);499 cairo_restore (cr);
537 }500 }
538 else501 else
@@ -541,14 +504,14 @@
541 cairo_save (cr);504 cairo_save (cr);
542 cairo_translate (cr, 8.5, 8.5);505 cairo_translate (cr, 8.5, 8.5);
543 cairo_rotate (cr, G_PI * 0.5); 506 cairo_rotate (cr, G_PI * 0.5);
544 os_cairo_draw_arrow (cr, -0.5, 0, 4, 3);507 draw_arrow (cr, -0.5, 0, 4, 3);
545 cairo_restore (cr);508 cairo_restore (cr);
546509
547 /* direction RIGHT. */510 /* direction RIGHT. */
548 cairo_save (cr);511 cairo_save (cr);
549 cairo_translate (cr, width - 8.5, 8.5);512 cairo_translate (cr, width - 8.5, 8.5);
550 cairo_rotate (cr, G_PI * 1.5);513 cairo_rotate (cr, G_PI * 1.5);
551 os_cairo_draw_arrow (cr, 0.5, 0, 4, 3);514 draw_arrow (cr, 0.5, 0, 4, 3);
552 cairo_restore (cr);515 cairo_restore (cr);
553 }516 }
554517
@@ -649,7 +612,7 @@
649 {612 {
650 priv->use_tolerance = FALSE;613 priv->use_tolerance = FALSE;
651 priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,614 priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,
652 os_thumb_timeout_fade_out_cb,615 timeout_fade_out_cb,
653 thumb);616 thumb);
654 }617 }
655 }618 }
@@ -700,7 +663,7 @@
700 gtk_window_set_opacity (GTK_WINDOW (widget), 1.0f);663 gtk_window_set_opacity (GTK_WINDOW (widget), 1.0f);
701664
702 priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,665 priv->source_id = g_timeout_add (TIMEOUT_FADE_OUT,
703 os_thumb_timeout_fade_out_cb,666 timeout_fade_out_cb,
704 thumb);667 thumb);
705668
706 return FALSE;669 return FALSE;
@@ -742,6 +705,42 @@
742}705}
743706
744static void707static void
708os_thumb_dispose (GObject *object)
709{
710 OsThumb *thumb;
711 OsThumbPrivate *priv;
712
713 thumb = OS_THUMB (object);
714 priv = thumb->priv;
715
716 if (priv->source_id != 0)
717 {
718 g_source_remove (priv->source_id);
719 priv->source_id = 0;
720 }
721
722 if (priv->animation != NULL)
723 {
724 g_object_unref (priv->animation);
725 priv->animation = NULL;
726 }
727
728 if (priv->grabbed_widget != NULL)
729 {
730 g_object_unref (priv->grabbed_widget);
731 priv->grabbed_widget = NULL;
732 }
733
734 G_OBJECT_CLASS (os_thumb_parent_class)->dispose (object);
735}
736
737static void
738os_thumb_finalize (GObject *object)
739{
740 G_OBJECT_CLASS (os_thumb_parent_class)->finalize (object);
741}
742
743static void
745os_thumb_get_property (GObject *object,744os_thumb_get_property (GObject *object,
746 guint prop_id,745 guint prop_id,
747 GValue *value,746 GValue *value,

Subscribers

People subscribed via source and target branches