Merge lp:~sil2100/compiz/quickfix_1141079_0.9.9 into lp:compiz/0.9.9

Proposed by Łukasz Zemczak
Status: Merged
Approved by: Łukasz Zemczak
Approved revision: 3645
Merged at revision: 3648
Proposed branch: lp:~sil2100/compiz/quickfix_1141079_0.9.9
Merge into: lp:compiz/0.9.9
Diff against target: 233 lines (+135/-22)
5 files modified
src/event.cpp (+21/-19)
tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp (+97/-0)
tests/xorg-gtest/include/compiz-xorg-gtest.h (+2/-1)
tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp (+1/-0)
tests/xorg-gtest/src/compiz-xorg-gtest.cpp (+14/-2)
To merge this branch: bzr merge lp:~sil2100/compiz/quickfix_1141079_0.9.9
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Sam Spilsbury Approve
Łukasz Zemczak Pending
Daniel van Vugt Pending
Review via email: mp+156779@code.launchpad.net

This proposal supersedes a proposal from 2013-03-14.

Commit message

Qt is stupid since it uses the stupid X11 protocol - let's not set all the attributes (especially override_redirect) every time, only in cases when it's actually needed (LP: #1141079)

Description of the change

- Problem:

The fix introduced in revision 3606 triggers a regression with Qt menus. It seems that passing on the override_redirect state from xcreatewindow results in this regression happening. Pop-up menus in Qt apps sometimes are detected as a separate window.

- Fix:

We try not to invalidly unnecessarily pass the additional attributes to the event when there is no need. This way the override_redirect attribute is not corrupted and all is cool.

- Tests:

Attached related gtest tests.

To post a comment you must log in.
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal
Download full text (3.4 KiB)

Ugh, I hate all these broken toolkits.

Now I remember - Qt was stupid and sets the override redirect bit to zero for all windows until MapRequest time, something that IMO is broken about the X protocol (you shouldn't be able to change the override redirect state as there are no events for that, and it causes race conditions later) and also broken about Qt because it actually uses that bit of the protocol.

Can you:

 1. Put the wa.whatever assignments within the preceeding if () block, eg:

    if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))
    {
 privateScreen.setDefaultWindowAttributes (&wa);
 wa.x = event->xcreatewindow.x;
 wa.y = event->xcreatewindow.y;
 wa.width = event->xcreatewindow.width;
 wa.height = event->xcreatewindow.height;
 wa.border_width = event->xcreatewindow.border_width;
 wa.override_redirect = event->xcreatewindow.override_redirect;
    }

    I think the big concern that I had when writing this chunk of code was that destroyed windows on the server side (eg, no XGetWindowAttributes fails) wouldn't get any attributes set, including their override_redirect attribute. For Qt windows, it means that we'll just have to work off an invalid override_redirect attribute when handling incoming restack requests relative to their now-destroyed windows, but it shouldn't be too big a deal as I think we don't restack relative to unmapped windows which haven't yet been managed. For everyone else it means we have information that should be correct in 99% of cases.

 2. Move the comment up there
 3. Add some tests for that behavior, because this Qt "feature" is easy to forget about
    - have a look in compiz_xorg_gtest_configure_window.cpp for the general integration test structure
    - I think a general test for this would look like (in the AutostartCompizXorgSystemTestWithTestHelper fixture):
      a. Grab Server -> Create Window using XCreateWindow (with XCreateWindowAttributes.override_redirect = 1) -> Destroy Window -> Sync/Ungrab Server/Sync -> call WaitForWindowCreation and additionally verify that the override_redirect bit is "1"
         i. testhelper.cpp should be modified to return some basic window attributes in the TEST_HELPER_WINDOW_READY message in TestHelperWindow ctor. That would window->overrideRedirect () (converted to either 1 or 0)
         ii. WaitForWindowCreation could return a vector of long (extracted from event.xclient.data.l)
         iii. Have a simple helper function IsOverrideRedirect (std::vector <long> &data) to inspect that vector for the appropriate bit.
         iv. EXPECT_TRUE that function.
      b. Grab Server -> Create Window using XCreateWindow (with XCreateWindowAttributes.override_redirect = 0) -> Destroy Window -> Sync/Ungrab Server/Sync -> call WaitForWindowCreation and additionally verify that the override_redirect bit is "0"
      c. Grab Server -> Create Window using XCreateWindow (with XSetWindowAttributes.override_redirect = 0) -> call XChangeWindowAttributes (with XWindowAttributes.override_redirect = 1) -> Sync/Ungrab Server/Sync -> call WaitForWindowCreation and additionally verify that the override_redirect bit is "1"
      d. Grab Server -> Create W...

