Merge lp:~compiz-team/compiz/compiz.performance_1027211 into lp:compiz/0.9.9
- compiz.performance_1027211
- Merge into 0.9.9
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 |
Related bugs: |
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 sendConfigureNo
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-
Mutter seems to get it right. See bug 1027211 for details and my thoughts on that.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3511
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
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...
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:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
--
Sam Spilsbury
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:/
>> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>
>
>
> --
> Sam Spilsbury
--
Sam Spilsbury
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.
Daniel van Vugt (vanvugt) wrote : | # |
Well, maybe. Wait and see how well the proposals work together and individually.
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:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
--
Sam Spilsbury
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.
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.
Daniel van Vugt (vanvugt) wrote : | # |
OK, I've tracked down the main offenders that remain _after_ this fix.
1. XSync() inside PrivateWindow:
2. XShapeGetRectan
3. XShapeGetRectan
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) PrivateVertexBu
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. :(
Daniel van Vugt (vanvugt) : | # |
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.
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
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); |
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.