Merge lp:~unity-team/unity/unity.fix_847967 into lp:unity

Proposed by Sam Spilsbury
Status: Merged
Merged at revision: 1537
Proposed branch: lp:~unity-team/unity/unity.fix_847967
Merge into: lp:unity
Diff against target: 343 lines (+136/-46)
3 files modified
plugins/unityshell/src/inputremover.cpp (+69/-23)
plugins/unityshell/src/inputremover.h (+3/-0)
tests/test-input-remover/test-input-remover.cpp (+64/-23)
To merge this branch: bzr merge lp:~unity-team/unity/unity.fix_847967
Reviewer Review Type Date Requested Status
Robert Carr (community) Approve
Review via email: mp+75171@code.launchpad.net

Description of the change

Fixes LP#847967 and LP#848962

This requires an X Server patch at: http://lists.x.org/archives/xorg-devel/2011-September/024996.html

To post a comment you must log in.
Revision history for this message
Robert Carr (robertcarr) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/inputremover.cpp'
2--- plugins/unityshell/src/inputremover.cpp 2011-09-09 13:21:10 +0000
3+++ plugins/unityshell/src/inputremover.cpp 2011-09-13 14:00:42 +0000
4@@ -22,6 +22,7 @@
5 #include "inputremover.h"
6 #include <X11/Xregion.h>
7 #include <cstdio>
8+#include <cstring>
9
10 compiz::WindowInputRemover::WindowInputRemover (Display *dpy,
11 Window xid) :
12@@ -36,6 +37,8 @@
13 mBoundingRectOrdering (0),
14 mRemoved (false)
15 {
16+ /* FIXME: roundtrip */
17+ XShapeQueryExtension (mDpy, &mShapeEvent, &mShapeError);
18 }
19
20 compiz::WindowInputRemover::~WindowInputRemover ()
21@@ -47,11 +50,23 @@
22 void
23 compiz::WindowInputRemover::sendShapeNotify ()
24 {
25- /* Send a synthetic ShapeNotify event to the root window
26+ /* Send a synthetic ShapeNotify event to the client and parent window
27 * since we ignored shape events when setting visibility
28 * in order to avoid cycling in the shape handling code -
29 * ignore the sent shape notify event since that will
30- * be send_event = true */
31+ * be send_event = true
32+ *
33+ * NB: We must send ShapeNotify events to both the client
34+ * window and to the root window with SubstructureRedirectMask
35+ * since NoEventMask will only deliver the event to the client
36+ * (see xserver/dix/events.c on the handling of CantBeFiltered
37+ * messages)
38+ *
39+ * NB: This code will break if you don't have this patch on the
40+ * X Server since XSendEvent for non-core events are broken.
41+ *
42+ * http://lists.x.org/archives/xorg-devel/2011-September/024996.html
43+ */
44
45 XShapeEvent xsev;
46 XEvent *xev = (XEvent *) &xsev;
47@@ -60,13 +75,17 @@
48 Window *children;
49 int x, y, xOffset, yOffset;
50 unsigned int width, height, depth, border, nchildren;
51- int shapeEvent, shapeError, shapeMask;
52-
53- /* FIXME: roundtrip */
54- XShapeQueryExtension (mDpy, &shapeEvent, &shapeError);
55- shapeMask = XShapeInputSelected (mDpy, mShapeWindow);
56-
57- xev->type = shapeEvent + ShapeNotify;
58+
59+ memset (&xsev, 0, sizeof (XShapeEvent));
60+
61+ /* XXX: libXShape is weird and range checks the event
62+ * type on event_to_wire so ensure that we are setting
63+ * the event type on the right range */
64+ xsev.type = (mShapeEvent - ShapeNotify) & 0x7f;
65+ /* We must explicitly fill in these values to avoid padding errors */
66+ xsev.serial = 0L;
67+ xsev.send_event = TRUE;
68+ xsev.display = mDpy;
69 xsev.window = mShapeWindow;
70
71 if (!mRemoved)
72@@ -81,9 +100,10 @@
73 * rect of the window shape according to the Shape extension
74 * specification */
75
76- XTranslateCoordinates (mDpy, mShapeWindow, parentReturn, 0, 0, &xOffset, &yOffset, &childReturn);
77+ XTranslateCoordinates (mDpy, mShapeWindow, parentReturn, 0, 0,
78+ &xOffset, &yOffset, &childReturn);
79
80- xev->type = ShapeBounding;
81+ xsev.kind = ShapeBounding;
82
83 /* Calculate extents of the bounding shape */
84 if (!mNBoundingRects)
85@@ -112,9 +132,10 @@
86 }
87
88 xsev.time = CurrentTime;
89- XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
90
91- xev->type = ShapeInput;
92+ XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
93+ XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
94+ xsev.kind = ShapeInput;
95
96 /* Calculate extents of the bounding shape */
97 if (!mNInputRects)
98@@ -143,14 +164,18 @@
99 }
100
101 xsev.time = CurrentTime;
102- XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
103+
104+ XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
105+ XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
106
107 if (children)
108 XFree (children);
109 }
110 else
111 {
112- xev->type = ShapeBounding;
113+ XQueryTree (mDpy, mShapeWindow, &rootReturn, &parentReturn, &children, &nchildren);
114+
115+ xsev.kind = ShapeBounding;
116
117 xsev.x = 0;
118 xsev.y = 0;
119@@ -159,15 +184,20 @@
120 xsev.shaped = true;
121
122 xsev.time = CurrentTime;
123- XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
124+ XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
125+ XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
126
127- xev->type = ShapeInput;
128+ xsev.kind = ShapeInput;
129
130 /* Both ShapeBounding and ShapeInput are null */
131
132 xsev.time = CurrentTime;
133- XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
134+
135+ XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
136+ XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
137+
138 }
139+
140 }
141
142 bool
143@@ -211,6 +241,17 @@
144 rects = XShapeGetRectangles (mDpy, mShapeWindow, ShapeBounding,
145 &count, &ordering);
146
147+ /* check if the returned shape exactly matches the window shape -
148+ * if that is true, the window currently has no set bounding shape */
149+ if ((count == 1) &&
150+ (rects[0].x == -((int) border)) &&
151+ (rects[0].y == -((int) border)) &&
152+ (rects[0].width == (width + border)) &&
153+ (rects[0].height == (height + border)))
154+ {
155+ count = 0;
156+ }
157+
158 if (mBoundingRects)
159 XFree (mBoundingRects);
160
161@@ -236,17 +277,21 @@
162 XShapeCombineRectangles (mDpy, mShapeWindow, ShapeBounding, 0, 0,
163 NULL, 0, ShapeSet, 0);
164
165- XShapeSelectInput (mDpy, mShapeWindow, ShapeNotify);
166-
167- sendShapeNotify ();
168+ XShapeSelectInput (mDpy, mShapeWindow, mShapeMask);
169
170 mRemoved = true;
171+
172+ sendShapeNotify ();
173+
174 return true;
175 }
176
177 bool
178 compiz::WindowInputRemover::restore ()
179 {
180+
181+ XShapeSelectInput (mDpy, mShapeWindow, NoEventMask);
182+
183 if (mRemoved)
184 {
185 if (mNInputRects)
186@@ -283,9 +328,10 @@
187
188 XShapeSelectInput (mDpy, mShapeWindow, mShapeMask);
189
190- sendShapeNotify ();
191-
192 mRemoved = false;
193+
194+ sendShapeNotify ();
195+
196 mNInputRects = 0;
197 mInputRects = NULL;
198 mNBoundingRects = 0;
199
200=== modified file 'plugins/unityshell/src/inputremover.h'
201--- plugins/unityshell/src/inputremover.h 2011-09-09 13:21:10 +0000
202+++ plugins/unityshell/src/inputremover.h 2011-09-13 14:00:42 +0000
203@@ -57,6 +57,9 @@
204 int mBoundingRectOrdering;
205 bool mRemoved;
206
207+ int mShapeEvent;
208+ int mShapeError;
209+
210 };
211 }
212
213
214=== modified file 'tests/test-input-remover/test-input-remover.cpp'
215--- tests/test-input-remover/test-input-remover.cpp 2011-08-24 13:46:21 +0000
216+++ tests/test-input-remover/test-input-remover.cpp 2011-09-13 14:00:42 +0000
217@@ -77,9 +77,10 @@
218 Window xid;
219 int time = 0;
220 compiz::WindowInputRemover *remover;
221- bool shapeExt;
222- int shapeEvent;
223- int shapeError;
224+ bool shapeExt;
225+ int shapeEvent;
226+ int shapeError;
227+ XEvent event;
228
229 if ((argc == 2 && std::string (argv[1]) == "--help") || argc > 3)
230 {
231@@ -109,34 +110,38 @@
232 else
233 {
234 XSetWindowAttributes attrib;
235- XEvent e;
236+
237+ attrib.backing_pixel = 0x0;
238
239 xid = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, 100, 100, 0,
240 DefaultDepth (dpy, DefaultScreen (dpy)), InputOutput,
241- DefaultVisual (dpy, DefaultScreen (dpy)), 0, &attrib);
242+ DefaultVisual (dpy, DefaultScreen (dpy)), CWBackingPixel, &attrib);
243
244 XSelectInput (dpy, xid, ExposureMask | StructureNotifyMask);
245 XMapRaised (dpy, xid);
246- while (1)
247+ do
248 {
249- XNextEvent (dpy, &e);
250- bool exposed = false;
251-
252- switch (e.type)
253- {
254- case Expose:
255- if (e.xexpose.window == xid)
256- exposed = true;
257- break;
258- default:
259- break;
260- }
261-
262- if (exposed)
263+ XNextEvent (dpy, &event);
264+ bool exposed = false;
265+
266+ switch (event.type)
267+ {
268+ case Expose:
269+ if (event.xexpose.window == xid)
270+ exposed = true;
271+ break;
272+ default:
273+ break;
274+ }
275+
276+ if (exposed)
277 break;
278- }
279+
280+ } while (XPending (dpy));
281 }
282
283+ XShapeSelectInput (dpy, xid, ShapeNotifyMask);
284+
285 if (argc == 3)
286 std::stringstream (argv[2]) >> std::dec >> time;
287
288@@ -150,7 +155,26 @@
289 remover->save ();
290 std::cout << "Removing input shape of 0x" << std::hex << xid << std::dec << std::endl;
291 remover->remove ();
292- XSync (dpy, false);
293+
294+ /* We won't get a synethetic ShapeNotify event if this
295+ * is on a window that we don't own */
296+
297+ if (argc == 1)
298+ {
299+ do
300+ {
301+ XNextEvent (dpy, &event);
302+ if (event.type == shapeEvent + ShapeNotify &&
303+ event.xany.send_event)
304+ {
305+ std::cout << "received ShapeNotify on 0x" << std::hex << xid << std::endl;
306+ break;
307+ }
308+
309+ } while (XPending (dpy));
310+ }
311+ else
312+ XSync (dpy, false);
313
314 std::cout << "Getting input rects for 0x" << std::hex << xid << std::dec << std::endl;
315 if (print_rects (dpy, xid))
316@@ -163,9 +187,26 @@
317
318 std::cout << "Waiting " << std::dec << time << " seconds" << std::endl;
319 sleep (time);
320+
321 std::cout << "Restoring input shape of 0x" << std::hex << xid << std::dec << std::endl;
322 remover->restore ();
323- XSync (dpy, false);
324+
325+ if (argc == 1)
326+ {
327+ do
328+ {
329+ XNextEvent (dpy, &event);
330+ if (event.type == shapeEvent + ShapeNotify &&
331+ event.xany.send_event)
332+ {
333+ std::cout << "received ShapeNotify on 0x" << std::hex << xid << std::endl;
334+ break;
335+ }
336+
337+ } while (XPending (dpy));
338+ }
339+ else
340+ XSync (dpy, false);
341
342 if (!print_rects (dpy, xid))
343 {