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
=== modified file 'src/window.cpp'
--- src/window.cpp 2012-12-05 09:38:59 +0000
+++ src/window.cpp 2012-12-05 17:16:31 +0000
@@ -1268,66 +1268,50 @@
1268CompWindow::sendConfigureNotify ()1268CompWindow::sendConfigureNotify ()
1269{1269{
1270 XConfigureEvent xev;1270 XConfigureEvent xev;
1271 XWindowAttributes attrib;
1272 unsigned int nchildren;
1273 Window rootRet, parentRet = 0;
1274 Window *children;
12751271
1276 xev.type = ConfigureNotify;1272 xev.type = ConfigureNotify;
1277 xev.event = priv->id;1273 xev.event = priv->id;
1278 xev.window = priv->id;1274 xev.window = priv->id;
12791275
1280 /* in order to avoid race conditions we must use the current1276 xev.x = priv->serverGeometry.x ();
1281 * server configuration */1277 xev.y = priv->serverGeometry.y ();
12821278 xev.width = priv->serverGeometry.width ();
1283 XGrabServer (screen->dpy ());1279 xev.height = priv->serverGeometry.height ();
1284 XSync (screen->dpy (), false);1280 xev.border_width = priv->serverGeometry.border ();
12851281 xev.override_redirect = priv->attrib.override_redirect;
1286 if (XGetWindowAttributes (screen->dpy (), priv->id, &attrib))1282
1287 {1283 /* These used to be based on the actual sibling of the window
1288 xev.x = attrib.x;1284 * (eg, obtained using XQueryTree), but they are now zeroed out.
1289 xev.y = attrib.y;1285 *
1290 xev.width = attrib.width;1286 * The ICCCM is a big unclear on what these should be - it
1291 xev.height = attrib.height;1287 * requires that after the client attempts to configure a window
1292 xev.border_width = attrib.border_width;1288 * we should issue a synthetic ConfigureNotify to work around
1293 xev.above = None;1289 * the change of co-ordinates due to reparenting:
12941290 *
1295 /* Translate co-ordinates to root space */1291 * "A client will receive a synthetic ConfigureNotify event
1296 XTranslateCoordinates (screen->dpy (), priv->id, screen->root (), 0, 0,1292 * following the change that describes the new geometry of the window"
1297 &xev.x, &xev.y, &parentRet);1293 *
12981294 * However there is an acknowledgement on stacking order:
1299 /* We need to ensure that the stacking order is1295 *
1300 * based on the current server stacking order so1296 * "Not changing the size, location, border width,
1301 * find the sibling to this window's frame in the1297 * or stacking order of the window at all."
1302 * server side stack and stack above that */1298 *
1303 XQueryTree (screen->dpy (), screen->root (), &rootRet, &parentRet, &children, &nchildren);1299 * Since there isn't any advice as to what to set the above and
13041300 * detail members, the only choices are to either grab the server
1305 if (nchildren)1301 * and query it for the sibling to the window's parent, or to just
1306 {1302 * set them to zero.
1307 for (unsigned int i = 0; i < nchildren; i++)1303 *
1308 {1304 * An evaluation of other window managers showed that they just set
1309 if (i + 1 == nchildren ||1305 * these fields to zero. This is probably a safe option and justifies
1310 children[i + 1] == ROOTPARENT (this))1306 * the potential performance tradeoff that we get out of not having
1311 {1307 * to grab the server, query window attributes and children and
1312 xev.above = children[i];1308 * translate co-ordinates every time a window is moved
1313 break;1309 */
1314 }1310
1315 }1311 xev.above = None;
1316 }1312
13171313 XSendEvent (screen->dpy (), priv->id, false,
1318 if (children)1314 StructureNotifyMask, (XEvent *) &xev);
1319 XFree (children);
1320
1321 if (!xev.above)
1322 xev.above = (serverPrev) ? ROOTPARENT (serverPrev) : None;
1323 xev.override_redirect = priv->attrib.override_redirect;
1324
1325 XSendEvent (screen->dpy (), priv->id, false,
1326 StructureNotifyMask, (XEvent *) &xev);
1327 }
1328
1329 XUngrabServer (screen->dpy ());
1330 XSync (screen->dpy (), false);
1331}1315}
13321316
1333void1317void
@@ -3226,13 +3210,17 @@
3226 xwc->x = 0;3210 xwc->x = 0;
3227 xwc->y = 0;3211 xwc->y = 0;
3228 }3212 }
3229
3230 window->sendConfigureNotify ();
3231 }3213 }
32323214
3233 if (valueMask)3215 if (valueMask)
3234 XConfigureWindow (screen->dpy (), id, valueMask, xwc);3216 XConfigureWindow (screen->dpy (), id, valueMask, xwc);
32353217
3218 /* Send the synthetic configure notify
3219 * after the real configure notify arrives
3220 * (ICCCM s4.1.5) */
3221 if (serverFrame)
3222 window->sendConfigureNotify ();
3223
3236 /* When updating plugins we care about3224 /* When updating plugins we care about
3237 * the absolute position */3225 * the absolute position */
3238 if (dx)3226 if (dx)
32393227
=== modified file 'tests/system/xorg-gtest/include/compiz-xorg-gtest.h'
--- tests/system/xorg-gtest/include/compiz-xorg-gtest.h 2012-12-05 05:32:45 +0000
+++ tests/system/xorg-gtest/include/compiz-xorg-gtest.h 2012-12-05 17:16:31 +0000
@@ -29,6 +29,7 @@
29#include <xorg/gtest/xorg-gtest.h>29#include <xorg/gtest/xorg-gtest.h>
3030
31using ::testing::MatcherInterface;31using ::testing::MatcherInterface;
32using ::testing::MatchResultListener;
3233
33namespace compiz34namespace compiz
34{35{
@@ -36,6 +37,46 @@
36 {37 {
37 typedef ::testing::MatcherInterface <const XEvent &> XEventMatcher;38 typedef ::testing::MatcherInterface <const XEvent &> XEventMatcher;
3839
40 class PrivatePropertyNotifyXEventMatcher;
41 class PropertyNotifyXEventMatcher :
42 public compiz::testing::XEventMatcher
43 {
44 public:
45
46 PropertyNotifyXEventMatcher (Display *dpy,
47 const std::string &propertyName);
48
49 virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const;
50 virtual void DescribeTo (std::ostream *os) const;
51
52 private:
53
54 std::auto_ptr <PrivatePropertyNotifyXEventMatcher> priv;
55 };
56
57 class PrivateConfigureNotifyXEventMatcher;
58 class ConfigureNotifyXEventMatcher :
59 public compiz::testing::XEventMatcher
60 {
61 public:
62
63 ConfigureNotifyXEventMatcher (Window above,
64 unsigned int border,
65 int x,
66 int y,
67 unsigned int width,
68 unsigned int height);
69
70 virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const;
71 virtual void DescribeTo (std::ostream *os) const;
72
73 private:
74
75 std::auto_ptr <PrivateConfigureNotifyXEventMatcher> priv;
76 };
77
78 Window CreateNormalWindow (Display *dpy);
79
39 std::list <Window> NET_CLIENT_LIST_STACKING (Display *);80 std::list <Window> NET_CLIENT_LIST_STACKING (Display *);
40 bool AdvanceToNextEventOnSuccess (Display *dpy,81 bool AdvanceToNextEventOnSuccess (Display *dpy,
41 bool waitResult);82 bool waitResult);
4283
=== modified file 'tests/system/xorg-gtest/src/compiz-xorg-gtest.cpp'
--- tests/system/xorg-gtest/src/compiz-xorg-gtest.cpp 2012-12-05 05:32:45 +0000
+++ tests/system/xorg-gtest/src/compiz-xorg-gtest.cpp 2012-12-05 17:16:31 +0000
@@ -22,6 +22,7 @@
22 */22 */
23#include <list>23#include <list>
24#include <stdexcept>24#include <stdexcept>
25#include <iomanip>
25#include <gtest/gtest.h>26#include <gtest/gtest.h>
26#include <gmock/gmock.h>27#include <gmock/gmock.h>
27#include <boost/shared_ptr.hpp>28#include <boost/shared_ptr.hpp>
@@ -38,13 +39,46 @@
38namespace ct = compiz::testing;39namespace ct = compiz::testing;
39namespace40namespace
40{41{
41 void RemoveEventFromQueue (Display *dpy)42const int WINDOW_X = 0;
42 {43const int WINDOW_Y = 0;
43 XEvent event;44const unsigned int WINDOW_WIDTH = 640;
4445const unsigned int WINDOW_HEIGHT = 480;
45 if (XNextEvent (dpy, &event) != Success)46const unsigned int WINDOW_BORDER = 0;
46 throw std::runtime_error("Failed to remove X event");47const unsigned int WINDOW_DEPTH = CopyFromParent;
47 }48const unsigned int WINDOW_CLASS = InputOutput;
49Visual *WINDOW_VISUAL = CopyFromParent;
50
51
52const long WINDOW_ATTRIB_VALUE_MASK = 0;
53
54void RemoveEventFromQueue (Display *dpy)
55{
56 XEvent event;
57
58 if (XNextEvent (dpy, &event) != Success)
59 throw std::runtime_error("Failed to remove X event");
60}
61}
62
63Window
64ct::CreateNormalWindow (Display *dpy)
65{
66 XSetWindowAttributes WINDOW_ATTRIB;
67 Window w = XCreateWindow (dpy,
68 DefaultRootWindow (dpy),
69 WINDOW_X,
70 WINDOW_Y,
71 WINDOW_WIDTH,
72 WINDOW_HEIGHT,
73 WINDOW_BORDER,
74 WINDOW_DEPTH,
75 WINDOW_CLASS,
76 WINDOW_VISUAL,
77 WINDOW_ATTRIB_VALUE_MASK,
78 &WINDOW_ATTRIB);
79
80 XSelectInput (dpy, w, StructureNotifyMask);
81 return w;
48}82}
4983
50bool84bool
@@ -140,8 +174,6 @@
140 return stackingOrder;174 return stackingOrder;
141}175}
142176
143Display *d;
144
145namespace177namespace
146{178{
147class StartupClientMessageMatcher :179class StartupClientMessageMatcher :
@@ -188,6 +220,111 @@
188};220};
189}221}
190222
223class ct::PrivatePropertyNotifyXEventMatcher
224{
225 public:
226
227 PrivatePropertyNotifyXEventMatcher (Display *dpy,
228 const std::string &propertyName) :
229 mPropertyName (propertyName),
230 mProperty (XInternAtom (dpy, propertyName.c_str (), false))
231 {
232 }
233
234 std::string mPropertyName;
235 Atom mProperty;
236};
237
238ct::PropertyNotifyXEventMatcher::PropertyNotifyXEventMatcher (Display *dpy,
239 const std::string &propertyName) :
240 priv (new ct::PrivatePropertyNotifyXEventMatcher (dpy, propertyName))
241{
242}
243
244bool
245ct::PropertyNotifyXEventMatcher::MatchAndExplain (const XEvent &event, MatchResultListener *listener) const
246{
247 const XPropertyEvent *propertyEvent = reinterpret_cast <const XPropertyEvent *> (&event);
248
249 if (priv->mProperty == propertyEvent->atom)
250 return true;
251 else
252 return false;
253}
254
255void
256ct::PropertyNotifyXEventMatcher::DescribeTo (std::ostream *os) const
257{
258 *os << "Is property identified by " << priv->mPropertyName;
259}
260
261class ct::PrivateConfigureNotifyXEventMatcher
262{
263 public:
264
265 PrivateConfigureNotifyXEventMatcher (Window above,
266 unsigned int border,
267 int x,
268 int y,
269 unsigned int width,
270 unsigned int height) :
271 mAbove (above),
272 mBorder (border),
273 mX (x),
274 mY (y),
275 mWidth (width),
276 mHeight (height)
277 {
278 }
279
280 Window mAbove;
281 int mBorder;
282 int mX;
283 int mY;
284 int mWidth;
285 int mHeight;
286};
287
288ct::ConfigureNotifyXEventMatcher::ConfigureNotifyXEventMatcher (Window above,
289 unsigned int border,
290 int x,
291 int y,
292 unsigned int width,
293 unsigned int height) :
294 priv (new ct::PrivateConfigureNotifyXEventMatcher (above,
295 border,
296 x,
297 y,
298 width,
299 height))
300{
301}
302
303bool
304ct::ConfigureNotifyXEventMatcher::MatchAndExplain (const XEvent &event, MatchResultListener *listener) const
305{
306 const XConfigureEvent *ce = reinterpret_cast <const XConfigureEvent *> (&event);
307
308 return ce->above == priv->mAbove &&
309 ce->border_width == priv->mBorder &&
310 ce->x == priv->mX &&
311 ce->y == priv->mY &&
312 ce->width == priv->mWidth &&
313 ce->height == priv->mHeight;
314}
315
316void
317ct::ConfigureNotifyXEventMatcher::DescribeTo (std::ostream *os) const
318{
319 *os << "Matches ConfigureNotify with parameters : " << std::endl <<
320 " x: " << priv->mX <<
321 " y: " << priv->mY <<
322 " width: " << priv->mWidth <<
323 " height: " << priv->mHeight <<
324 " border: " << priv->mBorder <<
325 " above: " << std::hex << priv->mAbove << std::dec;
326}
327
191class ct::PrivateCompizProcess328class ct::PrivateCompizProcess
192{329{
193 public:330 public:
@@ -222,7 +359,6 @@
222359
223 StartupClientMessageMatcher matcher (startup, root, flags);360 StartupClientMessageMatcher matcher (startup, root, flags);
224361
225 d = dpy;
226 /* Save the current event mask and subscribe to StructureNotifyMask only */362 /* Save the current event mask and subscribe to StructureNotifyMask only */
227 ASSERT_TRUE (XGetWindowAttributes (dpy, root, &attrib));363 ASSERT_TRUE (XGetWindowAttributes (dpy, root, &attrib));
228 XSelectInput (dpy, root, StructureNotifyMask |364 XSelectInput (dpy, root, StructureNotifyMask |
@@ -323,6 +459,7 @@
323void459void
324ct::AutostartCompizXorgSystemTest::SetUp ()460ct::AutostartCompizXorgSystemTest::SetUp ()
325{461{
462 ct::CompizXorgSystemTest::SetUp ();
326 StartCompiz (static_cast <ct::CompizProcess::StartupFlags> (463 StartCompiz (static_cast <ct::CompizProcess::StartupFlags> (
327 ct::CompizProcess::ReplaceCurrentWM |464 ct::CompizProcess::ReplaceCurrentWM |
328 ct::CompizProcess::WaitForStartupMessage));465 ct::CompizProcess::WaitForStartupMessage));
329466
=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp'
--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp 2012-12-05 03:35:37 +0000
+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp 2012-12-05 17:16:31 +0000
@@ -51,6 +51,11 @@
51char TEST_FAILED_MSG = 's';51char TEST_FAILED_MSG = 's';
52char PROCESS_EXITED_MSG = 'd';52char PROCESS_EXITED_MSG = 'd';
5353
54bool Advance (Display *d, bool r)
55{
56 return ct::AdvanceToNextEventOnSuccess (d, r);
57}
58
54}59}
5560
56class WaitForSuccessDeathTask :61class WaitForSuccessDeathTask :
@@ -134,3 +139,129 @@
134 throw std::runtime_error ("compiz process did not exit with failure status");139 throw std::runtime_error ("compiz process did not exit with failure status");
135 }140 }
136}141}
142
143class AutostartCompizXorgSystemICCCM :
144 public ct::CompizXorgSystemTest
145{
146 public:
147
148 virtual void SetUp ()
149 {
150 ct::CompizXorgSystemTest::SetUp ();
151
152 ::Display *dpy = Display ();
153
154 XSelectInput (dpy, DefaultRootWindow (dpy),
155 StructureNotifyMask |
156 SubstructureNotifyMask |
157 FocusChangeMask |
158 PropertyChangeMask);
159
160 StartCompiz (static_cast <ct::CompizProcess::StartupFlags> (
161 ct::CompizProcess::ReplaceCurrentWM |
162 ct::CompizProcess::WaitForStartupMessage));
163 }
164};
165
166TEST_F (AutostartCompizXorgSystemICCCM, ConfigureRequestSendsBackAppropriateConfigureNotify)
167{
168 ::Display *dpy = Display ();
169 Window root = DefaultRootWindow (dpy);
170
171 Window w1 = ct::CreateNormalWindow (dpy);
172 Window w2 = ct::CreateNormalWindow (dpy);
173
174 XMapRaised (dpy, w1);
175 XMapRaised (dpy, w2);
176
177 ct::PropertyNotifyXEventMatcher propertyMatcher (dpy, "_NET_CLIENT_LIST_STACKING");
178
179 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
180 DefaultRootWindow (dpy),
181 PropertyNotify,
182 -1,
183 -1,
184 propertyMatcher)));
185 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
186 DefaultRootWindow (dpy),
187 PropertyNotify,
188 -1,
189 -1,
190 propertyMatcher)));
191
192 /* Select for StructureNotify on w1 */
193 XSelectInput (dpy, w1, StructureNotifyMask);
194
195 /* Send a ConfigureRequest to the server asking for
196 * a particular geometry and stack position relative
197 * to w2 */
198
199 XEvent event;
200 XConfigureRequestEvent *configureRequestEvent = &event.xconfigurerequest;
201
202 event.type = ConfigureRequest;
203
204 const Window REQUEST_ABOVE = w2;
205 const unsigned int REQUEST_BORDER_WIDTH = 0;
206 const unsigned int REQUEST_X = 110;
207 const unsigned int REQUEST_Y = 120;
208 const unsigned int REQUEST_WIDTH = 200;
209 const unsigned int REQUEST_HEIGHT = 200;
210
211 configureRequestEvent->window = w1;
212
213 configureRequestEvent->above = REQUEST_ABOVE;
214 configureRequestEvent->detail = Above;
215 configureRequestEvent->border_width = REQUEST_BORDER_WIDTH;
216 configureRequestEvent->x = REQUEST_X;
217 configureRequestEvent->y = REQUEST_Y;
218 configureRequestEvent->width = REQUEST_WIDTH;
219 configureRequestEvent->height = REQUEST_HEIGHT;
220
221 configureRequestEvent->value_mask = CWX |
222 CWY |
223 CWWidth |
224 CWHeight |
225 CWBorderWidth |
226 CWSibling |
227 CWStackMode;
228
229 XSendEvent (dpy,
230 root,
231 0,
232 SubstructureRedirectMask | SubstructureNotifyMask,
233 &event);
234
235 XFlush (dpy);
236
237 /* Now wait for a ConfigureNotify to be sent back */
238 ct::ConfigureNotifyXEventMatcher configureMatcher (0, // Always zero
239 REQUEST_BORDER_WIDTH,
240 REQUEST_X,
241 REQUEST_Y,
242 REQUEST_WIDTH,
243 REQUEST_HEIGHT);
244
245 /* Should get a ConfigureNotify with the right parameters */
246 EXPECT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
247 w1,
248 ConfigureNotify,
249 -1,
250 -1,
251 configureMatcher)));
252
253 /* Check if the window is actually above */
254 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
255 DefaultRootWindow (dpy),
256 PropertyNotify,
257 -1,
258 -1,
259 propertyMatcher)));
260
261 /* Check the client list to see that w1 > w2 */
262 std::list <Window> clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
263
264 ASSERT_EQ (2, clientList.size ());
265 EXPECT_EQ (w2, clientList.front ());
266 EXPECT_EQ (w1, clientList.back ());
267}
137268
=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp'
--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2012-12-04 15:21:08 +0000
+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2012-12-05 17:16:31 +0000
@@ -44,7 +44,7 @@
4444
45 virtual void SetUp ()45 virtual void SetUp ()
46 {46 {
47 ct::CompizXorgSystemTest::SetUp ();47 ct::AutostartCompizXorgSystemTest::SetUp ();
4848
49 ::Display *dpy = Display ();49 ::Display *dpy = Display ();
50 XSelectInput (dpy, DefaultRootWindow (dpy), SubstructureNotifyMask | PropertyChangeMask);50 XSelectInput (dpy, DefaultRootWindow (dpy), SubstructureNotifyMask | PropertyChangeMask);
@@ -53,18 +53,6 @@
5353
54namespace54namespace
55{55{
56 const int WINDOW_X = 0;
57 const int WINDOW_Y = 0;
58 const unsigned int WINDOW_WIDTH = 640;
59 const unsigned int WINDOW_HEIGHT = 480;
60 const unsigned int WINDOW_BORDER = 0;
61 const unsigned int WINDOW_DEPTH = CopyFromParent;
62 const unsigned int WINDOW_CLASS = InputOutput;
63 Visual *WINDOW_VISUAL = CopyFromParent;
64
65
66 const long WINDOW_ATTRIB_VALUE_MASK = 0;
67
68 bool Advance (Display *dpy,56 bool Advance (Display *dpy,
69 bool waitResult)57 bool waitResult)
70 {58 {
@@ -86,26 +74,6 @@
86 1);74 1);
87 }75 }
8876
89 Window CreateNormalWindow (Display *dpy)
90 {
91 XSetWindowAttributes WINDOW_ATTRIB;
92 Window w = XCreateWindow (dpy,
93 DefaultRootWindow (dpy),
94 WINDOW_X,
95 WINDOW_Y,
96 WINDOW_WIDTH,
97 WINDOW_HEIGHT,
98 WINDOW_BORDER,
99 WINDOW_DEPTH,
100 WINDOW_CLASS,
101 WINDOW_VISUAL,
102 WINDOW_ATTRIB_VALUE_MASK,
103 &WINDOW_ATTRIB);
104
105 XSelectInput (dpy, w, StructureNotifyMask);
106 return w;
107 }
108
109 void SetUserTime (Display *dpy, Window w, Time time)77 void SetUserTime (Display *dpy, Window w, Time time)
110 {78 {
111 Atom _NET_WM_USER_TIME = XInternAtom (dpy, "_NET_WM_USER_TIME", false);79 Atom _NET_WM_USER_TIME = XInternAtom (dpy, "_NET_WM_USER_TIME", false);
@@ -126,44 +94,6 @@
126 XA_WINDOW, 32, PropModeReplace,94 XA_WINDOW, 32, PropModeReplace,
127 (unsigned char *) &leader, 1);95 (unsigned char *) &leader, 1);
128 }96 }
129
130 class PropertyNotifyXEventMatcher :
131 public ct::XEventMatcher
132 {
133 public:
134
135 PropertyNotifyXEventMatcher (Display *dpy,
136 const std::string &propertyName) :
137 mPropertyName (propertyName),
138 mProperty (XInternAtom (dpy, propertyName.c_str (), false))
139 {
140 }
141
142 virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const
143 {
144 const XPropertyEvent *propertyEvent = reinterpret_cast <const XPropertyEvent *> (&event);
145
146 if (mProperty == propertyEvent->atom)
147 return true;
148 else
149 return false;
150 }
151
152 virtual void DescribeTo (std::ostream *os) const
153 {
154 *os << "Is property identified by " << mPropertyName;
155 }
156
157 virtual void DescribeNegationTo (std::ostream *os) const
158 {
159 *os << "Is not a property identified by" << mPropertyName;
160 }
161
162 private:
163
164 std::string mPropertyName;
165 Atom mProperty;
166 };
167}97}
16898
169TEST_F (CompizXorgSystemStackingTest, TestSetup)99TEST_F (CompizXorgSystemStackingTest, TestSetup)
@@ -174,8 +104,8 @@
174{104{
175 ::Display *dpy = Display ();105 ::Display *dpy = Display ();
176106
177 Window w1 = CreateNormalWindow (dpy);107 Window w1 = ct::CreateNormalWindow (dpy);
178 Window w2 = CreateNormalWindow (dpy);108 Window w2 = ct::CreateNormalWindow (dpy);
179109
180 XMapRaised (dpy, w1);110 XMapRaised (dpy, w1);
181 XMapRaised (dpy, w2);111 XMapRaised (dpy, w2);
@@ -186,7 +116,7 @@
186 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w2, ReparentNotify, -1, -1)));116 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w2, ReparentNotify, -1, -1)));
187 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w2, MapNotify, -1, -1)));117 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w2, MapNotify, -1, -1)));
188118
189 PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");119 ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
190120
191 /* Wait for property change notify on the root window to happen twice */121 /* Wait for property change notify on the root window to happen twice */
192 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,122 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
@@ -213,9 +143,9 @@
213TEST_F (CompizXorgSystemStackingTest, TestCreateWindowsAndRestackRelativeToEachOtherDockAlwaysOnTop)143TEST_F (CompizXorgSystemStackingTest, TestCreateWindowsAndRestackRelativeToEachOtherDockAlwaysOnTop)
214{144{
215 ::Display *dpy = Display ();145 ::Display *dpy = Display ();
216 PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");146 ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
217147
218 Window dock = CreateNormalWindow (dpy);148 Window dock = ct::CreateNormalWindow (dpy);
219149
220 /* Make it a dock */150 /* Make it a dock */
221 MakeDock (dpy, dock);151 MakeDock (dpy, dock);
@@ -236,8 +166,8 @@
236 std::list <Window> clientList = ct::NET_CLIENT_LIST_STACKING (dpy);166 std::list <Window> clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
237 ASSERT_EQ (clientList.size (), 1);167 ASSERT_EQ (clientList.size (), 1);
238168
239 Window w1 = CreateNormalWindow (dpy);169 Window w1 = ct::CreateNormalWindow (dpy);
240 Window w2 = CreateNormalWindow (dpy);170 Window w2 = ct::CreateNormalWindow (dpy);
241171
242 XSelectInput (dpy, w2, StructureNotifyMask);172 XSelectInput (dpy, w2, StructureNotifyMask);
243173
@@ -278,11 +208,11 @@
278TEST_F (CompizXorgSystemStackingTest, TestMapWindowWithOldUserTime)208TEST_F (CompizXorgSystemStackingTest, TestMapWindowWithOldUserTime)
279{209{
280 ::Display *dpy = Display ();210 ::Display *dpy = Display ();
281 PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");211 ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
282212
283 Window w1 = CreateNormalWindow (dpy);213 Window w1 = ct::CreateNormalWindow (dpy);
284 Window w2 = CreateNormalWindow (dpy);214 Window w2 = ct::CreateNormalWindow (dpy);
285 Window w3 = CreateNormalWindow (dpy);215 Window w3 = ct::CreateNormalWindow (dpy);
286216
287 XMapRaised (dpy, w1);217 XMapRaised (dpy, w1);
288 XMapRaised (dpy, w2);218 XMapRaised (dpy, w2);
@@ -322,11 +252,11 @@
322TEST_F (CompizXorgSystemStackingTest, TestMapWindowAndDenyFocus)252TEST_F (CompizXorgSystemStackingTest, TestMapWindowAndDenyFocus)
323{253{
324 ::Display *dpy = Display ();254 ::Display *dpy = Display ();
325 PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");255 ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
326256
327 Window w1 = CreateNormalWindow (dpy);257 Window w1 = ct::CreateNormalWindow (dpy);
328 Window w2 = CreateNormalWindow (dpy);258 Window w2 = ct::CreateNormalWindow (dpy);
329 Window w3 = CreateNormalWindow (dpy);259 Window w3 = ct::CreateNormalWindow (dpy);
330260
331 XMapRaised (dpy, w1);261 XMapRaised (dpy, w1);
332 XMapRaised (dpy, w2);262 XMapRaised (dpy, w2);

Subscribers

People subscribed via source and target branches