Merge lp:~vanvugt/unity/fix-687567-unity4 into lp:unity

Proposed by Daniel van Vugt
Status: Merged
Merged at revision: 1279
Proposed branch: lp:~vanvugt/unity/fix-687567-unity4
Merge into: lp:unity
Diff against target: 194 lines (+55/-104)
1 file modified
services/panel-service.c (+55/-104)
To merge this branch: bzr merge lp:~vanvugt/unity/fix-687567-unity4
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Review via email: mp+67922@code.launchpad.net

Description of the change

Fix white "flashes" seen in the panel menus during scrubbing or when they're unmapped (LP: #687567)

The problem it seems, was that we were calling gdk/gtk/X11 functions in the middle of a GDK event filter. Removing these function calls and replacing them with a simpler more optimized solution solves the problem.

This is the unity-4 version of the fix. A similar fix for natty has already been proposed for unity-3:
https://code.launchpad.net/~vanvugt/unity/fix-687567-unity3.0/+merge/67816

To post a comment you must log in.
Revision history for this message
Neil J. Patel (njpatel) wrote :

Works perfectly, approved!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'services/panel-service.c'
2--- services/panel-service.c 2011-06-30 16:23:04 +0000
3+++ services/panel-service.c 2011-07-14 07:24:35 +0000
4@@ -57,6 +57,10 @@
5 guint32 last_menu_move_id;
6 gint32 last_x;
7 gint32 last_y;
8+ gint last_left;
9+ gint last_top;
10+ gint last_right;
11+ gint last_bottom;
12 guint32 last_menu_button;
13
14 gint last_menu_x;
15@@ -213,114 +217,39 @@
16 static GdkFilterReturn
17 event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self)
18 {
19+ PanelServicePrivate *priv = self->priv;
20 XEvent *e = (XEvent *)ev;
21 GdkFilterReturn ret = GDK_FILTER_CONTINUE;
22
23 if (!PANEL_IS_SERVICE (self))
24- {
25- g_warning ("%s: Invalid PanelService instance", G_STRLOC);
26- return ret;
27- }
28-
29- if (!GTK_IS_WIDGET (self->priv->last_menu))
30- return ret;
31-
32- /* Use XI2 to read the event data */
33- XGenericEventCookie *cookie = &e->xcookie;
34- if (cookie->type == GenericEvent)
35- {
36- XIDeviceEvent *event = cookie->data;
37-
38- if (event->evtype == XI_ButtonRelease &&
39- self->priv->last_menu_button != 0) //FocusChange
40- {
41- gint x=0, y=0, width=0, height=0, x_root=0, y_root=0;
42- GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (self->priv->last_menu));
43- if (window == NULL)
44- {
45- g_warning ("%s: gtk_widget_get_window (self->priv->last_menu) == NULL", G_STRLOC);
46- return GDK_FILTER_CONTINUE;
47- }
48-
49- Window xwindow = gdk_x11_window_get_xid (window);
50-
51- if (xwindow == 0)
52- {
53- g_warning ("%s: gdk_x11_window_get_xid (last_menu->window) == 0", G_STRLOC);
54- return GDK_FILTER_CONTINUE;
55- }
56-
57- Window root = 0, child = 0;
58- int win_x=0, win_y = 0;
59- guint32 mask_return = 0;
60-
61- XQueryPointer (gdk_x11_display_get_xdisplay (gdk_display_get_default ()),
62- xwindow,
63- &root,
64- &child,
65- &x_root,
66- &y_root,
67- &win_x,
68- &win_y,
69- &mask_return);
70-
71- gdk_window_get_geometry (window, &x, &y, &width, &height);
72- gdk_window_get_origin (window, &x, &y);
73-
74- if (x_root > x
75- && x_root < x + width
76- && y_root > y
77- && y_root < y + height)
78- {
79- ret = GDK_FILTER_CONTINUE;
80- }
81- else
82- {
83- ret = GDK_FILTER_REMOVE;
84- }
85-
86- self->priv->last_menu_button = 0;
87- }
88-
89- // FIXME: THIS IS HORRIBLE AND WILL BE CHANGED BEFORE RELEASE
90- // ITS A WORKAROUND SO I CAN TEST THE PANEL SCRUBBING
91- // DONT HATE ME
92- // --------------------------------------------------------------------------
93- //FIXME-GTK3 - i'm not porting this, fix your code :P
94-
95- else if (event->evtype == XI_Motion)
96- {
97- int x_root=0, y_root=0;
98- GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (self->priv->last_menu));
99- Window xwindow = gdk_x11_window_get_xid (window);
100- Window root = 0, child = 0;
101- int win_x=0, win_y = 0;
102- guint32 mask_return = 0;
103-
104- XQueryPointer (gdk_x11_display_get_xdisplay (gdk_display_get_default ()),
105- xwindow,
106- &root,
107- &child,
108- &x_root,
109- &y_root,
110- &win_x,
111- &win_y,
112- &mask_return);
113-
114- self->priv->last_menu_x = x_root;
115- self->priv->last_menu_y = y_root;
116-
117- if (y_root <= self->priv->last_y)
118- {
119- g_signal_emit (self, _service_signals[ACTIVE_MENU_POINTER_MOTION], 0);
120- }
121- }
122- // -> I HATE YOU
123- // /DONT HATE ME
124- // /FIXME
125- // --------------------------------------------------------------------------
126- }
127-
128+ {
129+ g_warning ("%s: Invalid PanelService instance", G_STRLOC);
130+ return ret;
131+ }
132+
133+ if (!GTK_IS_WIDGET (priv->last_menu))
134+ return ret;
135+
136+ // Don't call any gdk/gtk/X functions in here or you risk creating graphical
137+ // glitches (LP: #687567) and of course slowing down event processing.
138+ if (e->type == ButtonRelease && priv->last_menu_button != 0)
139+ {
140+ if (e->xbutton.x_root < priv->last_left ||
141+ e->xbutton.x_root > priv->last_right ||
142+ e->xbutton.y_root < priv->last_top ||
143+ e->xbutton.y_root > priv->last_bottom)
144+ {
145+ ret = GDK_FILTER_REMOVE;
146+ }
147+ priv->last_menu_button = 0;
148+ }
149+ else if (e->type == MotionNotify)
150+ {
151+ priv->last_menu_x = e->xmotion.x_root;
152+ priv->last_menu_y = e->xmotion.y_root;
153+ if (priv->last_menu_y <= priv->last_y)
154+ g_signal_emit (self, _service_signals[ACTIVE_MENU_POINTER_MOTION], 0);
155+ }
156 return ret;
157 }
158
159@@ -885,6 +814,10 @@
160 priv->last_menu_id = 0;
161 priv->last_menu_move_id = 0;
162 priv->last_entry = NULL;
163+ priv->last_left = 0;
164+ priv->last_right = 0;
165+ priv->last_top = 0;
166+ priv->last_bottom = 0;
167
168 g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, "");
169 }
170@@ -1182,6 +1115,24 @@
171
172 indicator_object_entry_activate (object, entry, CurrentTime);
173 gtk_menu_popup (priv->last_menu, NULL, NULL, positon_menu, self, 0, CurrentTime);
174+ GdkWindow *gdkwin = gtk_widget_get_window (GTK_WIDGET (priv->last_menu));
175+ if (gdkwin != NULL)
176+ {
177+ gint left=0, top=0, width=0, height=0;
178+ gdk_window_get_geometry (gdkwin, NULL, NULL, &width, &height);
179+ gdk_window_get_origin (gdkwin, &left, &top);
180+ priv->last_left = left;
181+ priv->last_right = left + width -1;
182+ priv->last_top = top;
183+ priv->last_bottom = top + height -1;
184+ }
185+ else
186+ {
187+ priv->last_left = 0;
188+ priv->last_right = 0;
189+ priv->last_top = 0;
190+ priv->last_bottom = 0;
191+ }
192
193 g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, entry_id);
194 }