Merge lp:~compiz-team/compiz/compiz.fix_1171314 into lp:compiz/0.9.10

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1171314
Merge into: lp:compiz/0.9.10
Diff against target: 771 lines (+542/-71)
10 files modified
src/privatewindow.h (+1/-0)
src/window.cpp (+40/-54)
tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp (+1/-15)
tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp (+403/-0)
tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp (+5/-1)
tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h (+2/-0)
tests/xorg-gtest/include/compiz-xorg-gtest.h (+2/-0)
tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp (+61/-1)
tests/xorg-gtest/plugins/testhelper/src/testhelper.h (+6/-0)
tests/xorg-gtest/src/compiz-xorg-gtest.cpp (+21/-0)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1171314
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Compiz Maintainers Pending
Review via email: mp+171504@code.launchpad.net

This proposal has been superseded by a proposal from 2013-06-26.

Commit message

Don't add the frame to the toplevel stack if it hasn't been created yet.

In the event that a window is unreparented or destroyed, we usually need
to add its frame window to the toplevel window stack until the time at
which we recieve a DestroyNotify for it, as there may be incoming
ConfigureNotify events puporting to stack other windows relative to
that frame.

However, this does not apply in the case where we have not yet received
a CreateNotify for the frame window. In that case, it is not possible
for any stacking requests to be made relative to this window, so it
does not need to be added immediately. Instead, we can add it at the
time that we recieve a CreateNotify for it as a regular override
redirect window until the time that it is later destroyed.

