Merge lp:~townsend/compiz/fix-lp1158267-0.9.10 into lp:compiz/0.9.10

Proposed by Christopher Townsend
Status: Merged
Approved by: Christopher Townsend
Approved revision: 3787
Merged at revision: 3787
Proposed branch: lp:~townsend/compiz/fix-lp1158267-0.9.10
Merge into: lp:compiz/0.9.10
Diff against target: 448 lines (+259/-56)
3 files modified
plugins/decor/src/decor.cpp (+57/-48)
plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt (+4/-2)
plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp (+198/-6)
To merge this branch: bzr merge lp:~townsend/compiz/fix-lp1158267-0.9.10
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+184317@code.launchpad.net

Commit message

Work done by Sam Spilsbury:
- Ensure that the frame region is always set as soon as the window is decorated.
- Further ensure that the window decoration isn't needlessly reset if the window already had one.
- Refactored XShape usage into a common function.
- Added tests to verify the behaviour of shape set on initially creating a decorated window and also upon changing the input frame window shape.

Description of the change

This is a backport to 0.9.10 of the work Sam Spilsbury did in https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1158267.update-tests/+merge/176801.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

LGTM

review: Approve
Revision history for this message
Christopher Townsend (townsend) wrote :

Globally approving since the trunk MP has merged.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/decor/src/decor.cpp'
2--- plugins/decor/src/decor.cpp 2013-07-19 15:49:47 +0000
3+++ plugins/decor/src/decor.cpp 2013-09-06 14:28:07 +0000
4@@ -44,6 +44,34 @@
5
6 namespace cwe = compiz::window::extents;
7
8+namespace
9+{
10+void updateRegionWithShapeRectangles (Display *dpy,
11+ Window w,
12+ CompRegion &region)
13+{
14+ int n = 0;
15+ int order = 0;
16+ XRectangle *shapeRects = NULL;
17+
18+ shapeRects =
19+ XShapeGetRectangles (dpy,
20+ w, ShapeInput,
21+ &n, &order);
22+ if (!shapeRects)
23+ return;
24+
25+ for (int i = 0; i < n; i++)
26+ region +=
27+ CompRegion (shapeRects[i].x,
28+ shapeRects[i].y,
29+ shapeRects[i].width,
30+ shapeRects[i].height);
31+
32+ XFree (shapeRects);
33+}
34+}
35+
36 MatchedDecorClipGroup::MatchedDecorClipGroup (const CompMatch &match) :
37 mMatch (match)
38 {
39@@ -1590,13 +1618,6 @@
40 lastMaximizedStateDecorated == decorMaximizeState)
41 return false;
42
43- /* Destroy the old WindowDecoration */
44- if (old)
45- {
46- WindowDecoration::destroy (wd);
47- wd = NULL;
48- }
49-
50 /* If a decoration was found for this window, create
51 * a new WindowDecoration for it and set the frame
52 * extents accordingly. We should also move the
53@@ -1622,6 +1643,8 @@
54 if (decorate ||
55 shadowOnly)
56 {
57+ if (wd)
58+ WindowDecoration::destroy (wd);
59 wd = WindowDecoration::create (decoration);
60 if (!wd)
61 {
62@@ -1649,7 +1672,12 @@
63 else
64 {
65 CompWindowExtents emptyExtents;
66- wd = NULL;
67+
68+ if (wd)
69+ {
70+ WindowDecoration::destroy (wd);
71+ wd = NULL;
72+ }
73
74 /* _NET_FRAME_EXTENTS should be updated before the frame
75 * atom is */
76@@ -1903,6 +1931,13 @@
77 ShapeSet, YXBanded);
78
79 frameRegion = CompRegion ();
80+
81+ /* Immediately query shape rectangles so that we can
82+ * report them if core asks for them */
83+ updateRegionWithShapeRectangles (screen->dpy (),
84+ inputFrame,
85+ frameRegion);
86+ window->updateFrameRegion ();
87 }
88
89 XUngrabServer (screen->dpy ());
90@@ -2045,6 +2080,13 @@
91 ShapeSet, YXBanded);
92
93 frameRegion = CompRegion ();
94+
95+ /* Immediately query shape rectangles so that we can
96+ * report them if core asks for them */
97+ updateRegionWithShapeRectangles (screen->dpy (),
98+ outputFrame,
99+ frameRegion);
100+ window->updateFrameRegion ();
101 }
102
103 XUngrabServer (screen->dpy ());
104@@ -2168,6 +2210,7 @@
105 DecorWindow::updateFrameRegion (CompRegion &region)
106 {
107 window->updateFrameRegion (region);
108+
109 if (wd)
110 {
111 if (!frameRegion.isEmpty ())
112@@ -2180,10 +2223,6 @@
113 region += frameRegion.translated (x - wd->decor->input.left,
114 y - wd->decor->input.top);
115 }
116- else
117- {
118- region += infiniteRegion;
119- }
120 }
121
122 updateReg = true;
123@@ -2602,54 +2641,24 @@
124 if (dw->inputFrame ==
125 ((XShapeEvent *) event)->window)
126 {
127- XRectangle *shapeRects = 0;
128- int order, n;
129-
130 dw->frameRegion = CompRegion ();
131
132- shapeRects =
133- XShapeGetRectangles (screen->dpy (),
134- dw->inputFrame, ShapeInput,
135- &n, &order);
136- if (!shapeRects || !n)
137- break;
138-
139- for (int i = 0; i < n; i++)
140- dw->frameRegion +=
141- CompRegion (shapeRects[i].x,
142- shapeRects[i].y,
143- shapeRects[i].width,
144- shapeRects[i].height);
145+ updateRegionWithShapeRectangles (screen->dpy (),
146+ dw->inputFrame,
147+ dw->frameRegion);
148
149 w->updateFrameRegion ();
150-
151- XFree (shapeRects);
152 }
153 else if (dw->outputFrame ==
154 ((XShapeEvent *) event)->window)
155 {
156- XRectangle *shapeRects = 0;
157- int order, n;
158-
159 dw->frameRegion = CompRegion ();
160
161- shapeRects =
162- XShapeGetRectangles (screen->dpy (),
163- dw->outputFrame, ShapeBounding,
164- &n, &order);
165- if (!n || !shapeRects)
166- break;
167-
168- for (int i = 0; i < n; i++)
169- dw->frameRegion +=
170- CompRegion (shapeRects[i].x,
171- shapeRects[i].y,
172- shapeRects[i].width,
173- shapeRects[i].height);
174+ updateRegionWithShapeRectangles (screen->dpy (),
175+ dw->outputFrame,
176+ dw->frameRegion);
177
178 w->updateFrameRegion ();
179-
180- XFree (shapeRects);
181 }
182 }
183 }
184
185=== modified file 'plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt'
186--- plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt 2013-07-15 20:11:19 +0000
187+++ plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt 2013-09-06 14:28:07 +0000
188@@ -1,6 +1,8 @@
189 include (FindPkgConfig)
190
191-if (BUILD_XORG_GTEST)
192+pkg_check_modules (X11_XI x11 xi xext)
193+
194+if (BUILD_XORG_GTEST AND X11_XI_FOUND)
195
196 include_directories (${compiz_SOURCE_DIR}/tests/shared
197 ${COMPIZ_XORG_SYSTEM_TEST_INCLUDE_DIR}
198@@ -35,5 +37,5 @@
199 # Disabled until the tests can be run without opengl
200 #compiz_discover_tests (compiz_test_decor_acceptance WITH_XORG_GTEST)
201
202-endif (BUILD_XORG_GTEST)
203+endif (BUILD_XORG_GTEST AND X11_XI_FOUND)
204
205
206=== modified file 'plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp'
207--- plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp 2013-07-19 19:17:31 +0000
208+++ plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp 2013-09-06 14:28:07 +0000
209@@ -33,6 +33,7 @@
210
211 #include <X11/Xlib.h>
212 #include <X11/Xatom.h>
213+#include <X11/extensions/shape.h>
214
215 #include "decoration.h"
216
217@@ -48,7 +49,10 @@
218 namespace xt = xorg::testing;
219 namespace ct = compiz::testing;
220
221+using ::testing::AllOf;
222 using ::testing::AtLeast;
223+using ::testing::Eq;
224+using ::testing::Field;
225 using ::testing::ReturnNull;
226 using ::testing::Return;
227 using ::testing::MatcherInterface;
228@@ -1208,6 +1212,17 @@
229 return parent;
230 }
231
232+bool WaitForReparent (::Display *dpy,
233+ Window w)
234+{
235+ return Advance (dpy,
236+ ct::WaitForEventOfTypeOnWindow (dpy,
237+ w,
238+ ReparentNotify,
239+ -1,
240+ -1));
241+}
242+
243 void FreeWindowArray (Window *array)
244 {
245 if (array)
246@@ -1667,6 +1682,188 @@
247 inputExtents));
248 }
249
250+class DecorPixmapShapeSetAcceptance :
251+ public DecorWithPixmapDefaultsAcceptance
252+{
253+ public:
254+
255+ virtual void SetUp ();
256+
257+ protected:
258+
259+ int shapeEvent;
260+ int shapeError;
261+
262+ int shapeMajor;
263+ int shapeMinor;
264+};
265+
266+void
267+DecorPixmapShapeSetAcceptance::SetUp ()
268+{
269+ DecorWithPixmapDefaultsAcceptance::SetUp ();
270+
271+ if (!XShapeQueryVersion (Display (), &shapeMajor, &shapeMinor))
272+ throw std::runtime_error ("Unable to query shape extension version");
273+
274+ if (!XShapeQueryExtension (Display (), &shapeEvent, &shapeError))
275+ throw std::runtime_error ("Unable to initialize shape extension");
276+}
277+
278+std::ostream &
279+operator<< (std::ostream &os, const XRectangle &r)
280+{
281+ os << "XRectangle: "
282+ << " x: " << r.x
283+ << " y: " << r.y
284+ << " width: " << r.width
285+ << " height: " << r.height;
286+
287+ return os;
288+}
289+
290+namespace
291+{
292+void FreeXRectangleArray (XRectangle *array)
293+{
294+ XFree (array);
295+}
296+
297+boost::shared_array <XRectangle>
298+ShapeRectangles (::Display *dpy,
299+ Window w,
300+ int &n,
301+ int &order)
302+{
303+ XRectangle *rects = XShapeGetRectangles(dpy,
304+ w,
305+ ShapeInput,
306+ &n,
307+ &order);
308+
309+ return boost::shared_array <XRectangle> (rects,
310+ boost::bind (FreeXRectangleArray,
311+ _1));
312+}
313+}
314+
315+TEST_F (DecorPixmapShapeSetAcceptance, FrameWindowHasInitialFullShape)
316+{
317+ Window w = ct::CreateNormalWindow (Display ());
318+
319+ RecievePropertyNotifyEvents (Display (), w);
320+ XMapRaised (Display (), w);
321+ WaitForPropertyNotify (Display (), w, "_NET_FRAME_EXTENTS");
322+
323+ Window parent = FindParent (Display (), w);
324+
325+ int x, y;
326+ unsigned int width, height, border;
327+
328+ ct::AbsoluteWindowGeometry (Display (),
329+ parent,
330+ x,
331+ y,
332+ width,
333+ height,
334+ border);
335+
336+ int n, order;
337+ boost::shared_array <XRectangle> rects (ShapeRectangles (Display (),
338+ parent,
339+ n,
340+ order));
341+
342+ ASSERT_THAT (n, Eq (1));
343+ EXPECT_THAT (rects[0],
344+ AllOf (Field (&XRectangle::x, Eq (0)),
345+ Field (&XRectangle::y, Eq (0)),
346+ Field (&XRectangle::width, Eq (width)),
347+ Field (&XRectangle::height, Eq (height))));
348+}
349+
350+TEST_F (DecorPixmapShapeSetAcceptance, FrameWindowShapeIsUpdated)
351+{
352+ Window w = ct::CreateNormalWindow (Display ());
353+
354+ RecievePropertyNotifyEvents (Display (), w);
355+ XMapRaised (Display (), w);
356+ WaitForReparent (Display (), w);
357+ WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
358+
359+ Window parent = FindParent (Display (), w);
360+
361+ int clientX, clientY;
362+ unsigned int clientWidth, clientHeight, border;
363+
364+ ct::AbsoluteWindowGeometry (Display (),
365+ w,
366+ clientX,
367+ clientY,
368+ clientWidth,
369+ clientHeight,
370+ border);
371+
372+ /* Get the input frame remove its input shape completely */
373+ boost::shared_ptr <unsigned char> inputFramePropertyData;
374+ FetchAndVerifyProperty (Display (),
375+ w,
376+ mDecorationInputFrameAtom,
377+ XA_WINDOW,
378+ 32,
379+ 1,
380+ 0L,
381+ inputFramePropertyData);
382+
383+ Window inputFrame = *(reinterpret_cast <Window *> (inputFramePropertyData.get ()));
384+
385+ /* Sync first, and then combine rectangles on the input frame */
386+ XSync (Display (), false);
387+ XShapeSelectInput (Display (), parent, ShapeNotifyMask);
388+ XShapeCombineRectangles (Display (),
389+ inputFrame,
390+ ShapeInput,
391+ 0,
392+ 0,
393+ NULL,
394+ 0,
395+ ShapeSet,
396+ 0);
397+
398+ clientX += ActiveBorderExtent;
399+ clientY += ActiveBorderExtent;
400+
401+ /* Wait for a shape event on the frame window */
402+ ct::ShapeNotifyXEventMatcher matcher (ShapeInput,
403+ clientX,
404+ clientY,
405+ clientWidth,
406+ clientHeight,
407+ 1);
408+ Advance (Display (),
409+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
410+ parent,
411+ shapeEvent + ShapeNotify,
412+ -1,
413+ 0,
414+ matcher));
415+
416+ /* Grab the shape rectangles of the parent, they should
417+ * be equal to the client window size */
418+ int n, order;
419+ boost::shared_array <XRectangle> rects (ShapeRectangles (Display (),
420+ parent,
421+ n,
422+ order));
423+
424+ ASSERT_THAT (n, Eq (1));
425+ EXPECT_THAT (rects[0],
426+ AllOf (Field (&XRectangle::x, Eq (clientX)),
427+ Field (&XRectangle::y, Eq (clientY)),
428+ Field (&XRectangle::width, Eq (clientWidth)),
429+ Field (&XRectangle::height, Eq (clientHeight))));
430+}
431+
432 /* TODO: Get bare decorations tests */
433
434 /* Helper class with some useful member functions */
435@@ -1745,12 +1942,7 @@
436 XMapRaised (display, window);
437
438 /* Wait for the window to be reparented */
439- Advance (Display (),
440- ct::WaitForEventOfTypeOnWindow (display,
441- window,
442- ReparentNotify,
443- -1,
444- -1));
445+ WaitForReparent (display, window);
446
447 /* Select for StructureNotify on the parent and wrapper
448 * windows */

Subscribers

People subscribed via source and target branches