Read more...

Revision history for this message
Łukasz Zemczak (sil2100) wrote : Posted in a previous version of this proposal

Thanks for the comment and review Sam (as always, excellently described and explained)! Will proceed as advised. Indeed testing this behaviour might be the right way to go. Once I'm over the current task I'm working on, I'll update the merge branches.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Looks like its on the right track!

(I'm changing this to WIP so I can keep track). Thanks heaps.

Revision history for this message
Łukasz Zemczak (sil2100) wrote : Posted in a previous version of this proposal

Hi Sam! Could you check the testing code?

Since I don't know if I'm doing anything wrong, but it seems the override_redirect attribute is not properly propagated with the XCreateWindow() call when using this branch. The CreateDestroyWindowOverrideRedirectTrue test I created fails, and when debugging in detail it seems that the CompWindow that reaches the TestHelperWindow ctor for the window I created (with the override_redirect attribute set) has the override_redirect flag reset to 0 again ;/ Not sure where that happens...
Do you have any clue what's wrong by any chance?

review: Needs Information
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Heya,

Haven't had a chance to run the code yet, but I spotted something here:

97 + Window w = XCreateWindow (dpy, DefaultRootWindow (dpy),
98 + 0, 0, 100, 100, 0, CopyFromParent,
99 + InputOutput, CopyFromParent, 0,
100 + &attr);

You need to specify a changemask for attr, eg

unsigned int mask = CWOverrideRedirect;

97 + Window w = XCreateWindow (dpy, DefaultRootWindow (dpy),
98 + 0, 0, 100, 100, 0, CopyFromParent,
99 + InputOutput, CopyFromParent, mask,
100 + &attr);

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Looks great for now.

There is some further refactoring that I think could be done, but this should probably be merged into a change focused on refactoring and not on blocking this work.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Please target all fixes to lp:compiz first (0.9.10). And then lp:compiz/0.9.9 (the new raring branch) second.

review: Needs Resubmitting
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
Łukasz Zemczak (sil2100) wrote :

Waiting for https://code.launchpad.net/~sil2100/compiz/quickfix_1141079_trunk/+merge/157084 - it currently fails due to jenkins CI compiz issues.

Revision history for this message
Sam Spilsbury (smspillaz) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:3645
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~sil2100/compiz/quickfix_1141079_0.9.9/+merge/156779/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-ci/1/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-gles-ci/./build=pbuilder,distribution=raring,flavor=amd64/1/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-pbuilder/./build=pbuilder,distribution=raring,flavor=amd64/1/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/compiz-0.9.9-ci/1/rebuild

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

FAILED: Continuous integration, rev:3645
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~sil2100/compiz/quickfix_1141079_0.9.9/+merge/156779/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-ci/2/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-gles-ci/./build=pbuilder,distribution=raring,flavor=amd64/2/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-pbuilder/./build=pbuilder,distribution=raring,flavor=amd64/2/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/compiz-0.9.9-ci/2/rebuild

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

FAILED: Continuous integration, rev:3645
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~sil2100/compiz/quickfix_1141079_0.9.9/+merge/156779/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-ci/3/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-gles-ci/./build=pbuilder,distribution=raring,flavor=amd64/3
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-0.9.9-pbuilder/./build=pbuilder,distribution=raring,flavor=amd64/3

Click here to trigger a rebuild:
http://s-jenkins:8080/job/compiz-0.9.9-ci/3/rebuild

review: Needs Fixing (continuous-integration)
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/event.cpp'
--- src/event.cpp 2013-02-10 05:01:50 +0000
+++ src/event.cpp 2013-04-03 09:12:32 +0000
@@ -1285,19 +1285,20 @@
1285 * the window to the window list as we might get configure requests1285 * the window to the window list as we might get configure requests
1286 * which require us to stack other windows relative to it. Setting1286 * which require us to stack other windows relative to it. Setting
1287 * some default values if this is the case. */1287 * some default values if this is the case. */
1288 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))1288 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa)) {
1289 privateScreen.setDefaultWindowAttributes (&wa);1289 privateScreen.setDefaultWindowAttributes (&wa);
12901290
1291 /* That being said, we should store as much information as possible1291 /* That being said, we should store as much information as possible
1292 * about it. There may be requests relative to this window that could1292 * about it. There may be requests relative to this window that could
1293 * use the data in the XCreateWindowEvent structure, especially the1293 * use the data in the XCreateWindowEvent structure, especially the
1294 * override redirect state */1294 * override redirect state */
1295 wa.x = event->xcreatewindow.x;1295 wa.x = event->xcreatewindow.x;
1296 wa.y = event->xcreatewindow.y;1296 wa.y = event->xcreatewindow.y;
1297 wa.width = event->xcreatewindow.width;1297 wa.width = event->xcreatewindow.width;
1298 wa.height = event->xcreatewindow.height;1298 wa.height = event->xcreatewindow.height;
1299 wa.border_width = event->xcreatewindow.border_width;1299 wa.border_width = event->xcreatewindow.border_width;
1300 wa.override_redirect = event->xcreatewindow.override_redirect;1300 wa.override_redirect = event->xcreatewindow.override_redirect;
1301 }
13011302
1302 foreach (CompWindow *w, screen->windows ())1303 foreach (CompWindow *w, screen->windows ())
1303 {1304 {
@@ -1475,16 +1476,17 @@
1475 * the window to the window list as we might get configure requests1476 * the window to the window list as we might get configure requests
1476 * which require us to stack other windows relative to it. Setting1477 * which require us to stack other windows relative to it. Setting
1477 * some default values if this is the case. */1478 * some default values if this is the case. */
1478 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))1479 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa)) {
1479 privateScreen.setDefaultWindowAttributes (&wa);1480 privateScreen.setDefaultWindowAttributes (&wa);
14801481
1481 /* That being said, we should store as much information as possible1482 /* That being said, we should store as much information as possible
1482 * about it. There may be requests relative to this window that could1483 * about it. There may be requests relative to this window that could
1483 * use the data in the XCreateWindowEvent structure, especially the1484 * use the data in the XCreateWindowEvent structure, especially the
1484 * override redirect state */1485 * override redirect state */
1485 wa.x = event->xreparent.x;1486 wa.x = event->xreparent.x;
1486 wa.y = event->xreparent.y;1487 wa.y = event->xreparent.y;
1487 wa.override_redirect = event->xreparent.override_redirect;1488 wa.override_redirect = event->xreparent.override_redirect;
1489 }
14881490
1489 PrivateWindow::createCompWindow (getTopWindow ()->id (), getTopServerWindow ()->id (), wa, event->xreparent.window);1491 PrivateWindow::createCompWindow (getTopWindow ()->id (), getTopServerWindow ()->id (), wa, event->xreparent.window);
1490 break;1492 break;
14911493
=== 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-04-02 06:17:37 +0000
+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp 2013-04-03 09:12:32 +0000
@@ -212,6 +212,14 @@
212 bool VerifySetFrameExtentsResponse (Window w, int left, int right, int top, int bottom);212 bool VerifySetFrameExtentsResponse (Window w, int left, int right, int top, int bottom);
213 bool VerifyWindowSize (Window w, int x, int y, int width, int height);213 bool VerifyWindowSize (Window w, int x, int y, int width, int height);
214214
215 /* Helper functions for the Create*WindowOverrideRedirect* tests */
216 Window GrabAndCreateWindowWithAttrs (::Display *dpy,
217 XSetWindowAttributes &attr);
218 void UngrabSyncAndTestOverride (::Display *dpy,
219 Window w,
220 bool overrideAssert);
221
222
215 protected:223 protected:
216224
217 ReparentedWindow CreateWindow (::Display *);225 ReparentedWindow CreateWindow (::Display *);
@@ -750,3 +758,92 @@
750 currentWidth,758 currentWidth,
751 currentHeight));759 currentHeight));
752}760}
761
762Window
763CompizXorgSystemConfigureWindowTest::GrabAndCreateWindowWithAttrs (::Display *dpy,
764 XSetWindowAttributes &attr)
765{
766 /* NOTE: We need to ungrab the server after this function */
767 XGrabServer (dpy);
768
769 /* Create a window with our custom attributes */
770 return XCreateWindow (dpy, DefaultRootWindow (dpy),
771 0, 0, 100, 100, 0, CopyFromParent,
772 InputOutput, CopyFromParent, CWOverrideRedirect,
773 &attr);
774}
775
776void
777CompizXorgSystemConfigureWindowTest::UngrabSyncAndTestOverride (::Display *dpy,
778 Window w,
779 bool overrideAssert)
780{
781 XSync (dpy, false);
782
783 XUngrabServer (dpy);
784
785 XSync (dpy, false);
786
787 /* Check if the created window had the attributes passed correctly */
788 std::vector <long> data = WaitForWindowCreation (w);
789 EXPECT_EQ (overrideAssert, IsOverrideRedirect (data));
790}
791
792
793TEST_F (CompizXorgSystemConfigureWindowTest, CreateDestroyWindowOverrideRedirectTrue)
794{
795 ::Display *dpy = Display ();
796 XSetWindowAttributes attr;
797 attr.override_redirect = 1;
798
799 Window w = GrabAndCreateWindowWithAttrs (dpy, attr);
800
801 XDestroyWindow (dpy, w);
802
803 UngrabSyncAndTestOverride (dpy, w, true);
804}
805
806TEST_F (CompizXorgSystemConfigureWindowTest, CreateDestroyWindowOverrideRedirectFalse)
807{
808 ::Display *dpy = Display ();
809 XSetWindowAttributes attr;
810 attr.override_redirect = 0;
811
812 Window w = GrabAndCreateWindowWithAttrs (dpy, attr);
813
814 XDestroyWindow (dpy, w);
815
816 UngrabSyncAndTestOverride (dpy, w, false);
817}
818
819TEST_F (CompizXorgSystemConfigureWindowTest, CreateChangeWindowOverrideRedirectTrue)
820{
821 ::Display *dpy = Display ();
822 XSetWindowAttributes attr;
823 attr.override_redirect = 0;
824
825 Window w = GrabAndCreateWindowWithAttrs (dpy, attr);
826
827 attr.override_redirect = 1;
828 XChangeWindowAttributes (dpy, w, CWOverrideRedirect, &attr);
829
830 UngrabSyncAndTestOverride (dpy, w, true);
831
832 XDestroyWindow (dpy, w);
833}
834
835TEST_F (CompizXorgSystemConfigureWindowTest, CreateChangeWindowOverrideRedirectFalse)
836{
837 ::Display *dpy = Display ();
838 XSetWindowAttributes attr;
839 attr.override_redirect = 1;
840
841 Window w = GrabAndCreateWindowWithAttrs (dpy, attr);
842
843 attr.override_redirect = 0;
844 XChangeWindowAttributes (dpy, w, CWOverrideRedirect, &attr);
845
846 UngrabSyncAndTestOverride (dpy, w, false);
847
848 XDestroyWindow (dpy, w);
849}
753850
=== modified file 'tests/xorg-gtest/include/compiz-xorg-gtest.h'
--- tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-02-23 10:47:18 +0000
+++ tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-04-03 09:12:32 +0000
@@ -214,7 +214,8 @@
214 protected:214 protected:
215215
216 Atom FetchAtom (const char *);216 Atom FetchAtom (const char *);
217 void WaitForWindowCreation (Window w);217 std::vector <long> WaitForWindowCreation (Window w);
218 bool IsOverrideRedirect (std::vector <long> &data);
218219
219 virtual int GetEventMask ();220 virtual int GetEventMask ();
220221
221222
=== modified file 'tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp'
--- tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 2013-02-14 12:12:53 +0000
+++ tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 2013-04-03 09:12:32 +0000
@@ -192,6 +192,7 @@
192192
193 std::vector <long> data;193 std::vector <long> data;
194 data.push_back (static_cast <long> (window->id ()));194 data.push_back (static_cast <long> (window->id ()));
195 data.push_back (static_cast <long> (window->overrideRedirect ()));
195 ct::SendClientMessage (screen->dpy (),196 ct::SendClientMessage (screen->dpy (),
196 ts->fetchAtom (ctm::TEST_HELPER_WINDOW_READY),197 ts->fetchAtom (ctm::TEST_HELPER_WINDOW_READY),
197 screen->root (),198 screen->root (),
198199
=== modified file 'tests/xorg-gtest/src/compiz-xorg-gtest.cpp'
--- tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-02-23 08:23:05 +0000
+++ tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-04-03 09:12:32 +0000
@@ -738,7 +738,7 @@
738 std::auto_ptr <ct::MessageAtoms> mMessages;738 std::auto_ptr <ct::MessageAtoms> mMessages;
739};739};
740740
741void741std::vector <long>
742ct::AutostartCompizXorgSystemTestWithTestHelper::WaitForWindowCreation (Window w)742ct::AutostartCompizXorgSystemTestWithTestHelper::WaitForWindowCreation (Window w)
743{743{
744 ::Display *dpy = Display ();744 ::Display *dpy = Display ();
@@ -758,7 +758,19 @@
758758
759 }759 }
760760
761 ASSERT_TRUE (requestAcknowledged);761 EXPECT_TRUE (requestAcknowledged);
762
763 std::vector <long> data;
764 for (int i = 0; i < 5; ++i)
765 data.push_back(static_cast <long> (event.xclient.data.l[i]));
766
767 return data;
768}
769
770bool
771ct::AutostartCompizXorgSystemTestWithTestHelper::IsOverrideRedirect (std::vector <long> &data)
772{
773 return (data[1] > 0) ? true : false;
762}774}
763775
764Atom776Atom

Subscribers

People subscribed via source and target branches