Merge lp:~3v1n0/unity/send-events-to-active-indicators into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 1779
Proposed branch: lp:~3v1n0/unity/send-events-to-active-indicators
Merge into: lp:unity
Diff against target: 132 lines (+87/-27)
2 files modified
manual-tests/Indicators.txt (+14/-0)
services/panel-service.c (+73/-27)
To merge this branch: bzr merge lp:~3v1n0/unity/send-events-to-active-indicators
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Review via email: mp+82351@code.launchpad.net

Description of the change

In the current unity implementation when an indicator is opened, there's no way to send it scroll or middle-click events.

This commit fixes this, applying an exception to the case of the appmenu entries, that should handle the middle-click like any other click.

Testing this with autopilot plus a fake indicator which reports events should be doable in the near future.

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

How can we add a test for this in the panel service? Perhaps Neil could provide help here.

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

I've looked a little to the tests that already we have for the panel service, the main issue here is that to check this we'd need (at the current state) a manual test.

Otherwise I guess that we'd need do add a fake indicator, emitting an event to open it, and finally simulate a mouse event over it...

Revision history for this message
Tim Penhey (thumper) wrote :

Lets not block this. Add a manual test.

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

Manual test added.

Revision history for this message
Tim Penhey (thumper) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'manual-tests/Indicators.txt'
2--- manual-tests/Indicators.txt 1970-01-01 00:00:00 +0000
3+++ manual-tests/Indicators.txt 2011-12-08 05:11:24 +0000
4@@ -0,0 +1,14 @@
5+Middle-clicking or Scrolling over active Indicators
6+---------------------------------------------------
7+This test shows how the indicators icons should react to events when active.
8+
9+#. Start on a clean screen
10+#. Open an indicator Menu (i.e. indicator-sound, not a global menu item)
11+#. Move the mouse pointer over the indicator-sound and middle-click or scroll
12+ over it.
13+
14+Outcome
15+ The indicator-sound should mute/unmute on middle-clicks, and change the system
16+ volume on scroll.
17+ Middle-clicking over global-menu items should work as before (causing the open
18+ indicator menu to close).
19
20=== modified file 'services/panel-service.c'
21--- services/panel-service.c 2011-12-05 13:54:28 +0000
22+++ services/panel-service.c 2011-12-08 05:11:24 +0000
23@@ -260,36 +260,82 @@
24 {
25 priv->pressed_entry = get_entry_at (self, event->root_x, event->root_y);
26 priv->use_event = (priv->pressed_entry == NULL);
27+
28+ if (priv->pressed_entry)
29+ ret = GDK_FILTER_REMOVE;
30 }
31
32 if (event->evtype == XI_ButtonRelease)
33- {
34- if (priv->use_event)
35- {
36- priv->use_event = FALSE;
37- }
38- else
39- {
40- IndicatorObjectEntry *entry;
41- entry = get_entry_at (self, event->root_x, event->root_y);
42-
43- if (entry)
44- {
45- if (entry != priv->pressed_entry)
46- {
47- ret = GDK_FILTER_REMOVE;
48- priv->use_event = TRUE;
49- }
50- else if (priv->last_entry && entry != priv->last_entry)
51- {
52- /* If we were navigating over indicators using the keyboard
53- * and now we click over the indicator under the mouse, we
54- * must force it to show back again, not make it close */
55- gchar *entry_id = g_strdup_printf ("%p", entry);
56- g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id);
57- g_free (entry_id);
58- }
59- }
60+ {
61+ IndicatorObjectEntry *entry;
62+ gboolean event_is_a_click = FALSE;
63+ entry = get_entry_at (self, event->root_x, event->root_y);
64+
65+ if (XIMaskIsSet (event->buttons.mask, 1) || XIMaskIsSet (event->buttons.mask, 3))
66+ {
67+ /* Consider only right and left clicks over the indicators entries */
68+ event_is_a_click = TRUE;
69+ }
70+ else if (XIMaskIsSet (event->buttons.mask, 2) && entry)
71+ {
72+ /* Middle clicks over an appmenu entry are considered just like
73+ * all other clicks */
74+ IndicatorObject *obj = g_hash_table_lookup (priv->entry2indicator_hash, entry);
75+
76+ if (g_strcmp0 (g_object_get_data (G_OBJECT (obj), "id"), "libappmenu.so") == 0)
77+ {
78+ event_is_a_click = TRUE;
79+ }
80+ }
81+
82+ if (event_is_a_click)
83+ {
84+ if (priv->use_event)
85+ {
86+ priv->use_event = FALSE;
87+ }
88+ else
89+ {
90+ if (entry)
91+ {
92+ if (entry != priv->pressed_entry)
93+ {
94+ ret = GDK_FILTER_REMOVE;
95+ priv->use_event = TRUE;
96+ }
97+ else if (priv->last_entry && entry != priv->last_entry)
98+ {
99+ /* If we were navigating over indicators using the keyboard
100+ * and now we click over the indicator under the mouse, we
101+ * must force it to show back again, not make it close */
102+ gchar *entry_id = g_strdup_printf ("%p", entry);
103+ g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id);
104+ g_free (entry_id);
105+ }
106+ }
107+ }
108+ }
109+ else if ((XIMaskIsSet (event->buttons.mask, 2) ||
110+ XIMaskIsSet (event->buttons.mask, 4) ||
111+ XIMaskIsSet (event->buttons.mask, 5)) && entry)
112+ {
113+ /* If we're scrolling or middle-clicking over an indicator
114+ * (which is not an appmenu entry) then we need to send the
115+ * event to the indicator itself, and avoid it to close */
116+ gchar *entry_id = g_strdup_printf ("%p", entry);
117+
118+ if (XIMaskIsSet (event->buttons.mask, 4) || XIMaskIsSet (event->buttons.mask, 5))
119+ {
120+ gint32 delta = XIMaskIsSet (event->buttons.mask, 4) ? 120 : -120;
121+ panel_service_scroll_entry (self, entry_id, delta);
122+ }
123+ else if (entry == priv->pressed_entry)
124+ {
125+ panel_service_secondary_activate_entry (self, entry_id, time(NULL));
126+ }
127+
128+ ret = GDK_FILTER_REMOVE;
129+ g_free (entry_id);
130 }
131 }
132 }