Merge lp:~cimi/overlay-scrollbar/visual-connection into lp:overlay-scrollbar

Proposed by Andrea Cimitan
Status: Merged
Merged at revision: 233
Proposed branch: lp:~cimi/overlay-scrollbar/visual-connection
Merge into: lp:overlay-scrollbar
Diff against target: 543 lines (+253/-28)
4 files modified
os/os-pager.c (+174/-5)
os/os-private.h (+6/-0)
os/os-scrollbar.c (+73/-14)
os/os-thumb.c (+0/-9)
To merge this branch: bzr merge lp:~cimi/overlay-scrollbar/visual-connection
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+60852@code.launchpad.net

Description of the change

Add a visual connection between pager and thumb when detached

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'os/os-pager.c'
2--- os/os-pager.c 2011-04-27 00:44:09 +0000
3+++ os/os-pager.c 2011-05-12 23:41:31 +0000
4@@ -39,11 +39,14 @@
5
6 struct _OsPagerPrivate {
7 GdkWindow *pager_window;
8+ GdkWindow *connection_window;
9 GtkWidget *parent;
10 GdkRectangle mask;
11+ GdkRectangle connection_mask; /* in theory not needed, but easier to read. */
12 GdkRectangle allocation;
13 OsAnimation *animation;
14 gboolean active;
15+ gboolean detached;
16 gboolean visible;
17 gfloat weight;
18 gint width;
19@@ -57,6 +60,7 @@
20 static void os_pager_change_state_cb (gfloat weight, gpointer user_data);
21 static void os_pager_create (OsPager *pager);
22 static void os_pager_draw (OsPager *pager);
23+static void os_pager_draw_connection (OsPager *pager);
24 static void os_pager_mask (OsPager *pager);
25 static void os_pager_notify_gtk_theme_name_cb (GObject *object, GParamSpec* pspec, gpointer user_data);
26
27@@ -85,7 +89,21 @@
28
29 /* Instead reparenting,
30 * which doesn't seem to work well,
31- * destroy the window. */
32+ * destroy the two windows. */
33+ if (priv->connection_window != NULL)
34+ {
35+ /* From the Gdk documentation:
36+ * "Note that a window will not be destroyed
37+ * automatically when its reference count
38+ * reaches zero. You must call
39+ * gdk_window_destroy ()
40+ * yourself before that happens". */
41+ gdk_window_destroy (priv->connection_window);
42+
43+ g_object_unref (priv->connection_window);
44+ priv->connection_window = NULL;
45+ }
46+
47 if (priv->pager_window != NULL)
48 {
49 /* From the Gdk documentation:
50@@ -107,14 +125,30 @@
51 attributes.visual = gtk_widget_get_visual (priv->parent);
52 attributes.colormap = gtk_widget_get_colormap (priv->parent);
53
54+ /* connection_window */
55+ priv->connection_window = gdk_window_new (gtk_widget_get_window (priv->parent),
56+ &attributes,
57+ GDK_WA_VISUAL | GDK_WA_COLORMAP);
58+
59+ g_object_ref_sink (priv->connection_window);
60+
61+ gdk_window_set_transient_for (priv->connection_window,
62+ gtk_widget_get_window (priv->parent));
63+
64+ gdk_window_input_shape_combine_region (priv->connection_window,
65+ gdk_region_new (),
66+ 0, 0);
67+
68+ /* pager_window */
69 priv->pager_window = gdk_window_new (gtk_widget_get_window (priv->parent),
70 &attributes,
71 GDK_WA_VISUAL | GDK_WA_COLORMAP);
72
73 g_object_ref_sink (priv->pager_window);
74
75+ /* stay above the connection_window */
76 gdk_window_set_transient_for (priv->pager_window,
77- gtk_widget_get_window (priv->parent));
78+ priv->connection_window);
79
80 gdk_window_input_shape_combine_region (priv->pager_window,
81 gdk_region_new (),
82@@ -137,10 +171,11 @@
83 if (priv->parent == NULL)
84 return;
85
86+ os_pager_draw_connection (pager);
87 os_pager_draw (pager);
88 }
89
90-/* Draw on the pager. */
91+/* Draw on the pager_window. */
92 static void
93 os_pager_draw (OsPager *pager)
94 {
95@@ -179,7 +214,30 @@
96 gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
97 }
98
99-/* Mask the pager. */
100+/* Draw on the connection_window. */
101+static void
102+os_pager_draw_connection (OsPager *pager)
103+{
104+ GdkColor color;
105+ OsPagerPrivate *priv;
106+
107+ priv = pager->priv;
108+
109+ /* 0.6 is taken from os_thumb_expose. */
110+ color.red = 65535 * 0.6;
111+ color.green = 65535 * 0.6;
112+ color.blue = 65535 * 0.6;
113+
114+ gdk_colormap_alloc_color (gdk_drawable_get_colormap (priv->connection_window), &color, FALSE, TRUE);
115+
116+ gdk_window_set_background (priv->connection_window, &color);
117+
118+ gdk_window_clear (priv->connection_window);
119+
120+ gdk_window_invalidate_rect (gtk_widget_get_window (priv->parent), &priv->allocation, TRUE);
121+}
122+
123+/* Mask the pager_window. */
124 static void
125 os_pager_mask (OsPager *pager)
126 {
127@@ -194,6 +252,21 @@
128 gdk_window_clear (priv->pager_window);
129 }
130
131+/* Mask the connection_window. */
132+static void
133+os_pager_mask_connection (OsPager *pager)
134+{
135+ OsPagerPrivate *priv;
136+
137+ priv = pager->priv;
138+
139+ gdk_window_shape_combine_region (priv->connection_window,
140+ gdk_region_rectangle (&priv->connection_mask),
141+ 0, 0);
142+
143+ gdk_window_clear (priv->connection_window);
144+}
145+
146 static void
147 os_pager_notify_gtk_theme_name_cb (GObject* gobject,
148 GParamSpec* pspec,
149@@ -205,9 +278,12 @@
150 pager = OS_PAGER (user_data);
151 priv = pager->priv;
152
153- if (priv->parent == NULL || priv->pager_window == NULL)
154+ if (priv->parent == NULL ||
155+ priv->pager_window == NULL ||
156+ priv->connection_window == NULL)
157 return;
158
159+ os_pager_draw_connection (pager);
160 os_pager_draw (pager);
161 }
162
163@@ -249,9 +325,11 @@
164 mask.width = 1;
165 mask.height = 1;
166
167+ priv->connection_mask = mask;
168 priv->mask = mask;
169
170 priv->active = FALSE;
171+ priv->detached = FALSE;
172 priv->visible = FALSE;
173
174 priv->weight = 1.0f;
175@@ -278,6 +356,20 @@
176 priv->animation = NULL;
177 }
178
179+ if (priv->connection_window != NULL)
180+ {
181+ /* From the Gdk documentation:
182+ * "Note that a window will not be destroyed
183+ * automatically when its reference count
184+ * reaches zero. You must call
185+ * gdk_window_destroy ()
186+ * yourself before that happens". */
187+ gdk_window_destroy (priv->connection_window);
188+
189+ g_object_unref (priv->connection_window);
190+ priv->connection_window = NULL;
191+ }
192+
193 if (priv->pager_window != NULL)
194 {
195 /* From the Gdk documentation:
196@@ -322,6 +414,34 @@
197 }
198
199 /**
200+ * os_pager_connect:
201+ * @pager: a #OsPager
202+ * @mask: a #GdkRectangle with the position and dimension of the connection
203+ *
204+ * Moves and resizes connection.
205+ **/
206+void
207+os_pager_connect (OsPager *pager,
208+ GdkRectangle mask)
209+{
210+ OsPagerPrivate *priv;
211+
212+ g_return_if_fail (OS_PAGER (pager));
213+
214+ priv = pager->priv;
215+
216+ if (!rectangle_changed (priv->connection_mask, mask))
217+ return;
218+
219+ priv->connection_mask = mask;
220+
221+ if (priv->parent == NULL)
222+ return;
223+
224+ os_pager_mask_connection (pager);
225+}
226+
227+/**
228 * os_pager_hide:
229 * @pager: a #OsPager
230 *
231@@ -344,6 +464,7 @@
232 /* if there's an animation currently running, stop it. */
233 os_animation_stop (priv->animation);
234
235+ gdk_window_hide (priv->connection_window);
236 gdk_window_hide (priv->pager_window);
237 }
238
239@@ -419,6 +540,41 @@
240 }
241
242 /**
243+ * os_pager_set_detached:
244+ * @pager: a #OsPager
245+ * @detached: whether the pager is detached or not
246+ *
247+ * Changes the detached state of @pager.
248+ **/
249+void
250+os_pager_set_detached (OsPager *pager,
251+ gboolean detached)
252+{
253+ OsPagerPrivate *priv;
254+
255+ g_return_if_fail (OS_PAGER (pager));
256+
257+ priv = pager->priv;
258+
259+ if (priv->detached != detached)
260+ {
261+ priv->detached = detached;
262+
263+ if (priv->parent == NULL)
264+ return;
265+
266+ if (priv->detached)
267+ {
268+ gdk_window_show (priv->connection_window);
269+
270+ gdk_window_clear (priv->connection_window);
271+ }
272+ else
273+ gdk_window_hide (priv->connection_window);
274+ }
275+}
276+
277+/**
278 * os_pager_set_parent:
279 * @pager: a #OsPager
280 * @parent: a #GtkWidget
281@@ -453,9 +609,16 @@
282 priv->weight = 1.0f;
283
284 os_pager_create (pager);
285+ os_pager_draw_connection (pager);
286 os_pager_draw (pager);
287 os_pager_mask (pager);
288
289+ gdk_window_move_resize (priv->connection_window,
290+ priv->allocation.x,
291+ priv->allocation.y,
292+ priv->allocation.width,
293+ priv->allocation.height);
294+
295 gdk_window_move_resize (priv->pager_window,
296 priv->allocation.x,
297 priv->allocation.y,
298@@ -521,6 +684,12 @@
299 if (priv->parent == NULL)
300 return;
301
302+ gdk_window_move_resize (priv->connection_window,
303+ rectangle.x,
304+ rectangle.y,
305+ rectangle.width,
306+ rectangle.height);
307+
308 gdk_window_move_resize (priv->pager_window,
309 rectangle.x,
310 rectangle.y,
311
312=== modified file 'os/os-private.h'
313--- os/os-private.h 2011-05-06 15:46:50 +0000
314+++ os/os-private.h 2011-05-12 23:41:31 +0000
315@@ -208,12 +208,18 @@
316
317 void os_pager_hide (OsPager *overlay);
318
319+void os_pager_connect (OsPager *overlay,
320+ GdkRectangle mask);
321+
322 void os_pager_move_resize (OsPager *overlay,
323 GdkRectangle mask);
324
325 void os_pager_set_active (OsPager *overlay,
326 gboolean active);
327
328+void os_pager_set_detached (OsPager *overlay,
329+ gboolean detached);
330+
331 void os_pager_set_parent (OsPager *pager,
332 GtkWidget *parent);
333
334
335=== modified file 'os/os-scrollbar.c'
336--- os/os-scrollbar.c 2011-05-08 14:06:01 +0000
337+++ os/os-scrollbar.c 2011-05-12 23:41:31 +0000
338@@ -494,10 +494,8 @@
339 gpointer user_data)
340 {
341 OsScrollbar *scrollbar;
342- OsScrollbarPrivate *priv;
343
344 scrollbar = OS_SCROLLBAR (object);
345- priv = scrollbar->priv;
346
347 os_scrollbar_swap_adjustment (scrollbar, gtk_range_get_adjustment (GTK_RANGE (object)));
348 }
349@@ -854,14 +852,12 @@
350 {
351 Display *display;
352 OsScrollbar *scrollbar;
353- OsScrollbarPrivate *priv;
354 XWindowChanges changes;
355 guint32 xid, xid_parent;
356 unsigned int value_mask = CWSibling | CWStackMode;
357 int res;
358
359 scrollbar = OS_SCROLLBAR (user_data);
360- priv = scrollbar->priv;
361
362 xid = GDK_WINDOW_XID (gtk_widget_get_window (widget));
363 xid_parent = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (scrollbar)));
364@@ -1027,6 +1023,8 @@
365 scrollbar = OS_SCROLLBAR (user_data);
366 priv = scrollbar->priv;
367
368+ priv->value_changed_event = TRUE;
369+
370 delta = os_scrollbar_get_wheel_delta (scrollbar, event->direction);
371
372 gtk_adjustment_set_value (priv->adjustment,
373@@ -1051,6 +1049,8 @@
374 priv->button_press_event = FALSE;
375 priv->motion_notify_event = FALSE;
376 priv->enter_notify_event = FALSE;
377+
378+ os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
379 }
380
381 /* Move the pager to the right position. */
382@@ -1169,7 +1169,10 @@
383 {
384 /* if we're dragging the thumb, it can't be detached. */
385 if (priv->motion_notify_event)
386- os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
387+ {
388+ os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
389+ os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
390+ }
391 else
392 {
393 gint x_pos, y_pos;
394@@ -1177,19 +1180,73 @@
395
396 if (priv->orientation == GTK_ORIENTATION_VERTICAL)
397 {
398- if ((priv->win_y + priv->overlay.y > y_pos + priv->slider.height) ||
399- (priv->win_y + priv->overlay.y + priv->overlay.height < y_pos))
400- os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
401- else
402- os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
403+ if (priv->win_y + priv->overlay.y > y_pos + priv->slider.height)
404+ {
405+ GdkRectangle mask;
406+
407+ mask.x = 0;
408+ mask.y = y_pos + priv->slider.height / 2 - priv->win_y;
409+ mask.width = DEFAULT_PAGER_WIDTH;
410+ mask.height = priv->overlay.y - mask.y;
411+
412+ os_pager_connect (OS_PAGER (priv->pager), mask);
413+ os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
414+
415+ os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
416+ }
417+ else if (priv->win_y + priv->overlay.y + priv->overlay.height < y_pos)
418+ {
419+ GdkRectangle mask;
420+
421+ mask.x = 0;
422+ mask.y = priv->overlay.y + priv->overlay.height;
423+ mask.width = DEFAULT_PAGER_WIDTH;
424+ mask.height = y_pos + priv->slider.height / 2 - priv->win_y - mask.y;
425+
426+ os_pager_connect (OS_PAGER (priv->pager), mask);
427+ os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
428+
429+ os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
430+ }
431+ else
432+ {
433+ os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
434+ os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
435+ }
436 }
437 else
438 {
439- if ((priv->win_x + priv->overlay.x > x_pos + priv->slider.width) ||
440- (priv->win_x + priv->overlay.x + priv->overlay.width < x_pos))
441- os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
442+ if (priv->win_x + priv->overlay.x > x_pos + priv->slider.width)
443+ {
444+ GdkRectangle mask;
445+
446+ mask.x = x_pos + priv->slider.width / 2 - priv->win_x;
447+ mask.y = 0;
448+ mask.width = priv->overlay.x - mask.x;
449+ mask.height = DEFAULT_PAGER_WIDTH;
450+
451+ os_pager_connect (OS_PAGER (priv->pager), mask);
452+ os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
453+
454+ os_thumb_set_detached (OS_THUMB (priv->thumb), TRUE);
455+ }
456+ else if (priv->win_x + priv->overlay.x + priv->overlay.width < x_pos)
457+ {
458+ GdkRectangle mask;
459+
460+ mask.x = priv->overlay.y + priv->overlay.height;
461+ mask.y = 0;
462+ mask.width = x_pos + priv->slider.width / 2 - priv->win_x - mask.x;
463+ mask.height = DEFAULT_PAGER_WIDTH;
464+
465+ os_pager_connect (OS_PAGER (priv->pager), mask);
466+ os_pager_set_detached (OS_PAGER (priv->pager), TRUE);
467+ }
468 else
469- os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
470+ {
471+ os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
472+ os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
473+ }
474 }
475 }
476 }
477@@ -1431,6 +1488,7 @@
478 os_scrollbar_move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
479 }
480
481+ os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
482 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
483 gtk_widget_show (GTK_WIDGET (priv->thumb));
484 }
485@@ -1471,6 +1529,7 @@
486 os_scrollbar_move_thumb (scrollbar, priv->win_x + priv->slider.x, priv->win_y);
487 }
488
489+ os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
490 os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
491 gtk_widget_show (GTK_WIDGET (priv->thumb));
492 }
493
494=== modified file 'os/os-thumb.c'
495--- os/os-thumb.c 2011-05-08 14:06:01 +0000
496+++ os/os-thumb.c 2011-05-12 23:41:31 +0000
497@@ -138,12 +138,9 @@
498 gpointer user_data)
499 {
500 OsThumb *thumb;
501- OsThumbPrivate *priv;
502
503 thumb = OS_THUMB (user_data);
504
505- priv = thumb->priv;
506-
507 if (weight < 1.0f)
508 gtk_window_set_opacity (GTK_WINDOW (thumb), fabs (weight - 1.0f));
509 else
510@@ -379,7 +376,6 @@
511 GdkEventExpose *event)
512 {
513 GtkAllocation allocation;
514- GtkStateType state_type_down, state_type_up;
515 GtkStyle *style;
516 OsThumb *thumb;
517 OsThumbPrivate *priv;
518@@ -393,9 +389,6 @@
519 thumb = OS_THUMB (widget);
520 priv = thumb->priv;
521
522- state_type_down = GTK_STATE_NORMAL;
523- state_type_up = GTK_STATE_NORMAL;
524-
525 gtk_widget_get_allocation (widget, &allocation);
526
527 x = 0;
528@@ -445,7 +438,6 @@
529 if ((priv->orientation == GTK_ORIENTATION_VERTICAL && (priv->pointer_y < height / 2)) ||
530 (priv->orientation == GTK_ORIENTATION_HORIZONTAL && (priv->pointer_x < width / 2)))
531 {
532- state_type_up = GTK_STATE_ACTIVE;
533 cairo_pattern_add_color_stop_rgba (pat, 0.0, 0.8, 0.8, 0.8, 0.8);
534 cairo_pattern_add_color_stop_rgba (pat, 0.49, 1.0, 1.0, 1.0, 0.0);
535 cairo_pattern_add_color_stop_rgba (pat, 0.49, 0.8, 0.8, 0.8, 0.5);
536@@ -453,7 +445,6 @@
537 }
538 else
539 {
540- state_type_down = GTK_STATE_ACTIVE;
541 cairo_pattern_add_color_stop_rgba (pat, 0.0, 1.0, 1.0, 1.0, 0.8);
542 cairo_pattern_add_color_stop_rgba (pat, 0.49, 1.0, 1.0, 1.0, 0.0);
543 cairo_pattern_add_color_stop_rgba (pat, 0.49, 0.8, 0.8, 0.8, 0.5);

Subscribers

People subscribed via source and target branches