(LP: #1171314)

Description of the change

Don't add the frame to the toplevel stack if it hasn't been created yet.

In the event that a window is unreparented or destroyed, we usually need
to add its frame window to the toplevel window stack until the time at
which we recieve a DestroyNotify for it, as there may be incoming
ConfigureNotify events puporting to stack other windows relative to
that frame.

However, this does not apply in the case where we have not yet received
a CreateNotify for the frame window. In that case, it is not possible
for any stacking requests to be made relative to this window, so it
does not need to be added immediately. Instead, we can add it at the
time that we recieve a CreateNotify for it as a regular override
redirect window until the time that it is later destroyed.

(LP: #1171314)

To post a comment you must log in.
3748. By Sam Spilsbury

Remove timeout

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/privatewindow.h'
2--- src/privatewindow.h 2013-03-06 12:31:24 +0000
3+++ src/privatewindow.h 2013-06-26 11:06:25 +0000
4@@ -252,6 +252,7 @@
5
6 bool reparent ();
7 void unreparent ();
8+ void manageFrameWindowSeparately ();
9
10 void hide ();
11
12
13=== modified file 'src/window.cpp'
14--- src/window.cpp 2013-05-27 16:19:59 +0000
15+++ src/window.cpp 2013-06-26 11:06:25 +0000
16@@ -1189,33 +1189,7 @@
17 CompWindow *oldNext = next;
18 CompWindow *oldPrev = prev;
19
20- /* This is where things get tricky ... it is possible
21- * to receive a ConfigureNotify relative to a frame window
22- * for a destroyed window in case we process a ConfigureRequest
23- * for the destroyed window and then a DestroyNotify for it directly
24- * afterwards. In that case, we will receive the ConfigureNotify
25- * for the XConfigureWindow request we made relative to that frame
26- * window. Because of this, we must keep the frame window in the stack
27- * as a new toplevel window so that the ConfigureNotify will be processed
28- * properly until it too receives a DestroyNotify */
29-
30- if (priv->serverFrame)
31- {
32- XWindowAttributes attrib;
33-
34- /* It's possible that the frame window was already destroyed because
35- * the client was unreparented before it was destroyed (eg
36- * UnmapNotify before DestroyNotify). In that case the frame window
37- * is going to be an invalid window but since we haven't received
38- * a DestroyNotify for it yet, it is possible that restacking
39- * operations could occurr relative to it so we need to hold it
40- * in the stack for now. Ensure that it is marked override redirect */
41- XGetWindowAttributes (screen->dpy (), priv->serverFrame, &attrib);
42-
43- /* Put the frame window "above" the client window
44- * in the stack */
45- PrivateWindow::createCompWindow (priv->id, priv->id, attrib, priv->serverFrame);
46- }
47+ priv->manageFrameWindowSeparately ();
48
49 /* Immediately unhook the window once destroyed
50 * as the stacking order will be invalid if we don't
51@@ -6867,6 +6841,44 @@
52 }
53
54 void
55+PrivateWindow::manageFrameWindowSeparately ()
56+{
57+ /* This is where things get tricky ... it is possible
58+ * to receive a ConfigureNotify relative to a frame window
59+ * for a destroyed window in case we process a ConfigureRequest
60+ * for the destroyed window and then a DestroyNotify for it directly
61+ * afterwards. In that case, we will receive the ConfigureNotify
62+ * for the XConfigureWindow request we made relative to that frame
63+ * window. Because of this, we must keep the frame window in the stack
64+ * as a new toplevel window so that the ConfigureNotify will be processed
65+ * properly until it too receives a DestroyNotify
66+ *
67+ * We only wish to do this if we have recieved a CreateNotify for the
68+ * frame window. If we have not, then there will be no stacking operations
69+ * dependent on it and we should wait until CreateNotify in order to manage
70+ * it normally */
71+
72+ if (frame)
73+ {
74+ XWindowAttributes attrib;
75+
76+ /* It's possible that the frame window was already destroyed because
77+ * the client was unreparented before it was destroyed (eg
78+ * UnmapNotify before DestroyNotify). In that case the frame window
79+ * is going to be an invalid window but since we haven't received
80+ * a DestroyNotify for it yet, it is possible that restacking
81+ * operations could occurr relative to it so we need to hold it
82+ * in the stack for now. Ensure that it is marked override redirect */
83+ window->priv->queryFrameAttributes (attrib);
84+
85+ /* Put the frame window "above" the client window
86+ * in the stack */
87+ PrivateWindow::createCompWindow (id, id, attrib, frame);
88+ }
89+
90+}
91+
92+void
93 PrivateWindow::unreparent ()
94 {
95 if (!serverFrame)
96@@ -6961,33 +6973,7 @@
97 if (dbg)
98 dbg->addDestroyedFrame (serverFrame);
99
100- /* This is where things get tricky ... it is possible
101- * to receive a ConfigureNotify relative to a frame window
102- * for a destroyed window in case we process a ConfigureRequest
103- * for the destroyed window and then a DestroyNotify for it directly
104- * afterwards. In that case, we will receive the ConfigureNotify
105- * for the XConfigureWindow request we made relative to that frame
106- * window. Because of this, we must keep the frame window in the stack
107- * as a new toplevel window so that the ConfigureNotify will be processed
108- * properly until it too receives a DestroyNotify */
109-
110- if (serverFrame)
111- {
112- XWindowAttributes attrib;
113-
114- /* It's possible that the frame window was already destroyed because
115- * the client was unreparented before it was destroyed (eg
116- * UnmapNotify before DestroyNotify). In that case the frame window
117- * is going to be an invalid window but since we haven't received
118- * a DestroyNotify for it yet, it is possible that restacking
119- * operations could occurr relative to it so we need to hold it
120- * in the stack for now. Ensure that it is marked override redirect */
121- window->priv->queryFrameAttributes (attrib);
122-
123- /* Put the frame window "above" the client window
124- * in the stack */
125- PrivateWindow::createCompWindow (id, id, attrib, serverFrame);
126- }
127+ manageFrameWindowSeparately ();
128
129 /* Issue a DestroyNotify */
130 XDestroyWindow (screen->dpy (), serverFrame);
131
132=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp'
133--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp 2013-06-22 12:27:36 +0000
134+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp 2013-06-26 11:06:25 +0000
135@@ -59,21 +59,7 @@
136 Window GetTopParent (Display *display,
137 Window w)
138 {
139- Window rootReturn = 0;
140- Window parentReturn = w;
141- Window lastParent = 0;
142-
143- do
144- {
145- lastParent = parentReturn;
146-
147- parentReturn = ct::GetImmediateParent (display,
148- lastParent,
149- rootReturn);
150-
151- } while (parentReturn != rootReturn);
152-
153- return lastParent;
154+ return ct::GetTopmostNonRootParent (display, w);
155 }
156
157 bool QueryGeometry (Display *dpy,
158
159=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp'
160--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2013-02-26 11:56:10 +0000
161+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2013-06-26 11:06:25 +0000
162@@ -25,8 +25,13 @@
163 #include <stdexcept>
164 #include <gtest/gtest.h>
165 #include <gmock/gmock.h>
166+
167+#include <boost/shared_array.hpp>
168+#include <boost/bind.hpp>
169+
170 #include <xorg/gtest/xorg-gtest.h>
171 #include <compiz-xorg-gtest.h>
172+#include <compiz_xorg_gtest_communicator.h>
173
174 #include <X11/Xlib.h>
175 #include <X11/Xatom.h>
176@@ -36,6 +41,7 @@
177 using ::testing::Matcher;
178
179 namespace ct = compiz::testing;
180+namespace ctm = compiz::testing::messages;
181
182 class CompizXorgSystemStackingTest :
183 public ct::AutostartCompizXorgSystemTest
184@@ -429,3 +435,400 @@
185 EXPECT_EQ (dock, (*it++));
186 EXPECT_EQ (w1, (*it++));
187 }
188+
189+class StackingSync :
190+ public ct::AutostartCompizXorgSystemTestWithTestHelper
191+{
192+ public:
193+
194+ void SetUp ();
195+};
196+
197+void
198+StackingSync::SetUp ()
199+{
200+ ct::AutostartCompizXorgSystemTestWithTestHelper::SetUp ();
201+
202+ XSelectInput (Display (), DefaultRootWindow (Display ()), StructureNotifyMask |
203+ SubstructureNotifyMask);
204+}
205+
206+namespace
207+{
208+ Window CreateAndWaitForCreation (Display *dpy)
209+ {
210+ Window w = ct::CreateNormalWindow (dpy);
211+ Advance (dpy,
212+ ct::WaitForEventOfTypeOnWindow (dpy,
213+ DefaultRootWindow (dpy),
214+ CreateNotify,
215+ -1,
216+ -1));
217+ return w;
218+ }
219+
220+ Window CreateOverrideRedirectWindow (Display *dpy)
221+ {
222+ XSetWindowAttributes attrib;
223+
224+ attrib.override_redirect = true;
225+
226+ Window w =
227+ XCreateWindow (dpy, DefaultRootWindow (dpy),
228+ ct::WINDOW_X,
229+ ct::WINDOW_Y,
230+ ct::WINDOW_WIDTH,
231+ ct::WINDOW_HEIGHT,
232+ 0,
233+ DefaultDepth (dpy, 0),
234+ InputOutput,
235+ DefaultVisual (dpy, DefaultScreen (dpy)),
236+ CWOverrideRedirect,
237+ &attrib);
238+
239+ XSelectInput (dpy, w, StructureNotifyMask);
240+ return w;
241+ }
242+
243+ Window MapAndWaitForParent (Display *dpy, Window w)
244+ {
245+ XMapRaised (dpy, w);
246+
247+ Advance (dpy,
248+ ct::WaitForEventOfTypeOnWindow (dpy,
249+ w,
250+ ReparentNotify,
251+ -1,
252+ -1));
253+
254+ return ct::GetTopmostNonRootParent (dpy, w);
255+ }
256+
257+ void DestroyOnReparent (Display *dpy,
258+ ct::MessageAtoms &atoms,
259+ Window w)
260+ {
261+ Window root = DefaultRootWindow (dpy);
262+ Atom atom =
263+ atoms.FetchForString (ctm::TEST_HELPER_DESTROY_ON_REPARENT);
264+
265+ std::vector <long> data (4);
266+
267+ ct::SendClientMessage (dpy, atom, root, w, data);
268+ }
269+
270+ Window WaitForNextCreatedWindow (Display *dpy)
271+ {
272+ XEvent ev;
273+ while (true)
274+ {
275+ XNextEvent (dpy, &ev);
276+ if (ev.type == CreateNotify)
277+ return ev.xcreatewindow.window;
278+ }
279+
280+ return 0;
281+ }
282+
283+ void WaitForManage (Display *dpy,
284+ ct::MessageAtoms &atoms)
285+ {
286+ Atom atom =
287+ atoms.FetchForString (ctm::TEST_HELPER_WINDOW_READY);
288+ XEvent ev;
289+
290+ ct::ReceiveMessage (dpy, atom, ev);
291+ }
292+
293+ void RestackAbove (Display *dpy,
294+ Window w,
295+ Window above)
296+ {
297+ XWindowChanges xwc;
298+
299+ xwc.stack_mode = Above;
300+ xwc.sibling = above;
301+
302+ XConfigureWindow (dpy, w, CWStackMode | CWSibling, &xwc);
303+ }
304+
305+ void RestackAtLeastAbove (Display *dpy,
306+ ct::MessageAtoms &atoms,
307+ Window w,
308+ Window above)
309+ {
310+ Window root = DefaultRootWindow (dpy);
311+ Atom atom =
312+ atoms.FetchForString (ctm::TEST_HELPER_RESTACK_ATLEAST_ABOVE);
313+
314+ std::vector <long> data (4);
315+
316+ data[0] = above;
317+ ct::SendClientMessage (dpy, atom, root, w, data);
318+ }
319+
320+ void FreeWindowArray (Window *array)
321+ {
322+ XFree (array);
323+ }
324+
325+ typedef boost::shared_array <Window> WindowArray;
326+
327+ WindowArray GetChildren (Display *dpy,
328+ Window w,
329+ unsigned int &n)
330+ {
331+ Window unused;
332+ Window *children;
333+
334+ if (!XQueryTree (dpy, w, &unused, &unused, &children, &n))
335+ throw std::logic_error ("XQueryTree failed");
336+
337+ return WindowArray (children, boost::bind (FreeWindowArray, _1));
338+ }
339+
340+ class StackPositionMatcher :
341+ public MatcherInterface <Window>
342+ {
343+ public:
344+
345+ StackPositionMatcher (const WindowArray &array,
346+ Window cmp,
347+ unsigned int n);
348+
349+ protected:
350+
351+ bool MatchAndExplain (Window window,
352+ MatchResultListener *listener) const;
353+ void DescribeTo (std::ostream *os) const;
354+
355+ private:
356+
357+ virtual bool Compare (int lhsPos,
358+ int rhsPos) const = 0;
359+ virtual void ExplainCompare (std::ostream *os) const = 0;
360+
361+ WindowArray array;
362+ unsigned int arrayNum;
363+ Window cmp;
364+
365+ };
366+
367+ StackPositionMatcher::StackPositionMatcher (const WindowArray &array,
368+ Window cmp,
369+ unsigned int n) :
370+ array (array),
371+ arrayNum (n),
372+ cmp (cmp)
373+ {
374+ }
375+
376+ bool
377+ StackPositionMatcher::MatchAndExplain (Window window,
378+ MatchResultListener *listener) const
379+ {
380+ int lhsPos = -1, rhsPos = -1;
381+
382+ for (unsigned int i = 0; i < arrayNum; ++i)
383+ {
384+ if (array[i] == window)
385+ lhsPos = i;
386+ if (array[i] == cmp)
387+ rhsPos = i;
388+ }
389+
390+ if (lhsPos > -1 &&
391+ rhsPos > -1)
392+ {
393+ if (Compare (lhsPos, rhsPos))
394+ return true;
395+ }
396+
397+ /* Match failed, add stack to MatchResultListener */
398+ if (listener->IsInterested ())
399+ {
400+ std::stringstream windowStack;
401+
402+ windowStack << "Window Stack (bottom to top ["
403+ << arrayNum
404+ << "]): \n";
405+ *listener << windowStack.str ();
406+ for (unsigned int i = 0; i < arrayNum; ++i)
407+ {
408+ std::stringstream ss;
409+ ss << " - 0x"
410+ << std::hex
411+ << array[i]
412+ << std::dec
413+ << std::endl;
414+ *listener << ss.str ();
415+ }
416+
417+ std::stringstream lhsPosMsg, rhsPosMsg;
418+
419+ lhsPosMsg << "Position of 0x"
420+ << std::hex
421+ << window
422+ << std::dec
423+ << " : "
424+ << lhsPos;
425+
426+ rhsPosMsg << "Position of 0x"
427+ << std::hex
428+ << cmp
429+ << std::dec
430+ << " : "
431+ << rhsPos;
432+
433+ *listener << lhsPosMsg.str () << "\n";
434+ *listener << rhsPosMsg.str () << "\n";
435+ }
436+
437+ return false;
438+ }
439+
440+ void
441+ StackPositionMatcher::DescribeTo (std::ostream *os) const
442+ {
443+ *os << "Window is ";
444+ ExplainCompare (os);
445+ *os << " in relation to 0x" << std::hex << cmp << std::dec;
446+ }
447+
448+ class GreaterThanInStackMatcher :
449+ public StackPositionMatcher
450+ {
451+ public:
452+
453+ GreaterThanInStackMatcher (const WindowArray &array,
454+ Window cmp,
455+ unsigned int n);
456+
457+ private:
458+
459+ bool Compare (int lhsPos, int rhsPos) const;
460+ void ExplainCompare (std::ostream *os) const;
461+ };
462+
463+ GreaterThanInStackMatcher::GreaterThanInStackMatcher (const WindowArray &array,
464+ Window cmp,
465+ unsigned int n) :
466+ StackPositionMatcher (array, cmp, n)
467+ {
468+ }
469+
470+ bool GreaterThanInStackMatcher::Compare (int lhsPos, int rhsPos) const
471+ {
472+ return lhsPos > rhsPos;
473+ }
474+
475+ void GreaterThanInStackMatcher::ExplainCompare (std::ostream *os) const
476+ {
477+ *os << "greater than";
478+ }
479+
480+ class LessThanInStackMatcher :
481+ public StackPositionMatcher
482+ {
483+ public:
484+
485+ LessThanInStackMatcher (const WindowArray &array,
486+ Window cmp,
487+ unsigned int n);
488+
489+ private:
490+
491+ bool Compare (int lhsPos, int rhsPos) const;
492+ void ExplainCompare (std::ostream *os) const;
493+ };
494+
495+ LessThanInStackMatcher::LessThanInStackMatcher (const WindowArray &array,
496+ Window cmp,
497+ unsigned int n) :
498+ StackPositionMatcher (array, cmp, n)
499+ {
500+ }
501+
502+ bool LessThanInStackMatcher::Compare (int lhsPos, int rhsPos) const
503+ {
504+ return lhsPos < rhsPos;
505+ }
506+
507+ void LessThanInStackMatcher::ExplainCompare (std::ostream *os) const
508+ {
509+ *os << "less than";
510+ }
511+
512+ inline Matcher <Window> GreaterThanInStack (const WindowArray &array,
513+ unsigned int n,
514+ Window cmp)
515+ {
516+ return MakeMatcher (new GreaterThanInStackMatcher (array, cmp, n));
517+ }
518+
519+ inline Matcher <Window> LessThanInStack (const WindowArray &array,
520+ unsigned int n,
521+ Window cmp)
522+ {
523+ return MakeMatcher (new LessThanInStackMatcher (array, cmp, n));
524+ }
525+}
526+
527+TEST_F (StackingSync, DestroyClientJustBeforeReparent)
528+{
529+ ::Display *dpy = Display ();
530+
531+ ct::MessageAtoms atoms (dpy);
532+
533+ /* Set up three normal windows */
534+ Window w1 = CreateAndWaitForCreation (dpy);
535+ Window w2 = CreateAndWaitForCreation (dpy);
536+ Window w3 = CreateAndWaitForCreation (dpy);
537+
538+ Window p1 = MapAndWaitForParent (dpy, w1);
539+ Window p2 = MapAndWaitForParent (dpy, w2);
540+ Window p3 = MapAndWaitForParent (dpy, w3);
541+
542+ /* Create another normal window, but immediately mark
543+ * it destroyed within compiz as soon as it is reparented,
544+ * so that we force the reparented-but-destroyed strategy
545+ * to kick in */
546+ Window destroyed = CreateAndWaitForCreation (dpy);
547+
548+ DestroyOnReparent (dpy, atoms, destroyed);
549+ XMapRaised (dpy, destroyed);
550+
551+ /* Wait for the destroyed window's parent to be created
552+ * in the toplevel stack as a result of the reparent operation */
553+ Window parentOfDestroyed = WaitForNextCreatedWindow (dpy);
554+ WaitForManage (dpy, atoms);
555+
556+ /* Create an override redirect window and wait for it to be
557+ * managed */
558+ Window override = CreateOverrideRedirectWindow (dpy);
559+ WaitForManage (dpy, atoms);
560+
561+ /* Place the destroyed window's parent above
562+ * p1 in the stack directly */
563+ RestackAbove (dpy, parentOfDestroyed, p1);
564+
565+ /* Ask compiz to place the override redirect window
566+ * at least above the destroyed window's parent
567+ * in the stack. This requires compiz to locate the
568+ * destroyed window's parent in the stack */
569+ RestackAtLeastAbove (dpy, atoms, override, parentOfDestroyed);
570+
571+ /* Wait for the override window to be configured */
572+ Advance (dpy,
573+ ct::WaitForEventOfTypeOnWindow (dpy,
574+ override,
575+ ConfigureNotify,
576+ -1,
577+ -1));
578+
579+ unsigned int n;
580+ WindowArray windows (GetChildren (dpy, DefaultRootWindow (dpy), n));
581+
582+ EXPECT_THAT (p2, LessThanInStack (windows, n, override));
583+ EXPECT_THAT (p3, GreaterThanInStack (windows, n, override));
584+}
585
586=== modified file 'tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp'
587--- tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp 2013-02-23 07:08:20 +0000
588+++ tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp 2013-06-26 11:06:25 +0000
589@@ -50,6 +50,8 @@
590 "_COMPIZ_TEST_HELPER_FRAME_EXTENTS_CHANGED",
591 "_COMPIZ_TEST_HELPER_CONFIGURE_WINDOW",
592 "_COMPIZ_TEST_HELPER_WINDOW_CONFIGURE_PROCESSED",
593+ "_COMPIZ_TEST_HELPER_DESTROY_ON_REPARENT",
594+ "_COMPIZ_TEST_HELPER_RESTACK_ATLEAST_ABOVE",
595 "_COMPIZ_TEST_HELPER_WINDOW_READY"
596 };
597 }
598@@ -61,7 +63,9 @@
599 const char *TEST_HELPER_FRAME_EXTENTS_CHANGED = internal::messages[4];
600 const char *TEST_HELPER_CONFIGURE_WINDOW = internal::messages[5];
601 const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED = internal::messages[6];
602-const char *TEST_HELPER_WINDOW_READY = internal::messages[7];
603+const char *TEST_HELPER_DESTROY_ON_REPARENT = internal::messages[7];
604+const char *TEST_HELPER_RESTACK_ATLEAST_ABOVE = internal::messages[8];
605+const char *TEST_HELPER_WINDOW_READY = internal::messages[9];
606 }
607 }
608 }
609
610=== modified file 'tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h'
611--- tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h 2013-02-23 07:08:20 +0000
612+++ tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h 2013-06-26 11:06:25 +0000
613@@ -41,6 +41,8 @@
614 extern const char *TEST_HELPER_FRAME_EXTENTS_CHANGED;
615 extern const char *TEST_HELPER_CONFIGURE_WINDOW;
616 extern const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED;
617+extern const char *TEST_HELPER_DESTROY_ON_REPARENT;
618+extern const char *TEST_HELPER_RESTACK_ATLEAST_ABOVE;
619 extern const char *TEST_HELPER_WINDOW_READY;
620 }
621
622
623=== modified file 'tests/xorg-gtest/include/compiz-xorg-gtest.h'
624--- tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-06-22 12:27:36 +0000
625+++ tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-06-26 11:06:25 +0000
626@@ -125,6 +125,8 @@
627 Window GetImmediateParent (Display *display,
628 Window w,
629 Window &rootReturn);
630+ Window GetTopmostNonRootParent (Display *display,
631+ Window w);
632
633 std::list <Window> NET_CLIENT_LIST_STACKING (Display *);
634 bool AdvanceToNextEventOnSuccess (Display *dpy,
635
636=== modified file 'tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp'
637--- tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 2013-05-09 13:43:07 +0000
638+++ tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 2013-06-26 11:06:25 +0000
639@@ -181,10 +181,66 @@
640 }
641 }
642
643+void
644+TestHelperWindow::setDestroyOnReparent (long *)
645+{
646+ destroyOnReparent = true;
647+}
648+
649+void
650+TestHelperWindow::restackAtLeastAbove (long *data)
651+{
652+ ServerLock lock (screen->serverGrabInterface ());
653+
654+ Window above = data[0];
655+ XWindowAttributes attrib;
656+
657+ if (!XGetWindowAttributes (screen->dpy (), above, &attrib))
658+ return;
659+
660+ CompWindow *w = screen->findTopLevelWindow (above, true);
661+ for (; w; w = w->next)
662+ if (!w->overrideRedirect ())
663+ break;
664+
665+ if (!w)
666+ return;
667+
668+ XWindowChanges xwc;
669+
670+ xwc.stack_mode = Above;
671+ xwc.sibling = w->frame () ? w->frame () : w->id ();
672+
673+ window->restackAndConfigureXWindow (CWStackMode | CWSibling,
674+ &xwc,
675+ lock);
676+}
677+
678+void
679+TestHelperWindow::windowNotify (CompWindowNotify n)
680+{
681+ switch (n)
682+ {
683+ case CompWindowNotifyReparent:
684+ if (destroyOnReparent)
685+ {
686+ Window id = window->id ();
687+ window->destroy ();
688+ XDestroyWindow (screen->dpy (), id);
689+ }
690+ break;
691+ default:
692+ break;
693+ }
694+
695+ window->windowNotify (n);
696+}
697+
698 TestHelperWindow::TestHelperWindow (CompWindow *w) :
699 PluginClassHandler <TestHelperWindow, CompWindow> (w),
700 window (w),
701- configureLock ()
702+ configureLock (),
703+ destroyOnReparent (false)
704 {
705 WindowInterface::setHandler (w);
706
707@@ -214,6 +270,10 @@
708 &TestHelperWindow::setFrameExtentsAndReport);
709 watchForMessage (fetchAtom (ctm::TEST_HELPER_LOCK_CONFIGURE_REQUESTS),
710 &TestHelperWindow::setConfigureLock);
711+ watchForMessage (fetchAtom (ctm::TEST_HELPER_DESTROY_ON_REPARENT),
712+ &TestHelperWindow::setDestroyOnReparent);
713+ watchForMessage (fetchAtom (ctm::TEST_HELPER_RESTACK_ATLEAST_ABOVE),
714+ &TestHelperWindow::restackAtLeastAbove);
715
716 ct::SendClientMessage (s->dpy (),
717 mAtomStore.FetchForString (ctm::TEST_HELPER_READY_MSG),
718
719=== modified file 'tests/xorg-gtest/plugins/testhelper/src/testhelper.h'
720--- tests/xorg-gtest/plugins/testhelper/src/testhelper.h 2013-02-14 12:12:53 +0000
721+++ tests/xorg-gtest/plugins/testhelper/src/testhelper.h 2013-06-26 11:06:25 +0000
722@@ -77,11 +77,17 @@
723 void configureAndReport (long *);
724 void setFrameExtentsAndReport (long *);
725 void setConfigureLock (long *);
726+ void setDestroyOnReparent (long *);
727+ void restackAtLeastAbove (long *);
728
729 private:
730
731+ void windowNotify (CompWindowNotify n);
732+
733 CompWindow *window;
734 compiz::window::configure_buffers::Releasable::Ptr configureLock;
735+
736+ bool destroyOnReparent;
737 };
738
739 class TestHelperPluginVTable :
740
741=== modified file 'tests/xorg-gtest/src/compiz-xorg-gtest.cpp'
742--- tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-06-22 12:27:36 +0000
743+++ tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-06-26 11:06:25 +0000
744@@ -105,6 +105,27 @@
745 return parentReturn;
746 }
747
748+Window
749+ct::GetTopmostNonRootParent (Display *display,
750+ Window w)
751+{
752+ Window rootReturn = 0;
753+ Window parentReturn = w;
754+ Window lastParent = 0;
755+
756+ do
757+ {
758+ lastParent = parentReturn;
759+
760+ parentReturn = GetImmediateParent (display,
761+ lastParent,
762+ rootReturn);
763+
764+ } while (parentReturn != rootReturn);
765+
766+ return lastParent;
767+}
768+
769 bool
770 ct::AdvanceToNextEventOnSuccess (Display *dpy,
771 bool waitResult)

Subscribers

People subscribed via source and target branches

to all changes: