Merge lp:~smspillaz/unity/unity.stack_debug_fixed_minimized_windows into lp:unity

Proposed by Sam Spilsbury
Status: Merged
Approved by: Neil J. Patel
Approved revision: no longer in the source branch.
Merged at revision: 1529
Proposed branch: lp:~smspillaz/unity/unity.stack_debug_fixed_minimized_windows
Merge into: lp:unity
Diff against target: 277 lines (+142/-33)
4 files modified
plugins/unityshell/src/compizminimizedwindowhandler.h (+4/-30)
plugins/unityshell/src/inputremover.cpp (+132/-0)
plugins/unityshell/src/inputremover.h (+4/-1)
plugins/unityshell/src/minimizedwindowhandler.cpp (+2/-2)
To merge this branch: bzr merge lp:~smspillaz/unity/unity.stack_debug_fixed_minimized_windows
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Review via email: mp+74792@code.launchpad.net

Description of the change

Fixes a case where minimized windows would not get their frame region restored correctly because we used XShape on the frame window directly.

Send a synethetic ShapeNotify instead and let core figure it out.

To post a comment you must log in.
Revision history for this message
Neil J. Patel (njpatel) :
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/compizminimizedwindowhandler.h'
2--- plugins/unityshell/src/compizminimizedwindowhandler.h 2011-09-02 14:32:40 +0000
3+++ plugins/unityshell/src/compizminimizedwindowhandler.h 2011-09-09 13:52:44 +0000
4@@ -37,7 +37,6 @@
5 PrivateCompizMinimizedWindowHandler () {};
6
7 CompWindow *mWindow;
8- WindowInputRemover *clientInputRemover;
9 };
10
11 template <typename Screen, typename Window>
12@@ -87,7 +86,6 @@
13 priv = new PrivateCompizMinimizedWindowHandler ();
14
15 priv->mWindow = w;
16- priv->clientInputRemover = NULL;
17
18 }
19
20@@ -115,33 +113,7 @@
21 void
22 compiz::CompizMinimizedWindowHandler<Screen, Window>::setVisibility (bool visible)
23 {
24- CompWindow::Geometry gm = priv->mWindow->geometry ();
25- MinimizedWindowHandler::setVisibility (visible, ROOTPARENT (priv->mWindow));
26-
27- if (!visible && !priv->clientInputRemover)
28- {
29- priv->clientInputRemover = new compiz::WindowInputRemover (screen->dpy (), priv->mWindow->id ());
30- if (!priv->clientInputRemover)
31- return;
32-
33- if (priv->clientInputRemover->save ())
34- priv->clientInputRemover->remove ();
35- }
36- else if (visible && priv->clientInputRemover)
37- {
38- priv->clientInputRemover->restore ();
39-
40- delete priv->clientInputRemover;
41- priv->clientInputRemover = NULL;
42- }
43-
44- /* This is a little hack to ensure that the window region gets updated,
45- * because there's no API in core to do that */
46-
47- gm.setBorder (gm.border () + 1);
48- priv->mWindow->resize (gm);
49- gm.setBorder (gm.border () - 1);
50- priv->mWindow->resize (gm);
51+ MinimizedWindowHandler::setVisibility (visible, priv->mWindow->id ());
52
53 CompositeWindow::get (priv->mWindow)->addDamage ();
54 GLWindow::get (priv->mWindow)->glPaintSetEnabled (Window::get (priv->mWindow), !visible);
55@@ -285,8 +257,10 @@
56 void
57 compiz::CompizMinimizedWindowHandler<Screen, Window>::handleEvent (XEvent *event)
58 {
59+ /* Ignore sent events from the InputRemover */
60 if (screen->XShape () && event->type ==
61- screen->shapeEvent () + ShapeNotify)
62+ screen->shapeEvent () + ShapeNotify &&
63+ !event->xany.send_event)
64 {
65 CompWindow *w = screen->findWindow (((XShapeEvent *) event)->window);
66
67
68=== modified file 'plugins/unityshell/src/inputremover.cpp'
69--- plugins/unityshell/src/inputremover.cpp 2011-09-02 14:32:40 +0000
70+++ plugins/unityshell/src/inputremover.cpp 2011-09-09 13:52:44 +0000
71@@ -20,6 +20,7 @@
72 */
73
74 #include "inputremover.h"
75+#include <X11/Xregion.h>
76 #include <cstdio>
77
78 compiz::WindowInputRemover::WindowInputRemover (Display *dpy,
79@@ -43,6 +44,132 @@
80 restore ();
81 }
82
83+void
84+compiz::WindowInputRemover::sendShapeNotify ()
85+{
86+ /* Send a synthetic ShapeNotify event to the root window
87+ * since we ignored shape events when setting visibility
88+ * in order to avoid cycling in the shape handling code -
89+ * ignore the sent shape notify event since that will
90+ * be send_event = true */
91+
92+ XShapeEvent xsev;
93+ XEvent *xev = (XEvent *) &xsev;
94+ Window rootReturn, parentReturn;
95+ Window childReturn;
96+ Window *children;
97+ int x, y, xOffset, yOffset;
98+ unsigned int width, height, depth, border, nchildren;
99+ int shapeEvent, shapeError, shapeMask;
100+
101+ /* FIXME: roundtrip */
102+ XShapeQueryExtension (mDpy, &shapeEvent, &shapeError);
103+ shapeMask = XShapeInputSelected (mDpy, mShapeWindow);
104+
105+ xev->type = shapeEvent + ShapeNotify;
106+ xsev.window = mShapeWindow;
107+
108+ if (!mRemoved)
109+ {
110+ /* FIXME: these roundtrips suck */
111+ XGetGeometry (mDpy, mShapeWindow, &rootReturn, &x, &y, &width, &height, &depth, &border);
112+ XQueryTree (mDpy, mShapeWindow, &rootReturn, &parentReturn, &children, &nchildren);
113+
114+ /* We need to translate the co-ordinates of the origin to the
115+ * client window to its parent to find out the offset of its
116+ * position so that we can subtract that from the final bounding
117+ * rect of the window shape according to the Shape extension
118+ * specification */
119+
120+ XTranslateCoordinates (mDpy, mShapeWindow, parentReturn, 0, 0, &xOffset, &yOffset, &childReturn);
121+
122+ xev->type = ShapeBounding;
123+
124+ /* Calculate extents of the bounding shape */
125+ if (!mNBoundingRects)
126+ {
127+ /* No set input shape, we must use the client geometry */
128+ xsev.x = x - xOffset;
129+ xsev.y = y - yOffset;
130+ xsev.width = width;
131+ xsev.height = height;
132+ xsev.shaped = false;
133+ }
134+ else
135+ {
136+ Region boundingRegion = XCreateRegion ();
137+
138+ for (int i = 0; i < mNBoundingRects; i++)
139+ XUnionRectWithRegion (&(mBoundingRects[i]), boundingRegion, boundingRegion);
140+
141+ xsev.x = boundingRegion->extents.x1 - xOffset;
142+ xsev.y = boundingRegion->extents.y1 - yOffset;
143+ xsev.width = boundingRegion->extents.x2 - boundingRegion->extents.x1;
144+ xsev.height = boundingRegion->extents.y2 - boundingRegion->extents.y1;
145+ xsev.shaped = true;
146+
147+ XDestroyRegion (boundingRegion);
148+ }
149+
150+ xsev.time = CurrentTime;
151+ XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
152+
153+ xev->type = ShapeInput;
154+
155+ /* Calculate extents of the bounding shape */
156+ if (!mNInputRects)
157+ {
158+ /* No set input shape, we must use the client geometry */
159+ xsev.x = x - xOffset;
160+ xsev.y = y - yOffset;
161+ xsev.width = width;
162+ xsev.height = height;
163+ xsev.shaped = false;
164+ }
165+ else
166+ {
167+ Region inputRegion = XCreateRegion ();
168+
169+ for (int i = 0; i < mNInputRects; i++)
170+ XUnionRectWithRegion (&(mInputRects[i]), inputRegion, inputRegion);
171+
172+ xsev.x = inputRegion->extents.x1 - xOffset;
173+ xsev.y = inputRegion->extents.y1 - yOffset;
174+ xsev.width = inputRegion->extents.x2 - inputRegion->extents.x1;
175+ xsev.height = inputRegion->extents.y2 - inputRegion->extents.y1;
176+ xsev.shaped = true;
177+
178+ XDestroyRegion (inputRegion);
179+ }
180+
181+ xsev.time = CurrentTime;
182+ XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
183+
184+ if (children)
185+ XFree (children);
186+ }
187+ else
188+ {
189+ xev->type = ShapeBounding;
190+
191+ xsev.x = 0;
192+ xsev.y = 0;
193+ xsev.width = 0;
194+ xsev.height = 0;
195+ xsev.shaped = true;
196+
197+ xsev.time = CurrentTime;
198+ XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
199+
200+ xev->type = ShapeInput;
201+
202+ /* Both ShapeBounding and ShapeInput are null */
203+
204+ xsev.time = CurrentTime;
205+ XSendEvent (mDpy, DefaultRootWindow (mDpy), false, shapeMask, xev);
206+ }
207+}
208+
209 bool
210 compiz::WindowInputRemover::save ()
211 {
212@@ -111,6 +238,8 @@
213
214 XShapeSelectInput (mDpy, mShapeWindow, ShapeNotify);
215
216+ sendShapeNotify ();
217+
218 mRemoved = true;
219 return true;
220 }
221@@ -125,6 +254,7 @@
222 XShapeCombineRectangles (mDpy, mShapeWindow, ShapeInput, 0, 0,
223 mInputRects, mNInputRects,
224 ShapeSet, mInputRectOrdering);
225+
226 }
227 else
228 {
229@@ -153,6 +283,8 @@
230
231 XShapeSelectInput (mDpy, mShapeWindow, mShapeMask);
232
233+ sendShapeNotify ();
234+
235 mRemoved = false;
236 mNInputRects = 0;
237 mInputRects = NULL;
238
239=== modified file 'plugins/unityshell/src/inputremover.h'
240--- plugins/unityshell/src/inputremover.h 2011-09-01 17:18:02 +0000
241+++ plugins/unityshell/src/inputremover.h 2011-09-09 13:52:44 +0000
242@@ -41,6 +41,9 @@
243 bool restore ();
244
245 private:
246+
247+ void sendShapeNotify ();
248+
249 Display *mDpy;
250 Window mShapeWindow;
251 unsigned long mShapeMask;
252@@ -52,7 +55,7 @@
253 XRectangle *mBoundingRects;
254 int mNBoundingRects;
255 int mBoundingRectOrdering;
256- bool mRemoved;
257+ bool mRemoved;
258
259 };
260 }
261
262=== modified file 'plugins/unityshell/src/minimizedwindowhandler.cpp'
263--- plugins/unityshell/src/minimizedwindowhandler.cpp 2011-08-26 10:37:35 +0000
264+++ plugins/unityshell/src/minimizedwindowhandler.cpp 2011-09-09 13:52:44 +0000
265@@ -58,10 +58,10 @@
266 {
267 priv->mRemover = new compiz::WindowInputRemover (priv->mDpy, shapeWin);
268 if (!priv->mRemover)
269- return;
270+ return;
271
272 if (priv->mRemover->save ())
273- priv->mRemover->remove ();
274+ priv->mRemover->remove ();
275 }
276 else if (visible && priv->mRemover)
277 {