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

Proposed by Sam Spilsbury
Status: Merged
Approved by: Sam Spilsbury
Approved revision: 3748
Merged at revision: 3763
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 Approve
MC Return Approve
Review via email: mp+171669@code.launchpad.net

This proposal supersedes 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.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote :

LGTM, AFAICT. +1
I have not tested it though...

review: Approve
Revision history for this message
MC Return (mc-return) wrote :

Can anyone help with testing this ?

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/privatewindow.h'
--- src/privatewindow.h 2013-03-06 12:31:24 +0000
+++ src/privatewindow.h 2013-06-26 21:25:34 +0000
@@ -252,6 +252,7 @@
252252
253 bool reparent ();253 bool reparent ();
254 void unreparent ();254 void unreparent ();
255 void manageFrameWindowSeparately ();
255256
256 void hide ();257 void hide ();
257258
258259
=== modified file 'src/window.cpp'
--- src/window.cpp 2013-05-27 16:19:59 +0000
+++ src/window.cpp 2013-06-26 21:25:34 +0000
@@ -1189,33 +1189,7 @@
1189 CompWindow *oldNext = next;1189 CompWindow *oldNext = next;
1190 CompWindow *oldPrev = prev;1190 CompWindow *oldPrev = prev;
11911191
1192 /* This is where things get tricky ... it is possible1192 priv->manageFrameWindowSeparately ();
1193 * to receive a ConfigureNotify relative to a frame window
1194 * for a destroyed window in case we process a ConfigureRequest
1195 * for the destroyed window and then a DestroyNotify for it directly
1196 * afterwards. In that case, we will receive the ConfigureNotify
1197 * for the XConfigureWindow request we made relative to that frame
1198 * window. Because of this, we must keep the frame window in the stack
1199 * as a new toplevel window so that the ConfigureNotify will be processed
1200 * properly until it too receives a DestroyNotify */
1201
1202 if (priv->serverFrame)
1203 {
1204 XWindowAttributes attrib;
1205
1206 /* It's possible that the frame window was already destroyed because
1207 * the client was unreparented before it was destroyed (eg
1208 * UnmapNotify before DestroyNotify). In that case the frame window
1209 * is going to be an invalid window but since we haven't received
1210 * a DestroyNotify for it yet, it is possible that restacking
1211 * operations could occurr relative to it so we need to hold it
1212 * in the stack for now. Ensure that it is marked override redirect */
1213 XGetWindowAttributes (screen->dpy (), priv->serverFrame, &attrib);
1214
1215 /* Put the frame window "above" the client window
1216 * in the stack */
1217 PrivateWindow::createCompWindow (priv->id, priv->id, attrib, priv->serverFrame);
1218 }
12191193
1220 /* Immediately unhook the window once destroyed1194 /* Immediately unhook the window once destroyed
1221 * as the stacking order will be invalid if we don't1195 * as the stacking order will be invalid if we don't
@@ -6867,6 +6841,44 @@
6867}6841}
68686842
6869void6843void
6844PrivateWindow::manageFrameWindowSeparately ()
6845{
6846 /* This is where things get tricky ... it is possible
6847 * to receive a ConfigureNotify relative to a frame window
6848 * for a destroyed window in case we process a ConfigureRequest
6849 * for the destroyed window and then a DestroyNotify for it directly
6850 * afterwards. In that case, we will receive the ConfigureNotify
6851 * for the XConfigureWindow request we made relative to that frame
6852 * window. Because of this, we must keep the frame window in the stack
6853 * as a new toplevel window so that the ConfigureNotify will be processed
6854 * properly until it too receives a DestroyNotify
6855 *
6856 * We only wish to do this if we have recieved a CreateNotify for the
6857 * frame window. If we have not, then there will be no stacking operations
6858 * dependent on it and we should wait until CreateNotify in order to manage
6859 * it normally */
6860
6861 if (frame)
6862 {
6863 XWindowAttributes attrib;
6864
6865 /* It's possible that the frame window was already destroyed because
6866 * the client was unreparented before it was destroyed (eg
6867 * UnmapNotify before DestroyNotify). In that case the frame window
6868 * is going to be an invalid window but since we haven't received
6869 * a DestroyNotify for it yet, it is possible that restacking
6870 * operations could occurr relative to it so we need to hold it
6871 * in the stack for now. Ensure that it is marked override redirect */
6872 window->priv->queryFrameAttributes (attrib);
6873
6874 /* Put the frame window "above" the client window
6875 * in the stack */
6876 PrivateWindow::createCompWindow (id, id, attrib, frame);
6877 }
6878
6879}
6880
6881void
6870PrivateWindow::unreparent ()6882PrivateWindow::unreparent ()
6871{6883{
6872 if (!serverFrame)6884 if (!serverFrame)
@@ -6961,33 +6973,7 @@
6961 if (dbg)6973 if (dbg)
6962 dbg->addDestroyedFrame (serverFrame);6974 dbg->addDestroyedFrame (serverFrame);
69636975
6964 /* This is where things get tricky ... it is possible6976 manageFrameWindowSeparately ();
6965 * to receive a ConfigureNotify relative to a frame window
6966 * for a destroyed window in case we process a ConfigureRequest
6967 * for the destroyed window and then a DestroyNotify for it directly
6968 * afterwards. In that case, we will receive the ConfigureNotify
6969 * for the XConfigureWindow request we made relative to that frame
6970 * window. Because of this, we must keep the frame window in the stack
6971 * as a new toplevel window so that the ConfigureNotify will be processed
6972 * properly until it too receives a DestroyNotify */
6973
6974 if (serverFrame)
6975 {
6976 XWindowAttributes attrib;
6977
6978 /* It's possible that the frame window was already destroyed because
6979 * the client was unreparented before it was destroyed (eg
6980 * UnmapNotify before DestroyNotify). In that case the frame window
6981 * is going to be an invalid window but since we haven't received
6982 * a DestroyNotify for it yet, it is possible that restacking
6983 * operations could occurr relative to it so we need to hold it
6984 * in the stack for now. Ensure that it is marked override redirect */
6985 window->priv->queryFrameAttributes (attrib);
6986
6987 /* Put the frame window "above" the client window
6988 * in the stack */
6989 PrivateWindow::createCompWindow (id, id, attrib, serverFrame);
6990 }
69916977
6992 /* Issue a DestroyNotify */6978 /* Issue a DestroyNotify */
6993 XDestroyWindow (screen->dpy (), serverFrame);6979 XDestroyWindow (screen->dpy (), serverFrame);
69946980
=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp'
--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp 2013-06-22 12:27:36 +0000
+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp 2013-06-26 21:25:34 +0000
@@ -59,21 +59,7 @@
59Window GetTopParent (Display *display,59Window GetTopParent (Display *display,
60 Window w)60 Window w)
61{61{
62 Window rootReturn = 0;62 return ct::GetTopmostNonRootParent (display, w);
63 Window parentReturn = w;
64 Window lastParent = 0;
65
66 do
67 {
68 lastParent = parentReturn;
69
70 parentReturn = ct::GetImmediateParent (display,
71 lastParent,
72 rootReturn);
73
74 } while (parentReturn != rootReturn);
75
76 return lastParent;
77}63}
7864
79bool QueryGeometry (Display *dpy,65bool QueryGeometry (Display *dpy,
8066
=== 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 2013-02-26 11:56:10 +0000
+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2013-06-26 21:25:34 +0000
@@ -25,8 +25,13 @@
25#include <stdexcept>25#include <stdexcept>
26#include <gtest/gtest.h>26#include <gtest/gtest.h>
27#include <gmock/gmock.h>27#include <gmock/gmock.h>
28
29#include <boost/shared_array.hpp>
30#include <boost/bind.hpp>
31
28#include <xorg/gtest/xorg-gtest.h>32#include <xorg/gtest/xorg-gtest.h>
29#include <compiz-xorg-gtest.h>33#include <compiz-xorg-gtest.h>
34#include <compiz_xorg_gtest_communicator.h>
3035
31#include <X11/Xlib.h>36#include <X11/Xlib.h>
32#include <X11/Xatom.h>37#include <X11/Xatom.h>
@@ -36,6 +41,7 @@
36using ::testing::Matcher;41using ::testing::Matcher;
3742
38namespace ct = compiz::testing;43namespace ct = compiz::testing;
44namespace ctm = compiz::testing::messages;
3945
40class CompizXorgSystemStackingTest :46class CompizXorgSystemStackingTest :
41 public ct::AutostartCompizXorgSystemTest47 public ct::AutostartCompizXorgSystemTest
@@ -429,3 +435,400 @@
429 EXPECT_EQ (dock, (*it++));435 EXPECT_EQ (dock, (*it++));
430 EXPECT_EQ (w1, (*it++));436 EXPECT_EQ (w1, (*it++));
431}437}
438
439class StackingSync :
440 public ct::AutostartCompizXorgSystemTestWithTestHelper
441{
442 public:
443
444 void SetUp ();
445};
446
447void
448StackingSync::SetUp ()
449{
450 ct::AutostartCompizXorgSystemTestWithTestHelper::SetUp ();
451
452 XSelectInput (Display (), DefaultRootWindow (Display ()), StructureNotifyMask |
453 SubstructureNotifyMask);
454}
455
456namespace
457{
458 Window CreateAndWaitForCreation (Display *dpy)
459 {
460 Window w = ct::CreateNormalWindow (dpy);
461 Advance (dpy,
462 ct::WaitForEventOfTypeOnWindow (dpy,
463 DefaultRootWindow (dpy),
464 CreateNotify,
465 -1,
466 -1));
467 return w;
468 }
469
470 Window CreateOverrideRedirectWindow (Display *dpy)
471 {
472 XSetWindowAttributes attrib;
473
474 attrib.override_redirect = true;
475
476 Window w =
477 XCreateWindow (dpy, DefaultRootWindow (dpy),
478 ct::WINDOW_X,
479 ct::WINDOW_Y,
480 ct::WINDOW_WIDTH,
481 ct::WINDOW_HEIGHT,
482 0,
483 DefaultDepth (dpy, 0),
484 InputOutput,
485 DefaultVisual (dpy, DefaultScreen (dpy)),
486 CWOverrideRedirect,
487 &attrib);
488
489 XSelectInput (dpy, w, StructureNotifyMask);
490 return w;
491 }
492
493 Window MapAndWaitForParent (Display *dpy, Window w)
494 {
495 XMapRaised (dpy, w);
496
497 Advance (dpy,
498 ct::WaitForEventOfTypeOnWindow (dpy,
499 w,
500 ReparentNotify,
501 -1,
502 -1));
503
504 return ct::GetTopmostNonRootParent (dpy, w);
505 }
506
507 void DestroyOnReparent (Display *dpy,
508 ct::MessageAtoms &atoms,
509 Window w)
510 {
511 Window root = DefaultRootWindow (dpy);
512 Atom atom =
513 atoms.FetchForString (ctm::TEST_HELPER_DESTROY_ON_REPARENT);
514
515 std::vector <long> data (4);
516
517 ct::SendClientMessage (dpy, atom, root, w, data);
518 }
519
520 Window WaitForNextCreatedWindow (Display *dpy)
521 {
522 XEvent ev;
523 while (true)
524 {
525 XNextEvent (dpy, &ev);
526 if (ev.type == CreateNotify)
527 return ev.xcreatewindow.window;
528 }
529
530 return 0;
531 }
532
533 void WaitForManage (Display *dpy,
534 ct::MessageAtoms &atoms)
535 {
536 Atom atom =
537 atoms.FetchForString (ctm::TEST_HELPER_WINDOW_READY);
538 XEvent ev;
539
540 ct::ReceiveMessage (dpy, atom, ev);
541 }
542
543 void RestackAbove (Display *dpy,
544 Window w,
545 Window above)
546 {
547 XWindowChanges xwc;
548
549 xwc.stack_mode = Above;
550 xwc.sibling = above;
551
552 XConfigureWindow (dpy, w, CWStackMode | CWSibling, &xwc);
553 }
554
555 void RestackAtLeastAbove (Display *dpy,
556 ct::MessageAtoms &atoms,
557 Window w,
558 Window above)
559 {
560 Window root = DefaultRootWindow (dpy);
561 Atom atom =
562 atoms.FetchForString (ctm::TEST_HELPER_RESTACK_ATLEAST_ABOVE);
563
564 std::vector <long> data (4);
565
566 data[0] = above;
567 ct::SendClientMessage (dpy, atom, root, w, data);
568 }
569
570 void FreeWindowArray (Window *array)
571 {
572 XFree (array);
573 }
574
575 typedef boost::shared_array <Window> WindowArray;
576
577 WindowArray GetChildren (Display *dpy,
578 Window w,
579 unsigned int &n)
580 {
581 Window unused;
582 Window *children;
583
584 if (!XQueryTree (dpy, w, &unused, &unused, &children, &n))
585 throw std::logic_error ("XQueryTree failed");
586
587 return WindowArray (children, boost::bind (FreeWindowArray, _1));
588 }
589
590 class StackPositionMatcher :
591 public MatcherInterface <Window>
592 {
593 public:
594
595 StackPositionMatcher (const WindowArray &array,
596 Window cmp,
597 unsigned int n);
598
599 protected:
600
601 bool MatchAndExplain (Window window,
602 MatchResultListener *listener) const;
603 void DescribeTo (std::ostream *os) const;
604
605 private:
606
607 virtual bool Compare (int lhsPos,
608 int rhsPos) const = 0;
609 virtual void ExplainCompare (std::ostream *os) const = 0;
610
611 WindowArray array;
612 unsigned int arrayNum;
613 Window cmp;
614
615 };
616
617 StackPositionMatcher::StackPositionMatcher (const WindowArray &array,
618 Window cmp,
619 unsigned int n) :
620 array (array),
621 arrayNum (n),
622 cmp (cmp)
623 {
624 }
625
626 bool
627 StackPositionMatcher::MatchAndExplain (Window window,
628 MatchResultListener *listener) const
629 {
630 int lhsPos = -1, rhsPos = -1;
631
632 for (unsigned int i = 0; i < arrayNum; ++i)
633 {
634 if (array[i] == window)
635 lhsPos = i;
636 if (array[i] == cmp)
637 rhsPos = i;
638 }
639
640 if (lhsPos > -1 &&
641 rhsPos > -1)
642 {
643 if (Compare (lhsPos, rhsPos))
644 return true;
645 }
646
647 /* Match failed, add stack to MatchResultListener */
648 if (listener->IsInterested ())
649 {
650 std::stringstream windowStack;
651
652 windowStack << "Window Stack (bottom to top ["
653 << arrayNum
654 << "]): \n";
655 *listener << windowStack.str ();
656 for (unsigned int i = 0; i < arrayNum; ++i)
657 {
658 std::stringstream ss;
659 ss << " - 0x"
660 << std::hex
661 << array[i]
662 << std::dec
663 << std::endl;
664 *listener << ss.str ();
665 }
666
667 std::stringstream lhsPosMsg, rhsPosMsg;
668
669 lhsPosMsg << "Position of 0x"
670 << std::hex
671 << window
672 << std::dec
673 << " : "
674 << lhsPos;
675
676 rhsPosMsg << "Position of 0x"
677 << std::hex
678 << cmp
679 << std::dec
680 << " : "
681 << rhsPos;
682
683 *listener << lhsPosMsg.str () << "\n";
684 *listener << rhsPosMsg.str () << "\n";
685 }
686
687 return false;
688 }
689
690 void
691 StackPositionMatcher::DescribeTo (std::ostream *os) const
692 {
693 *os << "Window is ";
694 ExplainCompare (os);
695 *os << " in relation to 0x" << std::hex << cmp << std::dec;
696 }
697
698 class GreaterThanInStackMatcher :
699 public StackPositionMatcher
700 {
701 public:
702
703 GreaterThanInStackMatcher (const WindowArray &array,
704 Window cmp,
705 unsigned int n);
706
707 private:
708
709 bool Compare (int lhsPos, int rhsPos) const;
710 void ExplainCompare (std::ostream *os) const;
711 };
712
713 GreaterThanInStackMatcher::GreaterThanInStackMatcher (const WindowArray &array,
714 Window cmp,
715 unsigned int n) :
716 StackPositionMatcher (array, cmp, n)
717 {
718 }
719
720 bool GreaterThanInStackMatcher::Compare (int lhsPos, int rhsPos) const
721 {
722 return lhsPos > rhsPos;
723 }
724
725 void GreaterThanInStackMatcher::ExplainCompare (std::ostream *os) const
726 {
727 *os << "greater than";
728 }
729
730 class LessThanInStackMatcher :
731 public StackPositionMatcher
732 {
733 public:
734
735 LessThanInStackMatcher (const WindowArray &array,
736 Window cmp,
737 unsigned int n);
738
739 private:
740
741 bool Compare (int lhsPos, int rhsPos) const;
742 void ExplainCompare (std::ostream *os) const;
743 };
744
745 LessThanInStackMatcher::LessThanInStackMatcher (const WindowArray &array,
746 Window cmp,
747 unsigned int n) :
748 StackPositionMatcher (array, cmp, n)
749 {
750 }
751
752 bool LessThanInStackMatcher::Compare (int lhsPos, int rhsPos) const
753 {
754 return lhsPos < rhsPos;
755 }
756
757 void LessThanInStackMatcher::ExplainCompare (std::ostream *os) const
758 {
759 *os << "less than";
760 }
761
762 inline Matcher <Window> GreaterThanInStack (const WindowArray &array,
763 unsigned int n,
764 Window cmp)
765 {
766 return MakeMatcher (new GreaterThanInStackMatcher (array, cmp, n));
767 }
768
769 inline Matcher <Window> LessThanInStack (const WindowArray &array,
770 unsigned int n,
771 Window cmp)
772 {
773 return MakeMatcher (new LessThanInStackMatcher (array, cmp, n));
774 }
775}
776
777TEST_F (StackingSync, DestroyClientJustBeforeReparent)
778{
779 ::Display *dpy = Display ();
780
781 ct::MessageAtoms atoms (dpy);
782
783 /* Set up three normal windows */
784 Window w1 = CreateAndWaitForCreation (dpy);
785 Window w2 = CreateAndWaitForCreation (dpy);
786 Window w3 = CreateAndWaitForCreation (dpy);
787
788 Window p1 = MapAndWaitForParent (dpy, w1);
789 Window p2 = MapAndWaitForParent (dpy, w2);
790 Window p3 = MapAndWaitForParent (dpy, w3);
791
792 /* Create another normal window, but immediately mark
793 * it destroyed within compiz as soon as it is reparented,
794 * so that we force the reparented-but-destroyed strategy
795 * to kick in */
796 Window destroyed = CreateAndWaitForCreation (dpy);
797
798 DestroyOnReparent (dpy, atoms, destroyed);
799 XMapRaised (dpy, destroyed);
800
801 /* Wait for the destroyed window's parent to be created
802 * in the toplevel stack as a result of the reparent operation */
803 Window parentOfDestroyed = WaitForNextCreatedWindow (dpy);
804 WaitForManage (dpy, atoms);
805
806 /* Create an override redirect window and wait for it to be
807 * managed */
808 Window override = CreateOverrideRedirectWindow (dpy);
809 WaitForManage (dpy, atoms);
810
811 /* Place the destroyed window's parent above
812 * p1 in the stack directly */
813 RestackAbove (dpy, parentOfDestroyed, p1);
814
815 /* Ask compiz to place the override redirect window
816 * at least above the destroyed window's parent
817 * in the stack. This requires compiz to locate the
818 * destroyed window's parent in the stack */
819 RestackAtLeastAbove (dpy, atoms, override, parentOfDestroyed);
820
821 /* Wait for the override window to be configured */
822 Advance (dpy,
823 ct::WaitForEventOfTypeOnWindow (dpy,
824 override,
825 ConfigureNotify,
826 -1,
827 -1));
828
829 unsigned int n;
830 WindowArray windows (GetChildren (dpy, DefaultRootWindow (dpy), n));
831
832 EXPECT_THAT (p2, LessThanInStack (windows, n, override));
833 EXPECT_THAT (p3, GreaterThanInStack (windows, n, override));
834}
432835
=== modified file 'tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp'
--- tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp 2013-02-23 07:08:20 +0000
+++ tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp 2013-06-26 21:25:34 +0000
@@ -50,6 +50,8 @@
50 "_COMPIZ_TEST_HELPER_FRAME_EXTENTS_CHANGED",50 "_COMPIZ_TEST_HELPER_FRAME_EXTENTS_CHANGED",
51 "_COMPIZ_TEST_HELPER_CONFIGURE_WINDOW",51 "_COMPIZ_TEST_HELPER_CONFIGURE_WINDOW",
52 "_COMPIZ_TEST_HELPER_WINDOW_CONFIGURE_PROCESSED",52 "_COMPIZ_TEST_HELPER_WINDOW_CONFIGURE_PROCESSED",
53 "_COMPIZ_TEST_HELPER_DESTROY_ON_REPARENT",
54 "_COMPIZ_TEST_HELPER_RESTACK_ATLEAST_ABOVE",
53 "_COMPIZ_TEST_HELPER_WINDOW_READY"55 "_COMPIZ_TEST_HELPER_WINDOW_READY"
54};56};
55}57}
@@ -61,7 +63,9 @@
61const char *TEST_HELPER_FRAME_EXTENTS_CHANGED = internal::messages[4];63const char *TEST_HELPER_FRAME_EXTENTS_CHANGED = internal::messages[4];
62const char *TEST_HELPER_CONFIGURE_WINDOW = internal::messages[5];64const char *TEST_HELPER_CONFIGURE_WINDOW = internal::messages[5];
63const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED = internal::messages[6];65const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED = internal::messages[6];
64const char *TEST_HELPER_WINDOW_READY = internal::messages[7];66const char *TEST_HELPER_DESTROY_ON_REPARENT = internal::messages[7];
67const char *TEST_HELPER_RESTACK_ATLEAST_ABOVE = internal::messages[8];
68const char *TEST_HELPER_WINDOW_READY = internal::messages[9];
65}69}
66}70}
67}71}
6872
=== modified file 'tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h'
--- tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h 2013-02-23 07:08:20 +0000
+++ tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h 2013-06-26 21:25:34 +0000
@@ -41,6 +41,8 @@
41extern const char *TEST_HELPER_FRAME_EXTENTS_CHANGED;41extern const char *TEST_HELPER_FRAME_EXTENTS_CHANGED;
42extern const char *TEST_HELPER_CONFIGURE_WINDOW;42extern const char *TEST_HELPER_CONFIGURE_WINDOW;
43extern const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED;43extern const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED;
44extern const char *TEST_HELPER_DESTROY_ON_REPARENT;
45extern const char *TEST_HELPER_RESTACK_ATLEAST_ABOVE;
44extern const char *TEST_HELPER_WINDOW_READY;46extern const char *TEST_HELPER_WINDOW_READY;
45}47}
4648
4749
=== modified file 'tests/xorg-gtest/include/compiz-xorg-gtest.h'
--- tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-06-22 12:27:36 +0000
+++ tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-06-26 21:25:34 +0000
@@ -125,6 +125,8 @@
125 Window GetImmediateParent (Display *display,125 Window GetImmediateParent (Display *display,
126 Window w,126 Window w,
127 Window &rootReturn);127 Window &rootReturn);
128 Window GetTopmostNonRootParent (Display *display,
129 Window w);
128130
129 std::list <Window> NET_CLIENT_LIST_STACKING (Display *);131 std::list <Window> NET_CLIENT_LIST_STACKING (Display *);
130 bool AdvanceToNextEventOnSuccess (Display *dpy,132 bool AdvanceToNextEventOnSuccess (Display *dpy,
131133
=== modified file 'tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp'
--- tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 2013-05-09 13:43:07 +0000
+++ tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 2013-06-26 21:25:34 +0000
@@ -181,10 +181,66 @@
181 }181 }
182}182}
183183
184void
185TestHelperWindow::setDestroyOnReparent (long *)
186{
187 destroyOnReparent = true;
188}
189
190void
191TestHelperWindow::restackAtLeastAbove (long *data)
192{
193 ServerLock lock (screen->serverGrabInterface ());
194
195 Window above = data[0];
196 XWindowAttributes attrib;
197
198 if (!XGetWindowAttributes (screen->dpy (), above, &attrib))
199 return;
200
201 CompWindow *w = screen->findTopLevelWindow (above, true);
202 for (; w; w = w->next)
203 if (!w->overrideRedirect ())
204 break;
205
206 if (!w)
207 return;
208
209 XWindowChanges xwc;
210
211 xwc.stack_mode = Above;
212 xwc.sibling = w->frame () ? w->frame () : w->id ();
213
214 window->restackAndConfigureXWindow (CWStackMode | CWSibling,
215 &xwc,
216 lock);
217}
218
219void
220TestHelperWindow::windowNotify (CompWindowNotify n)
221{
222 switch (n)
223 {
224 case CompWindowNotifyReparent:
225 if (destroyOnReparent)
226 {
227 Window id = window->id ();
228 window->destroy ();
229 XDestroyWindow (screen->dpy (), id);
230 }
231 break;
232 default:
233 break;
234 }
235
236 window->windowNotify (n);
237}
238
184TestHelperWindow::TestHelperWindow (CompWindow *w) :239TestHelperWindow::TestHelperWindow (CompWindow *w) :
185 PluginClassHandler <TestHelperWindow, CompWindow> (w),240 PluginClassHandler <TestHelperWindow, CompWindow> (w),
186 window (w),241 window (w),
187 configureLock ()242 configureLock (),
243 destroyOnReparent (false)
188{244{
189 WindowInterface::setHandler (w);245 WindowInterface::setHandler (w);
190246
@@ -214,6 +270,10 @@
214 &TestHelperWindow::setFrameExtentsAndReport);270 &TestHelperWindow::setFrameExtentsAndReport);
215 watchForMessage (fetchAtom (ctm::TEST_HELPER_LOCK_CONFIGURE_REQUESTS),271 watchForMessage (fetchAtom (ctm::TEST_HELPER_LOCK_CONFIGURE_REQUESTS),
216 &TestHelperWindow::setConfigureLock);272 &TestHelperWindow::setConfigureLock);
273 watchForMessage (fetchAtom (ctm::TEST_HELPER_DESTROY_ON_REPARENT),
274 &TestHelperWindow::setDestroyOnReparent);
275 watchForMessage (fetchAtom (ctm::TEST_HELPER_RESTACK_ATLEAST_ABOVE),
276 &TestHelperWindow::restackAtLeastAbove);
217277
218 ct::SendClientMessage (s->dpy (),278 ct::SendClientMessage (s->dpy (),
219 mAtomStore.FetchForString (ctm::TEST_HELPER_READY_MSG),279 mAtomStore.FetchForString (ctm::TEST_HELPER_READY_MSG),
220280
=== modified file 'tests/xorg-gtest/plugins/testhelper/src/testhelper.h'
--- tests/xorg-gtest/plugins/testhelper/src/testhelper.h 2013-02-14 12:12:53 +0000
+++ tests/xorg-gtest/plugins/testhelper/src/testhelper.h 2013-06-26 21:25:34 +0000
@@ -77,11 +77,17 @@
77 void configureAndReport (long *);77 void configureAndReport (long *);
78 void setFrameExtentsAndReport (long *);78 void setFrameExtentsAndReport (long *);
79 void setConfigureLock (long *);79 void setConfigureLock (long *);
80 void setDestroyOnReparent (long *);
81 void restackAtLeastAbove (long *);
8082
81 private:83 private:
8284
85 void windowNotify (CompWindowNotify n);
86
83 CompWindow *window;87 CompWindow *window;
84 compiz::window::configure_buffers::Releasable::Ptr configureLock;88 compiz::window::configure_buffers::Releasable::Ptr configureLock;
89
90 bool destroyOnReparent;
85};91};
8692
87class TestHelperPluginVTable :93class TestHelperPluginVTable :
8894
=== modified file 'tests/xorg-gtest/src/compiz-xorg-gtest.cpp'
--- tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-06-22 12:27:36 +0000
+++ tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-06-26 21:25:34 +0000
@@ -105,6 +105,27 @@
105 return parentReturn;105 return parentReturn;
106}106}
107107
108Window
109ct::GetTopmostNonRootParent (Display *display,
110 Window w)
111{
112 Window rootReturn = 0;
113 Window parentReturn = w;
114 Window lastParent = 0;
115
116 do
117 {
118 lastParent = parentReturn;
119
120 parentReturn = GetImmediateParent (display,
121 lastParent,
122 rootReturn);
123
124 } while (parentReturn != rootReturn);
125
126 return lastParent;
127}
128
108bool129bool
109ct::AdvanceToNextEventOnSuccess (Display *dpy,130ct::AdvanceToNextEventOnSuccess (Display *dpy,
110 bool waitResult)131 bool waitResult)

Subscribers

People subscribed via source and target branches

to all changes: