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
=== modified file 'plugins/unityshell/src/inputremover.cpp'
--- plugins/unityshell/src/inputremover.cpp 2011-09-09 13:21:10 +0000
+++ plugins/unityshell/src/inputremover.cpp 2011-09-13 14:00:42 +0000
@@ -22,6 +22,7 @@
22#include "inputremover.h"22#include "inputremover.h"
23#include <X11/Xregion.h>23#include <X11/Xregion.h>
24#include <cstdio>24#include <cstdio>
25#include <cstring>
2526
26compiz::WindowInputRemover::WindowInputRemover (Display *dpy,27compiz::WindowInputRemover::WindowInputRemover (Display *dpy,
27 Window xid) :28 Window xid) :
@@ -36,6 +37,8 @@
36 mBoundingRectOrdering (0),37 mBoundingRectOrdering (0),
37 mRemoved (false)38 mRemoved (false)
38{39{
40 /* FIXME: roundtrip */
41 XShapeQueryExtension (mDpy, &mShapeEvent, &mShapeError);
39}42}
4043
41compiz::WindowInputRemover::~WindowInputRemover ()44compiz::WindowInputRemover::~WindowInputRemover ()
@@ -47,11 +50,23 @@
47void50void
48compiz::WindowInputRemover::sendShapeNotify ()51compiz::WindowInputRemover::sendShapeNotify ()
49{52{
50 /* Send a synthetic ShapeNotify event to the root window53 /* Send a synthetic ShapeNotify event to the client and parent window
51 * since we ignored shape events when setting visibility54 * since we ignored shape events when setting visibility
52 * in order to avoid cycling in the shape handling code -55 * in order to avoid cycling in the shape handling code -
53 * ignore the sent shape notify event since that will56 * ignore the sent shape notify event since that will
54 * be send_event = true */57 * be send_event = true
58 *
59 * NB: We must send ShapeNotify events to both the client
60 * window and to the root window with SubstructureRedirectMask
61 * since NoEventMask will only deliver the event to the client
62 * (see xserver/dix/events.c on the handling of CantBeFiltered
63 * messages)
64 *
65 * NB: This code will break if you don't have this patch on the
66 * X Server since XSendEvent for non-core events are broken.
67 *
68 * http://lists.x.org/archives/xorg-devel/2011-September/024996.html
69 */
5570
56 XShapeEvent xsev;71 XShapeEvent xsev;
57 XEvent *xev = (XEvent *) &xsev;72 XEvent *xev = (XEvent *) &xsev;
@@ -60,13 +75,17 @@
60 Window *children;75 Window *children;
61 int x, y, xOffset, yOffset;76 int x, y, xOffset, yOffset;
62 unsigned int width, height, depth, border, nchildren;77 unsigned int width, height, depth, border, nchildren;
63 int shapeEvent, shapeError, shapeMask;78
6479 memset (&xsev, 0, sizeof (XShapeEvent));
65 /* FIXME: roundtrip */80
66 XShapeQueryExtension (mDpy, &shapeEvent, &shapeError);81 /* XXX: libXShape is weird and range checks the event
67 shapeMask = XShapeInputSelected (mDpy, mShapeWindow);82 * type on event_to_wire so ensure that we are setting
6883 * the event type on the right range */
69 xev->type = shapeEvent + ShapeNotify;84 xsev.type = (mShapeEvent - ShapeNotify) & 0x7f;
85 /* We must explicitly fill in these values to avoid padding errors */
86 xsev.serial = 0L;
87 xsev.send_event = TRUE;
88 xsev.display = mDpy;
70 xsev.window = mShapeWindow;89 xsev.window = mShapeWindow;
7190
72 if (!mRemoved)91 if (!mRemoved)
@@ -81,9 +100,10 @@
81 * rect of the window shape according to the Shape extension100 * rect of the window shape according to the Shape extension
82 * specification */101 * specification */
83102
84 XTranslateCoordinates (mDpy, mShapeWindow, parentReturn, 0, 0, &xOffset, &yOffset, &childReturn);103 XTranslateCoordinates (mDpy, mShapeWindow, parentReturn, 0, 0,
104 &xOffset, &yOffset, &childReturn);
85105
86 xev->type = ShapeBounding;106 xsev.kind = ShapeBounding;
87107
88 /* Calculate extents of the bounding shape */108 /* Calculate extents of the bounding shape */
89 if (!mNBoundingRects)109 if (!mNBoundingRects)
@@ -112,9 +132,10 @@
112 }132 }
113133
114 xsev.time = CurrentTime;134 xsev.time = CurrentTime;
115 XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
116135
117 xev->type = ShapeInput;136 XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
137 XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
138 xsev.kind = ShapeInput;
118139
119 /* Calculate extents of the bounding shape */140 /* Calculate extents of the bounding shape */
120 if (!mNInputRects)141 if (!mNInputRects)
@@ -143,14 +164,18 @@
143 }164 }
144165
145 xsev.time = CurrentTime;166 xsev.time = CurrentTime;
146 XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);167
168 XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
169 XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
147170
148 if (children)171 if (children)
149 XFree (children);172 XFree (children);
150 }173 }
151 else174 else
152 {175 {
153 xev->type = ShapeBounding;176 XQueryTree (mDpy, mShapeWindow, &rootReturn, &parentReturn, &children, &nchildren);
177
178 xsev.kind = ShapeBounding;
154179
155 xsev.x = 0;180 xsev.x = 0;
156 xsev.y = 0;181 xsev.y = 0;
@@ -159,15 +184,20 @@
159 xsev.shaped = true;184 xsev.shaped = true;
160185
161 xsev.time = CurrentTime;186 xsev.time = CurrentTime;
162 XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);187 XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
188 XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
163189
164 xev->type = ShapeInput;190 xsev.kind = ShapeInput;
165191
166 /* Both ShapeBounding and ShapeInput are null */192 /* Both ShapeBounding and ShapeInput are null */
167193
168 xsev.time = CurrentTime;194 xsev.time = CurrentTime;
169 XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);195
196 XSendEvent (mDpy, mShapeWindow, FALSE, NoEventMask, xev);
197 XSendEvent (mDpy, parentReturn, FALSE, NoEventMask, xev);
198
170 }199 }
200
171}201}
172202
173bool203bool
@@ -211,6 +241,17 @@
211 rects = XShapeGetRectangles (mDpy, mShapeWindow, ShapeBounding,241 rects = XShapeGetRectangles (mDpy, mShapeWindow, ShapeBounding,
212 &count, &ordering);242 &count, &ordering);
213243
244 /* check if the returned shape exactly matches the window shape -
245 * if that is true, the window currently has no set bounding shape */
246 if ((count == 1) &&
247 (rects[0].x == -((int) border)) &&
248 (rects[0].y == -((int) border)) &&
249 (rects[0].width == (width + border)) &&
250 (rects[0].height == (height + border)))
251 {
252 count = 0;
253 }
254
214 if (mBoundingRects)255 if (mBoundingRects)
215 XFree (mBoundingRects);256 XFree (mBoundingRects);
216257
@@ -236,17 +277,21 @@
236 XShapeCombineRectangles (mDpy, mShapeWindow, ShapeBounding, 0, 0,277 XShapeCombineRectangles (mDpy, mShapeWindow, ShapeBounding, 0, 0,
237 NULL, 0, ShapeSet, 0);278 NULL, 0, ShapeSet, 0);
238279
239 XShapeSelectInput (mDpy, mShapeWindow, ShapeNotify);280 XShapeSelectInput (mDpy, mShapeWindow, mShapeMask);
240
241 sendShapeNotify ();
242281
243 mRemoved = true;282 mRemoved = true;
283
284 sendShapeNotify ();
285
244 return true;286 return true;
245}287}
246288
247bool289bool
248compiz::WindowInputRemover::restore ()290compiz::WindowInputRemover::restore ()
249{291{
292
293 XShapeSelectInput (mDpy, mShapeWindow, NoEventMask);
294
250 if (mRemoved)295 if (mRemoved)
251 {296 {
252 if (mNInputRects)297 if (mNInputRects)
@@ -283,9 +328,10 @@
283328
284 XShapeSelectInput (mDpy, mShapeWindow, mShapeMask);329 XShapeSelectInput (mDpy, mShapeWindow, mShapeMask);
285330
286 sendShapeNotify ();
287
288 mRemoved = false;331 mRemoved = false;
332
333 sendShapeNotify ();
334
289 mNInputRects = 0;335 mNInputRects = 0;
290 mInputRects = NULL;336 mInputRects = NULL;
291 mNBoundingRects = 0;337 mNBoundingRects = 0;
292338
=== modified file 'plugins/unityshell/src/inputremover.h'
--- plugins/unityshell/src/inputremover.h 2011-09-09 13:21:10 +0000
+++ plugins/unityshell/src/inputremover.h 2011-09-13 14:00:42 +0000
@@ -57,6 +57,9 @@
57 int mBoundingRectOrdering;57 int mBoundingRectOrdering;
58 bool mRemoved;58 bool mRemoved;
5959
60 int mShapeEvent;
61 int mShapeError;
62
60};63};
61}64}
6265
6366
=== modified file 'tests/test-input-remover/test-input-remover.cpp'
--- tests/test-input-remover/test-input-remover.cpp 2011-08-24 13:46:21 +0000
+++ tests/test-input-remover/test-input-remover.cpp 2011-09-13 14:00:42 +0000
@@ -77,9 +77,10 @@
77 Window xid;77 Window xid;
78 int time = 0;78 int time = 0;
79 compiz::WindowInputRemover *remover;79 compiz::WindowInputRemover *remover;
80 bool shapeExt;80 bool shapeExt;
81 int shapeEvent;81 int shapeEvent;
82 int shapeError;82 int shapeError;
83 XEvent event;
8384
84 if ((argc == 2 && std::string (argv[1]) == "--help") || argc > 3)85 if ((argc == 2 && std::string (argv[1]) == "--help") || argc > 3)
85 {86 {
@@ -109,34 +110,38 @@
109 else110 else
110 {111 {
111 XSetWindowAttributes attrib;112 XSetWindowAttributes attrib;
112 XEvent e;113
114 attrib.backing_pixel = 0x0;
113115
114 xid = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, 100, 100, 0,116 xid = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, 100, 100, 0,
115 DefaultDepth (dpy, DefaultScreen (dpy)), InputOutput,117 DefaultDepth (dpy, DefaultScreen (dpy)), InputOutput,
116 DefaultVisual (dpy, DefaultScreen (dpy)), 0, &attrib);118 DefaultVisual (dpy, DefaultScreen (dpy)), CWBackingPixel, &attrib);
117119
118 XSelectInput (dpy, xid, ExposureMask | StructureNotifyMask);120 XSelectInput (dpy, xid, ExposureMask | StructureNotifyMask);
119 XMapRaised (dpy, xid);121 XMapRaised (dpy, xid);
120 while (1)122 do
121 {123 {
122 XNextEvent (dpy, &e);124 XNextEvent (dpy, &event);
123 bool exposed = false;125 bool exposed = false;
124126
125 switch (e.type)127 switch (event.type)
126 {128 {
127 case Expose:129 case Expose:
128 if (e.xexpose.window == xid)130 if (event.xexpose.window == xid)
129 exposed = true;131 exposed = true;
130 break;132 break;
131 default:133 default:
132 break;134 break;
133 }135 }
134136
135 if (exposed)137 if (exposed)
136 break;138 break;
137 }139
140 } while (XPending (dpy));
138 }141 }
139142
143 XShapeSelectInput (dpy, xid, ShapeNotifyMask);
144
140 if (argc == 3)145 if (argc == 3)
141 std::stringstream (argv[2]) >> std::dec >> time;146 std::stringstream (argv[2]) >> std::dec >> time;
142147
@@ -150,7 +155,26 @@
150 remover->save ();155 remover->save ();
151 std::cout << "Removing input shape of 0x" << std::hex << xid << std::dec << std::endl;156 std::cout << "Removing input shape of 0x" << std::hex << xid << std::dec << std::endl;
152 remover->remove ();157 remover->remove ();
153 XSync (dpy, false);158
159 /* We won't get a synethetic ShapeNotify event if this
160 * is on a window that we don't own */
161
162 if (argc == 1)
163 {
164 do
165 {
166 XNextEvent (dpy, &event);
167 if (event.type == shapeEvent + ShapeNotify &&
168 event.xany.send_event)
169 {
170 std::cout << "received ShapeNotify on 0x" << std::hex << xid << std::endl;
171 break;
172 }
173
174 } while (XPending (dpy));
175 }
176 else
177 XSync (dpy, false);
154178
155 std::cout << "Getting input rects for 0x" << std::hex << xid << std::dec << std::endl;179 std::cout << "Getting input rects for 0x" << std::hex << xid << std::dec << std::endl;
156 if (print_rects (dpy, xid))180 if (print_rects (dpy, xid))
@@ -163,9 +187,26 @@
163187
164 std::cout << "Waiting " << std::dec << time << " seconds" << std::endl;188 std::cout << "Waiting " << std::dec << time << " seconds" << std::endl;
165 sleep (time);189 sleep (time);
190
166 std::cout << "Restoring input shape of 0x" << std::hex << xid << std::dec << std::endl;191 std::cout << "Restoring input shape of 0x" << std::hex << xid << std::dec << std::endl;
167 remover->restore ();192 remover->restore ();
168 XSync (dpy, false);193
194 if (argc == 1)
195 {
196 do
197 {
198 XNextEvent (dpy, &event);
199 if (event.type == shapeEvent + ShapeNotify &&
200 event.xany.send_event)
201 {
202 std::cout << "received ShapeNotify on 0x" << std::hex << xid << std::endl;
203 break;
204 }
205
206 } while (XPending (dpy));
207 }
208 else
209 XSync (dpy, false);
169210
170 if (!print_rects (dpy, xid))211 if (!print_rects (dpy, xid))
171 {212 {