Merge lp:~compiz-team/compiz/compiz.performance_1027211 into lp:compiz/0.9.9

Proposed by Sam Spilsbury
Status: Merged
Approved by: Daniel van Vugt
Approved revision: 3511
Merged at revision: 3512
Proposed branch: lp:~compiz-team/compiz/compiz.performance_1027211
Merge into: lp:compiz/0.9.9
Diff against target: 716 lines (+380/-153)
5 files modified
src/window.cpp (+45/-57)
tests/system/xorg-gtest/include/compiz-xorg-gtest.h (+41/-0)
tests/system/xorg-gtest/src/compiz-xorg-gtest.cpp (+147/-10)
tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp (+131/-0)
tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp (+16/-86)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.performance_1027211
Reviewer Review Type Date Requested Status
Daniel van Vugt Approve
PS Jenkins bot (community) continuous-integration Approve
MC Return Approve
Review via email: mp+138255@code.launchpad.net

Commit message

Send cached geometry and "none" as the stack-sibling in synthetic configure notify effects.

We don't need to grab the server and query for the current geometry and stack position, upon reading section 4.1.5 of the ICCCM, it seems that clients don't need to know about the stack sibling in synthetic ConfigureNotify events (and other window managers don't do this either).

This really helps with performance, since we're not constantly blocking on the server to process our geometry updates.

(First commit of many, required to fix LP: #1027211)

Description of the change

Ditch the logic that queries the server for the current stack position and
attributes of the window on sendConfigureNotify.

It seems like that's not a part of the spec upon reading s4.1.5

I haven't marked this as "fixing" bug 1027211 because its very difficult to classify what "fixes" a performance bug (you can always do better). However, here are my test results (dragging around glxgears):

GPU: NVIDIA 8600GTM
Resolution: 3360x1050
NVIDIA Sync to VBlank: Off
Driver Version: 304.41

Startup command: compiz --replace composite opengl move resize decor bench

With this branch, and with the XSync commented out handling damage repair: ~40fps dragging fast
Just with this branch: ~30fps dragging fast
Without this branch: ~20fps dragging fast

So this branch gains us about 10fps in dragging performance.

We should look into whether or not that XSync in the damage repair is really necessary. If it isn't, we get another 10fps, and as far as I can tell, won't be repeatedly calling synchronous protocol functions at all when doing things like window dragging.

Added appropriate tests to confirm the behaviour of synthetic ConfigureNotify events, as usual.

I note that with NVIDIA's sync to vblank its still really slow, even if I force the usage of the old copy-back-to-front-buffers path, so I suspect there's a problem with the driver there.

Mutter seems to get it right. See bug 1027211 for details and my thoughts on that.

To post a comment you must log in.
Revision history for this message
MC Return (mc-return) wrote :

LGTM. Compiles and seems to work. Hard to tell the exact speedup here though, because I'm having some troubles using the same CCSM configuration I usually use with the freshly compiled Compiz running from ~/staging.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

It's an improvement but definitely not a fix for bug 1027211. The bug is still quite noticeable. And if you try resizing another window while glxgears is running then you still get a complete freeze.

I know Sam said he had more ideas to try and will propose them tomorrow...

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

On Thu, Dec 6, 2012 at 2:44 PM, Daniel van Vugt
<email address hidden> wrote:
> Review: Needs Fixing
>
> It's an improvement but definitely not a fix for bug 1027211. The bug is still quite noticeable. And if you try resizing another window while glxgears is running then you still get a complete freeze.
>

Its not a fix, no, but it is an incremental improvement.

I don't think it should be marked needs fixing for that reason.

> I know Sam said he had more ideas to try and will propose them tomorrow...
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.performance_1027211/+merge/138255
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

On Thu, Dec 6, 2012 at 2:46 PM, Sam Spilsbury <email address hidden> wrote:
> On Thu, Dec 6, 2012 at 2:44 PM, Daniel van Vugt
> <email address hidden> wrote:
>> Review: Needs Fixing
>>
>> It's an improvement but definitely not a fix for bug 1027211. The bug is still quite noticeable. And if you try resizing another window while glxgears is running then you still get a complete freeze.
>>
>
> Its not a fix, no, but it is an incremental improvement.

Also, we should have this anyways.

The way the code currently works doesn't make any sense in the broad
scheme of things and is just highly inefficient protocol requests for
reasons that no application would need to us.

The other fix I'm thinking of for slow opengl movement peformance is
quite separate to this, so it doesn't make sense to put them together.

>
> I don't think it should be marked needs fixing for that reason.
>
>> I know Sam said he had more ideas to try and will propose them tomorrow...
>> --
>> https://code.launchpad.net/~compiz-team/compiz/compiz.performance_1027211/+merge/138255
>> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>
>
>
> --
> Sam Spilsbury

--
Sam Spilsbury

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I'd rather have a single proposal that actually fixes the bug. It creates confusion for people looking at the history later if you have proposals linked to a bug that don't fix it.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Well, maybe. Wait and see how well the proposals work together and individually.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Shall I create a new bug and resubmit then ?

On Thu, Dec 6, 2012 at 3:00 PM, Daniel van Vugt
<email address hidden> wrote:
> I'd rather have a single proposal that actually fixes the bug. It creates confusion for people looking at the history later if you have proposals linked to a bug that don't fix it.
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.performance_1027211/+merge/138255
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Also, I'm only testing right now. I won't do any code review till there's a patch or set of patches that completely fixes the bug.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I just got around to analyzing some snapshots of the original hang. This proposal definitely fixes the primary problem. Weirdly though, after applying this fix the remaining hangs seem to be XSync calls from compiz_core too but gdb is not getting any symbol information to tell me which XSync is the primary offender now. I get function "??" at an address inside compiz_core.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

OK, I've tracked down the main offenders that remain _after_ this fix.

1. XSync() inside PrivateWindow::updateRegion()
2. XShapeGetRectangles() inside PrivateWindow::updateRegion()
3. XShapeGetRectangles() called from decor.

If you remove those from the equation then there is no longer a complete freeze. But it still stutters. Further analysis then shows compiz spending its time in one of:

(a) XSync in PixmapBinding::bind
(b) bindTexImageGLX
(c) PrivateVertexBuffer::render

I should add that reverting to the old asynchronous damage handling does not help at all with stutters/freezing. The main issues are those listed above.

I now agree that fixing bug 1027211 will be a long-term effort of many different proposals after this one. :(

Revision history for this message
Daniel van Vugt (vanvugt) :
review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Also, making Compiz work without XShape should be possible right? It seems quite broken if I force the extension disabled in core.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

OK, found and fixed the primary bug that happens when XShape is disabled: bug 1087193.
It's not the only one but probably the most severe issue.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/window.cpp'
2--- src/window.cpp 2012-12-05 09:38:59 +0000
3+++ src/window.cpp 2012-12-05 17:16:31 +0000
4@@ -1268,66 +1268,50 @@
5 CompWindow::sendConfigureNotify ()
6 {
7 XConfigureEvent xev;
8- XWindowAttributes attrib;
9- unsigned int nchildren;
10- Window rootRet, parentRet = 0;
11- Window *children;
12
13 xev.type = ConfigureNotify;
14 xev.event = priv->id;
15 xev.window = priv->id;
16
17- /* in order to avoid race conditions we must use the current
18- * server configuration */
19-
20- XGrabServer (screen->dpy ());
21- XSync (screen->dpy (), false);
22-
23- if (XGetWindowAttributes (screen->dpy (), priv->id, &attrib))
24- {
25- xev.x = attrib.x;
26- xev.y = attrib.y;
27- xev.width = attrib.width;
28- xev.height = attrib.height;
29- xev.border_width = attrib.border_width;
30- xev.above = None;
31-
32- /* Translate co-ordinates to root space */
33- XTranslateCoordinates (screen->dpy (), priv->id, screen->root (), 0, 0,
34- &xev.x, &xev.y, &parentRet);
35-
36- /* We need to ensure that the stacking order is
37- * based on the current server stacking order so
38- * find the sibling to this window's frame in the
39- * server side stack and stack above that */
40- XQueryTree (screen->dpy (), screen->root (), &rootRet, &parentRet, &children, &nchildren);
41-
42- if (nchildren)
43- {
44- for (unsigned int i = 0; i < nchildren; i++)
45- {
46- if (i + 1 == nchildren ||
47- children[i + 1] == ROOTPARENT (this))
48- {
49- xev.above = children[i];
50- break;
51- }
52- }
53- }
54-
55- if (children)
56- XFree (children);
57-
58- if (!xev.above)
59- xev.above = (serverPrev) ? ROOTPARENT (serverPrev) : None;
60- xev.override_redirect = priv->attrib.override_redirect;
61-
62- XSendEvent (screen->dpy (), priv->id, false,
63- StructureNotifyMask, (XEvent *) &xev);
64- }
65-
66- XUngrabServer (screen->dpy ());
67- XSync (screen->dpy (), false);
68+ xev.x = priv->serverGeometry.x ();
69+ xev.y = priv->serverGeometry.y ();
70+ xev.width = priv->serverGeometry.width ();
71+ xev.height = priv->serverGeometry.height ();
72+ xev.border_width = priv->serverGeometry.border ();
73+ xev.override_redirect = priv->attrib.override_redirect;
74+
75+ /* These used to be based on the actual sibling of the window
76+ * (eg, obtained using XQueryTree), but they are now zeroed out.
77+ *
78+ * The ICCCM is a big unclear on what these should be - it
79+ * requires that after the client attempts to configure a window
80+ * we should issue a synthetic ConfigureNotify to work around
81+ * the change of co-ordinates due to reparenting:
82+ *
83+ * "A client will receive a synthetic ConfigureNotify event
84+ * following the change that describes the new geometry of the window"
85+ *
86+ * However there is an acknowledgement on stacking order:
87+ *
88+ * "Not changing the size, location, border width,
89+ * or stacking order of the window at all."
90+ *
91+ * Since there isn't any advice as to what to set the above and
92+ * detail members, the only choices are to either grab the server
93+ * and query it for the sibling to the window's parent, or to just
94+ * set them to zero.
95+ *
96+ * An evaluation of other window managers showed that they just set
97+ * these fields to zero. This is probably a safe option and justifies
98+ * the potential performance tradeoff that we get out of not having
99+ * to grab the server, query window attributes and children and
100+ * translate co-ordinates every time a window is moved
101+ */
102+
103+ xev.above = None;
104+
105+ XSendEvent (screen->dpy (), priv->id, false,
106+ StructureNotifyMask, (XEvent *) &xev);
107 }
108
109 void
110@@ -3226,13 +3210,17 @@
111 xwc->x = 0;
112 xwc->y = 0;
113 }
114-
115- window->sendConfigureNotify ();
116 }
117
118 if (valueMask)
119 XConfigureWindow (screen->dpy (), id, valueMask, xwc);
120
121+ /* Send the synthetic configure notify
122+ * after the real configure notify arrives
123+ * (ICCCM s4.1.5) */
124+ if (serverFrame)
125+ window->sendConfigureNotify ();
126+
127 /* When updating plugins we care about
128 * the absolute position */
129 if (dx)
130
131=== modified file 'tests/system/xorg-gtest/include/compiz-xorg-gtest.h'
132--- tests/system/xorg-gtest/include/compiz-xorg-gtest.h 2012-12-05 05:32:45 +0000
133+++ tests/system/xorg-gtest/include/compiz-xorg-gtest.h 2012-12-05 17:16:31 +0000
134@@ -29,6 +29,7 @@
135 #include <xorg/gtest/xorg-gtest.h>
136
137 using ::testing::MatcherInterface;
138+using ::testing::MatchResultListener;
139
140 namespace compiz
141 {
142@@ -36,6 +37,46 @@
143 {
144 typedef ::testing::MatcherInterface <const XEvent &> XEventMatcher;
145
146+ class PrivatePropertyNotifyXEventMatcher;
147+ class PropertyNotifyXEventMatcher :
148+ public compiz::testing::XEventMatcher
149+ {
150+ public:
151+
152+ PropertyNotifyXEventMatcher (Display *dpy,
153+ const std::string &propertyName);
154+
155+ virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const;
156+ virtual void DescribeTo (std::ostream *os) const;
157+
158+ private:
159+
160+ std::auto_ptr <PrivatePropertyNotifyXEventMatcher> priv;
161+ };
162+
163+ class PrivateConfigureNotifyXEventMatcher;
164+ class ConfigureNotifyXEventMatcher :
165+ public compiz::testing::XEventMatcher
166+ {
167+ public:
168+
169+ ConfigureNotifyXEventMatcher (Window above,
170+ unsigned int border,
171+ int x,
172+ int y,
173+ unsigned int width,
174+ unsigned int height);
175+
176+ virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const;
177+ virtual void DescribeTo (std::ostream *os) const;
178+
179+ private:
180+
181+ std::auto_ptr <PrivateConfigureNotifyXEventMatcher> priv;
182+ };
183+
184+ Window CreateNormalWindow (Display *dpy);
185+
186 std::list <Window> NET_CLIENT_LIST_STACKING (Display *);
187 bool AdvanceToNextEventOnSuccess (Display *dpy,
188 bool waitResult);
189
190=== modified file 'tests/system/xorg-gtest/src/compiz-xorg-gtest.cpp'
191--- tests/system/xorg-gtest/src/compiz-xorg-gtest.cpp 2012-12-05 05:32:45 +0000
192+++ tests/system/xorg-gtest/src/compiz-xorg-gtest.cpp 2012-12-05 17:16:31 +0000
193@@ -22,6 +22,7 @@
194 */
195 #include <list>
196 #include <stdexcept>
197+#include <iomanip>
198 #include <gtest/gtest.h>
199 #include <gmock/gmock.h>
200 #include <boost/shared_ptr.hpp>
201@@ -38,13 +39,46 @@
202 namespace ct = compiz::testing;
203 namespace
204 {
205- void RemoveEventFromQueue (Display *dpy)
206- {
207- XEvent event;
208-
209- if (XNextEvent (dpy, &event) != Success)
210- throw std::runtime_error("Failed to remove X event");
211- }
212+const int WINDOW_X = 0;
213+const int WINDOW_Y = 0;
214+const unsigned int WINDOW_WIDTH = 640;
215+const unsigned int WINDOW_HEIGHT = 480;
216+const unsigned int WINDOW_BORDER = 0;
217+const unsigned int WINDOW_DEPTH = CopyFromParent;
218+const unsigned int WINDOW_CLASS = InputOutput;
219+Visual *WINDOW_VISUAL = CopyFromParent;
220+
221+
222+const long WINDOW_ATTRIB_VALUE_MASK = 0;
223+
224+void RemoveEventFromQueue (Display *dpy)
225+{
226+ XEvent event;
227+
228+ if (XNextEvent (dpy, &event) != Success)
229+ throw std::runtime_error("Failed to remove X event");
230+}
231+}
232+
233+Window
234+ct::CreateNormalWindow (Display *dpy)
235+{
236+ XSetWindowAttributes WINDOW_ATTRIB;
237+ Window w = XCreateWindow (dpy,
238+ DefaultRootWindow (dpy),
239+ WINDOW_X,
240+ WINDOW_Y,
241+ WINDOW_WIDTH,
242+ WINDOW_HEIGHT,
243+ WINDOW_BORDER,
244+ WINDOW_DEPTH,
245+ WINDOW_CLASS,
246+ WINDOW_VISUAL,
247+ WINDOW_ATTRIB_VALUE_MASK,
248+ &WINDOW_ATTRIB);
249+
250+ XSelectInput (dpy, w, StructureNotifyMask);
251+ return w;
252 }
253
254 bool
255@@ -140,8 +174,6 @@
256 return stackingOrder;
257 }
258
259-Display *d;
260-
261 namespace
262 {
263 class StartupClientMessageMatcher :
264@@ -188,6 +220,111 @@
265 };
266 }
267
268+class ct::PrivatePropertyNotifyXEventMatcher
269+{
270+ public:
271+
272+ PrivatePropertyNotifyXEventMatcher (Display *dpy,
273+ const std::string &propertyName) :
274+ mPropertyName (propertyName),
275+ mProperty (XInternAtom (dpy, propertyName.c_str (), false))
276+ {
277+ }
278+
279+ std::string mPropertyName;
280+ Atom mProperty;
281+};
282+
283+ct::PropertyNotifyXEventMatcher::PropertyNotifyXEventMatcher (Display *dpy,
284+ const std::string &propertyName) :
285+ priv (new ct::PrivatePropertyNotifyXEventMatcher (dpy, propertyName))
286+{
287+}
288+
289+bool
290+ct::PropertyNotifyXEventMatcher::MatchAndExplain (const XEvent &event, MatchResultListener *listener) const
291+{
292+ const XPropertyEvent *propertyEvent = reinterpret_cast <const XPropertyEvent *> (&event);
293+
294+ if (priv->mProperty == propertyEvent->atom)
295+ return true;
296+ else
297+ return false;
298+}
299+
300+void
301+ct::PropertyNotifyXEventMatcher::DescribeTo (std::ostream *os) const
302+{
303+ *os << "Is property identified by " << priv->mPropertyName;
304+}
305+
306+class ct::PrivateConfigureNotifyXEventMatcher
307+{
308+ public:
309+
310+ PrivateConfigureNotifyXEventMatcher (Window above,
311+ unsigned int border,
312+ int x,
313+ int y,
314+ unsigned int width,
315+ unsigned int height) :
316+ mAbove (above),
317+ mBorder (border),
318+ mX (x),
319+ mY (y),
320+ mWidth (width),
321+ mHeight (height)
322+ {
323+ }
324+
325+ Window mAbove;
326+ int mBorder;
327+ int mX;
328+ int mY;
329+ int mWidth;
330+ int mHeight;
331+};
332+
333+ct::ConfigureNotifyXEventMatcher::ConfigureNotifyXEventMatcher (Window above,
334+ unsigned int border,
335+ int x,
336+ int y,
337+ unsigned int width,
338+ unsigned int height) :
339+ priv (new ct::PrivateConfigureNotifyXEventMatcher (above,
340+ border,
341+ x,
342+ y,
343+ width,
344+ height))
345+{
346+}
347+
348+bool
349+ct::ConfigureNotifyXEventMatcher::MatchAndExplain (const XEvent &event, MatchResultListener *listener) const
350+{
351+ const XConfigureEvent *ce = reinterpret_cast <const XConfigureEvent *> (&event);
352+
353+ return ce->above == priv->mAbove &&
354+ ce->border_width == priv->mBorder &&
355+ ce->x == priv->mX &&
356+ ce->y == priv->mY &&
357+ ce->width == priv->mWidth &&
358+ ce->height == priv->mHeight;
359+}
360+
361+void
362+ct::ConfigureNotifyXEventMatcher::DescribeTo (std::ostream *os) const
363+{
364+ *os << "Matches ConfigureNotify with parameters : " << std::endl <<
365+ " x: " << priv->mX <<
366+ " y: " << priv->mY <<
367+ " width: " << priv->mWidth <<
368+ " height: " << priv->mHeight <<
369+ " border: " << priv->mBorder <<
370+ " above: " << std::hex << priv->mAbove << std::dec;
371+}
372+
373 class ct::PrivateCompizProcess
374 {
375 public:
376@@ -222,7 +359,6 @@
377
378 StartupClientMessageMatcher matcher (startup, root, flags);
379
380- d = dpy;
381 /* Save the current event mask and subscribe to StructureNotifyMask only */
382 ASSERT_TRUE (XGetWindowAttributes (dpy, root, &attrib));
383 XSelectInput (dpy, root, StructureNotifyMask |
384@@ -323,6 +459,7 @@
385 void
386 ct::AutostartCompizXorgSystemTest::SetUp ()
387 {
388+ ct::CompizXorgSystemTest::SetUp ();
389 StartCompiz (static_cast <ct::CompizProcess::StartupFlags> (
390 ct::CompizProcess::ReplaceCurrentWM |
391 ct::CompizProcess::WaitForStartupMessage));
392
393=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp'
394--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp 2012-12-05 03:35:37 +0000
395+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp 2012-12-05 17:16:31 +0000
396@@ -51,6 +51,11 @@
397 char TEST_FAILED_MSG = 's';
398 char PROCESS_EXITED_MSG = 'd';
399
400+bool Advance (Display *d, bool r)
401+{
402+ return ct::AdvanceToNextEventOnSuccess (d, r);
403+}
404+
405 }
406
407 class WaitForSuccessDeathTask :
408@@ -134,3 +139,129 @@
409 throw std::runtime_error ("compiz process did not exit with failure status");
410 }
411 }
412+
413+class AutostartCompizXorgSystemICCCM :
414+ public ct::CompizXorgSystemTest
415+{
416+ public:
417+
418+ virtual void SetUp ()
419+ {
420+ ct::CompizXorgSystemTest::SetUp ();
421+
422+ ::Display *dpy = Display ();
423+
424+ XSelectInput (dpy, DefaultRootWindow (dpy),
425+ StructureNotifyMask |
426+ SubstructureNotifyMask |
427+ FocusChangeMask |
428+ PropertyChangeMask);
429+
430+ StartCompiz (static_cast <ct::CompizProcess::StartupFlags> (
431+ ct::CompizProcess::ReplaceCurrentWM |
432+ ct::CompizProcess::WaitForStartupMessage));
433+ }
434+};
435+
436+TEST_F (AutostartCompizXorgSystemICCCM, ConfigureRequestSendsBackAppropriateConfigureNotify)
437+{
438+ ::Display *dpy = Display ();
439+ Window root = DefaultRootWindow (dpy);
440+
441+ Window w1 = ct::CreateNormalWindow (dpy);
442+ Window w2 = ct::CreateNormalWindow (dpy);
443+
444+ XMapRaised (dpy, w1);
445+ XMapRaised (dpy, w2);
446+
447+ ct::PropertyNotifyXEventMatcher propertyMatcher (dpy, "_NET_CLIENT_LIST_STACKING");
448+
449+ ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
450+ DefaultRootWindow (dpy),
451+ PropertyNotify,
452+ -1,
453+ -1,
454+ propertyMatcher)));
455+ ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
456+ DefaultRootWindow (dpy),
457+ PropertyNotify,
458+ -1,
459+ -1,
460+ propertyMatcher)));
461+
462+ /* Select for StructureNotify on w1 */
463+ XSelectInput (dpy, w1, StructureNotifyMask);
464+
465+ /* Send a ConfigureRequest to the server asking for
466+ * a particular geometry and stack position relative
467+ * to w2 */
468+
469+ XEvent event;
470+ XConfigureRequestEvent *configureRequestEvent = &event.xconfigurerequest;
471+
472+ event.type = ConfigureRequest;
473+
474+ const Window REQUEST_ABOVE = w2;
475+ const unsigned int REQUEST_BORDER_WIDTH = 0;
476+ const unsigned int REQUEST_X = 110;
477+ const unsigned int REQUEST_Y = 120;
478+ const unsigned int REQUEST_WIDTH = 200;
479+ const unsigned int REQUEST_HEIGHT = 200;
480+
481+ configureRequestEvent->window = w1;
482+
483+ configureRequestEvent->above = REQUEST_ABOVE;
484+ configureRequestEvent->detail = Above;
485+ configureRequestEvent->border_width = REQUEST_BORDER_WIDTH;
486+ configureRequestEvent->x = REQUEST_X;
487+ configureRequestEvent->y = REQUEST_Y;
488+ configureRequestEvent->width = REQUEST_WIDTH;
489+ configureRequestEvent->height = REQUEST_HEIGHT;
490+
491+ configureRequestEvent->value_mask = CWX |
492+ CWY |
493+ CWWidth |
494+ CWHeight |
495+ CWBorderWidth |
496+ CWSibling |
497+ CWStackMode;
498+
499+ XSendEvent (dpy,
500+ root,
501+ 0,
502+ SubstructureRedirectMask | SubstructureNotifyMask,
503+ &event);
504+
505+ XFlush (dpy);
506+
507+ /* Now wait for a ConfigureNotify to be sent back */
508+ ct::ConfigureNotifyXEventMatcher configureMatcher (0, // Always zero
509+ REQUEST_BORDER_WIDTH,
510+ REQUEST_X,
511+ REQUEST_Y,
512+ REQUEST_WIDTH,
513+ REQUEST_HEIGHT);
514+
515+ /* Should get a ConfigureNotify with the right parameters */
516+ EXPECT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
517+ w1,
518+ ConfigureNotify,
519+ -1,
520+ -1,
521+ configureMatcher)));
522+
523+ /* Check if the window is actually above */
524+ ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
525+ DefaultRootWindow (dpy),
526+ PropertyNotify,
527+ -1,
528+ -1,
529+ propertyMatcher)));
530+
531+ /* Check the client list to see that w1 > w2 */
532+ std::list <Window> clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
533+
534+ ASSERT_EQ (2, clientList.size ());
535+ EXPECT_EQ (w2, clientList.front ());
536+ EXPECT_EQ (w1, clientList.back ());
537+}
538
539=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp'
540--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2012-12-04 15:21:08 +0000
541+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2012-12-05 17:16:31 +0000
542@@ -44,7 +44,7 @@
543
544 virtual void SetUp ()
545 {
546- ct::CompizXorgSystemTest::SetUp ();
547+ ct::AutostartCompizXorgSystemTest::SetUp ();
548
549 ::Display *dpy = Display ();
550 XSelectInput (dpy, DefaultRootWindow (dpy), SubstructureNotifyMask | PropertyChangeMask);
551@@ -53,18 +53,6 @@
552
553 namespace
554 {
555- const int WINDOW_X = 0;
556- const int WINDOW_Y = 0;
557- const unsigned int WINDOW_WIDTH = 640;
558- const unsigned int WINDOW_HEIGHT = 480;
559- const unsigned int WINDOW_BORDER = 0;
560- const unsigned int WINDOW_DEPTH = CopyFromParent;
561- const unsigned int WINDOW_CLASS = InputOutput;
562- Visual *WINDOW_VISUAL = CopyFromParent;
563-
564-
565- const long WINDOW_ATTRIB_VALUE_MASK = 0;
566-
567 bool Advance (Display *dpy,
568 bool waitResult)
569 {
570@@ -86,26 +74,6 @@
571 1);
572 }
573
574- Window CreateNormalWindow (Display *dpy)
575- {
576- XSetWindowAttributes WINDOW_ATTRIB;
577- Window w = XCreateWindow (dpy,
578- DefaultRootWindow (dpy),
579- WINDOW_X,
580- WINDOW_Y,
581- WINDOW_WIDTH,
582- WINDOW_HEIGHT,
583- WINDOW_BORDER,
584- WINDOW_DEPTH,
585- WINDOW_CLASS,
586- WINDOW_VISUAL,
587- WINDOW_ATTRIB_VALUE_MASK,
588- &WINDOW_ATTRIB);
589-
590- XSelectInput (dpy, w, StructureNotifyMask);
591- return w;
592- }
593-
594 void SetUserTime (Display *dpy, Window w, Time time)
595 {
596 Atom _NET_WM_USER_TIME = XInternAtom (dpy, "_NET_WM_USER_TIME", false);
597@@ -126,44 +94,6 @@
598 XA_WINDOW, 32, PropModeReplace,
599 (unsigned char *) &leader, 1);
600 }
601-
602- class PropertyNotifyXEventMatcher :
603- public ct::XEventMatcher
604- {
605- public:
606-
607- PropertyNotifyXEventMatcher (Display *dpy,
608- const std::string &propertyName) :
609- mPropertyName (propertyName),
610- mProperty (XInternAtom (dpy, propertyName.c_str (), false))
611- {
612- }
613-
614- virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const
615- {
616- const XPropertyEvent *propertyEvent = reinterpret_cast <const XPropertyEvent *> (&event);
617-
618- if (mProperty == propertyEvent->atom)
619- return true;
620- else
621- return false;
622- }
623-
624- virtual void DescribeTo (std::ostream *os) const
625- {
626- *os << "Is property identified by " << mPropertyName;
627- }
628-
629- virtual void DescribeNegationTo (std::ostream *os) const
630- {
631- *os << "Is not a property identified by" << mPropertyName;
632- }
633-
634- private:
635-
636- std::string mPropertyName;
637- Atom mProperty;
638- };
639 }
640
641 TEST_F (CompizXorgSystemStackingTest, TestSetup)
642@@ -174,8 +104,8 @@
643 {
644 ::Display *dpy = Display ();
645
646- Window w1 = CreateNormalWindow (dpy);
647- Window w2 = CreateNormalWindow (dpy);
648+ Window w1 = ct::CreateNormalWindow (dpy);
649+ Window w2 = ct::CreateNormalWindow (dpy);
650
651 XMapRaised (dpy, w1);
652 XMapRaised (dpy, w2);
653@@ -186,7 +116,7 @@
654 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w2, ReparentNotify, -1, -1)));
655 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w2, MapNotify, -1, -1)));
656
657- PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
658+ ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
659
660 /* Wait for property change notify on the root window to happen twice */
661 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
662@@ -213,9 +143,9 @@
663 TEST_F (CompizXorgSystemStackingTest, TestCreateWindowsAndRestackRelativeToEachOtherDockAlwaysOnTop)
664 {
665 ::Display *dpy = Display ();
666- PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
667+ ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
668
669- Window dock = CreateNormalWindow (dpy);
670+ Window dock = ct::CreateNormalWindow (dpy);
671
672 /* Make it a dock */
673 MakeDock (dpy, dock);
674@@ -236,8 +166,8 @@
675 std::list <Window> clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
676 ASSERT_EQ (clientList.size (), 1);
677
678- Window w1 = CreateNormalWindow (dpy);
679- Window w2 = CreateNormalWindow (dpy);
680+ Window w1 = ct::CreateNormalWindow (dpy);
681+ Window w2 = ct::CreateNormalWindow (dpy);
682
683 XSelectInput (dpy, w2, StructureNotifyMask);
684
685@@ -278,11 +208,11 @@
686 TEST_F (CompizXorgSystemStackingTest, TestMapWindowWithOldUserTime)
687 {
688 ::Display *dpy = Display ();
689- PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
690+ ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
691
692- Window w1 = CreateNormalWindow (dpy);
693- Window w2 = CreateNormalWindow (dpy);
694- Window w3 = CreateNormalWindow (dpy);
695+ Window w1 = ct::CreateNormalWindow (dpy);
696+ Window w2 = ct::CreateNormalWindow (dpy);
697+ Window w3 = ct::CreateNormalWindow (dpy);
698
699 XMapRaised (dpy, w1);
700 XMapRaised (dpy, w2);
701@@ -322,11 +252,11 @@
702 TEST_F (CompizXorgSystemStackingTest, TestMapWindowAndDenyFocus)
703 {
704 ::Display *dpy = Display ();
705- PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
706+ ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
707
708- Window w1 = CreateNormalWindow (dpy);
709- Window w2 = CreateNormalWindow (dpy);
710- Window w3 = CreateNormalWindow (dpy);
711+ Window w1 = ct::CreateNormalWindow (dpy);
712+ Window w2 = ct::CreateNormalWindow (dpy);
713+ Window w3 = ct::CreateNormalWindow (dpy);
714
715 XMapRaised (dpy, w1);
716 XMapRaised (dpy, w2);

Subscribers

People subscribed via source and target branches