Merge lp:~compiz-team/compiz/compiz.performance_1027211.2.1 into lp:compiz/0.9.9
- compiz.performance_1027211.2.1
- Merge into 0.9.9
Status: | Superseded |
---|---|
Proposed branch: | lp:~compiz-team/compiz/compiz.performance_1027211.2.1 |
Merge into: | lp:compiz/0.9.9 |
Diff against target: |
4386 lines (+3345/-156) 49 files modified
CMakeLists.txt (+16/-0) cmake/CompizGSettings.cmake (+12/-1) cmake/CompizPlugin.cmake (+34/-19) cmake/plugin_extensions/CompizGenGSettings.cmake (+7/-1) cmake/plugin_extensions/CompizGenGconf.cmake (+3/-1) cmake/plugin_extensions/CompizGenInstallData.cmake (+6/-4) cmake/plugin_extensions/CompizGenInstallImages.cmake (+7/-4) include/core/CMakeLists.txt (+1/-0) include/core/configurerequestbuffer.h (+73/-0) include/core/window.h (+26/-7) plugins/CMakeLists.txt (+1/-17) plugins/composite/src/window.cpp (+1/-5) plugins/move/move.xml.in (+1/-1) plugins/move/src/move.cpp (+12/-5) plugins/move/src/move.h (+2/-0) plugins/opengl/src/paint.cpp (+5/-2) plugins/opengl/src/privates.h (+3/-0) plugins/opengl/src/window.cpp (+2/-1) src/CMakeLists.txt (+7/-0) src/asyncserverwindow.h (+52/-0) src/configurerequestbuffer-impl.h (+145/-0) src/configurerequestbuffer.cpp (+363/-0) src/event.cpp (+1/-1) src/plugin.cpp (+7/-0) src/plugin/tests/CMakeLists.txt (+1/-0) src/plugin/tests/test-plugin.cpp (+29/-0) src/privatewindow.h (+45/-1) src/syncserverwindow.h (+49/-0) src/tests/CMakeLists.txt (+11/-0) src/tests/test_configurerequestbuffer.cpp (+667/-0) src/window.cpp (+192/-44) tests/acceptance-tests/xorg-gtest/tests/compiz_acceptance_replace_current_wm.cpp (+5/-0) tests/system/xorg-gtest/tests/CMakeLists.txt (+12/-1) tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp (+567/-0) tests/system/xorg-gtest/tests/compiz_xorg_gtest_ewmh.cpp (+2/-1) tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp (+15/-3) tests/xorg-gtest/CMakeLists.txt (+13/-1) tests/xorg-gtest/communicator/CMakeLists.txt (+17/-0) tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp (+200/-0) tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h (+67/-0) tests/xorg-gtest/include/compiz-xorg-gtest.h (+62/-4) tests/xorg-gtest/plugins/CMakeLists.txt (+10/-0) tests/xorg-gtest/plugins/testhelper/CMakeLists.txt (+7/-0) tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp (+231/-0) tests/xorg-gtest/plugins/testhelper/src/testhelper.h (+95/-0) tests/xorg-gtest/plugins/testhelper/testhelper.xml.in (+6/-0) tests/xorg-gtest/src/CMakeLists.txt (+0/-2) tests/xorg-gtest/src/compiz-xorg-gtest-config.h.in (+3/-2) tests/xorg-gtest/src/compiz-xorg-gtest.cpp (+252/-28) |
To merge this branch: | bzr merge lp:~compiz-team/compiz/compiz.performance_1027211.2.1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Compiz Maintainers | Pending | ||
MC Return | Pending | ||
Review via email: mp+149878@code.launchpad.net |
This proposal supersedes a proposal from 2013-02-21.
This proposal has been superseded by a proposal from 2013-02-22.
Commit message
Allow plugins to throttle delivery of ConfigureWindow requests within reason (LP: #1027211)
(LP: #1027211) seems to be caused by vsync in the nvidia driver and posting lots of ConfigureWindow requests to the server. The driver really chokes on these for some reason. As a result, two things were happening:
1. The driver slows down quite significantly
2. We get more time to post more ConfigureWindow requests to the driver, which just slows it down even more until it grinds to a halt.
This branch does three things:
1. Introduces infrastructure for plugins to hold a "lock" on delivering ConfigureWindow requests until they choose to release it later (eg, on paint, or on ungrab), while still allowing core to override the plugin's decisions in cases where we actually need to post a ConfigureWindow request to the server in order to continue (eg, some other request is dependent on it). That code was TDD'ed into existence and has test coverage.
2. Optimizes reconfigureXWindow to only configure the frame window if the only thing that happened was that we moved the window. This means that we only buffer up one ConfigureWindow instead of three per call to reconfigureXWindow
3. Implements ConfigureReques
Description of the change
Resubmitted with (LP: #1089279 fixed)
Allow plugins to throttle delivery of ConfigureWindow requests within reason (LP: #1027211)
(LP: #1027211) seems to be caused by vsync in the nvidia driver and posting lots of ConfigureWindow requests to the server. The driver really chokes on these for some reason. As a result, two things were happening:
1. The driver slows down quite significantly
2. We get more time to post more ConfigureWindow requests to the driver, which just slows it down even more until it grinds to a halt.
This branch does three things:
1. Introduces infrastructure for plugins to hold a "lock" on delivering ConfigureWindow requests until they choose to release it later (eg, on paint, or on ungrab), while still allowing core to override the plugin's decisions in cases where we actually need to post a ConfigureWindow request to the server in order to continue (eg, some other request is dependent on it). That code was TDD'ed into existence and has test coverage.
2. Optimizes reconfigureXWindow to only configure the frame window if the only thing that happened was that we moved the window. This means that we only buffer up one ConfigureWindow instead of three per call to reconfigureXWindow
3. Implements ConfigureReques
One question that might arise here is whether or not this branch is fundamentally unsafe because we allow the server to get "out of sync" with us. That isn't as much of a problem these days as it used to be. Nowadays we never track the incoming positions from the server to give us a representation of our own internal state, instead that is represented by what we meant to post to the server. So the internal state can never get mucked up. In areas where we do actually need to have our internal state represent what was really last sent to the server, I've structured the code such that in order to do those things, you have to release the queued up ConfigureWindow requests first.
Again, throw this at the wall and see if it introduces any bad regressions. I haven't see any so far.
Demonstrable numbers: moving opengl-rendered window around with vsync enabled in the driver goes from a constantly-
I've also added some further integration testing framework around this - with a "testhelper" plugin to facilitate communication between the test and compiz for requests that aren't usually exposed over EWMH or ICCCM.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3534
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3536
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Confirmed moving windows is much improved. There is no improvement with resizing though. I still encounter exactly the same freezes as mentioned previously:
1. XSync() inside PrivateWindow:
2. XShapeGetRectan
So please either:
(a) Don't touch XShape* in this proposal, and leave resize fixes for a later proposal; or
(b) Fix XShape* properly.
Given the large size of this proposal already, and that a proper fix for XShape should be to simply call it much less often (i.e. only for shaped windows), I recommend (a).
Secondly, I do support the concept of disabling lazy positioning in theory but would have to get my test machine (Atom) for that upgraded and working again before I approve it.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Also, without too much verbosity, why is it we need to implement window movement completely synchronously? My understanding is that waiting and locking should never be required when the user moves a window.
A window move should simply involve two events:
1. Motion event -> move plugin -> send request to X server (XConfigureWindow I think).
and some time later (should not care when):
2. XConfigureNotify (or whatever) -> core plugin -> compiz window position updated.
If this is lazy positioning then maybe I do support it. But historically we seem to have a lot more code than should be necessary to implement movement so I'm not sure.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
I mean; my understanding of lazy positioning is that we update the compiz position without waiting for the server to tell us it's done. Therefore the above method counts as non-lazy movement, but also does not require any waiting or locking. I think this is contrary to the proposed and established non-lazy algorithm that does sync for some reason.
If we want to keep lazy mode as an option and it does bypass the server as I suspect then OK. However I think at least non-lazy mode should be implemented as above, so that either way you never need to lock or sync to move a window.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
On Mon, Dec 10, 2012 at 2:16 PM, Daniel van Vugt
<email address hidden> wrote:
> Review: Needs Fixing
>
> Confirmed moving windows is much improved. There is no improvement with resizing though. I still encounter exactly the same freezes as mentioned previously:
> 1. XSync() inside PrivateWindow:
> 2. XShapeGetRectan
> So please either:
> (a) Don't touch XShape* in this proposal, and leave resize fixes for a later proposal; or
> (b) Fix XShape* properly.
> Given the large size of this proposal already, and that a proper fix for XShape should be to simply call it much less often (i.e. only for shaped windows), I recommend (a).
Ah, we actually need to touch it otherwise this proposal won't work
without it, though its not a very big touch, and more or less just a
wrapper around it to make sure that when it is called, we release the
geometry queue for that window.
The reason for that being that XShapeGetRectangles is dependent on us
having the most recent server size of the window actually posted to
the server by that point. If it isn't, then you'll get the wrong
client shape, and that will be incorrectly applied to the frame!
>
> Secondly, I do support the concept of disabling lazy positioning in theory but would have to get my test machine (Atom) for that upgraded and working again before I approve it.
>
> --
> https:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
--
Sam Spilsbury
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
On Mon, Dec 10, 2012 at 2:41 PM, Daniel van Vugt
<email address hidden> wrote:
> Also, without too much verbosity, why is it we need to implement window movement completely synchronously? My understanding is that waiting and locking should never be required when the user moves a window.
>
> A window move should simply involve two events:
> 1. Motion event -> move plugin -> send request to X server (XConfigureWindow I think).
> and some time later (should not care when):
> 2. XConfigureNotify (or whatever) -> core plugin -> compiz window position updated.
>
> I mean; my understanding of lazy positioning is that we update the compiz position without waiting for the server to tell us it's done. Therefore the above method counts as non-lazy movement, but also does not require any waiting or locking. I think this is contrary to the proposed and established non-lazy algorithm that does sync for some reason.
>
> If we want to keep lazy mode as an option and it does bypass the server as I suspect then OK. However I think at least non-lazy mode should be implemented as above, so that either way you never need to lock or sync to move a window.
Ah, I think there's a mixup of terminology here.
We're still completely async, both this branch and before this branch.
ConfigureWindow requests are in themselves async, you can post as many
as you want. There's absolutely no waiting for the server.
The problem is that the nvidia driver can't handle it. So instead of
sending it lots and lots of ConfigureWindow requests, we let plugins
"lock out" core from doing that until it makes sense for us to do it.
This means that:
1. In the case of "lazy positioning" being disabled, we just wait
until just before the next frame and post the request
2. In the case of "lazy positioning" enabled, we wait until the window
is ungrabbed.
Both are overridden in cases where we have to ask the server
something. But that's not too often.
> --
> https:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
--
Sam Spilsbury
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
It will take me a while to get the code compiled 32-bit and running on the Atom where I tested all the previous lazy-mode regressions. Until then, some style issues:
1. This is hard to read. I recommend (but don't require) all on one line...
48 +namespace compiz
49 +{
50 +namespace window
51 +{
52 +namespace configure_buffers
53 +{
2. MOVE_WINDOW (w) - Using macros to declare local variables via side-effect is dangerous and very hard to understand if you're new to compiz. I suggest not doing this in future code. Instead use an explicit:
MoveWindow *mw = MoveWindow::get(w);
3. From a high-level perspective, even if the implementation turns out to be right then I think maybe more analysis was required. This fix is an example of where the medicine could be worse than the disease. It's only useful to nvidia because nvidia is buggy IMHO. And the price to pay is more abstraction and complication that hinders maintainability of the code. We might be better off not trying to "fix" window movement any further. Though resizing needs work still.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
OK, verified window movement is absolutely perfect on the Atom with this change. So no non-lazy-mode regression to worry about.
Just need (want) to reconsider the style issues and the philosophical point above.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
FYI, window resizing on the Atom (i915) freezes just like with Nvidia so that's another good test platform.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
> It will take me a while to get the code compiled 32-bit and running on the
> Atom where I tested all the previous lazy-mode regressions. Until then, some
> style issues:
>
> 1. This is hard to read. I recommend (but don't require) all on one line...
> 48 +namespace compiz
> 49 +{
> 50 +namespace window
> 51 +{
> 52 +namespace configure_buffers
> 53 +{
>
> 2. MOVE_WINDOW (w) - Using macros to declare local variables via side-effect
> is dangerous and very hard to understand if you're new to compiz. I suggest
> not doing this in future code. Instead use an explicit:
> MoveWindow *mw = MoveWindow::get(w);
+1
>
> 3. From a high-level perspective, even if the implementation turns out to be
> right then I think maybe more analysis was required. This fix is an example of
> where the medicine could be worse than the disease. It's only useful to nvidia
> because nvidia is buggy IMHO. And the price to pay is more abstraction and
> complication that hinders maintainability of the code. We might be better off
> not trying to "fix" window movement any further. Though resizing needs work
> still.
It is a little more abstract and complex, yes, however having an unusable system on nvidia is not an acceptable alternative either.
I don't think the code is "unmaintainable", I think it just works in a way that is a tad more complex and different to the way that you would expect. Its fully tested and encapsulated from the other code, so future maintainers don't need to worry about inadvertently breaking it (except for their usage of the client hooks).
In addition, if there are any problems you can just "turn it off" - just don't take a lock on the configure request queue in the opengl plugin.
Speaking of medicine worse than the disease, you just named one of my favourite pieces of music :P (http://
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
>
> +1
>
> >
> > 3. From a high-level perspective, even if the implementation turns out to be
> > right then I think maybe more analysis was required. This fix is an example
> of
> > where the medicine could be worse than the disease. It's only useful to
> nvidia
> > because nvidia is buggy IMHO. And the price to pay is more abstraction and
> > complication that hinders maintainability of the code. We might be better
> off
> > not trying to "fix" window movement any further. Though resizing needs work
> > still.
>
> It is a little more abstract and complex, yes, however having an unusable
> system on nvidia is not an acceptable alternative either.
>
> I don't think the code is "unmaintainable", I think it just works in a way
> that is a tad more complex and different to the way that you would expect. Its
> fully tested and encapsulated from the other code, so future maintainers don't
> need to worry about inadvertently breaking it (except for their usage of the
> client hooks).
>
On the same note.
Over my many years of developing compiz, I've often found that the little quirks between drivers, opengl, the way the xserver works, the way specs are implemented etc often means the issues aren't that simple, so its means that the implementation is almost never going to be simple.
If you have a look at any window manager, they are often large and complicated beasts, doing lots of things that you wouldn't even expect a window manager to have to do.
However, window managers often start small and grow to accomadate the quirks in their surrounding environment. The best approach, in my opinion, is to encapsulate complexity into clearly defined areas of the code, so that your handing of corner cases doesn't pollute your main buisness logic or get tangled in-between it. While doing that, ensure that the corner cases are tested codepaths that future maintainers can rely upon the tests when making changes.
This is something that I think compiz really succeeds at. While our test coverage is pretty absymal at best, no other non-niche window manager I can think of is as well tested as compiz is. And its starting to pay off - I've been able to rely on the test suite alone for making some changes now, which is something that I was never able to do.
That being said, I think you're right into looking into any more workarounds for the nvidia problems with ConfigureWindow requests and simultaneous redirected GL. We've found the main cause and root of the problem now, so lets stick with this implementation and work on other things. Window movement is 60FPS here with this applied, so I doubt we can make it any faster :)
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
OK, forget the style issues. I don't want to spend any more hours on testing more revisions.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Sorry, I had to revert this merge in r3528. It caused too many regressions. See bug 1089279.
Daniel van Vugt (vanvugt) : Posted in a previous version of this proposal | # |
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Ah, I thought there might be some regressions.
Thanks, I'll get on to it.
On Thu, Dec 13, 2012 at 4:50 PM, Daniel van Vugt
<email address hidden> wrote:
> Review: Needs Fixing
>
>
> --
> https:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
--
Sam Spilsbury
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
I've fixed (LP: #1089279) by forcing any changes to the size of the window to release the queue immediately. Also to be on the safe side, I've made it so that changes to clients or the wrapper window release the queue immediately. We can have a look into those a bit later.
I can understand if you don't want to merge this for this year and wait until later until we have more testing. I've been setting up a ppa with a bunch of performance related things at ppa:smspillaz/
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3541
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Somehow this was merged. It shouldn't have been, see https:/
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3557
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
MC Return (mc-return) wrote : Posted in a previous version of this proposal | # |
Tested this. Moved around and resized windows. Could not spot any obvious regressions.
+1
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3558
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3559
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3560
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3561
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3562
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
MC Return (mc-return) wrote : Posted in a previous version of this proposal | # |
There is a minor indentation problem in move.xml.in:
299 - <default>
300 + <default>
You are using 16 spaces here, instead of 2 tabs.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3563
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3564
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3565
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3565
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3566
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2013-02-15 11:28:27 +0000 |
3 | +++ CMakeLists.txt 2013-02-21 16:57:22 +0000 |
4 | @@ -139,6 +139,22 @@ |
5 | DESTINATION ${libdir}/pkgconfig |
6 | ) |
7 | |
8 | +set (COMPIZ_INTERNAL_INCLUDES |
9 | + ${CMAKE_CURRENT_SOURCE_DIR}/include |
10 | + ${CMAKE_CURRENT_SOURCE_DIR}/src |
11 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/timer/include |
12 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/string/include |
13 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/pluginclasshandler/include |
14 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/point/include |
15 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/rect/include |
16 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/servergrab/include |
17 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/region/include |
18 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/window/geometry/include |
19 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/window/geometry-saver/include |
20 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/window/extents/include |
21 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/window/constrainment/include |
22 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/logmessage/include) |
23 | + |
24 | if (COMPIZ_BUILD_TESTING) |
25 | |
26 | find_package (GoogleTest) |
27 | |
28 | === modified file 'cmake/CompizGSettings.cmake' |
29 | --- cmake/CompizGSettings.cmake 2012-09-10 07:49:26 +0000 |
30 | +++ cmake/CompizGSettings.cmake 2013-02-21 16:57:22 +0000 |
31 | @@ -205,7 +205,18 @@ |
32 | add_custom_target (${_name}_gsettings_schema |
33 | DEPENDS ${_dst}) |
34 | |
35 | - compiz_install_gsettings_schema (${_dst} ${_inst}) |
36 | + set (_install_gsettings_schema ON) |
37 | + |
38 | + foreach (ARG ${ARGN}) |
39 | + if (${ARG} STREQUAL "NOINSTALL") |
40 | + set (_install_gsettings_schema OFF) |
41 | + endif (${ARG} STREQUAL "NOINSTALL") |
42 | + endforeach () |
43 | + |
44 | + if (_install_gsettings_schema) |
45 | + compiz_install_gsettings_schema (${_dst} ${_inst}) |
46 | + endif (_install_gsettings_schema) |
47 | + |
48 | add_gsettings_schema_to_recompilation_list (${_name}_gsettings_schema) |
49 | endif () |
50 | endfunction () |
51 | |
52 | === modified file 'cmake/CompizPlugin.cmake' |
53 | --- cmake/CompizPlugin.cmake 2012-10-16 13:53:20 +0000 |
54 | +++ cmake/CompizPlugin.cmake 2013-02-21 16:57:22 +0000 |
55 | @@ -36,6 +36,7 @@ |
56 | # LIBRARIES = libraries added to link command |
57 | # LIBDIRS = additional link directories |
58 | # INCDIRS = additional include directories |
59 | +# NOINSTALL = do not install this plugin |
60 | # |
61 | # The following variables will be used by this macro: |
62 | # |
63 | @@ -185,6 +186,14 @@ |
64 | ) |
65 | endif (COMPIZ_PLUGIN_INSTALL_TYPE) |
66 | |
67 | + set (_install_plugin_${plugin} ON) |
68 | + |
69 | + foreach (ARG ${ARGN}) |
70 | + if (${ARG} STREQUAL "NOINSTALL") |
71 | + set (_install_plugin_${plugin} OFF) |
72 | + endif (${ARG} STREQUAL "NOINSTALL") |
73 | + endforeach () |
74 | + |
75 | _get_parameters (${_PLUGIN} ${ARGN}) |
76 | _prepare_directories () |
77 | |
78 | @@ -241,11 +250,13 @@ |
79 | |
80 | if (_translated_xml) |
81 | |
82 | - # install xml |
83 | - install ( |
84 | - FILES ${_translated_xml} |
85 | - DESTINATION $ENV{DESTDIR}${PLUGIN_XMLDIR} |
86 | - ) |
87 | + if (_install_plugin_${plugin}) |
88 | + # install xml |
89 | + install ( |
90 | + FILES ${_translated_xml} |
91 | + DESTINATION $ENV{DESTDIR}${PLUGIN_XMLDIR} |
92 | + ) |
93 | + endif (_install_plugin_${plugin}) |
94 | endif (_translated_xml) |
95 | |
96 | find_file ( |
97 | @@ -287,14 +298,16 @@ |
98 | PKGCONFIG_LIBS |
99 | ) |
100 | |
101 | - install ( |
102 | - FILES ${CMAKE_BINARY_DIR}/generated/compiz-${plugin}.pc |
103 | - DESTINATION ${PLUGIN_PKGDIR} |
104 | - ) |
105 | - install ( |
106 | - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/${plugin} |
107 | - DESTINATION ${PLUGIN_INCDIR}/compiz |
108 | - ) |
109 | + if (_install_plugin_${plugin}) |
110 | + install ( |
111 | + FILES ${CMAKE_BINARY_DIR}/generated/compiz-${plugin}.pc |
112 | + DESTINATION ${PLUGIN_PKGDIR} |
113 | + ) |
114 | + install ( |
115 | + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/${plugin} |
116 | + DESTINATION ${PLUGIN_INCDIR}/compiz |
117 | + ) |
118 | + endif () |
119 | endif () |
120 | endif () |
121 | |
122 | @@ -412,16 +425,18 @@ |
123 | compiz_core |
124 | ) |
125 | |
126 | - install ( |
127 | - TARGETS ${plugin} |
128 | - LIBRARY DESTINATION ${PLUGIN_LIBDIR} |
129 | - ) |
130 | + if (_install_plugin_${plugin}) |
131 | + install ( |
132 | + TARGETS ${plugin} |
133 | + LIBRARY DESTINATION ${PLUGIN_LIBDIR} |
134 | + ) |
135 | + endif (_install_plugin_${plugin}) |
136 | |
137 | - if (NOT _COMPIZ_INTERNAL) |
138 | + if (NOT _COMPIZ_INTERNAL AND _install_plugin_${plugin}) |
139 | |
140 | compiz_add_uninstall () |
141 | |
142 | - endif (NOT _COMPIZ_INTERNAL) |
143 | + endif (NOT _COMPIZ_INTERNAL AND _install_plugin_${plugin}) |
144 | |
145 | if (NOT COMPIZ_PLUGIN_PACK_BUILD) |
146 | set (CMAKE_PROJECT_NAME plugin-${plugin}) |
147 | |
148 | === modified file 'cmake/plugin_extensions/CompizGenGSettings.cmake' |
149 | --- cmake/plugin_extensions/CompizGenGSettings.cmake 2012-07-10 10:35:16 +0000 |
150 | +++ cmake/plugin_extensions/CompizGenGSettings.cmake 2013-02-21 16:57:22 +0000 |
151 | @@ -36,10 +36,16 @@ |
152 | set (PLUGIN_GSETTINGS_SCHEMA_DST |
153 | ${CMAKE_BINARY_DIR}/generated/glib-2.0/schemas/org.compiz.${COMPIZ_CURRENT_PLUGIN}.gschema.xml) |
154 | |
155 | + set (_install_gsettings_schema ) |
156 | + if (NOT _install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
157 | + set (_install_gsettings_schema NOINSTALL) |
158 | + endif (NOT _install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
159 | + |
160 | compiz_gsettings_schema (${COMPIZ_CURRENT_PLUGIN} |
161 | ${COMPIZ_CURRENT_XML_FILE} |
162 | ${PLUGIN_GSETTINGS_SCHEMA_DST} |
163 | - ${PLUGIN_SCHEMADIR}) |
164 | + ${PLUGIN_SCHEMADIR} |
165 | + ${_install_gsettings_schema}) |
166 | list (APPEND COMPIZ_CURRENT_SOURCES_ADDS ${PLUGIN_GSETTINGS_SCHEMA_DST}) |
167 | |
168 | endif (USE_GSETTINGS) |
169 | |
170 | === modified file 'cmake/plugin_extensions/CompizGenGconf.cmake' |
171 | --- cmake/plugin_extensions/CompizGenGconf.cmake 2012-05-24 00:55:17 +0000 |
172 | +++ cmake/plugin_extensions/CompizGenGconf.cmake 2013-02-21 16:57:22 +0000 |
173 | @@ -74,6 +74,8 @@ |
174 | DEPENDS ${COMPIZ_CURRENT_XML_FILE} |
175 | ) |
176 | |
177 | - compiz_install_gconf_schema ("${CMAKE_BINARY_DIR}/generated/compiz-${COMPIZ_CURRENT_PLUGIN}.schemas" ${PLUGIN_SCHEMADIR}) |
178 | + if (_install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
179 | + compiz_install_gconf_schema ("${CMAKE_BINARY_DIR}/generated/compiz-${COMPIZ_CURRENT_PLUGIN}.schemas" ${PLUGIN_SCHEMADIR}) |
180 | + endif (_install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
181 | list (APPEND COMPIZ_CURRENT_SOURCES_ADDS ${CMAKE_BINARY_DIR}/generated/compiz-${COMPIZ_CURRENT_PLUGIN}.schemas) |
182 | endif () |
183 | |
184 | === modified file 'cmake/plugin_extensions/CompizGenInstallData.cmake' |
185 | --- cmake/plugin_extensions/CompizGenInstallData.cmake 2012-05-24 00:55:17 +0000 |
186 | +++ cmake/plugin_extensions/CompizGenInstallData.cmake 2013-02-21 16:57:22 +0000 |
187 | @@ -17,9 +17,11 @@ |
188 | # install plugin data files |
189 | if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/data) |
190 | compiz_data_prepare_dirs () |
191 | - install ( |
192 | - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data |
193 | - DESTINATION ${PLUGIN_DATADIR} |
194 | - ) |
195 | + if (_install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
196 | + install ( |
197 | + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data |
198 | + DESTINATION ${PLUGIN_DATADIR} |
199 | + ) |
200 | + endif (_install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
201 | list (APPEND COMPIZ_DEFINITIONS_ADD "-DDATADIR='\"${PLUGIN_DATADIR}\"'") |
202 | endif () |
203 | |
204 | === modified file 'cmake/plugin_extensions/CompizGenInstallImages.cmake' |
205 | --- cmake/plugin_extensions/CompizGenInstallImages.cmake 2012-05-24 00:55:17 +0000 |
206 | +++ cmake/plugin_extensions/CompizGenInstallImages.cmake 2013-02-21 16:57:22 +0000 |
207 | @@ -17,9 +17,12 @@ |
208 | # install plugin data files |
209 | if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/images) |
210 | compiz_images_prepare_dirs () |
211 | - install ( |
212 | - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/images |
213 | - DESTINATION ${PLUGIN_IMAGEDIR} |
214 | - ) |
215 | + |
216 | + if (_install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
217 | + install ( |
218 | + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/images |
219 | + DESTINATION ${PLUGIN_IMAGEDIR} |
220 | + ) |
221 | + endif (_install_plugin_${COMPIZ_CURRENT_PLUGIN}) |
222 | list (APPEND COMPIZ_DEFINITIONS_ADD "-DIMAGEDIR='\"${PLUGIN_IMAGEDIR}\"'") |
223 | endif () |
224 | |
225 | === modified file 'include/core/CMakeLists.txt' |
226 | --- include/core/CMakeLists.txt 2012-12-13 10:12:23 +0000 |
227 | +++ include/core/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
228 | @@ -1,6 +1,7 @@ |
229 | set (_headers |
230 | action.h |
231 | atoms.h |
232 | + configurerequestbuffer.h |
233 | core.h |
234 | countedlist.h |
235 | global.h |
236 | |
237 | === added file 'include/core/configurerequestbuffer.h' |
238 | --- include/core/configurerequestbuffer.h 1970-01-01 00:00:00 +0000 |
239 | +++ include/core/configurerequestbuffer.h 2013-02-21 16:57:22 +0000 |
240 | @@ -0,0 +1,73 @@ |
241 | +/* |
242 | + * Copyright © 2012 Sam Spilsbury |
243 | + * |
244 | + * Permission to use, copy, modify, distribute, and sell this software |
245 | + * and its documentation for any purpose is hereby granted without |
246 | + * fee, provided that the above copyright notice appear in all copies |
247 | + * and that both that copyright notice and this permission notice |
248 | + * appear in supporting documentation, and that the name of |
249 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
250 | + * distribution of the software without specific, written prior permission. |
251 | + * Canonical Ltd. makes no representations about the suitability of this |
252 | + * software for any purpose. It is provided "as is" without express or |
253 | + * implied warranty. |
254 | + * |
255 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
256 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
257 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
258 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
259 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
260 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
261 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
262 | + * |
263 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
264 | + */ |
265 | +#ifndef _COMPIZ_CONFIGURE_REQUEST_BUFFER_H |
266 | +#define _COMPIZ_CONFIGURE_REQUEST_BUFFER_H |
267 | + |
268 | +#include <boost/shared_ptr.hpp> |
269 | +#include <X11/Xlib.h> |
270 | +#include <syncserverwindow.h> |
271 | + |
272 | +namespace compiz |
273 | +{ |
274 | +namespace window |
275 | +{ |
276 | +namespace configure_buffers |
277 | +{ |
278 | +class Releasable |
279 | +{ |
280 | + public: |
281 | + |
282 | + typedef boost::shared_ptr <Releasable> Ptr; |
283 | + |
284 | + virtual void release () = 0; |
285 | +}; |
286 | + |
287 | +class Buffer : |
288 | + public SyncServerWindow |
289 | +{ |
290 | + public: |
291 | + |
292 | + typedef boost::shared_ptr <Buffer> Ptr; |
293 | + |
294 | + virtual ~Buffer () {} |
295 | + |
296 | + virtual void pushClientRequest (const XWindowChanges &xwc, unsigned int mask) = 0; |
297 | + virtual void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask) = 0; |
298 | + virtual void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask) = 0; |
299 | + |
300 | + virtual void pushSyntheticConfigureNotify () = 0; |
301 | + |
302 | + virtual Releasable::Ptr obtainLock () = 0; |
303 | + |
304 | + /* This API will all configure requests to be |
305 | + * released. It should only be used in situations |
306 | + * where you have a server grab and need |
307 | + * to have complete sync with the server */ |
308 | + virtual void forceRelease () = 0; |
309 | +}; |
310 | +} |
311 | +} |
312 | +} |
313 | +#endif |
314 | |
315 | === modified file 'include/core/window.h' |
316 | --- include/core/window.h 2013-01-03 16:06:41 +0000 |
317 | +++ include/core/window.h 2013-02-21 16:57:22 +0000 |
318 | @@ -54,13 +54,26 @@ |
319 | class PrivateWindow; |
320 | struct CompStartupSequence; |
321 | |
322 | -namespace compiz { namespace private_screen { |
323 | - class Ping; |
324 | - class GrabManager; |
325 | - class OutputDevices; |
326 | - class WindowManager; |
327 | - class StartupSequence; |
328 | -}} |
329 | +namespace compiz |
330 | +{ |
331 | +namespace window |
332 | +{ |
333 | +namespace configure_buffers |
334 | +{ |
335 | +class Releasable; |
336 | +typedef boost::shared_ptr <Releasable> ReleasablePtr; |
337 | +} |
338 | +} |
339 | + |
340 | +namespace private_screen |
341 | +{ |
342 | +class Ping; |
343 | +class GrabManager; |
344 | +class OutputDevices; |
345 | +class WindowManager; |
346 | +class StartupSequence; |
347 | +} |
348 | +} |
349 | |
350 | #define ROOTPARENT(x) (((x)->frame ()) ? (x)->frame () : (x)->id ()) |
351 | |
352 | @@ -529,6 +542,12 @@ |
353 | bool updateStruts (); |
354 | const CompStruts *struts () const; |
355 | |
356 | + bool queryAttributes (XWindowAttributes &); |
357 | + bool queryFrameAttributes (XWindowAttributes &); |
358 | + |
359 | + compiz::window::configure_buffers::ReleasablePtr |
360 | + obtainLockOnConfigureRequests (); |
361 | + |
362 | WRAPABLE_HND (0, WindowInterface, void, getOutputExtents, |
363 | CompWindowExtents&); |
364 | WRAPABLE_HND (1, WindowInterface, void, getAllowedActions, |
365 | |
366 | === modified file 'plugins/CMakeLists.txt' |
367 | --- plugins/CMakeLists.txt 2013-02-12 02:43:44 +0000 |
368 | +++ plugins/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
369 | @@ -7,23 +7,7 @@ |
370 | |
371 | add_definitions ( -DHAVE_CONFIG_H) |
372 | |
373 | -include_directories( |
374 | - ${CMAKE_CURRENT_SOURCE_DIR}/../include |
375 | - |
376 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src |
377 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/timer/include |
378 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/string/include |
379 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/pluginclasshandler/include |
380 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/point/include |
381 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/rect/include |
382 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/servergrab/include |
383 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/region/include |
384 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/window/geometry/include |
385 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/window/geometry-saver/include |
386 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/window/extents/include |
387 | - ${CMAKE_CURRENT_SOURCE_DIR}/../src/window/constrainment/include |
388 | - ${CMAKE_CURRENT_SOURCE_DIR}/../logmessage/include |
389 | -) |
390 | +include_directories (${COMPIZ_INTERNAL_INCLUDES}) |
391 | |
392 | # temporarily disable plugins that aren't ported yet |
393 | set (COMPIZ_DISABLE_PLUGIN_ANIMATIONADDON ON) |
394 | |
395 | === modified file 'plugins/composite/src/window.cpp' |
396 | --- plugins/composite/src/window.cpp 2012-12-13 10:12:23 +0000 |
397 | +++ plugins/composite/src/window.cpp 2013-02-21 16:57:22 +0000 |
398 | @@ -181,11 +181,7 @@ |
399 | bool |
400 | PrivateCompositeWindow::getAttributes (XWindowAttributes &attr) |
401 | { |
402 | - if (XGetWindowAttributes (screen->dpy (), |
403 | - ROOTPARENT (window), &attr)) |
404 | - return true; |
405 | - |
406 | - return false; |
407 | + return window->queryFrameAttributes (attr); |
408 | } |
409 | |
410 | bool |
411 | |
412 | === modified file 'plugins/move/move.xml.in' |
413 | --- plugins/move/move.xml.in 2012-12-13 10:12:23 +0000 |
414 | +++ plugins/move/move.xml.in 2013-02-21 16:57:22 +0000 |
415 | @@ -42,7 +42,7 @@ |
416 | <option name="lazy_positioning" type="bool"> |
417 | <_short>Lazy Positioning</_short> |
418 | <_long>Do not update the server-side position of windows until finished moving</_long> |
419 | - <default>true</default> |
420 | + <default>false</default> |
421 | </option> |
422 | </options> |
423 | </plugin> |
424 | |
425 | === modified file 'plugins/move/src/move.cpp' |
426 | --- plugins/move/src/move.cpp 2012-12-13 10:12:23 +0000 |
427 | +++ plugins/move/src/move.cpp 2013-02-21 16:57:22 +0000 |
428 | @@ -158,6 +158,14 @@ |
429 | if (mw->gWindow) |
430 | mw->gWindow->glPaintSetEnabled (mw, true); |
431 | } |
432 | + |
433 | + if (ms->optionGetLazyPositioning ()) |
434 | + { |
435 | + MOVE_WINDOW (w); |
436 | + |
437 | + if (mw->gWindow) |
438 | + mw->releasable = w->obtainLockOnConfigureRequests (); |
439 | + } |
440 | } |
441 | } |
442 | |
443 | @@ -173,6 +181,8 @@ |
444 | |
445 | if (ms->w) |
446 | { |
447 | + MOVE_WINDOW (ms->w); |
448 | + |
449 | if (state & CompAction::StateCancel) |
450 | ms->w->move (ms->savedX - ms->w->geometry ().x (), |
451 | ms->savedY - ms->w->geometry ().y (), false); |
452 | @@ -194,14 +204,14 @@ |
453 | |
454 | if (ms->moveOpacity != OPAQUE) |
455 | { |
456 | - MOVE_WINDOW (ms->w); |
457 | - |
458 | if (mw->cWindow) |
459 | mw->cWindow->addDamage (); |
460 | if (mw->gWindow) |
461 | mw->gWindow->glPaintSetEnabled (mw, false); |
462 | } |
463 | |
464 | + mw->releasable.reset (); |
465 | + |
466 | ms->w = 0; |
467 | ms->releaseButton = 0; |
468 | } |
469 | @@ -489,9 +499,6 @@ |
470 | w->move (wX + dx - w->geometry ().x (), |
471 | wY + dy - w->geometry ().y (), false); |
472 | |
473 | - if (!ms->optionGetLazyPositioning ()) |
474 | - w->syncPosition (); |
475 | - |
476 | ms->x -= dx; |
477 | ms->y -= dy; |
478 | } |
479 | |
480 | === modified file 'plugins/move/src/move.h' |
481 | --- plugins/move/src/move.h 2012-12-13 10:12:23 +0000 |
482 | +++ plugins/move/src/move.h 2013-02-21 16:57:22 +0000 |
483 | @@ -27,6 +27,7 @@ |
484 | |
485 | #include <core/screen.h> |
486 | #include <core/pluginclasshandler.h> |
487 | +#include <core/configurerequestbuffer.h> |
488 | |
489 | #include <composite/composite.h> |
490 | #include <opengl/opengl.h> |
491 | @@ -117,6 +118,7 @@ |
492 | CompWindow *window; |
493 | GLWindow *gWindow; |
494 | CompositeWindow *cWindow; |
495 | + compiz::window::configure_buffers::Releasable::Ptr releasable; |
496 | }; |
497 | |
498 | #define MOVE_SCREEN(s) \ |
499 | |
500 | === modified file 'plugins/opengl/src/paint.cpp' |
501 | --- plugins/opengl/src/paint.cpp 2013-01-01 10:04:50 +0000 |
502 | +++ plugins/opengl/src/paint.cpp 2013-02-21 16:57:22 +0000 |
503 | @@ -418,6 +418,11 @@ |
504 | if (w->destroyed ()) |
505 | continue; |
506 | |
507 | + gw = GLWindow::get (w); |
508 | + |
509 | + /* Release any queued ConfigureWindow requests now */ |
510 | + gw->priv->configureLock->release (); |
511 | + |
512 | if (unredirected.find (w) != unredirected.end ()) |
513 | continue; |
514 | |
515 | @@ -427,8 +432,6 @@ |
516 | continue; |
517 | } |
518 | |
519 | - gw = GLWindow::get (w); |
520 | - |
521 | const CompRegion &clip = |
522 | (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) ? |
523 | gw->clip () : region; |
524 | |
525 | === modified file 'plugins/opengl/src/privates.h' |
526 | --- plugins/opengl/src/privates.h 2013-01-01 09:41:41 +0000 |
527 | +++ plugins/opengl/src/privates.h 2013-02-21 16:57:22 +0000 |
528 | @@ -33,6 +33,7 @@ |
529 | #include <composite/composite.h> |
530 | #include <opengl/opengl.h> |
531 | #include <core/atoms.h> |
532 | +#include <core/configurerequestbuffer.h> |
533 | |
534 | #ifdef USE_GLES |
535 | #include <opengl/framebufferobject.h> |
536 | @@ -283,6 +284,8 @@ |
537 | GLVertexBuffer::AutoProgram *autoProgram; |
538 | |
539 | std::list<GLIcon> icons; |
540 | + |
541 | + compiz::window::configure_buffers::Releasable::Ptr configureLock; |
542 | }; |
543 | |
544 | #endif |
545 | |
546 | === modified file 'plugins/opengl/src/window.cpp' |
547 | --- plugins/opengl/src/window.cpp 2012-12-13 10:12:23 +0000 |
548 | +++ plugins/opengl/src/window.cpp 2013-02-21 16:57:22 +0000 |
549 | @@ -86,7 +86,8 @@ |
550 | bindFailed (false), |
551 | vertexBuffer (new GLVertexBuffer ()), |
552 | autoProgram(new GLWindowAutoProgram(this)), |
553 | - icons () |
554 | + icons (), |
555 | + configureLock (w->obtainLockOnConfigureRequests ()) |
556 | { |
557 | paint.xScale = 1.0f; |
558 | paint.yScale = 1.0f; |
559 | |
560 | === modified file 'src/CMakeLists.txt' |
561 | --- src/CMakeLists.txt 2012-12-13 10:12:23 +0000 |
562 | +++ src/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
563 | @@ -160,6 +160,12 @@ |
564 | compiz_window_geometry |
565 | ) |
566 | |
567 | +add_library (compiz_configurerequestbuffer STATIC |
568 | + configurerequestbuffer.cpp) |
569 | + |
570 | +target_link_libraries (compiz_configurerequestbuffer |
571 | + compiz_window_geometry) |
572 | + |
573 | # workaround for build race |
574 | add_dependencies (compiz core-xml-file) |
575 | |
576 | @@ -192,6 +198,7 @@ |
577 | compiz_servergrab |
578 | compiz_output |
579 | compiz_outputdevices |
580 | + compiz_configurerequestbuffer |
581 | -Wl,-no-whole-archive |
582 | # ${CORE_MOD_LIBRARIES} |
583 | ) |
584 | |
585 | === added file 'src/asyncserverwindow.h' |
586 | --- src/asyncserverwindow.h 1970-01-01 00:00:00 +0000 |
587 | +++ src/asyncserverwindow.h 2013-02-21 16:57:22 +0000 |
588 | @@ -0,0 +1,52 @@ |
589 | +/* |
590 | + * Copyright © 2012 Sam Spilsbury |
591 | + * |
592 | + * Permission to use, copy, modify, distribute, and sell this software |
593 | + * and its documentation for any purpose is hereby granted without |
594 | + * fee, provided that the above copyright notice appear in all copies |
595 | + * and that both that copyright notice and this permission notice |
596 | + * appear in supporting documentation, and that the name of |
597 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
598 | + * distribution of the software without specific, written prior permission. |
599 | + * Canonical Ltd. makes no representations about the suitability of this |
600 | + * software for any purpose. It is provided "as is" without express or |
601 | + * implied warranty. |
602 | + * |
603 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
604 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
605 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
606 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
607 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
608 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
609 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
610 | + * |
611 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
612 | + */ |
613 | +#ifndef _COMPIZ_ASYNC_SERVER_WINDOW_H |
614 | +#define _COMPIZ_ASYNC_SERVER_WINDOW_H |
615 | + |
616 | +#include <X11/Xlib.h> |
617 | + |
618 | +namespace compiz |
619 | +{ |
620 | +namespace window |
621 | +{ |
622 | +class AsyncServerWindow |
623 | +{ |
624 | + public: |
625 | + |
626 | + virtual ~AsyncServerWindow () {}; |
627 | + |
628 | + virtual int requestConfigureOnClient (const XWindowChanges &xwc, |
629 | + unsigned int valueMask) = 0; |
630 | + virtual int requestConfigureOnWrapper (const XWindowChanges &xwc, |
631 | + unsigned int valueMask) = 0; |
632 | + virtual int requestConfigureOnFrame (const XWindowChanges &xwc, |
633 | + unsigned int valueMask) = 0; |
634 | + virtual void sendSyntheticConfigureNotify () = 0; |
635 | + virtual bool hasCustomShape () const = 0; |
636 | +}; |
637 | +} |
638 | +} |
639 | + |
640 | +#endif |
641 | |
642 | === added file 'src/configurerequestbuffer-impl.h' |
643 | --- src/configurerequestbuffer-impl.h 1970-01-01 00:00:00 +0000 |
644 | +++ src/configurerequestbuffer-impl.h 2013-02-21 16:57:22 +0000 |
645 | @@ -0,0 +1,145 @@ |
646 | +/* |
647 | + * Copyright © 2012 Sam Spilsbury |
648 | + * |
649 | + * Permission to use, copy, modify, distribute, and sell this software |
650 | + * and its documentation for any purpose is hereby granted without |
651 | + * fee, provided that the above copyright notice appear in all copies |
652 | + * and that both that copyright notice and this permission notice |
653 | + * appear in supporting documentation, and that the name of |
654 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
655 | + * distribution of the software without specific, written prior permission. |
656 | + * Canonical Ltd. makes no representations about the suitability of this |
657 | + * software for any purpose. It is provided "as is" without express or |
658 | + * implied warranty. |
659 | + * |
660 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
661 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
662 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
663 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
664 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
665 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
666 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
667 | + * |
668 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
669 | + */ |
670 | +#ifndef _COMPIZ_GEOMETRY_UPDATE_QUEUE_H |
671 | +#define _COMPIZ_GEOMETRY_UPDATE_QUEUE_H |
672 | + |
673 | +#include <memory> |
674 | +#include <vector> |
675 | +#include <boost/weak_ptr.hpp> |
676 | +#include <boost/shared_ptr.hpp> |
677 | +#include <boost/function.hpp> |
678 | +#include <X11/Xlib.h> |
679 | + |
680 | +#include <core/configurerequestbuffer.h> |
681 | + |
682 | +namespace compiz |
683 | +{ |
684 | +namespace window |
685 | +{ |
686 | +class AsyncServerWindow; |
687 | +namespace configure_buffers |
688 | +{ |
689 | + |
690 | +class Lockable |
691 | +{ |
692 | + public: |
693 | + |
694 | + typedef boost::shared_ptr <Lockable> Ptr; |
695 | + typedef boost::weak_ptr <Lockable> Weak; |
696 | + |
697 | + virtual ~Lockable () {} |
698 | + |
699 | + virtual void lock () = 0; |
700 | +}; |
701 | + |
702 | +class BufferLock : |
703 | + public Lockable, |
704 | + public Releasable |
705 | +{ |
706 | + public: |
707 | + typedef boost::shared_ptr <BufferLock> Ptr; |
708 | + |
709 | + virtual ~BufferLock () {} |
710 | +}; |
711 | + |
712 | +class CountedFreeze |
713 | +{ |
714 | + public: |
715 | + |
716 | + virtual ~CountedFreeze () {} |
717 | + |
718 | + virtual void freeze () = 0; |
719 | + virtual void release () = 0; |
720 | + |
721 | + virtual void untrackLock (compiz::window::configure_buffers::BufferLock *lock) = 0; |
722 | +}; |
723 | + |
724 | +class ConfigureRequestBuffer : |
725 | + public CountedFreeze, |
726 | + public Buffer |
727 | +{ |
728 | + public: |
729 | + |
730 | + typedef boost::function <BufferLock::Ptr (CountedFreeze *)> LockFactory; |
731 | + |
732 | + void freeze (); |
733 | + void release (); |
734 | + |
735 | + void untrackLock (compiz::window::configure_buffers::BufferLock *lock); |
736 | + |
737 | + void pushClientRequest (const XWindowChanges &xwc, unsigned int mask); |
738 | + void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask); |
739 | + void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask); |
740 | + void pushSyntheticConfigureNotify (); |
741 | + compiz::window::configure_buffers::Releasable::Ptr obtainLock (); |
742 | + |
743 | + /* Implement getAttributes and require that |
744 | + * the queue is released before calling through |
745 | + * to the SyncServerWindow */ |
746 | + bool queryAttributes (XWindowAttributes &attrib); |
747 | + bool queryFrameAttributes (XWindowAttributes &attrib); |
748 | + XRectangle * queryShapeRectangles (int kind, |
749 | + int *count, |
750 | + int *ordering); |
751 | + |
752 | + void forceRelease (); |
753 | + |
754 | + static compiz::window::configure_buffers::Buffer::Ptr |
755 | + Create (AsyncServerWindow *asyncServerWindow, |
756 | + SyncServerWindow *syncServerWindow, |
757 | + const LockFactory &factory); |
758 | + |
759 | + private: |
760 | + |
761 | + ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow, |
762 | + SyncServerWindow *syncServerWindow, |
763 | + const LockFactory &factory); |
764 | + |
765 | + class Private; |
766 | + std::auto_ptr <Private> priv; |
767 | +}; |
768 | + |
769 | +class ConfigureBufferLock : |
770 | + public compiz::window::configure_buffers::BufferLock |
771 | +{ |
772 | + public: |
773 | + |
774 | + typedef boost::shared_ptr <ConfigureBufferLock> Ptr; |
775 | + |
776 | + ConfigureBufferLock (CountedFreeze *); |
777 | + ~ConfigureBufferLock (); |
778 | + |
779 | + void lock (); |
780 | + void release (); |
781 | + |
782 | + private: |
783 | + |
784 | + class Private; |
785 | + std::auto_ptr <Private> priv; |
786 | +}; |
787 | +} |
788 | +} |
789 | +} |
790 | +#endif |
791 | |
792 | === added file 'src/configurerequestbuffer.cpp' |
793 | --- src/configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000 |
794 | +++ src/configurerequestbuffer.cpp 2013-02-21 16:57:22 +0000 |
795 | @@ -0,0 +1,363 @@ |
796 | +/* |
797 | + * Copyright © 2012 Sam Spilsbury |
798 | + * |
799 | + * Permission to use, copy, modify, distribute, and sell this software |
800 | + * and its documentation for any purpose is hereby granted without |
801 | + * fee, provided that the above copyright notice appear in all copies |
802 | + * and that both that copyright notice and this permission notice |
803 | + * appear in supporting documentation, and that the name of |
804 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
805 | + * distribution of the software without specific, written prior permission. |
806 | + * Canonical Ltd. makes no representations about the suitability of this |
807 | + * software for any purpose. It is provided "as is" without express or |
808 | + * implied warranty. |
809 | + * |
810 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
811 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
812 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
813 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
814 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
815 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
816 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
817 | + * |
818 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
819 | + */ |
820 | +#include <cstdio> |
821 | +#include <cassert> |
822 | +#include <boost/foreach.hpp> |
823 | +#include <boost/weak_ptr.hpp> |
824 | +#include <boost/bind.hpp> |
825 | +#include "asyncserverwindow.h" |
826 | +#include "configurerequestbuffer-impl.h" |
827 | + |
828 | +#ifndef foreach |
829 | +#define foreach BOOST_FOREACH |
830 | +#endif |
831 | + |
832 | +namespace crb = compiz::window::configure_buffers; |
833 | +namespace cw = compiz::window; |
834 | + |
835 | +class crb::ConfigureRequestBuffer::Private |
836 | +{ |
837 | + public: |
838 | + |
839 | + typedef crb::Lockable::Weak LockObserver; |
840 | + |
841 | + Private (cw::AsyncServerWindow *asyncServerWindow, |
842 | + cw::SyncServerWindow *syncServerWindow, |
843 | + const crb::ConfigureRequestBuffer::LockFactory &lockFactory) : |
844 | + clientChangeMask (0), |
845 | + wrapperChangeMask (0), |
846 | + frameChangeMask (0), |
847 | + sendSyntheticConfigure (false), |
848 | + lockCount (0), |
849 | + asyncServerWindow (asyncServerWindow), |
850 | + syncServerWindow (syncServerWindow), |
851 | + lockFactory (lockFactory) |
852 | + { |
853 | + } |
854 | + |
855 | + void dispatchConfigure (bool force = false); |
856 | + |
857 | + XWindowChanges clientChanges; |
858 | + unsigned int clientChangeMask; |
859 | + |
860 | + XWindowChanges wrapperChanges; |
861 | + unsigned int wrapperChangeMask; |
862 | + |
863 | + XWindowChanges frameChanges; |
864 | + unsigned int frameChangeMask; |
865 | + |
866 | + bool sendSyntheticConfigure; |
867 | + |
868 | + unsigned int lockCount; |
869 | + |
870 | + cw::AsyncServerWindow *asyncServerWindow; |
871 | + cw::SyncServerWindow *syncServerWindow; |
872 | + |
873 | + crb::ConfigureRequestBuffer::LockFactory lockFactory; |
874 | + std::vector <LockObserver> locks; |
875 | +}; |
876 | + |
877 | +void |
878 | +crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force) |
879 | +{ |
880 | + const unsigned int allEventMasks = 0x7f; |
881 | + bool immediate = frameChangeMask & (CWStackMode | CWSibling); |
882 | + |
883 | + /* This is a stop-gap solution for not having a plugin API to |
884 | + * query the window shape. Once we have that, we can safely |
885 | + * remove these and require the queue to be unlocked when that |
886 | + * happens. Its a separate unit of work for improving resize |
887 | + * performance anyways. |
888 | + */ |
889 | + immediate |= (frameChangeMask & (CWWidth | CWHeight | CWBorderWidth)); |
890 | + immediate |= (wrapperChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY)); |
891 | + immediate |= (clientChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY)); |
892 | + immediate |= force; |
893 | + |
894 | + bool clientDispatch = (clientChangeMask & allEventMasks); |
895 | + bool wrapperDispatch = (wrapperChangeMask & allEventMasks); |
896 | + bool frameDispatch = (frameChangeMask & allEventMasks); |
897 | + |
898 | + bool dispatch = !lockCount && (clientDispatch || |
899 | + wrapperDispatch || |
900 | + frameDispatch || |
901 | + sendSyntheticConfigure); |
902 | + |
903 | + if (dispatch || immediate) |
904 | + { |
905 | + if (frameDispatch) |
906 | + { |
907 | + asyncServerWindow->requestConfigureOnFrame (frameChanges, |
908 | + frameChangeMask); |
909 | + frameChangeMask = 0; |
910 | + } |
911 | + |
912 | + if (wrapperDispatch) |
913 | + { |
914 | + asyncServerWindow->requestConfigureOnWrapper (wrapperChanges, |
915 | + wrapperChangeMask); |
916 | + wrapperChangeMask = 0; |
917 | + } |
918 | + |
919 | + if (clientDispatch) |
920 | + { |
921 | + asyncServerWindow->requestConfigureOnClient (clientChanges, |
922 | + clientChangeMask); |
923 | + clientChangeMask = 0; |
924 | + } |
925 | + |
926 | + if (sendSyntheticConfigure) |
927 | + { |
928 | + asyncServerWindow->sendSyntheticConfigureNotify (); |
929 | + sendSyntheticConfigure = false; |
930 | + } |
931 | + |
932 | + foreach (const LockObserver &lock, locks) |
933 | + { |
934 | + crb::Lockable::Ptr strongLock (lock.lock ()); |
935 | + |
936 | + /* We might be in a lock's destructor so check |
937 | + * if this can really be re-locked, if not, its |
938 | + * no big deal as the lock is going away anyways |
939 | + */ |
940 | + if (strongLock) |
941 | + strongLock->lock (); |
942 | + } |
943 | + } |
944 | +} |
945 | + |
946 | +void |
947 | +crb::ConfigureRequestBuffer::freeze () |
948 | +{ |
949 | + priv->lockCount++; |
950 | + |
951 | + assert (priv->lockCount <= priv->locks.size ()); |
952 | +} |
953 | + |
954 | +void |
955 | +crb::ConfigureRequestBuffer::release () |
956 | +{ |
957 | + assert (priv->lockCount); |
958 | + |
959 | + priv->lockCount--; |
960 | + |
961 | + priv->dispatchConfigure (); |
962 | +} |
963 | + |
964 | +namespace |
965 | +{ |
966 | +void applyChangeToXWC (const XWindowChanges &from, |
967 | + XWindowChanges &to, |
968 | + unsigned int mask) |
969 | +{ |
970 | + if (mask & CWX) |
971 | + to.x = from.x; |
972 | + |
973 | + if (mask & CWY) |
974 | + to.y = from.y; |
975 | + |
976 | + if (mask & CWWidth) |
977 | + to.width = from.width; |
978 | + |
979 | + if (mask & CWHeight) |
980 | + to.height = from.height; |
981 | + |
982 | + if (mask & CWBorderWidth) |
983 | + to.border_width = from.border_width; |
984 | + |
985 | + if (mask & CWSibling) |
986 | + to.sibling = from.sibling; |
987 | + |
988 | + if (mask & CWStackMode) |
989 | + to.stack_mode = from.stack_mode; |
990 | +} |
991 | +} |
992 | + |
993 | +void |
994 | +crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc, |
995 | + unsigned int mask) |
996 | +{ |
997 | + applyChangeToXWC (xwc, priv->clientChanges, mask); |
998 | + priv->clientChangeMask |= mask; |
999 | + |
1000 | + priv->dispatchConfigure (); |
1001 | +} |
1002 | + |
1003 | +void |
1004 | +crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc, |
1005 | + unsigned int mask) |
1006 | +{ |
1007 | + applyChangeToXWC (xwc, priv->wrapperChanges, mask); |
1008 | + priv->wrapperChangeMask |= mask; |
1009 | + |
1010 | + priv->dispatchConfigure (); |
1011 | +} |
1012 | + |
1013 | +void |
1014 | +crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc, |
1015 | + unsigned int mask) |
1016 | +{ |
1017 | + applyChangeToXWC (xwc, priv->frameChanges, mask); |
1018 | + priv->frameChangeMask |= mask; |
1019 | + |
1020 | + priv->dispatchConfigure (); |
1021 | +} |
1022 | + |
1023 | +void |
1024 | +crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify () |
1025 | +{ |
1026 | + priv->sendSyntheticConfigure = true; |
1027 | + |
1028 | + priv->dispatchConfigure (); |
1029 | +} |
1030 | + |
1031 | +crb::Releasable::Ptr |
1032 | +crb::ConfigureRequestBuffer::obtainLock () |
1033 | +{ |
1034 | + crb::BufferLock::Ptr lock (priv->lockFactory (this)); |
1035 | + |
1036 | + priv->locks.push_back (crb::Lockable::Weak (lock)); |
1037 | + lock->lock (); |
1038 | + |
1039 | + return lock; |
1040 | +} |
1041 | + |
1042 | +namespace |
1043 | +{ |
1044 | +bool isLock (const crb::Lockable::Weak &lockable, |
1045 | + crb::BufferLock *lock) |
1046 | +{ |
1047 | + crb::Lockable::Ptr strongLockable (lockable.lock ()); |
1048 | + |
1049 | + /* Asserting that the lock did not go away without telling |
1050 | + * us first */ |
1051 | + assert (strongLockable.get ()); |
1052 | + |
1053 | + if (strongLockable.get () == lock) |
1054 | + return true; |
1055 | + |
1056 | + return false; |
1057 | +} |
1058 | +} |
1059 | + |
1060 | +void |
1061 | +crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock) |
1062 | +{ |
1063 | + std::remove_if (priv->locks.begin (), |
1064 | + priv->locks.end (), |
1065 | + boost::bind (isLock, _1, lock)); |
1066 | +} |
1067 | + |
1068 | +bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib) |
1069 | +{ |
1070 | + priv->dispatchConfigure (true); |
1071 | + return priv->syncServerWindow->queryAttributes (attrib); |
1072 | +} |
1073 | + |
1074 | +bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib) |
1075 | +{ |
1076 | + priv->dispatchConfigure (true); |
1077 | + return priv->syncServerWindow->queryFrameAttributes (attrib); |
1078 | +} |
1079 | + |
1080 | +/* This is more or less of a stop-gap for the fact that |
1081 | + * when resizing window we re-query the window shape |
1082 | + * and apply that to the frame. That's a separate unit of |
1083 | + * work and should be dealt with separately. For now, force |
1084 | + * a release of the queue whenever we do that so that |
1085 | + * XShapeGetRectangles doesn't return an unexpected value |
1086 | + */ |
1087 | +XRectangle * |
1088 | +crb::ConfigureRequestBuffer::queryShapeRectangles (int kind, |
1089 | + int *count, |
1090 | + int *ordering) |
1091 | +{ |
1092 | + priv->dispatchConfigure (true); |
1093 | + return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering); |
1094 | +} |
1095 | + |
1096 | +void crb::ConfigureRequestBuffer::forceRelease () |
1097 | +{ |
1098 | + priv->dispatchConfigure (true); |
1099 | +} |
1100 | + |
1101 | +crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow, |
1102 | + SyncServerWindow *syncServerWindow, |
1103 | + const crb::ConfigureRequestBuffer::LockFactory &factory) : |
1104 | + priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory)) |
1105 | +{ |
1106 | +} |
1107 | + |
1108 | +compiz::window::configure_buffers::Buffer::Ptr |
1109 | +crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow, |
1110 | + SyncServerWindow *syncServerWindow, |
1111 | + const LockFactory &factory) |
1112 | +{ |
1113 | + return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow, |
1114 | + syncServerWindow, |
1115 | + factory)); |
1116 | +} |
1117 | + |
1118 | +class crb::ConfigureBufferLock::Private |
1119 | +{ |
1120 | + public: |
1121 | + |
1122 | + Private (crb::CountedFreeze *freezable) : |
1123 | + freezable (freezable), |
1124 | + armed (false) |
1125 | + { |
1126 | + } |
1127 | + |
1128 | + crb::CountedFreeze *freezable; |
1129 | + bool armed; |
1130 | +}; |
1131 | + |
1132 | +crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) : |
1133 | + priv (new crb::ConfigureBufferLock::Private (freezable)) |
1134 | +{ |
1135 | +} |
1136 | + |
1137 | +crb::ConfigureBufferLock::~ConfigureBufferLock () |
1138 | +{ |
1139 | + release (); |
1140 | +} |
1141 | + |
1142 | +void |
1143 | +crb::ConfigureBufferLock::lock () |
1144 | +{ |
1145 | + if (!priv->armed) |
1146 | + priv->freezable->freeze (); |
1147 | + |
1148 | + priv->armed = true; |
1149 | +} |
1150 | + |
1151 | +void |
1152 | +crb::ConfigureBufferLock::release () |
1153 | +{ |
1154 | + if (priv->armed) |
1155 | + priv->freezable->release (); |
1156 | + |
1157 | + priv->armed = false; |
1158 | +} |
1159 | |
1160 | === modified file 'src/event.cpp' |
1161 | --- src/event.cpp 2013-01-03 16:06:41 +0000 |
1162 | +++ src/event.cpp 2013-02-21 16:57:22 +0000 |
1163 | @@ -1947,7 +1947,7 @@ |
1164 | |
1165 | /* We should check the override_redirect flag here, because the |
1166 | client might have changed it while being unmapped. */ |
1167 | - if (XGetWindowAttributes (privateScreen.dpy, w->id (), &attr)) |
1168 | + if (w->queryAttributes (attr)) |
1169 | w->priv->setOverrideRedirect (attr.override_redirect != 0); |
1170 | |
1171 | if (w->state () & CompWindowStateHiddenMask) |
1172 | |
1173 | === modified file 'src/plugin.cpp' |
1174 | --- src/plugin.cpp 2013-01-24 14:18:03 +0000 |
1175 | +++ src/plugin.cpp 2013-02-21 16:57:22 +0000 |
1176 | @@ -398,6 +398,7 @@ |
1177 | CompPlugin * |
1178 | CompPlugin::load (const char *name) |
1179 | { |
1180 | + char *compiz_plugin_dir_override = getenv ("COMPIZ_PLUGIN_DIR"); |
1181 | std::auto_ptr<CompPlugin>p(new CompPlugin ()); |
1182 | |
1183 | p->devPrivate.uval = 0; |
1184 | @@ -406,6 +407,12 @@ |
1185 | |
1186 | compLogMessage (here, CompLogLevelInfo, "Loading plugin: %s", name); |
1187 | |
1188 | + if (compiz_plugin_dir_override) |
1189 | + { |
1190 | + if (loaderLoadPlugin (p.get (), compiz_plugin_dir_override, name)) |
1191 | + return p.release (); |
1192 | + } |
1193 | + |
1194 | if (char* home = getenv ("HOME")) |
1195 | { |
1196 | boost::scoped_array<char> plugindir(new char [strlen (home) + strlen (HOME_PLUGINDIR) + 3]); |
1197 | |
1198 | === modified file 'src/plugin/tests/CMakeLists.txt' |
1199 | --- src/plugin/tests/CMakeLists.txt 2012-08-01 00:42:38 +0000 |
1200 | +++ src/plugin/tests/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
1201 | @@ -5,6 +5,7 @@ |
1202 | |
1203 | ${compiz_SOURCE_DIR}/include |
1204 | ${compiz_SOURCE_DIR}/src |
1205 | + ${compiz_SOURCE_DIR}/tests/shared |
1206 | ) |
1207 | |
1208 | add_definitions ( |
1209 | |
1210 | === modified file 'src/plugin/tests/test-plugin.cpp' |
1211 | --- src/plugin/tests/test-plugin.cpp 2012-06-24 09:00:27 +0000 |
1212 | +++ src/plugin/tests/test-plugin.cpp 2013-02-21 16:57:22 +0000 |
1213 | @@ -9,6 +9,7 @@ |
1214 | |
1215 | #include <gtest/gtest.h> |
1216 | #include <gmock/gmock.h> |
1217 | +#include <gtest_shared_tmpenv.h> |
1218 | |
1219 | namespace { |
1220 | |
1221 | @@ -136,6 +137,34 @@ |
1222 | CompPlugin::unload(cp); |
1223 | } |
1224 | |
1225 | +TEST(PluginTest, load_plugin_from_COMPIZ_PLUGIN_DIR_env_succeeds) |
1226 | +{ |
1227 | + const char *COMPIZ_PLUGIN_DIR_VALUE = "/path/to/plugin/dir"; |
1228 | + TmpEnv env ("COMPIZ_PLUGIN_DIR", COMPIZ_PLUGIN_DIR_VALUE); |
1229 | + MockPluginFilesystem mockfs; |
1230 | + |
1231 | + using namespace testing; |
1232 | + |
1233 | + EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(COMPIZ_PLUGIN_DIR_VALUE), StrEq("dummy"))). |
1234 | + WillOnce(Return(true)); |
1235 | + |
1236 | + EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("dummy"))). |
1237 | + Times(AtMost(0)); |
1238 | + |
1239 | + EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(PLUGINDIR), StrEq("dummy"))). |
1240 | + Times(AtMost(0)); |
1241 | + |
1242 | + EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), Eq((void*)0), StrEq("dummy"))). |
1243 | + Times(AtMost(0)); |
1244 | + |
1245 | + EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(1); |
1246 | + |
1247 | + CompPlugin* cp = CompPlugin::load("dummy"); |
1248 | + ASSERT_NE((void*)0, cp); |
1249 | + |
1250 | + CompPlugin::unload(cp); |
1251 | +} |
1252 | + |
1253 | TEST(PluginTest, load_plugin_from_void_succeeds) |
1254 | { |
1255 | MockPluginFilesystem mockfs; |
1256 | |
1257 | === modified file 'src/privatewindow.h' |
1258 | --- src/privatewindow.h 2013-01-03 16:06:41 +0000 |
1259 | +++ src/privatewindow.h 2013-02-21 16:57:22 +0000 |
1260 | @@ -35,6 +35,11 @@ |
1261 | |
1262 | #include <boost/shared_ptr.hpp> |
1263 | |
1264 | +#include <core/configurerequestbuffer.h> |
1265 | + |
1266 | +#include "syncserverwindow.h" |
1267 | +#include "asyncserverwindow.h" |
1268 | + |
1269 | #define XWINDOWCHANGES_INIT {0, 0, 0, 0, 0, None, 0} |
1270 | |
1271 | namespace compiz {namespace X11 |
1272 | @@ -107,12 +112,47 @@ |
1273 | |
1274 | typedef CompWindowExtents CompFullscreenMonitorSet; |
1275 | |
1276 | -class PrivateWindow { |
1277 | +class X11SyncServerWindow : |
1278 | + public compiz::window::SyncServerWindow |
1279 | +{ |
1280 | + public: |
1281 | + |
1282 | + X11SyncServerWindow (Display *dpy, |
1283 | + const Window *w, |
1284 | + const Window *frame); |
1285 | + |
1286 | + bool queryAttributes (XWindowAttributes &attrib); |
1287 | + bool queryFrameAttributes (XWindowAttributes &attrib); |
1288 | + XRectangle * queryShapeRectangles(int kind, int *count, int *ordering); |
1289 | + |
1290 | + private: |
1291 | + |
1292 | + Display *mDpy; |
1293 | + const Window *mWindow; |
1294 | + const Window *mFrame; |
1295 | +}; |
1296 | + |
1297 | +class PrivateWindow : |
1298 | + public compiz::window::SyncServerWindow, |
1299 | + public compiz::window::AsyncServerWindow |
1300 | +{ |
1301 | |
1302 | public: |
1303 | PrivateWindow (); |
1304 | ~PrivateWindow (); |
1305 | |
1306 | + bool queryAttributes (XWindowAttributes &attrib); |
1307 | + bool queryFrameAttributes (XWindowAttributes &attrib); |
1308 | + XRectangle * queryShapeRectangles (int kind, int *count, int *ordering); |
1309 | + int requestConfigureOnClient (const XWindowChanges &xwc, |
1310 | + unsigned int valueMask); |
1311 | + int requestConfigureOnWrapper (const XWindowChanges &xwc, |
1312 | + unsigned int valueMask); |
1313 | + int requestConfigureOnFrame (const XWindowChanges &xwc, |
1314 | + unsigned int valueMask); |
1315 | + void sendSyntheticConfigureNotify (); |
1316 | + bool hasCustomShape () const; |
1317 | + |
1318 | void recalcNormalHints (); |
1319 | |
1320 | void updateFrameWindow (); |
1321 | @@ -382,6 +422,7 @@ |
1322 | |
1323 | CompWindowExtents input; |
1324 | CompWindowExtents serverInput; |
1325 | + CompWindowExtents lastServerInput; |
1326 | CompWindowExtents border; |
1327 | CompWindowExtents output; |
1328 | |
1329 | @@ -407,6 +448,9 @@ |
1330 | Time lastCloseRequestTime; |
1331 | |
1332 | bool nextMoveImmediate; |
1333 | + |
1334 | + X11SyncServerWindow syncServerWindow; |
1335 | + compiz::window::configure_buffers::Buffer::Ptr configureBuffer; |
1336 | }; |
1337 | |
1338 | #endif |
1339 | |
1340 | === added file 'src/serverwindow.h' |
1341 | === added file 'src/syncserverwindow.h' |
1342 | --- src/syncserverwindow.h 1970-01-01 00:00:00 +0000 |
1343 | +++ src/syncserverwindow.h 2013-02-21 16:57:22 +0000 |
1344 | @@ -0,0 +1,49 @@ |
1345 | +/* |
1346 | + * Copyright © 2012 Sam Spilsbury |
1347 | + * |
1348 | + * Permission to use, copy, modify, distribute, and sell this software |
1349 | + * and its documentation for any purpose is hereby granted without |
1350 | + * fee, provided that the above copyright notice appear in all copies |
1351 | + * and that both that copyright notice and this permission notice |
1352 | + * appear in supporting documentation, and that the name of |
1353 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
1354 | + * distribution of the software without specific, written prior permission. |
1355 | + * Canonical Ltd. makes no representations about the suitability of this |
1356 | + * software for any purpose. It is provided "as is" without express or |
1357 | + * implied warranty. |
1358 | + * |
1359 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
1360 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
1361 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
1362 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
1363 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
1364 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
1365 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1366 | + * |
1367 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
1368 | + */ |
1369 | +#ifndef _COMPIZ_SYNC_SERVER_WINDOW_H |
1370 | +#define _COMPIZ_SYNC_SERVER_WINDOW_H |
1371 | + |
1372 | +#include <X11/Xlib.h> |
1373 | + |
1374 | +namespace compiz |
1375 | +{ |
1376 | +namespace window |
1377 | +{ |
1378 | +class SyncServerWindow |
1379 | +{ |
1380 | + public: |
1381 | + |
1382 | + virtual ~SyncServerWindow () {} |
1383 | + |
1384 | + virtual bool queryAttributes (XWindowAttributes &attrib) = 0; |
1385 | + virtual bool queryFrameAttributes (XWindowAttributes &attrib) = 0; |
1386 | + virtual XRectangle * queryShapeRectangles (int kind, |
1387 | + int *count, |
1388 | + int *ordering) = 0; |
1389 | +}; |
1390 | +} |
1391 | +} |
1392 | + |
1393 | +#endif |
1394 | |
1395 | === modified file 'src/tests/CMakeLists.txt' |
1396 | --- src/tests/CMakeLists.txt 2013-01-03 16:06:41 +0000 |
1397 | +++ src/tests/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
1398 | @@ -30,3 +30,14 @@ |
1399 | |
1400 | compiz_discover_tests(compiz_test_outputdevices COVERAGE compiz_core) |
1401 | |
1402 | +add_executable (compiz_test_configurerequestbuffer |
1403 | + test_configurerequestbuffer.cpp) |
1404 | + |
1405 | +target_link_libraries (compiz_test_configurerequestbuffer |
1406 | + compiz_configurerequestbuffer |
1407 | + ${GTEST_BOTH_LIBRARIES} |
1408 | + ${GMOCK_MAIN_LIBRARY} |
1409 | + ${GMOCK_LIBRARY} |
1410 | +) |
1411 | + |
1412 | +compiz_discover_tests(compiz_test_configurerequestbuffer COVERAGE compiz_configurerequestbuffer) |
1413 | |
1414 | === added file 'src/tests/test_configurerequestbuffer.cpp' |
1415 | --- src/tests/test_configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000 |
1416 | +++ src/tests/test_configurerequestbuffer.cpp 2013-02-21 16:57:22 +0000 |
1417 | @@ -0,0 +1,667 @@ |
1418 | +/* |
1419 | + * Copyright © 2012 Sam Spilsbury |
1420 | + * |
1421 | + * Permission to use, copy, modify, distribute, and sell this software |
1422 | + * and its documentation for any purpose is hereby granted without |
1423 | + * fee, provided that the above copyright notice appear in all copies |
1424 | + * and that both that copyright notice and this permission notice |
1425 | + * appear in supporting documentation, and that the name of |
1426 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
1427 | + * distribution of the software without specific, written prior permission. |
1428 | + * Canonical Ltd. makes no representations about the suitability of this |
1429 | + * software for any purpose. It is provided "as is" without express or |
1430 | + * implied warranty. |
1431 | + * |
1432 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
1433 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
1434 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
1435 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
1436 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
1437 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
1438 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1439 | + * |
1440 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
1441 | + */ |
1442 | +#include <deque> |
1443 | +#include <boost/shared_ptr.hpp> |
1444 | +#include <boost/make_shared.hpp> |
1445 | +#include <boost/bind.hpp> |
1446 | +#include <gmock/gmock.h> |
1447 | +#include <gtest/gtest.h> |
1448 | +#include <X11/Xlib.h> |
1449 | + |
1450 | +#include "configurerequestbuffer-impl.h" |
1451 | +#include "asyncserverwindow.h" |
1452 | + |
1453 | +namespace crb = compiz::window::configure_buffers; |
1454 | +namespace cw = compiz::window; |
1455 | + |
1456 | +using testing::_; |
1457 | +using testing::NiceMock; |
1458 | +using testing::Return; |
1459 | +using testing::Invoke; |
1460 | +using testing::WithArgs; |
1461 | +using testing::SetArgReferee; |
1462 | +using testing::DoAll; |
1463 | +using testing::InSequence; |
1464 | +using testing::ReturnNull; |
1465 | +using testing::IsNull; |
1466 | + |
1467 | +class MockAsyncServerWindow : |
1468 | + public cw::AsyncServerWindow |
1469 | +{ |
1470 | + public: |
1471 | + |
1472 | + MOCK_METHOD2 (requestConfigureOnClient, int (const XWindowChanges &, unsigned int)); |
1473 | + MOCK_METHOD2 (requestConfigureOnFrame, int (const XWindowChanges &, unsigned int)); |
1474 | + MOCK_METHOD2 (requestConfigureOnWrapper, int (const XWindowChanges &, unsigned int)); |
1475 | + MOCK_METHOD0 (sendSyntheticConfigureNotify, void ()); |
1476 | + MOCK_CONST_METHOD0 (hasCustomShape, bool ()); |
1477 | +}; |
1478 | + |
1479 | +class MockSyncServerWindow : |
1480 | + public cw::SyncServerWindow |
1481 | +{ |
1482 | + public: |
1483 | + |
1484 | + MOCK_METHOD1 (queryAttributes, bool (XWindowAttributes &)); |
1485 | + MOCK_METHOD1 (queryFrameAttributes, bool (XWindowAttributes &)); |
1486 | + MOCK_METHOD3 (queryShapeRectangles, XRectangle * (int, int *, int *)); |
1487 | +}; |
1488 | + |
1489 | +namespace |
1490 | +{ |
1491 | +int REQUEST_X = 1; |
1492 | +int REQUEST_Y = 2; |
1493 | +int REQUEST_WIDTH = 3; |
1494 | +int REQUEST_HEIGHT = 4; |
1495 | +int REQUEST_BORDER = 5; |
1496 | + |
1497 | +Window REQUEST_ABOVE = 6; |
1498 | +unsigned int REQUEST_MODE = 7; |
1499 | + |
1500 | +crb::BufferLock::Ptr |
1501 | +CreateNormalLock (crb::CountedFreeze *cf) |
1502 | +{ |
1503 | + return boost::make_shared <crb::ConfigureBufferLock> (cf); |
1504 | +} |
1505 | + |
1506 | +} |
1507 | + |
1508 | +MATCHER_P2 (MaskXWC, xwc, vm, "Matches XWindowChanges") |
1509 | +{ |
1510 | + if (vm & CWX) |
1511 | + if (xwc.x != arg.x) |
1512 | + return false; |
1513 | + |
1514 | + if (vm & CWY) |
1515 | + if (xwc.y != arg.y) |
1516 | + return false; |
1517 | + |
1518 | + if (vm & CWWidth) |
1519 | + if (xwc.width != arg.width) |
1520 | + return false; |
1521 | + |
1522 | + if (vm & CWHeight) |
1523 | + if (xwc.height != arg.height) |
1524 | + return false; |
1525 | + |
1526 | + if (vm & CWBorderWidth) |
1527 | + if (xwc.border_width != arg.border_width) |
1528 | + return false; |
1529 | + |
1530 | + if (vm & CWStackMode) |
1531 | + if (xwc.stack_mode != arg.stack_mode) |
1532 | + return false; |
1533 | + |
1534 | + if (vm & CWSibling) |
1535 | + if (xwc.sibling != arg.sibling) |
1536 | + return false; |
1537 | + |
1538 | + return true; |
1539 | +} |
1540 | + |
1541 | +class ConfigureRequestBuffer : |
1542 | + public testing::Test |
1543 | +{ |
1544 | + public: |
1545 | + |
1546 | + ConfigureRequestBuffer () |
1547 | + { |
1548 | + /* Initialize xwc, we control it |
1549 | + * through the value masks */ |
1550 | + xwc.x = REQUEST_X; |
1551 | + xwc.y = REQUEST_Y; |
1552 | + xwc.width = REQUEST_WIDTH; |
1553 | + xwc.height = REQUEST_HEIGHT; |
1554 | + xwc.border_width = REQUEST_BORDER; |
1555 | + xwc.sibling = REQUEST_ABOVE; |
1556 | + xwc.stack_mode = REQUEST_MODE; |
1557 | + } |
1558 | + |
1559 | + protected: |
1560 | + |
1561 | + XWindowChanges xwc; |
1562 | + MockAsyncServerWindow asyncServerWindow; |
1563 | + MockSyncServerWindow syncServerWindow; |
1564 | +}; |
1565 | + |
1566 | +class ConfigureRequestBufferDispatch : |
1567 | + public ConfigureRequestBuffer |
1568 | +{ |
1569 | + protected: |
1570 | + |
1571 | + ConfigureRequestBufferDispatch () : |
1572 | + ConfigureRequestBuffer (), |
1573 | + factory (boost::bind (CreateNormalLock, _1)), |
1574 | + buffer ( |
1575 | + crb::ConfigureRequestBuffer::Create (&asyncServerWindow, |
1576 | + &syncServerWindow, |
1577 | + factory)) |
1578 | + { |
1579 | + } |
1580 | + |
1581 | + crb::ConfigureRequestBuffer::LockFactory factory; |
1582 | + crb::Buffer::Ptr buffer; |
1583 | +}; |
1584 | + |
1585 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectSyntheticConfigureNotify) |
1586 | +{ |
1587 | + EXPECT_CALL (asyncServerWindow, sendSyntheticConfigureNotify ()); |
1588 | + |
1589 | + buffer->pushSyntheticConfigureNotify (); |
1590 | +} |
1591 | + |
1592 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectClientUpdate) |
1593 | +{ |
1594 | + unsigned int valueMask = CWX | CWY | CWBorderWidth | |
1595 | + CWSibling | CWStackMode; |
1596 | + |
1597 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask), |
1598 | + valueMask)); |
1599 | + |
1600 | + buffer->pushClientRequest (xwc, valueMask); |
1601 | +} |
1602 | + |
1603 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectWrapperUpdate) |
1604 | +{ |
1605 | + unsigned int valueMask = CWX | CWY | CWBorderWidth | |
1606 | + CWSibling | CWStackMode; |
1607 | + |
1608 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask), |
1609 | + valueMask)); |
1610 | + |
1611 | + buffer->pushWrapperRequest (xwc, valueMask); |
1612 | +} |
1613 | + |
1614 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectFrameUpdate) |
1615 | +{ |
1616 | + unsigned int valueMask = CWX | CWY | CWBorderWidth | |
1617 | + CWSibling | CWStackMode; |
1618 | + |
1619 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
1620 | + valueMask)); |
1621 | + |
1622 | + buffer->pushFrameRequest (xwc, valueMask); |
1623 | +} |
1624 | + |
1625 | +TEST_F (ConfigureRequestBufferDispatch, PushUpdateLocked) |
1626 | +{ |
1627 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1628 | + |
1629 | + unsigned int valueMask = 0; |
1630 | + |
1631 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1632 | + |
1633 | + buffer->pushFrameRequest (xwc, valueMask); |
1634 | +} |
1635 | + |
1636 | +TEST_F (ConfigureRequestBufferDispatch, PushCombinedUpdateLocked) |
1637 | +{ |
1638 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1639 | + |
1640 | + unsigned int valueMask = CWX; |
1641 | + |
1642 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1643 | + |
1644 | + buffer->pushFrameRequest (xwc, valueMask); |
1645 | + |
1646 | + valueMask |= CWY; |
1647 | + |
1648 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1649 | + |
1650 | + buffer->pushFrameRequest (xwc, valueMask); |
1651 | + |
1652 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
1653 | + valueMask)); |
1654 | + |
1655 | + lock->release (); |
1656 | +} |
1657 | + |
1658 | +/* |
1659 | + * This test is disabled until we can expose the QueryShapeRectangles API |
1660 | + * to plugins |
1661 | + */ |
1662 | +TEST_F (ConfigureRequestBufferDispatch, DISABLED_PushUpdateLockedReleaseInOrder) |
1663 | +{ |
1664 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1665 | + |
1666 | + unsigned int valueMask = CWX | CWY; |
1667 | + |
1668 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1669 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (_, _)).Times (0); |
1670 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (_, _)).Times (0); |
1671 | + |
1672 | + buffer->pushClientRequest (xwc, valueMask); |
1673 | + buffer->pushWrapperRequest (xwc, 0); |
1674 | + buffer->pushFrameRequest (xwc, 0); |
1675 | + |
1676 | + InSequence s; |
1677 | + |
1678 | + /* Always frame -> wrapper -> client */ |
1679 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
1680 | + valueMask)); |
1681 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask), |
1682 | + valueMask)); |
1683 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask), |
1684 | + valueMask)); |
1685 | + |
1686 | + lock->release (); |
1687 | +} |
1688 | + |
1689 | +TEST_F (ConfigureRequestBufferDispatch, UnlockBuffer) |
1690 | +{ |
1691 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1692 | + |
1693 | + unsigned int valueMask = CWX | CWY; |
1694 | + |
1695 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1696 | + |
1697 | + buffer->pushFrameRequest (xwc, valueMask); |
1698 | + |
1699 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
1700 | + valueMask)); |
1701 | + |
1702 | + lock->release (); |
1703 | +} |
1704 | + |
1705 | +TEST_F (ConfigureRequestBufferDispatch, ImplicitUnlockBuffer) |
1706 | +{ |
1707 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1708 | + |
1709 | + unsigned int valueMask = CWX | CWY; |
1710 | + |
1711 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1712 | + |
1713 | + buffer->pushFrameRequest (xwc, valueMask); |
1714 | + |
1715 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
1716 | + valueMask)); |
1717 | +} |
1718 | + |
1719 | +TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnRestack) |
1720 | +{ |
1721 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1722 | + |
1723 | + unsigned int valueMask = CWStackMode | CWSibling; |
1724 | + |
1725 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
1726 | + valueMask)); |
1727 | + |
1728 | + buffer->pushFrameRequest (xwc, valueMask); |
1729 | +} |
1730 | + |
1731 | +TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWindowSizeChange) |
1732 | +{ |
1733 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1734 | + |
1735 | + unsigned int valueMask = CWWidth | CWHeight | CWBorderWidth; |
1736 | + |
1737 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
1738 | + valueMask)); |
1739 | + |
1740 | + buffer->pushFrameRequest (xwc, valueMask); |
1741 | +} |
1742 | + |
1743 | +TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnClientReposition) |
1744 | +{ |
1745 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1746 | + |
1747 | + unsigned int valueMask = CWX | CWY; |
1748 | + |
1749 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask), |
1750 | + valueMask)); |
1751 | + |
1752 | + buffer->pushClientRequest (xwc, valueMask); |
1753 | +} |
1754 | + |
1755 | +TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWrapperReposition) |
1756 | +{ |
1757 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
1758 | + |
1759 | + unsigned int valueMask = CWX | CWY; |
1760 | + |
1761 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask), |
1762 | + valueMask)); |
1763 | + |
1764 | + buffer->pushWrapperRequest (xwc, valueMask); |
1765 | +} |
1766 | + |
1767 | +namespace |
1768 | +{ |
1769 | +class MockLock : |
1770 | + public crb::BufferLock |
1771 | +{ |
1772 | + public: |
1773 | + |
1774 | + /* We're currently importing the locks statefulness and coupling |
1775 | + * the caller with that */ |
1776 | + MockLock () : |
1777 | + armed (false) |
1778 | + { |
1779 | + ON_CALL (*this, lock ()).WillByDefault ( |
1780 | + Invoke (this, &MockLock::FreezeIfUnarmed)); |
1781 | + ON_CALL (*this, release ()).WillByDefault ( |
1782 | + Invoke (this, &MockLock::ReleaseIfArmed)); |
1783 | + } |
1784 | + |
1785 | + void OperateOver (crb::CountedFreeze *cf) |
1786 | + { |
1787 | + countedFreeze = cf; |
1788 | + } |
1789 | + |
1790 | + void FreezeIfUnarmed () |
1791 | + { |
1792 | + if (!armed) |
1793 | + { |
1794 | + countedFreeze->freeze (); |
1795 | + armed = true; |
1796 | + } |
1797 | + } |
1798 | + |
1799 | + void ReleaseIfArmed () |
1800 | + { |
1801 | + if (armed) |
1802 | + { |
1803 | + countedFreeze->release (); |
1804 | + armed = false; |
1805 | + } |
1806 | + } |
1807 | + |
1808 | + typedef boost::shared_ptr <MockLock> Ptr; |
1809 | + |
1810 | + MOCK_METHOD0 (lock, void ()); |
1811 | + MOCK_METHOD0 (release, void ()); |
1812 | + |
1813 | + private: |
1814 | + |
1815 | + crb::CountedFreeze *countedFreeze; |
1816 | + bool armed; |
1817 | +}; |
1818 | + |
1819 | +class MockLockFactory |
1820 | +{ |
1821 | + public: |
1822 | + |
1823 | + crb::BufferLock::Ptr |
1824 | + CreateMockLock (crb::CountedFreeze *cf) |
1825 | + { |
1826 | + MockLock::Ptr mockLock (locks.front ()); |
1827 | + mockLock->OperateOver (cf); |
1828 | + |
1829 | + locks.pop_front (); |
1830 | + |
1831 | + return mockLock; |
1832 | + } |
1833 | + |
1834 | + void |
1835 | + QueueLockForCreation (const MockLock::Ptr &lock) |
1836 | + { |
1837 | + locks.push_back (lock); |
1838 | + } |
1839 | + |
1840 | + private: |
1841 | + |
1842 | + std::deque <MockLock::Ptr> locks; |
1843 | +}; |
1844 | +} |
1845 | + |
1846 | +class ConfigureRequestBufferLockBehaviour : |
1847 | + public ConfigureRequestBuffer |
1848 | +{ |
1849 | + public: |
1850 | + |
1851 | + ConfigureRequestBufferLockBehaviour () : |
1852 | + ConfigureRequestBuffer (), |
1853 | + lock (boost::make_shared <MockLock> ()), |
1854 | + factory ( |
1855 | + boost::bind (&MockLockFactory::CreateMockLock, |
1856 | + &mockLockFactory, |
1857 | + _1)), |
1858 | + buffer ( |
1859 | + crb::ConfigureRequestBuffer::Create ( |
1860 | + &asyncServerWindow, |
1861 | + &syncServerWindow, |
1862 | + factory)) |
1863 | + |
1864 | + { |
1865 | + mockLockFactory.QueueLockForCreation (lock); |
1866 | + } |
1867 | + |
1868 | + protected: |
1869 | + |
1870 | + typedef NiceMock <MockAsyncServerWindow> NiceServerWindow; |
1871 | + typedef crb::ConfigureRequestBuffer::LockFactory LockFactory; |
1872 | + |
1873 | + MockLock::Ptr lock; |
1874 | + MockLockFactory mockLockFactory; |
1875 | + |
1876 | + LockFactory factory; |
1877 | + crb::Buffer::Ptr buffer; |
1878 | +}; |
1879 | + |
1880 | +TEST_F (ConfigureRequestBufferLockBehaviour, RearmBufferLockOnRelease) |
1881 | +{ |
1882 | + EXPECT_CALL (*lock, lock ()); |
1883 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
1884 | + |
1885 | + unsigned int valueMask = CWX | CWY; |
1886 | + |
1887 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1888 | + |
1889 | + buffer->pushFrameRequest (xwc, valueMask); |
1890 | + |
1891 | + /* We are releasing this lock */ |
1892 | + EXPECT_CALL (*lock, release ()); |
1893 | + |
1894 | + /* Now the buffer will dispatch is configure request */ |
1895 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
1896 | + |
1897 | + /* Rearm locks on release */ |
1898 | + EXPECT_CALL (*lock, lock ()); |
1899 | + |
1900 | + /* Directly release the queue */ |
1901 | + releasable->release (); |
1902 | +} |
1903 | + |
1904 | +TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockNoReleaseRequired) |
1905 | +{ |
1906 | + /* Locks get armed on construction */ |
1907 | + EXPECT_CALL (*lock, lock ()); |
1908 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
1909 | + |
1910 | + /* No call to requestConfigureOnFrame if there's nothing to be configured */ |
1911 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1912 | + |
1913 | + /* We are releasing this lock */ |
1914 | + EXPECT_CALL (*lock, release ()); |
1915 | + |
1916 | + /* No rearm - we haven't released the whole buffer */ |
1917 | + EXPECT_CALL (*lock, lock ()).Times (0); |
1918 | + |
1919 | + /* Directly release the queue */ |
1920 | + releasable->release (); |
1921 | +} |
1922 | + |
1923 | +TEST_F (ConfigureRequestBufferLockBehaviour, RearmWhenPushReady) |
1924 | +{ |
1925 | + /* Locks get armed on construction */ |
1926 | + EXPECT_CALL (*lock, lock ()); |
1927 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
1928 | + |
1929 | + /* We are releasing this lock */ |
1930 | + EXPECT_CALL (*lock, release ()); |
1931 | + |
1932 | + /* No call to requestConfigureOnFrame if there's nothing to be configured */ |
1933 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1934 | + |
1935 | + /* No rearm - we haven't released it */ |
1936 | + EXPECT_CALL (*lock, lock ()).Times (0); |
1937 | + |
1938 | + /* Directly release the queue */ |
1939 | + releasable->release (); |
1940 | + |
1941 | + /* Since we're now going to push something to a queue |
1942 | + * that's effectively not locked, the locks should now |
1943 | + * be released */ |
1944 | + unsigned int valueMask = CWX | CWY; |
1945 | + |
1946 | + /* Now rearm it */ |
1947 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
1948 | + EXPECT_CALL (*lock, lock ()); |
1949 | + |
1950 | + buffer->pushFrameRequest (xwc, valueMask); |
1951 | +} |
1952 | + |
1953 | +TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockOnNoRelease) |
1954 | +{ |
1955 | + MockLock::Ptr second (boost::make_shared <MockLock> ()); |
1956 | + mockLockFactory.QueueLockForCreation (second); |
1957 | + |
1958 | + /* Locks get armed on construction */ |
1959 | + EXPECT_CALL (*lock, lock ()); |
1960 | + EXPECT_CALL (*second, lock ()); |
1961 | + |
1962 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
1963 | + crb::Releasable::Ptr otherReleasable (buffer->obtainLock ()); |
1964 | + |
1965 | + /* We are releasing this lock */ |
1966 | + EXPECT_CALL (*lock, release ()); |
1967 | + |
1968 | + /* No call to requestConfigureOnFrame if there's nothing to be configured */ |
1969 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1970 | + |
1971 | + /* No rearm - we haven't released it */ |
1972 | + EXPECT_CALL (*lock, lock ()).Times (0); |
1973 | + |
1974 | + releasable->release (); |
1975 | +} |
1976 | + |
1977 | +TEST_F (ConfigureRequestBufferLockBehaviour, QueryAttributesDispatchAndRearm) |
1978 | +{ |
1979 | + /* Locks get armed on construction */ |
1980 | + EXPECT_CALL (*lock, lock ()); |
1981 | + |
1982 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
1983 | + |
1984 | + unsigned int valueMask = CWX | CWY; |
1985 | + |
1986 | + /* Queue locked */ |
1987 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
1988 | + |
1989 | + buffer->pushFrameRequest (xwc, valueMask); |
1990 | + |
1991 | + /* Queue forceably unlocked, locks rearmed */ |
1992 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
1993 | + EXPECT_CALL (*lock, lock ()); |
1994 | + |
1995 | + /* Expect a call to XGetWindowAttributes */ |
1996 | + EXPECT_CALL (syncServerWindow, queryShapeRectangles (_, _, _)) |
1997 | + .WillOnce ( |
1998 | + ReturnNull ()); |
1999 | + |
2000 | + int a, b; |
2001 | + |
2002 | + EXPECT_THAT (buffer->queryShapeRectangles (0, &a, &b), IsNull ()); |
2003 | +} |
2004 | + |
2005 | +TEST_F (ConfigureRequestBufferLockBehaviour, QueryFrameAttributesDispatchAndRearm) |
2006 | +{ |
2007 | + /* Locks get armed on construction */ |
2008 | + EXPECT_CALL (*lock, lock ()); |
2009 | + |
2010 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
2011 | + |
2012 | + unsigned int valueMask = CWX | CWY; |
2013 | + |
2014 | + /* Queue locked */ |
2015 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
2016 | + |
2017 | + buffer->pushFrameRequest (xwc, valueMask); |
2018 | + |
2019 | + /* Queue forceably unlocked, locks rearmed */ |
2020 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
2021 | + EXPECT_CALL (*lock, lock ()); |
2022 | + |
2023 | + /* Expect a call to XGetWindowAttributes */ |
2024 | + XWindowAttributes xwa; |
2025 | + EXPECT_CALL (syncServerWindow, queryFrameAttributes (_)) |
2026 | + .WillOnce ( |
2027 | + DoAll ( |
2028 | + SetArgReferee <0> (xwa), |
2029 | + Return (true))); |
2030 | + |
2031 | + buffer->queryFrameAttributes (xwa); |
2032 | +} |
2033 | + |
2034 | +TEST_F (ConfigureRequestBufferLockBehaviour, QueryShapeRectanglesDispatchAndRearm) |
2035 | +{ |
2036 | + /* Locks get armed on construction */ |
2037 | + EXPECT_CALL (*lock, lock ()); |
2038 | + |
2039 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
2040 | + |
2041 | + unsigned int valueMask = CWX | CWY; |
2042 | + |
2043 | + /* Queue locked */ |
2044 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
2045 | + |
2046 | + buffer->pushFrameRequest (xwc, valueMask); |
2047 | + |
2048 | + /* Queue forceably unlocked, locks rearmed */ |
2049 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
2050 | + EXPECT_CALL (*lock, lock ()); |
2051 | + |
2052 | + /* Expect a call to XGetWindowAttributes */ |
2053 | + XWindowAttributes xwa; |
2054 | + EXPECT_CALL (syncServerWindow, queryFrameAttributes (_)) |
2055 | + .WillOnce ( |
2056 | + DoAll ( |
2057 | + SetArgReferee <0> (xwa), |
2058 | + Return (true))); |
2059 | + |
2060 | + buffer->queryFrameAttributes (xwa); |
2061 | +} |
2062 | + |
2063 | +TEST_F (ConfigureRequestBufferLockBehaviour, ForceReleaseDispatchAndRearm) |
2064 | +{ |
2065 | + /* Locks get armed on construction */ |
2066 | + EXPECT_CALL (*lock, lock ()); |
2067 | + |
2068 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
2069 | + |
2070 | + unsigned int valueMask = CWX | CWY; |
2071 | + |
2072 | + /* Queue locked */ |
2073 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
2074 | + |
2075 | + buffer->pushFrameRequest (xwc, valueMask); |
2076 | + |
2077 | + /* Queue forceably unlocked, locks rearmed */ |
2078 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
2079 | + EXPECT_CALL (*lock, lock ()); |
2080 | + |
2081 | + /* Force release */ |
2082 | + buffer->forceRelease (); |
2083 | +} |
2084 | + |
2085 | |
2086 | === modified file 'src/window.cpp' |
2087 | --- src/window.cpp 2013-02-18 22:51:33 +0000 |
2088 | +++ src/window.cpp 2013-02-21 16:57:22 +0000 |
2089 | @@ -37,6 +37,7 @@ |
2090 | #include <math.h> |
2091 | |
2092 | #include <boost/bind.hpp> |
2093 | +#include <boost/make_shared.hpp> |
2094 | |
2095 | #include <core/icon.h> |
2096 | #include <core/atoms.h> |
2097 | @@ -45,8 +46,13 @@ |
2098 | #include "privatescreen.h" |
2099 | #include "privatestackdebugger.h" |
2100 | |
2101 | +#include "configurerequestbuffer-impl.h" |
2102 | + |
2103 | #include <boost/scoped_array.hpp> |
2104 | |
2105 | +namespace crb = compiz::window::configure_buffers; |
2106 | +namespace cw = compiz::window; |
2107 | + |
2108 | template class WrapableInterface<CompWindow, WindowInterface>; |
2109 | |
2110 | PluginClassStorage::Indices windowPluginClassIndices (0); |
2111 | @@ -3028,6 +3034,80 @@ |
2112 | return pc->matchRequest (xwc, valueMask); |
2113 | } |
2114 | |
2115 | +bool |
2116 | +PrivateWindow::queryAttributes (XWindowAttributes &attrib) |
2117 | +{ |
2118 | + return configureBuffer->queryAttributes (attrib); |
2119 | +} |
2120 | + |
2121 | +bool |
2122 | +PrivateWindow::queryFrameAttributes (XWindowAttributes &attrib) |
2123 | +{ |
2124 | + return configureBuffer->queryFrameAttributes (attrib); |
2125 | +} |
2126 | + |
2127 | +XRectangle * |
2128 | +PrivateWindow::queryShapeRectangles (int kind, int *count, int *ordering) |
2129 | +{ |
2130 | + return configureBuffer->queryShapeRectangles (kind, count, ordering); |
2131 | +} |
2132 | + |
2133 | +int |
2134 | +PrivateWindow::requestConfigureOnClient (const XWindowChanges &xwc, |
2135 | + unsigned int valueMask) |
2136 | +{ |
2137 | + int ret = XConfigureWindow (screen->dpy (), |
2138 | + id, |
2139 | + valueMask, |
2140 | + const_cast <XWindowChanges *> (&xwc)); |
2141 | + |
2142 | + return ret; |
2143 | +} |
2144 | + |
2145 | +int |
2146 | +PrivateWindow::requestConfigureOnWrapper (const XWindowChanges &xwc, |
2147 | + unsigned int valueMask) |
2148 | +{ |
2149 | + return XConfigureWindow (screen->dpy (), |
2150 | + wrapper, |
2151 | + valueMask, |
2152 | + const_cast <XWindowChanges *> (&xwc)); |
2153 | +} |
2154 | + |
2155 | +int |
2156 | +PrivateWindow::requestConfigureOnFrame (const XWindowChanges &xwc, |
2157 | + unsigned int frameValueMask) |
2158 | +{ |
2159 | + XWindowChanges wc = xwc; |
2160 | + |
2161 | + wc.x = serverFrameGeometry.x (); |
2162 | + wc.y = serverFrameGeometry.y (); |
2163 | + wc.width = serverFrameGeometry.width (); |
2164 | + wc.height = serverFrameGeometry.height (); |
2165 | + |
2166 | + compiz::X11::PendingEvent::Ptr pc ( |
2167 | + new compiz::X11::PendingConfigureEvent ( |
2168 | + screen->dpy (), |
2169 | + priv->serverFrame, |
2170 | + frameValueMask, &wc)); |
2171 | + |
2172 | + pendingConfigures.add (pc); |
2173 | + |
2174 | + return XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc); |
2175 | +} |
2176 | + |
2177 | +void |
2178 | +PrivateWindow::sendSyntheticConfigureNotify () |
2179 | +{ |
2180 | + window->sendConfigureNotify (); |
2181 | +} |
2182 | + |
2183 | +bool |
2184 | +PrivateWindow::hasCustomShape () const |
2185 | +{ |
2186 | + return false; |
2187 | +} |
2188 | + |
2189 | void |
2190 | PrivateWindow::reconfigureXWindow (unsigned int valueMask, |
2191 | XWindowChanges *xwc) |
2192 | @@ -3240,47 +3320,41 @@ |
2193 | if (serverFrame) |
2194 | { |
2195 | if (frameValueMask) |
2196 | - { |
2197 | - XWindowChanges wc = *xwc; |
2198 | - |
2199 | - wc.x = serverFrameGeometry.x (); |
2200 | - wc.y = serverFrameGeometry.y (); |
2201 | - wc.width = serverFrameGeometry.width (); |
2202 | - wc.height = serverFrameGeometry.height (); |
2203 | - |
2204 | - compiz::X11::PendingEvent::Ptr pc = |
2205 | - boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr ( |
2206 | - new compiz::X11::PendingConfigureEvent ( |
2207 | - screen->dpy (), priv->serverFrame, frameValueMask, &wc))); |
2208 | - |
2209 | - pendingConfigures.add (pc); |
2210 | - |
2211 | - XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc); |
2212 | - } |
2213 | - |
2214 | - valueMask &= ~(CWSibling | CWStackMode); |
2215 | + priv->configureBuffer->pushFrameRequest (*xwc, frameValueMask); |
2216 | + |
2217 | + valueMask = frameValueMask & (CWWidth | CWHeight); |
2218 | |
2219 | /* If the frame has changed position (eg, serverInput.top |
2220 | * or serverInput.left have changed) then we also need to |
2221 | * update the client and wrapper position */ |
2222 | - if (!(valueMask & CWX)) |
2223 | - valueMask |= frameValueMask & CWX; |
2224 | - if (!(valueMask & CWY)) |
2225 | - valueMask |= frameValueMask & CWY; |
2226 | + if (lastServerInput.left != serverInput.left) |
2227 | + valueMask |= CWX; |
2228 | + if (lastServerInput.top != serverInput.top) |
2229 | + valueMask |= CWY; |
2230 | + |
2231 | + if (lastServerInput.right - lastServerInput.left != |
2232 | + serverInput.right - serverInput.left) |
2233 | + valueMask |= CWWidth; |
2234 | + if (lastServerInput.bottom - lastServerInput.top != |
2235 | + serverInput.bottom - serverInput.top) |
2236 | + valueMask |= CWHeight; |
2237 | |
2238 | if (valueMask) |
2239 | { |
2240 | xwc->x = serverInput.left; |
2241 | xwc->y = serverInput.top; |
2242 | - XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc); |
2243 | |
2244 | - xwc->x = 0; |
2245 | - xwc->y = 0; |
2246 | + priv->configureBuffer->pushWrapperRequest (*xwc, valueMask); |
2247 | } |
2248 | } |
2249 | |
2250 | + /* Client is reparented, the only things that can change |
2251 | + * are the width, height and border width */ |
2252 | + if (serverFrame) |
2253 | + valueMask &= (CWWidth | CWHeight | CWBorderWidth); |
2254 | + |
2255 | if (valueMask) |
2256 | - XConfigureWindow (screen->dpy (), id, valueMask, xwc); |
2257 | + priv->configureBuffer->pushClientRequest (*xwc, valueMask); |
2258 | |
2259 | /* Send the synthetic configure notify |
2260 | * after the real configure notify arrives |
2261 | @@ -5811,6 +5885,24 @@ |
2262 | return priv->struts; |
2263 | } |
2264 | |
2265 | +bool |
2266 | +CompWindow::queryAttributes (XWindowAttributes &attrib) |
2267 | +{ |
2268 | + return priv->queryAttributes (attrib); |
2269 | +} |
2270 | + |
2271 | +bool |
2272 | +CompWindow::queryFrameAttributes (XWindowAttributes &attrib) |
2273 | +{ |
2274 | + return priv->queryFrameAttributes (attrib); |
2275 | +} |
2276 | + |
2277 | +crb::Releasable::Ptr |
2278 | +CompWindow::obtainLockOnConfigureRequests () |
2279 | +{ |
2280 | + return priv->configureBuffer->obtainLock (); |
2281 | +} |
2282 | + |
2283 | int & |
2284 | CompWindow::saveMask () const |
2285 | { |
2286 | @@ -6349,6 +6441,55 @@ |
2287 | delete priv; |
2288 | } |
2289 | |
2290 | +X11SyncServerWindow::X11SyncServerWindow (Display *dpy, |
2291 | + const Window *w, |
2292 | + const Window *frame) : |
2293 | + mDpy (dpy), |
2294 | + mWindow (w), |
2295 | + mFrame (frame) |
2296 | +{ |
2297 | +} |
2298 | + |
2299 | +bool |
2300 | +X11SyncServerWindow::queryAttributes (XWindowAttributes &attrib) |
2301 | +{ |
2302 | + if (XGetWindowAttributes (mDpy, *mWindow, &attrib)) |
2303 | + return true; |
2304 | + |
2305 | + return false; |
2306 | +} |
2307 | + |
2308 | +bool |
2309 | +X11SyncServerWindow::queryFrameAttributes (XWindowAttributes &attrib) |
2310 | +{ |
2311 | + Window w = *mFrame ? *mFrame : *mWindow; |
2312 | + |
2313 | + if (XGetWindowAttributes (mDpy, w, &attrib)) |
2314 | + return true; |
2315 | + |
2316 | + return false; |
2317 | +} |
2318 | + |
2319 | +XRectangle * |
2320 | +X11SyncServerWindow::queryShapeRectangles (int kind, |
2321 | + int *count, |
2322 | + int *ordering) |
2323 | +{ |
2324 | + return XShapeGetRectangles (mDpy, *mWindow, |
2325 | + kind, |
2326 | + count, |
2327 | + ordering); |
2328 | +} |
2329 | + |
2330 | +namespace |
2331 | +{ |
2332 | +crb::BufferLock::Ptr |
2333 | +createConfigureBufferLock (crb::CountedFreeze *cf) |
2334 | +{ |
2335 | + return boost::make_shared <crb::ConfigureBufferLock> (cf); |
2336 | +} |
2337 | +} |
2338 | + |
2339 | PrivateWindow::PrivateWindow () : |
2340 | priv (this), |
2341 | refcnt (1), |
2342 | @@ -6420,27 +6561,27 @@ |
2343 | |
2344 | syncWait (false), |
2345 | closeRequests (false), |
2346 | - lastCloseRequestTime (0) |
2347 | + lastCloseRequestTime (0), |
2348 | + |
2349 | + syncServerWindow (screen->dpy (), |
2350 | + &id, |
2351 | + &serverFrame), |
2352 | + configureBuffer ( |
2353 | + crb::ConfigureRequestBuffer::Create ( |
2354 | + this, |
2355 | + &syncServerWindow, |
2356 | + boost::bind (createConfigureBufferLock, _1))) |
2357 | { |
2358 | input.left = 0; |
2359 | input.right = 0; |
2360 | input.top = 0; |
2361 | input.bottom = 0; |
2362 | |
2363 | - serverInput.left = 0; |
2364 | - serverInput.right = 0; |
2365 | - serverInput.top = 0; |
2366 | - serverInput.bottom = 0; |
2367 | - |
2368 | - border.top = 0; |
2369 | - border.bottom = 0; |
2370 | - border.left = 0; |
2371 | - border.right = 0; |
2372 | - |
2373 | - output.left = 0; |
2374 | - output.right = 0; |
2375 | - output.top = 0; |
2376 | - output.bottom = 0; |
2377 | + /* Zero initialize */ |
2378 | + serverInput = input; |
2379 | + lastServerInput = input; |
2380 | + border = input; |
2381 | + output = input; |
2382 | |
2383 | syncWaitTimer.setTimes (1000, 1200); |
2384 | syncWaitTimer.setCallback (boost::bind (&PrivateWindow::handleSyncAlarm, |
2385 | @@ -6648,6 +6789,9 @@ |
2386 | * whenever the frame extents update |
2387 | * so that plugins can re-position appropriately */ |
2388 | moveNotify (0, 0, true); |
2389 | + |
2390 | + /* Once we have updated everything, re-set lastServerInput */ |
2391 | + priv->lastServerInput = priv->serverInput; |
2392 | } |
2393 | |
2394 | /* Use b for _NET_WM_FRAME_EXTENTS here because |
2395 | @@ -6710,7 +6854,11 @@ |
2396 | XSync (dpy, false); |
2397 | XGrabServer (dpy); |
2398 | |
2399 | - if (!XGetWindowAttributes (dpy, id, &wa)) |
2400 | + /* We need to flush all queued up requests */ |
2401 | + foreach (CompWindow *w, screen->windows ()) |
2402 | + w->priv->configureBuffer->forceRelease (); |
2403 | + |
2404 | + if (!window->priv->queryAttributes (wa)) |
2405 | { |
2406 | XUngrabServer (dpy); |
2407 | XSync (dpy, false); |
2408 | @@ -6997,7 +7145,7 @@ |
2409 | * a DestroyNotify for it yet, it is possible that restacking |
2410 | * operations could occurr relative to it so we need to hold it |
2411 | * in the stack for now. Ensure that it is marked override redirect */ |
2412 | - XGetWindowAttributes (screen->dpy (), serverFrame, &attrib); |
2413 | + window->priv->queryFrameAttributes (attrib); |
2414 | |
2415 | /* Put the frame window "above" the client window |
2416 | * in the stack */ |
2417 | |
2418 | === modified file 'tests/acceptance-tests/xorg-gtest/tests/compiz_acceptance_replace_current_wm.cpp' |
2419 | --- tests/acceptance-tests/xorg-gtest/tests/compiz_acceptance_replace_current_wm.cpp 2012-12-05 03:40:20 +0000 |
2420 | +++ tests/acceptance-tests/xorg-gtest/tests/compiz_acceptance_replace_current_wm.cpp 2013-02-21 16:57:22 +0000 |
2421 | @@ -101,6 +101,7 @@ |
2422 | TmpEnv env ("XORG_GTEST_CHILD_STDOUT", "1"); |
2423 | ProcessPtr compiz (boost::make_shared <ct::CompizProcess> (Display (), |
2424 | ct::CompizProcess::WaitForStartupMessage, |
2425 | + ct::CompizProcess::PluginList (), |
2426 | 3000)); |
2427 | |
2428 | pid_t firstProcessPid = compiz->Pid (); |
2429 | @@ -130,6 +131,7 @@ |
2430 | TmpEnv env ("XORG_GTEST_CHILD_STDOUT", "1"); |
2431 | ProcessPtr firstCompiz (boost::make_shared <ct::CompizProcess> (Display (), |
2432 | ct::CompizProcess::WaitForStartupMessage, |
2433 | + ct::CompizProcess::PluginList (), |
2434 | 3000)); |
2435 | |
2436 | /* Expect it to exit */ |
2437 | @@ -142,6 +144,7 @@ |
2438 | static_cast <ct::CompizProcess::StartupFlags> ( |
2439 | ct::CompizProcess::WaitForStartupMessage | |
2440 | ct::CompizProcess::ReplaceCurrentWM), |
2441 | + ct::CompizProcess::PluginList (), |
2442 | maximumWaitTime)); |
2443 | |
2444 | if (!task->ReadMsgFromTask (PROCESS_EXITED_MSG, maximumWaitTime)) |
2445 | @@ -223,6 +226,7 @@ |
2446 | TmpEnv env ("XORG_GTEST_CHILD_STDOUT", "1"); |
2447 | ProcessPtr firstCompiz (boost::make_shared <ct::CompizProcess> (dpy, |
2448 | ct::CompizProcess::WaitForStartupMessage, |
2449 | + ct::CompizProcess::PluginList (), |
2450 | 3000)); |
2451 | |
2452 | SlowDownTask::GetProcessState procState (boost::bind (&ct::CompizProcess::State, |
2453 | @@ -244,6 +248,7 @@ |
2454 | static_cast <ct::CompizProcess::StartupFlags> ( |
2455 | ct::CompizProcess::ReplaceCurrentWM | |
2456 | ct::CompizProcess::WaitForStartupMessage), |
2457 | + ct::CompizProcess::PluginList (), |
2458 | maximumWaitTime)); |
2459 | |
2460 | /* Wait until the first one goes away */ |
2461 | |
2462 | === modified file 'tests/system/xorg-gtest/tests/CMakeLists.txt' |
2463 | --- tests/system/xorg-gtest/tests/CMakeLists.txt 2013-02-20 07:31:57 +0000 |
2464 | +++ tests/system/xorg-gtest/tests/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
2465 | @@ -7,7 +7,8 @@ |
2466 | ${X11_INCLUDE_DIRS} |
2467 | ${XORG_SERVER_INCLUDE_XORG_GTEST} |
2468 | ${XORG_SERVER_GTEST_SRC} |
2469 | - ${GTEST_INCLUDE_DIRS}) |
2470 | + ${GTEST_INCLUDE_DIRS} |
2471 | + ${COMPIZ_XORG_GTEST_COMMUNICATOR_INCLUDE_DIR}) |
2472 | |
2473 | link_directories (${X11_XI_LIBRARY_DIRS} |
2474 | ${compiz_BINARY_DIR}/tests/shared/src) |
2475 | @@ -15,6 +16,9 @@ |
2476 | add_executable (compiz_xorg_gtest_test_window_stacking |
2477 | ${CMAKE_CURRENT_SOURCE_DIR}/compiz_xorg_gtest_test_window_stacking.cpp) |
2478 | |
2479 | + add_executable (compiz_xorg_gtest_test_configure_window |
2480 | + ${CMAKE_CURRENT_SOURCE_DIR}/compiz_xorg_gtest_configure_window.cpp) |
2481 | + |
2482 | add_executable (compiz_xorg_gtest_test_icccm |
2483 | ${CMAKE_CURRENT_SOURCE_DIR}/compiz_xorg_gtest_icccm.cpp) |
2484 | |
2485 | @@ -54,4 +58,11 @@ |
2486 | |
2487 | compiz_discover_tests (compiz_xorg_gtest_test_shape_handling WITH_XORG_GTEST) |
2488 | |
2489 | + target_link_libraries (compiz_xorg_gtest_test_configure_window |
2490 | + ${COMPIZ_XORG_GTEST_LIBRARIES}) |
2491 | + |
2492 | + add_dependencies (compiz_xorg_gtest_test_configure_window testhelper) |
2493 | + |
2494 | + compiz_discover_tests (compiz_xorg_gtest_test_configure_window WITH_XORG_GTEST) |
2495 | + |
2496 | endif (BUILD_XORG_GTEST AND X11_XI_FOUND) |
2497 | |
2498 | === added file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp' |
2499 | --- tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp 1970-01-01 00:00:00 +0000 |
2500 | +++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_configure_window.cpp 2013-02-21 16:57:22 +0000 |
2501 | @@ -0,0 +1,567 @@ |
2502 | +/* |
2503 | + * Compiz XOrg GTest, ConfigureWindow handling |
2504 | + * |
2505 | + * Copyright (C) 2012 Sam Spilsbury (smspillaz@gmail.com) |
2506 | + * |
2507 | +* Permission to use, copy, modify, distribute, and sell this software |
2508 | +* and its documentation for any purpose is hereby granted without |
2509 | +* fee, provided that the above copyright notice appear in all copies |
2510 | +* and that both that copyright notice and this permission notice |
2511 | +* appear in supporting documentation, and that the name of |
2512 | +* Novell, Inc. not be used in advertising or publicity pertaining to |
2513 | +* distribution of the software without specific, written prior permission. |
2514 | +* Novell, Inc. makes no representations about the suitability of this |
2515 | +* software for any purpose. It is provided "as is" without express or |
2516 | +* implied warranty. |
2517 | +* |
2518 | +* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
2519 | +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
2520 | +* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
2521 | +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
2522 | +* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
2523 | +* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
2524 | +* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
2525 | + * |
2526 | + * Authored By: |
2527 | + * Sam Spilsbury <smspillaz@gmail.com> |
2528 | + */ |
2529 | +#include <list> |
2530 | +#include <string> |
2531 | +#include <stdexcept> |
2532 | +#include <gtest/gtest.h> |
2533 | +#include <gmock/gmock.h> |
2534 | +#include <boost/function.hpp> |
2535 | +#include <boost/bind.hpp> |
2536 | +#include <xorg/gtest/xorg-gtest.h> |
2537 | +#include <compiz-xorg-gtest.h> |
2538 | +#include <compiz_xorg_gtest_communicator.h> |
2539 | + |
2540 | +#include <gtest_shared_tmpenv.h> |
2541 | + |
2542 | +#include <X11/Xlib.h> |
2543 | +#include <X11/Xatom.h> |
2544 | + |
2545 | +using ::testing::MatchResultListener; |
2546 | +using ::testing::MakeMatcher; |
2547 | +using ::testing::Matcher; |
2548 | + |
2549 | +namespace ct = compiz::testing; |
2550 | + |
2551 | +namespace |
2552 | +{ |
2553 | + |
2554 | +bool Advance (Display *d, bool r) |
2555 | +{ |
2556 | + return ct::AdvanceToNextEventOnSuccess (d, r); |
2557 | +} |
2558 | + |
2559 | +Window GetTopParent (Display *display, |
2560 | + Window w) |
2561 | +{ |
2562 | + Window rootReturn; |
2563 | + Window parentReturn = w; |
2564 | + Window *childrenReturn; |
2565 | + unsigned int nChildrenReturn; |
2566 | + |
2567 | + Window lastParent = 0; |
2568 | + |
2569 | + do |
2570 | + { |
2571 | + lastParent = parentReturn; |
2572 | + |
2573 | + XQueryTree (display, |
2574 | + lastParent, |
2575 | + &rootReturn, |
2576 | + &parentReturn, |
2577 | + &childrenReturn, |
2578 | + &nChildrenReturn); |
2579 | + XFree (childrenReturn); |
2580 | + } while (parentReturn != rootReturn); |
2581 | + |
2582 | + return lastParent; |
2583 | +} |
2584 | + |
2585 | +bool QueryGeometry (Display *dpy, |
2586 | + Window w, |
2587 | + int &x, |
2588 | + int &y, |
2589 | + unsigned int &width, |
2590 | + unsigned int &height) |
2591 | +{ |
2592 | + Window rootRet; |
2593 | + unsigned int depth, border; |
2594 | + |
2595 | + if (!XGetGeometry (dpy, |
2596 | + w, |
2597 | + &rootRet, |
2598 | + &x, |
2599 | + &y, |
2600 | + &width, |
2601 | + &height, |
2602 | + &depth, |
2603 | + &border)) |
2604 | + return false; |
2605 | + |
2606 | + return true; |
2607 | +} |
2608 | + |
2609 | +bool WaitForReparentAndMap (Display *dpy, |
2610 | + Window w) |
2611 | +{ |
2612 | + bool ret = Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, |
2613 | + w, |
2614 | + ReparentNotify, |
2615 | + -1, |
2616 | + -1)); |
2617 | + EXPECT_TRUE (ret); |
2618 | + if (!ret) |
2619 | + return false; |
2620 | + |
2621 | + |
2622 | + ret = Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, |
2623 | + w, |
2624 | + MapNotify, |
2625 | + -1, |
2626 | + -1)); |
2627 | + EXPECT_TRUE (ret); |
2628 | + if (!ret) |
2629 | + return false; |
2630 | + |
2631 | + return true; |
2632 | +} |
2633 | + |
2634 | +struct ReparentedWindow |
2635 | +{ |
2636 | + Window client; |
2637 | + Window frame; |
2638 | +}; |
2639 | + |
2640 | +typedef boost::function <void (Window)> CreateWaitFunc; |
2641 | + |
2642 | +ReparentedWindow |
2643 | +GetNewWindowAndFrame (Display *dpy, const CreateWaitFunc &waitForCreation) |
2644 | +{ |
2645 | + ReparentedWindow w; |
2646 | + |
2647 | + w.client = ct::CreateNormalWindow (dpy); |
2648 | + waitForCreation (w.client); |
2649 | + |
2650 | + XMapRaised (dpy, w.client); |
2651 | + WaitForReparentAndMap (dpy, w.client); |
2652 | + |
2653 | + w.frame = GetTopParent (dpy, w.client); |
2654 | + |
2655 | + XSelectInput (dpy, w.frame, StructureNotifyMask); |
2656 | + |
2657 | + return w; |
2658 | +} |
2659 | + |
2660 | +bool |
2661 | +WaitForConfigureNotify (Display *dpy, |
2662 | + Window w, |
2663 | + int x, |
2664 | + int y, |
2665 | + int width, |
2666 | + int height, |
2667 | + int border, |
2668 | + Window above, |
2669 | + unsigned int mask) |
2670 | +{ |
2671 | + ct::ConfigureNotifyXEventMatcher matcher (above, border, x, y, width, height, |
2672 | + mask); |
2673 | + |
2674 | + return Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy, |
2675 | + w, |
2676 | + ConfigureNotify, |
2677 | + -1, |
2678 | + -1, |
2679 | + matcher)); |
2680 | +} |
2681 | + |
2682 | +} |
2683 | + |
2684 | +class CompizXorgSystemConfigureWindowTest : |
2685 | + public ct::AutostartCompizXorgSystemTestWithTestHelper |
2686 | +{ |
2687 | + public: |
2688 | + |
2689 | + CompizXorgSystemConfigureWindowTest () : |
2690 | + /* See note in the acceptance tests about this */ |
2691 | + env ("XORG_GTEST_CHILD_STDOUT", "1") |
2692 | + { |
2693 | + } |
2694 | + |
2695 | + void SendConfigureRequest (Window w, int x, int y, int width, int height, int mask); |
2696 | + void SendSetFrameExtentsRequest (Window w, int left, int right, int top, int bottom); |
2697 | + void SendConfigureLockRequest (Window w, bool lockRequests); |
2698 | + bool VerifyConfigureResponse (Window w, int x, int y, int width, int height); |
2699 | + bool VerifySetFrameExtentsResponse (Window w, int left, int right, int top, int bottom); |
2700 | + bool VerifyWindowSize (Window w, int x, int y, int width, int height); |
2701 | + |
2702 | + protected: |
2703 | + |
2704 | + ReparentedWindow CreateWindow (::Display *); |
2705 | + int GetEventMask (); |
2706 | + |
2707 | + private: |
2708 | + |
2709 | + TmpEnv env; |
2710 | +}; |
2711 | + |
2712 | +int |
2713 | +CompizXorgSystemConfigureWindowTest::GetEventMask () |
2714 | +{ |
2715 | + return ct::AutostartCompizXorgSystemTestWithTestHelper::GetEventMask () | |
2716 | + SubstructureNotifyMask; |
2717 | +} |
2718 | + |
2719 | +void |
2720 | +CompizXorgSystemConfigureWindowTest::SendConfigureRequest (Window w, |
2721 | + int x, |
2722 | + int y, |
2723 | + int width, |
2724 | + int height, |
2725 | + int mask) |
2726 | +{ |
2727 | + ::Display *dpy = Display (); |
2728 | + |
2729 | + std::vector <long> data; |
2730 | + data.push_back (x); |
2731 | + data.push_back (y); |
2732 | + data.push_back (width); |
2733 | + data.push_back (height); |
2734 | + data.push_back (mask); |
2735 | + |
2736 | + ct::SendClientMessage (dpy, |
2737 | + FetchAtom (ct::messages::TEST_HELPER_CONFIGURE_WINDOW), |
2738 | + DefaultRootWindow (dpy), |
2739 | + w, |
2740 | + data); |
2741 | +} |
2742 | + |
2743 | +void |
2744 | +CompizXorgSystemConfigureWindowTest::SendSetFrameExtentsRequest (Window w, |
2745 | + int left, |
2746 | + int right, |
2747 | + int top, |
2748 | + int bottom) |
2749 | +{ |
2750 | + ::Display *dpy = Display (); |
2751 | + |
2752 | + std::vector <long> data; |
2753 | + data.push_back (left); |
2754 | + data.push_back (right); |
2755 | + data.push_back (top); |
2756 | + data.push_back (bottom); |
2757 | + |
2758 | + ct::SendClientMessage (dpy, |
2759 | + FetchAtom (ct::messages::TEST_HELPER_CHANGE_FRAME_EXTENTS), |
2760 | + DefaultRootWindow (dpy), |
2761 | + w, |
2762 | + data); |
2763 | +} |
2764 | + |
2765 | +void |
2766 | +CompizXorgSystemConfigureWindowTest::SendConfigureLockRequest (Window w, |
2767 | + bool lockRequests) |
2768 | +{ |
2769 | + ::Display *dpy = Display (); |
2770 | + |
2771 | + std::vector <long> data; |
2772 | + data.push_back (lockRequests ? 1 : 0); |
2773 | + |
2774 | + ct::SendClientMessage (dpy, |
2775 | + FetchAtom (ct::messages::TEST_HELPER_LOCK_CONFIGURE_REQUESTS), |
2776 | + DefaultRootWindow (dpy), |
2777 | + w, |
2778 | + data); |
2779 | +} |
2780 | + |
2781 | +bool |
2782 | +CompizXorgSystemConfigureWindowTest::VerifyConfigureResponse (Window w, |
2783 | + int x, |
2784 | + int y, |
2785 | + int width, |
2786 | + int height) |
2787 | +{ |
2788 | + ::Display *dpy = Display (); |
2789 | + XEvent event; |
2790 | + |
2791 | + while (ct::ReceiveMessage (dpy, |
2792 | + FetchAtom (ct::messages::TEST_HELPER_WINDOW_CONFIGURE_PROCESSED), |
2793 | + event)) |
2794 | + { |
2795 | + bool requestAcknowledged = |
2796 | + x == event.xclient.data.l[0] && |
2797 | + y == event.xclient.data.l[1] && |
2798 | + width == event.xclient.data.l[2] && |
2799 | + height == event.xclient.data.l[3]; |
2800 | + |
2801 | + if (requestAcknowledged) |
2802 | + return true; |
2803 | + |
2804 | + } |
2805 | + |
2806 | + return false; |
2807 | +} |
2808 | + |
2809 | +bool |
2810 | +CompizXorgSystemConfigureWindowTest::VerifySetFrameExtentsResponse (Window w, |
2811 | + int left, |
2812 | + int right, |
2813 | + int top, |
2814 | + int bottom) |
2815 | +{ |
2816 | + ::Display *dpy = Display (); |
2817 | + XEvent event; |
2818 | + |
2819 | + while (ct::ReceiveMessage (dpy, |
2820 | + FetchAtom (ct::messages::TEST_HELPER_FRAME_EXTENTS_CHANGED), |
2821 | + event)) |
2822 | + { |
2823 | + bool requestAcknowledged = |
2824 | + left == event.xclient.data.l[0] && |
2825 | + right == event.xclient.data.l[1] && |
2826 | + top == event.xclient.data.l[2] && |
2827 | + bottom == event.xclient.data.l[3]; |
2828 | + |
2829 | + if (requestAcknowledged) |
2830 | + return true; |
2831 | + |
2832 | + } |
2833 | + |
2834 | + return false; |
2835 | +} |
2836 | + |
2837 | +bool |
2838 | +CompizXorgSystemConfigureWindowTest::VerifyWindowSize (Window w, |
2839 | + int x, |
2840 | + int y, |
2841 | + int width, |
2842 | + int height) |
2843 | +{ |
2844 | + ::Display *dpy = Display (); |
2845 | + |
2846 | + int xRet, yRet; |
2847 | + unsigned int widthRet, heightRet; |
2848 | + if (!QueryGeometry (dpy, w, xRet, yRet, widthRet, heightRet)) |
2849 | + return false; |
2850 | + |
2851 | + EXPECT_EQ (x, xRet); |
2852 | + EXPECT_EQ (y, yRet); |
2853 | + EXPECT_EQ (width, widthRet); |
2854 | + EXPECT_EQ (height, heightRet); |
2855 | + |
2856 | + return true; |
2857 | +} |
2858 | + |
2859 | +ReparentedWindow |
2860 | +CompizXorgSystemConfigureWindowTest::CreateWindow (::Display *dpy) |
2861 | +{ |
2862 | + return GetNewWindowAndFrame (dpy, |
2863 | + boost::bind (&CompizXorgSystemConfigureWindowTest::WaitForWindowCreation, |
2864 | + this, |
2865 | + _1)); |
2866 | +} |
2867 | + |
2868 | +TEST_F (CompizXorgSystemConfigureWindowTest, ConfigureAndReponseUnlocked) |
2869 | +{ |
2870 | + ::Display *dpy = Display (); |
2871 | + |
2872 | + int x = 1; |
2873 | + int y = 1; |
2874 | + int width = 100; |
2875 | + int height = 200; |
2876 | + int mask = CWX | CWY | CWWidth | CWHeight; |
2877 | + |
2878 | + ReparentedWindow w = CreateWindow (dpy); |
2879 | + |
2880 | + SendConfigureRequest (w.client, x, y, width, height, mask); |
2881 | + |
2882 | + /* Wait for a response */ |
2883 | + ASSERT_TRUE (VerifyConfigureResponse (w.client, x, y, width, height)); |
2884 | + |
2885 | + /* Query the window size again */ |
2886 | + ASSERT_TRUE (VerifyWindowSize (w.frame, x, y, width, height)); |
2887 | + |
2888 | +} |
2889 | + |
2890 | +TEST_F (CompizXorgSystemConfigureWindowTest, FrameExtentsAndReponseUnlocked) |
2891 | +{ |
2892 | + ::Display *dpy = Display (); |
2893 | + |
2894 | + int left = 1; |
2895 | + int right = 2; |
2896 | + int top = 3; |
2897 | + int bottom = 4; |
2898 | + |
2899 | + ReparentedWindow w = CreateWindow (dpy); |
2900 | + |
2901 | + int x, y; |
2902 | + unsigned int width, height; |
2903 | + ASSERT_TRUE (QueryGeometry (dpy, w.client, x, y, width, height)); |
2904 | + |
2905 | + SendSetFrameExtentsRequest (w.client, left, right, top, bottom); |
2906 | + |
2907 | + /* Wait for a response */ |
2908 | + ASSERT_TRUE (VerifySetFrameExtentsResponse (w.client, left, right, top, bottom)); |
2909 | + |
2910 | + /* Client geometry is always unchanged */ |
2911 | + ASSERT_TRUE (VerifyWindowSize (w.client, x, y, width, height)); |
2912 | + |
2913 | + /* Frame geometry is frame geometry offset by extents */ |
2914 | + x -= left; |
2915 | + y -= top; |
2916 | + width += left + right; |
2917 | + height += top + bottom; |
2918 | + |
2919 | + ASSERT_TRUE (VerifyWindowSize (w.frame, x, y, width, height)); |
2920 | +} |
2921 | + |
2922 | +TEST_F (CompizXorgSystemConfigureWindowTest, MoveFrameLocked) |
2923 | +{ |
2924 | + ::Display *dpy = Display (); |
2925 | + |
2926 | + int x = 1; |
2927 | + int y = 1; |
2928 | + int width = 0; int height = 0; |
2929 | + int mask = CWX | CWY; |
2930 | + |
2931 | + ReparentedWindow w = CreateWindow (dpy); |
2932 | + |
2933 | + int currentX, currentY; |
2934 | + unsigned int currentWidth, currentHeight; |
2935 | + ASSERT_TRUE (QueryGeometry (dpy, |
2936 | + w.frame, |
2937 | + currentX, |
2938 | + currentY, |
2939 | + currentWidth, |
2940 | + currentHeight)); |
2941 | + |
2942 | + SendConfigureLockRequest (w.client, true); |
2943 | + SendConfigureRequest (w.client, x, y, width, height, mask); |
2944 | + |
2945 | + /* Wait for a response */ |
2946 | + ASSERT_TRUE (VerifyConfigureResponse (w.client, x, y, width, height)); |
2947 | + |
2948 | + /* Query the window size again - it should be the same */ |
2949 | + ASSERT_TRUE (VerifyWindowSize (w.frame, |
2950 | + currentX, |
2951 | + currentY, |
2952 | + currentWidth, |
2953 | + currentHeight)); |
2954 | + |
2955 | + |
2956 | + SendConfigureLockRequest (w.client, false); |
2957 | + |
2958 | + /* Expect buffer to be released */ |
2959 | + ASSERT_TRUE (WaitForConfigureNotify (dpy, |
2960 | + w.frame, |
2961 | + x, |
2962 | + y, |
2963 | + 0, |
2964 | + 0, |
2965 | + 0, |
2966 | + 0, |
2967 | + mask)); |
2968 | + |
2969 | +} |
2970 | + |
2971 | +TEST_F (CompizXorgSystemConfigureWindowTest, ResizeFrameLocked) |
2972 | +{ |
2973 | + ::Display *dpy = Display (); |
2974 | + |
2975 | + int x = 0; |
2976 | + int y = 0; |
2977 | + int width = 200; int height = 300; |
2978 | + int mask = CWWidth | CWHeight; |
2979 | + |
2980 | + ReparentedWindow w = CreateWindow (dpy); |
2981 | + |
2982 | + int currentX, currentY; |
2983 | + unsigned int currentWidth, currentHeight; |
2984 | + ASSERT_TRUE (QueryGeometry (dpy, |
2985 | + w.frame, |
2986 | + currentX, |
2987 | + currentY, |
2988 | + currentWidth, |
2989 | + currentHeight)); |
2990 | + |
2991 | + SendConfigureLockRequest (w.client, true); |
2992 | + SendConfigureRequest (w.client, x, y, width, height, mask); |
2993 | + |
2994 | + /* Expect buffer to be released immediately */ |
2995 | + ASSERT_TRUE (WaitForConfigureNotify (dpy, |
2996 | + w.frame, |
2997 | + 0, |
2998 | + 0, |
2999 | + width, |
3000 | + height, |
3001 | + 0, |
3002 | + 0, |
3003 | + mask)); |
3004 | + |
3005 | + /* Wait for a response */ |
3006 | + ASSERT_TRUE (VerifyConfigureResponse (w.client, x, y, width, height)); |
3007 | + |
3008 | + SendConfigureLockRequest (w.client, false); |
3009 | + |
3010 | + /* Query the window size again - it should be the same */ |
3011 | + ASSERT_TRUE (VerifyWindowSize (w.frame, |
3012 | + currentX, |
3013 | + currentY, |
3014 | + width, |
3015 | + height)); |
3016 | +} |
3017 | + |
3018 | +TEST_F (CompizXorgSystemConfigureWindowTest, SetFrameExtentsLocked) |
3019 | +{ |
3020 | + ::Display *dpy = Display (); |
3021 | + |
3022 | + /* Give the client window a 1px border, this will cause |
3023 | + * the client to move within the frame window by 1, 1 , |
3024 | + * the frame window to move by -1, -1 and resize by 2, 2 */ |
3025 | + int left = 1; |
3026 | + int right = 1; |
3027 | + int top = 1; |
3028 | + int bottom = 1; |
3029 | + int frameMask = CWX | CWY | CWWidth | CWHeight; |
3030 | + |
3031 | + ReparentedWindow w = CreateWindow (dpy); |
3032 | + |
3033 | + int currentX, currentY; |
3034 | + unsigned int currentWidth, currentHeight; |
3035 | + ASSERT_TRUE (QueryGeometry (dpy, |
3036 | + w.frame, |
3037 | + currentX, |
3038 | + currentY, |
3039 | + currentWidth, |
3040 | + currentHeight)); |
3041 | + |
3042 | + SendConfigureLockRequest (w.client, true); |
3043 | + SendSetFrameExtentsRequest (w.client, left, right, top, bottom); |
3044 | + |
3045 | + /* Expect buffer to be released immediately */ |
3046 | + ASSERT_TRUE (WaitForConfigureNotify (dpy, |
3047 | + w.frame, |
3048 | + currentX - left, |
3049 | + currentY - top, |
3050 | + currentWidth + (left + right), |
3051 | + currentHeight + (top + bottom), |
3052 | + 0, |
3053 | + 0, |
3054 | + frameMask)); |
3055 | + |
3056 | + |
3057 | + /* Wait for a response */ |
3058 | + ASSERT_TRUE (VerifySetFrameExtentsResponse (w.client, left, right, top, bottom)); |
3059 | + |
3060 | + SendConfigureLockRequest (w.client, false); |
3061 | + |
3062 | + /* Query the window size again - it should be the same */ |
3063 | + ASSERT_TRUE (VerifyWindowSize (w.frame, |
3064 | + currentX - left, |
3065 | + currentY - top, |
3066 | + currentWidth + (left + right), |
3067 | + currentHeight + (top + bottom))); |
3068 | +} |
3069 | |
3070 | === modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_ewmh.cpp' |
3071 | --- tests/system/xorg-gtest/tests/compiz_xorg_gtest_ewmh.cpp 2013-01-16 01:48:25 +0000 |
3072 | +++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_ewmh.cpp 2013-02-21 16:57:22 +0000 |
3073 | @@ -94,7 +94,8 @@ |
3074 | { |
3075 | ::Display *dpy = Display (); |
3076 | StartCompiz (static_cast <ct::CompizProcess::StartupFlags> ( |
3077 | - ct::CompizProcess::ReplaceCurrentWM)); |
3078 | + ct::CompizProcess::ReplaceCurrentWM), |
3079 | + ct::CompizProcess::PluginList ()); |
3080 | |
3081 | ct::PropertyNotifyXEventMatcher desktopHintsProperty (dpy, |
3082 | "_NET_DESKTOP_GEOMETRY"); |
3083 | |
3084 | === modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp' |
3085 | --- tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp 2013-02-15 11:28:27 +0000 |
3086 | +++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_icccm.cpp 2013-02-21 16:57:22 +0000 |
3087 | @@ -95,6 +95,12 @@ |
3088 | { |
3089 | public: |
3090 | |
3091 | + CompizXorgSystemICCCM () : |
3092 | + /* See note in the acceptance tests about this */ |
3093 | + env ("XORG_GTEST_CHILD_STDOUT", "1") |
3094 | + { |
3095 | + } |
3096 | + |
3097 | virtual void SetUp () |
3098 | { |
3099 | ct::CompizXorgSystemTest::SetUp (); |
3100 | @@ -109,6 +115,8 @@ |
3101 | } |
3102 | |
3103 | private: |
3104 | + |
3105 | + TmpEnv env; |
3106 | }; |
3107 | |
3108 | TEST_F (CompizXorgSystemICCCM, SomeoneElseHasSubstructureRedirectMask) |
3109 | @@ -116,7 +124,8 @@ |
3110 | StartCompiz (static_cast <ct::CompizProcess::StartupFlags> ( |
3111 | ct::CompizProcess::ExpectStartupFailure | |
3112 | ct::CompizProcess::ReplaceCurrentWM | |
3113 | - ct::CompizProcess::WaitForStartupMessage)); |
3114 | + ct::CompizProcess::WaitForStartupMessage), |
3115 | + ct::CompizProcess::PluginList ()); |
3116 | |
3117 | WaitForSuccessDeathTask::GetProcessState processState (boost::bind (&CompizXorgSystemICCCM::CompizProcessState, |
3118 | this)); |
3119 | @@ -152,7 +161,8 @@ |
3120 | |
3121 | StartCompiz (static_cast <ct::CompizProcess::StartupFlags> ( |
3122 | ct::CompizProcess::ReplaceCurrentWM | |
3123 | - ct::CompizProcess::WaitForStartupMessage)); |
3124 | + ct::CompizProcess::WaitForStartupMessage), |
3125 | + ct::CompizProcess::PluginList ()); |
3126 | } |
3127 | }; |
3128 | |
3129 | @@ -233,7 +243,9 @@ |
3130 | REQUEST_X, |
3131 | REQUEST_Y, |
3132 | REQUEST_WIDTH, |
3133 | - REQUEST_HEIGHT); |
3134 | + REQUEST_HEIGHT, |
3135 | + configureRequestEvent->value_mask & |
3136 | + ~(CWSibling | CWStackMode)); |
3137 | |
3138 | /* Should get a ConfigureNotify with the right parameters */ |
3139 | EXPECT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy, |
3140 | |
3141 | === modified file 'tests/xorg-gtest/CMakeLists.txt' |
3142 | --- tests/xorg-gtest/CMakeLists.txt 2013-02-15 11:28:27 +0000 |
3143 | +++ tests/xorg-gtest/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
3144 | @@ -1,6 +1,10 @@ |
3145 | set (COMPIZ_LD_LIBRARY_PATH ${CMAKE_BINARY_DIR}/src CACHE STRING "" FORCE) |
3146 | set (COMPIZ_BINARY ${CMAKE_BINARY_DIR}/src/compiz CACHE STRING "" FORCE) |
3147 | |
3148 | +set (COMPIZ_XORG_GTEST_COMMUNICATOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/communicator CACHE PATH "" FORCE) |
3149 | +set (COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARY_DIRS ${CMAKE_CURRENT_BINARY_DIR}/communicator CACHE PATH "" FORCE) |
3150 | +set (COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARY compiz_xorg_gtest_communicator CACHE STRING "" FORCE) |
3151 | + |
3152 | configure_file (${CMAKE_CURRENT_SOURCE_DIR}/src/compiz-xorg-gtest-config.h.in |
3153 | ${CMAKE_CURRENT_BINARY_DIR}/src/compiz-xorg-gtest-config.h |
3154 | @ONLY) |
3155 | @@ -9,7 +13,8 @@ |
3156 | ${XORG_SERVER_GTEST_INCLUDES} |
3157 | ${COMPIZ_XORG_SYSTEM_TEST_INCLUDE_DIR} |
3158 | ${CMAKE_CURRENT_BINARY_DIR}/src |
3159 | - ${compiz_SOURCE_DIR}/tests/shared) |
3160 | + ${compiz_SOURCE_DIR}/tests/shared |
3161 | + ${COMPIZ_XORG_GTEST_COMMUNICATOR_INCLUDE_DIR}) |
3162 | |
3163 | link_directories (${XORG_SERVER_LIBRARY_DIRS}) |
3164 | |
3165 | @@ -49,4 +54,11 @@ |
3166 | ${GTEST_BOTH_LIBRARIES} |
3167 | ${CMAKE_THREAD_LIBS_INIT} |
3168 | ${XORG_SERVER_LIBRARIES} |
3169 | + ${COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARY} |
3170 | ${X11_XI_LIBRARIES}) |
3171 | + |
3172 | +add_executable (xorg_gtest_wrapper |
3173 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/xorg_gtest_wrapper.cpp) |
3174 | + |
3175 | +add_subdirectory (communicator) |
3176 | +add_subdirectory (plugins) |
3177 | |
3178 | === added directory 'tests/xorg-gtest/communicator' |
3179 | === added file 'tests/xorg-gtest/communicator/CMakeLists.txt' |
3180 | --- tests/xorg-gtest/communicator/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3181 | +++ tests/xorg-gtest/communicator/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
3182 | @@ -0,0 +1,17 @@ |
3183 | +include (FindPkgConfig) |
3184 | + |
3185 | +pkg_check_modules (COMPIZ_XORG_GTEST_COMMUNICATOR x11) |
3186 | + |
3187 | +if (COMPIZ_XORG_GTEST_COMMUNICATOR_FOUND) |
3188 | + |
3189 | + include_directories (${COMPIZ_XORG_GTEST_COMMUNICATOR_INCLUDE_DIRS} |
3190 | + ${CMAKE_CURRENT_SOURCE_DIR}) |
3191 | + link_directories (${COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARY_DIRS}) |
3192 | + |
3193 | + add_library (${COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARY} STATIC |
3194 | + ${CMAKE_CURRENT_SOURCE_DIR}/compiz_xorg_gtest_communicator.cpp) |
3195 | + |
3196 | + target_link_libraries (${COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARY} |
3197 | + ${COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARIES}) |
3198 | + |
3199 | +endif (COMPIZ_XORG_GTEST_COMMUNICATOR_FOUND) |
3200 | |
3201 | === added file 'tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp' |
3202 | --- tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp 1970-01-01 00:00:00 +0000 |
3203 | +++ tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.cpp 2013-02-21 16:57:22 +0000 |
3204 | @@ -0,0 +1,200 @@ |
3205 | +/* |
3206 | +* Copyright © 2013 Sam Spilsbury |
3207 | +* |
3208 | +* Permission to use, copy, modify, distribute, and sell this software |
3209 | +* and its documentation for any purpose is hereby granted without |
3210 | +* fee, provided that the above copyright notice appear in all copies |
3211 | +* and that both that copyright notice and this permission notice |
3212 | +* appear in supporting documentation, and that the name of |
3213 | +* Novell, Inc. not be used in advertising or publicity pertaining to |
3214 | +* distribution of the software without specific, written prior permission. |
3215 | +* Novell, Inc. makes no representations about the suitability of this |
3216 | +* software for any purpose. It is provided "as is" without express or |
3217 | +* implied warranty. |
3218 | +* |
3219 | +* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
3220 | +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
3221 | +* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
3222 | +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
3223 | +* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
3224 | +* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
3225 | +* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
3226 | +* |
3227 | +* Author: Sam Spilsbury <smspillaz@gmail.com> |
3228 | +*/ |
3229 | + |
3230 | +#include <cstdio> |
3231 | +#include <cstring> |
3232 | +#include <map> |
3233 | +#include <string> |
3234 | +#include <sstream> |
3235 | +#include <stdexcept> |
3236 | +#include <poll.h> |
3237 | +#include <X11/Xlib.h> |
3238 | +#include <compiz_xorg_gtest_communicator.h> |
3239 | + |
3240 | +namespace compiz |
3241 | +{ |
3242 | +namespace testing |
3243 | +{ |
3244 | +namespace messages |
3245 | +{ |
3246 | +namespace internal |
3247 | +{ |
3248 | +const char *messages[] = |
3249 | +{ |
3250 | + "_COMPIZ_TEST_HELPER_READY", |
3251 | + "_COMPIZ_TEST_HELPER_REGISTER_CLIENT", |
3252 | + "_COMPIZ_TEST_HELPER_LOCK_CONFIGURE_REQUESTS", |
3253 | + "_COMPIZ_TEST_HELPER_CHANGE_FRAME_EXTENTS", |
3254 | + "_COMPIZ_TEST_HELPER_FRAME_EXTENTS_CHANGED", |
3255 | + "_COMPIZ_TEST_HELPER_CONFIGURE_WINDOW", |
3256 | + "_COMPIZ_TEST_HELPER_WINDOW_CONFIGURE_PROCESSED", |
3257 | + "_COMPIZ_TEST_HELPER_WINDOW_READY" |
3258 | +}; |
3259 | +} |
3260 | + |
3261 | +const char *TEST_HELPER_READY_MSG = internal::messages[0]; |
3262 | +const char *TEST_HELPER_REGISTER_CLIENT = internal::messages[1]; |
3263 | +const char *TEST_HELPER_LOCK_CONFIGURE_REQUESTS = internal::messages[2]; |
3264 | +const char *TEST_HELPER_CHANGE_FRAME_EXTENTS = internal::messages[3]; |
3265 | +const char *TEST_HELPER_FRAME_EXTENTS_CHANGED = internal::messages[4]; |
3266 | +const char *TEST_HELPER_CONFIGURE_WINDOW = internal::messages[5]; |
3267 | +const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED = internal::messages[6]; |
3268 | +const char *TEST_HELPER_WINDOW_READY = internal::messages[7]; |
3269 | +} |
3270 | +} |
3271 | +} |
3272 | + |
3273 | +namespace ct = compiz::testing; |
3274 | +namespace ctmi = compiz::testing::messages::internal; |
3275 | + |
3276 | +class ct::MessageAtoms::Private |
3277 | +{ |
3278 | + public: |
3279 | + |
3280 | + std::map <const char *, Atom> atoms; |
3281 | +}; |
3282 | + |
3283 | +ct::MessageAtoms::MessageAtoms (Display *display) : |
3284 | + priv (new ct::MessageAtoms::Private) |
3285 | +{ |
3286 | + int nAtoms = sizeof (ctmi::messages) / sizeof (const char *); |
3287 | + Atom atoms[nAtoms]; |
3288 | + |
3289 | + if (!XInternAtoms (display, |
3290 | + const_cast <char **> (ctmi::messages), |
3291 | + sizeof (ctmi::messages) / sizeof (const char *), |
3292 | + 0, |
3293 | + atoms)) |
3294 | + throw std::runtime_error ("XInternAtoms generated an error"); |
3295 | + |
3296 | + for (int i = 0; i < nAtoms; ++i) |
3297 | + priv->atoms[ctmi::messages[i]] = atoms[i]; |
3298 | +} |
3299 | + |
3300 | +Atom |
3301 | +ct::MessageAtoms::FetchForString (const char *message) |
3302 | +{ |
3303 | + std::map <const char *, Atom>::iterator it (priv->atoms.find (message)); |
3304 | + |
3305 | + if (it == priv->atoms.end ()) |
3306 | + { |
3307 | + std::stringstream ss; |
3308 | + |
3309 | + ss << "Atom for message " << message << " does not exist"; |
3310 | + throw std::runtime_error (ss.str ()); |
3311 | + } |
3312 | + |
3313 | + return it->second; |
3314 | +} |
3315 | + |
3316 | +namespace |
3317 | +{ |
3318 | +bool FindClientMessage (Display *display, |
3319 | + XEvent &event, |
3320 | + Atom message) |
3321 | +{ |
3322 | + while (XPending (display)) |
3323 | + { |
3324 | + XNextEvent (display, &event); |
3325 | + |
3326 | + if (event.type == ClientMessage) |
3327 | + { |
3328 | + if (event.xclient.message_type == message) |
3329 | + return true; |
3330 | + } |
3331 | + } |
3332 | + |
3333 | + return false; |
3334 | +} |
3335 | +} |
3336 | + |
3337 | +bool |
3338 | +ct::ReceiveMessage (Display *display, |
3339 | + Atom message, |
3340 | + XEvent &event, |
3341 | + int timeout) |
3342 | +{ |
3343 | + if (FindClientMessage (display, event, message)) |
3344 | + return true; |
3345 | + else |
3346 | + { |
3347 | + XSync (display, false); |
3348 | + |
3349 | + struct pollfd pfd; |
3350 | + pfd.events = POLLIN | POLLHUP | POLLERR; |
3351 | + pfd.revents = 0; |
3352 | + pfd.fd = ConnectionNumber (display); |
3353 | + |
3354 | + poll (&pfd, 1, timeout); |
3355 | + |
3356 | + /* Make sure we get something */ |
3357 | + if ((pfd.revents & POLLIN) && |
3358 | + !(pfd.revents & (POLLHUP | POLLERR))) |
3359 | + { |
3360 | + return ReceiveMessage (display, message, event, timeout); |
3361 | + } |
3362 | + else |
3363 | + return false; |
3364 | + } |
3365 | + |
3366 | + return false; |
3367 | +} |
3368 | + |
3369 | +void |
3370 | +ct::SendClientMessage (Display *display, |
3371 | + Atom message, |
3372 | + Window destination, |
3373 | + Window target, |
3374 | + const std::vector<long> &data) |
3375 | +{ |
3376 | + if (data.size () > 5) |
3377 | + throw std::runtime_error ("data size must be less than 5"); |
3378 | + |
3379 | + XEvent event; |
3380 | + |
3381 | + memset (&event, 0, sizeof (XEvent)); |
3382 | + |
3383 | + event.type = ClientMessage; |
3384 | + |
3385 | + event.xclient.display = display; |
3386 | + event.xclient.send_event = 1; |
3387 | + event.xclient.serial = 0; |
3388 | + |
3389 | + event.xclient.message_type = message; |
3390 | + event.xclient.window = target; |
3391 | + event.xclient.format = 32; |
3392 | + |
3393 | + int count = 0; |
3394 | + for (std::vector <long>::const_iterator it = data.begin (); |
3395 | + it != data.end (); |
3396 | + ++it) |
3397 | + event.xclient.data.l[count++] = *it; |
3398 | + |
3399 | + XSendEvent (display, |
3400 | + destination, |
3401 | + 0, |
3402 | + StructureNotifyMask, |
3403 | + &event); |
3404 | +}; |
3405 | |
3406 | === added file 'tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h' |
3407 | --- tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h 1970-01-01 00:00:00 +0000 |
3408 | +++ tests/xorg-gtest/communicator/compiz_xorg_gtest_communicator.h 2013-02-21 16:57:22 +0000 |
3409 | @@ -0,0 +1,67 @@ |
3410 | +/* |
3411 | +* Copyright © 2013 Sam Spilsbury |
3412 | +* |
3413 | +* Permission to use, copy, modify, distribute, and sell this software |
3414 | +* and its documentation for any purpose is hereby granted without |
3415 | +* fee, provided that the above copyright notice appear in all copies |
3416 | +* and that both that copyright notice and this permission notice |
3417 | +* appear in supporting documentation, and that the name of |
3418 | +* Novell, Inc. not be used in advertising or publicity pertaining to |
3419 | +* distribution of the software without specific, written prior permission. |
3420 | +* Novell, Inc. makes no representations about the suitability of this |
3421 | +* software for any purpose. It is provided "as is" without express or |
3422 | +* implied warranty. |
3423 | +* |
3424 | +* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
3425 | +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
3426 | +* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
3427 | +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
3428 | +* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
3429 | +* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
3430 | +* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
3431 | +* |
3432 | +* Author: Sam Spilsbury <smspillaz@gmail.com> |
3433 | +*/ |
3434 | +#ifndef _COMPIZ_XORG_GTEST_COMMUNICATOR_H |
3435 | +#define _COMPIZ_XORG_GTEST_COMMUNICATOR_H |
3436 | + |
3437 | +#include <memory> |
3438 | +#include <vector> |
3439 | + |
3440 | +namespace compiz |
3441 | +{ |
3442 | +namespace testing |
3443 | +{ |
3444 | +namespace messages |
3445 | +{ |
3446 | +extern const char *TEST_HELPER_READY_MSG; |
3447 | +extern const char *TEST_HELPER_REGISTER_CLIENT; |
3448 | +extern const char *TEST_HELPER_LOCK_CONFIGURE_REQUESTS; |
3449 | +extern const char *TEST_HELPER_CHANGE_FRAME_EXTENTS; |
3450 | +extern const char *TEST_HELPER_FRAME_EXTENTS_CHANGED; |
3451 | +extern const char *TEST_HELPER_CONFIGURE_WINDOW; |
3452 | +extern const char *TEST_HELPER_WINDOW_CONFIGURE_PROCESSED; |
3453 | +extern const char *TEST_HELPER_WINDOW_READY; |
3454 | +} |
3455 | + |
3456 | + |
3457 | +class MessageAtoms |
3458 | +{ |
3459 | + public: |
3460 | + |
3461 | + MessageAtoms (Display *); |
3462 | + |
3463 | + Atom FetchForString (const char *string); |
3464 | + |
3465 | + private: |
3466 | + |
3467 | + class Private; |
3468 | + std::auto_ptr <Private> priv; |
3469 | +}; |
3470 | + |
3471 | +bool ReceiveMessage (Display *, Atom, XEvent &, int timeout = 1000); |
3472 | +void SendClientMessage (Display *, Atom, Window, Window, const std::vector <long> &data); |
3473 | +} |
3474 | +} |
3475 | + |
3476 | +#endif |
3477 | |
3478 | === modified file 'tests/xorg-gtest/include/compiz-xorg-gtest.h' |
3479 | --- tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-01-11 06:27:22 +0000 |
3480 | +++ tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-02-21 16:57:22 +0000 |
3481 | @@ -37,6 +37,24 @@ |
3482 | { |
3483 | typedef ::testing::MatcherInterface <const XEvent &> XEventMatcher; |
3484 | |
3485 | + class PrivateClientMessageXEventMatcher; |
3486 | + class ClientMessageXEventMatcher : |
3487 | + public compiz::testing::XEventMatcher |
3488 | + { |
3489 | + public: |
3490 | + |
3491 | + ClientMessageXEventMatcher (Display *display, |
3492 | + Atom message, |
3493 | + Window target); |
3494 | + |
3495 | + virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const; |
3496 | + virtual void DescribeTo (std::ostream *os) const; |
3497 | + |
3498 | + private: |
3499 | + |
3500 | + std::auto_ptr <PrivateClientMessageXEventMatcher> priv; |
3501 | + }; |
3502 | + |
3503 | class PrivatePropertyNotifyXEventMatcher; |
3504 | class PropertyNotifyXEventMatcher : |
3505 | public compiz::testing::XEventMatcher |
3506 | @@ -65,7 +83,8 @@ |
3507 | int x, |
3508 | int y, |
3509 | unsigned int width, |
3510 | - unsigned int height); |
3511 | + unsigned int height, |
3512 | + unsigned int mask); |
3513 | |
3514 | virtual bool MatchAndExplain (const XEvent &event, MatchResultListener *listener) const; |
3515 | virtual void DescribeTo (std::ostream *os) const; |
3516 | @@ -132,7 +151,12 @@ |
3517 | ExpectStartupFailure = (1 << 2) |
3518 | } StartupFlags; |
3519 | |
3520 | - CompizProcess (Display *dpy, StartupFlags, unsigned int waitTimeout); |
3521 | + typedef std::vector <std::string> PluginList; |
3522 | + |
3523 | + CompizProcess (Display *dpy, |
3524 | + StartupFlags, |
3525 | + const PluginList &plugins, |
3526 | + unsigned int waitTimeout); |
3527 | ~CompizProcess (); |
3528 | xorg::testing::Process::State State (); |
3529 | pid_t Pid (); |
3530 | @@ -153,18 +177,52 @@ |
3531 | virtual void TearDown (); |
3532 | |
3533 | xorg::testing::Process::State CompizProcessState (); |
3534 | - void StartCompiz (CompizProcess::StartupFlags flags); |
3535 | + void StartCompiz (CompizProcess::StartupFlags flags, |
3536 | + const CompizProcess::PluginList &plugins); |
3537 | |
3538 | private: |
3539 | std::auto_ptr <PrivateCompizXorgSystemTest> priv; |
3540 | }; |
3541 | |
3542 | + class PrivateAutostartCompizXorgSystemTest; |
3543 | class AutostartCompizXorgSystemTest : |
3544 | public CompizXorgSystemTest |
3545 | { |
3546 | public: |
3547 | |
3548 | - virtual void SetUp (); |
3549 | + AutostartCompizXorgSystemTest (); |
3550 | + |
3551 | + virtual CompizProcess::StartupFlags GetStartupFlags (); |
3552 | + virtual int GetEventMask (); |
3553 | + virtual CompizProcess::PluginList GetPluginList (); |
3554 | + virtual void SetUp (); |
3555 | + |
3556 | + private: |
3557 | + std::auto_ptr <PrivateAutostartCompizXorgSystemTest> priv; |
3558 | + }; |
3559 | + |
3560 | + class PrivateAutostartCompizXorgSystemTestWithTestHelper; |
3561 | + class AutostartCompizXorgSystemTestWithTestHelper : |
3562 | + public AutostartCompizXorgSystemTest |
3563 | + { |
3564 | + public: |
3565 | + |
3566 | + AutostartCompizXorgSystemTestWithTestHelper (); |
3567 | + |
3568 | + virtual CompizProcess::PluginList GetPluginList (); |
3569 | + |
3570 | + protected: |
3571 | + |
3572 | + Atom FetchAtom (const char *); |
3573 | + void WaitForWindowCreation (Window w); |
3574 | + |
3575 | + virtual int GetEventMask (); |
3576 | + |
3577 | + private: |
3578 | + |
3579 | + virtual void SetUp (); |
3580 | + |
3581 | + std::auto_ptr <PrivateAutostartCompizXorgSystemTestWithTestHelper> priv; |
3582 | }; |
3583 | } |
3584 | } |
3585 | |
3586 | === added directory 'tests/xorg-gtest/plugins' |
3587 | === added file 'tests/xorg-gtest/plugins/CMakeLists.txt' |
3588 | --- tests/xorg-gtest/plugins/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3589 | +++ tests/xorg-gtest/plugins/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
3590 | @@ -0,0 +1,10 @@ |
3591 | +set (COMPIZ_CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) |
3592 | +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${COMPIZ_CMAKE_MODULE_PATH}) |
3593 | +include (CompizDefaults) |
3594 | +include (CompizCommon) |
3595 | + |
3596 | +set (COMPIZ_FOUND "true") |
3597 | + |
3598 | +include_directories (${COMPIZ_INTERNAL_INCLUDES}) |
3599 | + |
3600 | +add_subdirectory (testhelper) |
3601 | |
3602 | === added directory 'tests/xorg-gtest/plugins/testhelper' |
3603 | === added file 'tests/xorg-gtest/plugins/testhelper/CMakeLists.txt' |
3604 | --- tests/xorg-gtest/plugins/testhelper/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3605 | +++ tests/xorg-gtest/plugins/testhelper/CMakeLists.txt 2013-02-21 16:57:22 +0000 |
3606 | @@ -0,0 +1,7 @@ |
3607 | +find_package (Compiz REQUIRED) |
3608 | + |
3609 | +include (CompizPlugin) |
3610 | + |
3611 | +include_directories (${COMPIZ_XORG_GTEST_COMMUNICATOR_INCLUDE_DIR}) |
3612 | + |
3613 | +compiz_plugin (testhelper NOINSTALL LIBRARIES ${COMPIZ_XORG_GTEST_COMMUNICATOR_LIBRARY}) |
3614 | |
3615 | === added directory 'tests/xorg-gtest/plugins/testhelper/src' |
3616 | === added file 'tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp' |
3617 | --- tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 1970-01-01 00:00:00 +0000 |
3618 | +++ tests/xorg-gtest/plugins/testhelper/src/testhelper.cpp 2013-02-21 16:57:22 +0000 |
3619 | @@ -0,0 +1,231 @@ |
3620 | +/* |
3621 | +* Copyright © 2013 Sam Spilsbury |
3622 | +* |
3623 | +* Permission to use, copy, modify, distribute, and sell this software |
3624 | +* and its documentation for any purpose is hereby granted without |
3625 | +* fee, provided that the above copyright notice appear in all copies |
3626 | +* and that both that copyright notice and this permission notice |
3627 | +* appear in supporting documentation, and that the name of |
3628 | +* Novell, Inc. not be used in advertising or publicity pertaining to |
3629 | +* distribution of the software without specific, written prior permission. |
3630 | +* Novell, Inc. makes no representations about the suitability of this |
3631 | +* software for any purpose. It is provided "as is" without express or |
3632 | +* implied warranty. |
3633 | +* |
3634 | +* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
3635 | +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
3636 | +* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
3637 | +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
3638 | +* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
3639 | +* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
3640 | +* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
3641 | +* |
3642 | +* Author: Sam Spilsbury <smspillaz@gmail.com> |
3643 | +*/ |
3644 | + |
3645 | +#include <boost/shared_ptr.hpp> |
3646 | +#include <boost/bind.hpp> |
3647 | +#include "testhelper.h" |
3648 | + |
3649 | +COMPIZ_PLUGIN_20090315 (testhelper, TestHelperPluginVTable) |
3650 | + |
3651 | +namespace |
3652 | +{ |
3653 | +template <typename T> |
3654 | +void XFreeT (T *t) |
3655 | +{ |
3656 | + XFree (t); |
3657 | +} |
3658 | +} |
3659 | + |
3660 | +namespace ct = compiz::testing; |
3661 | +namespace ctm = compiz::testing::messages; |
3662 | + |
3663 | +void |
3664 | +TestHelperScreen::handleEvent (XEvent *event) |
3665 | +{ |
3666 | + if (event->type == ClientMessage) |
3667 | + { |
3668 | + if (event->xclient.window != screen->root ()) |
3669 | + { |
3670 | + std::map <Atom, ClientMessageHandler>::iterator it = |
3671 | + mMessageHandlers.find (event->xclient.message_type); |
3672 | + |
3673 | + if (it != mMessageHandlers.end ()) |
3674 | + { |
3675 | + ClientMessageHandler handler (it->second); |
3676 | + CompWindow *w = screen->findWindow (event->xclient.window); |
3677 | + |
3678 | + XClientMessageEvent *xce = &event->xclient; |
3679 | + long *data = xce->data.l; |
3680 | + |
3681 | + if (w) |
3682 | + ((*TestHelperWindow::get (w)).*(handler)) (data); |
3683 | + } |
3684 | + } |
3685 | + } |
3686 | + |
3687 | + screen->handleEvent (event); |
3688 | +} |
3689 | + |
3690 | +void |
3691 | +TestHelperScreen::watchForMessage (Atom message, ClientMessageHandler handler) |
3692 | +{ |
3693 | + if (mMessageHandlers.find (message) != mMessageHandlers.end ()) |
3694 | + { |
3695 | + boost::shared_ptr <char> name (XGetAtomName (screen->dpy (), message), |
3696 | + boost::bind (XFreeT <char>, _1)); |
3697 | + compLogMessage ("testhelper", CompLogLevelWarn, |
3698 | + "a message handler was already defined for %s", |
3699 | + name.get ()); |
3700 | + return; |
3701 | + } |
3702 | + |
3703 | + mMessageHandlers[message] = handler; |
3704 | +} |
3705 | + |
3706 | +void |
3707 | +TestHelperScreen::removeMessageWatch (Atom message) |
3708 | +{ |
3709 | + std::map <Atom, ClientMessageHandler>::iterator it = |
3710 | + mMessageHandlers.find (message); |
3711 | + |
3712 | + if (it != mMessageHandlers.end ()) |
3713 | + mMessageHandlers.erase (it); |
3714 | +} |
3715 | + |
3716 | +Atom |
3717 | +TestHelperScreen::fetchAtom (const char *message) |
3718 | +{ |
3719 | + return mAtomStore.FetchForString (message); |
3720 | +} |
3721 | + |
3722 | +void |
3723 | +TestHelperWindow::configureAndReport (long *data) |
3724 | +{ |
3725 | + XWindowChanges xwc; |
3726 | + XWindowChanges saved; |
3727 | + |
3728 | + xwc.x = data[0]; |
3729 | + xwc.y = data[1]; |
3730 | + xwc.width = data[2]; |
3731 | + xwc.height = data[3]; |
3732 | + int mask = data[4]; |
3733 | + |
3734 | + /* configureXWindow has a nasty side-effect of |
3735 | + * changing xwc to the client-window co-ordinates, |
3736 | + * so we should back it up first */ |
3737 | + saved = xwc; |
3738 | + |
3739 | + window->configureXWindow (mask, &xwc); |
3740 | + |
3741 | + xwc = saved; |
3742 | + |
3743 | + std::vector <long> response; |
3744 | + |
3745 | + response.push_back (xwc.x); |
3746 | + response.push_back (xwc.y); |
3747 | + response.push_back (xwc.width); |
3748 | + response.push_back (xwc.height); |
3749 | + |
3750 | + TestHelperScreen *ts = TestHelperScreen::get (screen); |
3751 | + const Atom atom = ts->fetchAtom (ctm::TEST_HELPER_WINDOW_CONFIGURE_PROCESSED); |
3752 | + |
3753 | + ct::SendClientMessage (screen->dpy (), |
3754 | + atom, |
3755 | + screen->root (), |
3756 | + window->id (), |
3757 | + response); |
3758 | +} |
3759 | + |
3760 | +void |
3761 | +TestHelperWindow::setFrameExtentsAndReport (long *data) |
3762 | +{ |
3763 | + CompWindowExtents input; |
3764 | + |
3765 | + input.left = data[0]; |
3766 | + input.right = data[1]; |
3767 | + input.top = data[2]; |
3768 | + input.bottom = data[3]; |
3769 | + |
3770 | + window->setWindowFrameExtents (&input, &input); |
3771 | + |
3772 | + std::vector <long> response; |
3773 | + |
3774 | + response.push_back (input.left); |
3775 | + response.push_back (input.right); |
3776 | + response.push_back (input.top); |
3777 | + response.push_back (input.bottom); |
3778 | + |
3779 | + TestHelperScreen *ts = TestHelperScreen::get (screen); |
3780 | + const Atom atom = ts->fetchAtom (ctm::TEST_HELPER_FRAME_EXTENTS_CHANGED); |
3781 | + |
3782 | + ct::SendClientMessage (screen->dpy (), |
3783 | + atom, |
3784 | + screen->root (), |
3785 | + window->id (), |
3786 | + response); |
3787 | +} |
3788 | + |
3789 | +void |
3790 | +TestHelperWindow::setConfigureLock (long *data) |
3791 | +{ |
3792 | + bool enabled = data[0] ? true : false; |
3793 | + |
3794 | + if (enabled && !configureLock) |
3795 | + configureLock = window->obtainLockOnConfigureRequests (); |
3796 | + else if (!enabled && configureLock) |
3797 | + { |
3798 | + configureLock->release (); |
3799 | + configureLock.reset (); |
3800 | + } |
3801 | +} |
3802 | + |
3803 | +TestHelperWindow::TestHelperWindow (CompWindow *w) : |
3804 | + PluginClassHandler <TestHelperWindow, CompWindow> (w), |
3805 | + window (w), |
3806 | + configureLock () |
3807 | +{ |
3808 | + WindowInterface::setHandler (w); |
3809 | + |
3810 | + TestHelperScreen *ts = TestHelperScreen::get (screen); |
3811 | + |
3812 | + std::vector <long> data; |
3813 | + data.push_back (static_cast <long> (window->id ())); |
3814 | + ct::SendClientMessage (screen->dpy (), |
3815 | + ts->fetchAtom (ctm::TEST_HELPER_WINDOW_READY), |
3816 | + screen->root (), |
3817 | + screen->root (), |
3818 | + data); |
3819 | +} |
3820 | + |
3821 | +TestHelperScreen::TestHelperScreen (CompScreen *s) : |
3822 | + PluginClassHandler <TestHelperScreen, CompScreen> (s), |
3823 | + screen (s), |
3824 | + mAtomStore (s->dpy ()) |
3825 | +{ |
3826 | + ScreenInterface::setHandler (s); |
3827 | + |
3828 | + /* Register the message handlers on each window */ |
3829 | + watchForMessage (fetchAtom (ctm::TEST_HELPER_CONFIGURE_WINDOW), |
3830 | + &TestHelperWindow::configureAndReport); |
3831 | + watchForMessage (fetchAtom (ctm::TEST_HELPER_CHANGE_FRAME_EXTENTS), |
3832 | + &TestHelperWindow::setFrameExtentsAndReport); |
3833 | + watchForMessage (fetchAtom (ctm::TEST_HELPER_LOCK_CONFIGURE_REQUESTS), |
3834 | + &TestHelperWindow::setConfigureLock); |
3835 | + |
3836 | + ct::SendClientMessage (s->dpy (), |
3837 | + mAtomStore.FetchForString (ctm::TEST_HELPER_READY_MSG), |
3838 | + s->root (), |
3839 | + s->root (), |
3840 | + std::vector <long> ()); |
3841 | +} |
3842 | + |
3843 | +bool |
3844 | +TestHelperPluginVTable::init () |
3845 | +{ |
3846 | + if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION)) |
3847 | + return false; |
3848 | + |
3849 | + return true; |
3850 | +} |
3851 | |
3852 | === added file 'tests/xorg-gtest/plugins/testhelper/src/testhelper.h' |
3853 | --- tests/xorg-gtest/plugins/testhelper/src/testhelper.h 1970-01-01 00:00:00 +0000 |
3854 | +++ tests/xorg-gtest/plugins/testhelper/src/testhelper.h 2013-02-21 16:57:22 +0000 |
3855 | @@ -0,0 +1,95 @@ |
3856 | +/* |
3857 | +* Copyright © 2013 Sam Spilsbury |
3858 | +* |
3859 | +* Permission to use, copy, modify, distribute, and sell this software |
3860 | +* and its documentation for any purpose is hereby granted without |
3861 | +* fee, provided that the above copyright notice appear in all copies |
3862 | +* and that both that copyright notice and this permission notice |
3863 | +* appear in supporting documentation, and that the name of |
3864 | +* Novell, Inc. not be used in advertising or publicity pertaining to |
3865 | +* distribution of the software without specific, written prior permission. |
3866 | +* Novell, Inc. makes no representations about the suitability of this |
3867 | +* software for any purpose. It is provided "as is" without express or |
3868 | +* implied warranty. |
3869 | +* |
3870 | +* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
3871 | +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
3872 | +* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
3873 | +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
3874 | +* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
3875 | +* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
3876 | +* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
3877 | +* |
3878 | +* Author: Sam Spilsbury <smspillaz@gmail.com> |
3879 | +*/ |
3880 | +#ifndef _COMPIZ_TESTHELPER_H |
3881 | +#define _COMPIZ_TESTHELPER_H |
3882 | + |
3883 | +#include <map> |
3884 | +#include <boost/function.hpp> |
3885 | + |
3886 | +#include <X11/Xatom.h> |
3887 | + |
3888 | +#include <core/core.h> |
3889 | +#include <core/pluginclasshandler.h> |
3890 | +#include <core/configurerequestbuffer.h> |
3891 | + |
3892 | +#include <compiz_xorg_gtest_communicator.h> |
3893 | + |
3894 | +#include "testhelper_options.h" |
3895 | + |
3896 | +class TestHelperWindow; |
3897 | + |
3898 | +class TestHelperScreen : |
3899 | + public PluginClassHandler <TestHelperScreen, CompScreen>, |
3900 | + public ScreenInterface, |
3901 | + public TesthelperOptions |
3902 | +{ |
3903 | + public: |
3904 | + |
3905 | + typedef void (TestHelperWindow::*ClientMessageHandler) (long *); |
3906 | + |
3907 | + TestHelperScreen (CompScreen *); |
3908 | + |
3909 | + void handleEvent (XEvent *event); |
3910 | + |
3911 | + void watchForMessage (Atom, ClientMessageHandler); |
3912 | + void removeMessageWatch (Atom); |
3913 | + |
3914 | + Atom fetchAtom (const char *); |
3915 | + |
3916 | + |
3917 | + private: |
3918 | + |
3919 | + CompScreen *screen; |
3920 | + compiz::testing::MessageAtoms mAtomStore; |
3921 | + std::map <Atom, ClientMessageHandler> mMessageHandlers; |
3922 | +}; |
3923 | + |
3924 | +class TestHelperWindow : |
3925 | + public PluginClassHandler <TestHelperWindow, CompWindow>, |
3926 | + public WindowInterface |
3927 | +{ |
3928 | + public: |
3929 | + |
3930 | + TestHelperWindow (CompWindow *); |
3931 | + |
3932 | + void configureAndReport (long *); |
3933 | + void setFrameExtentsAndReport (long *); |
3934 | + void setConfigureLock (long *); |
3935 | + |
3936 | + private: |
3937 | + |
3938 | + CompWindow *window; |
3939 | + compiz::window::configure_buffers::Releasable::Ptr configureLock; |
3940 | +}; |
3941 | + |
3942 | +class TestHelperPluginVTable : |
3943 | + public CompPlugin::VTableForScreenAndWindow <TestHelperScreen, TestHelperWindow> |
3944 | +{ |
3945 | + public: |
3946 | + |
3947 | + bool init (); |
3948 | +}; |
3949 | + |
3950 | +#endif |
3951 | |
3952 | === added file 'tests/xorg-gtest/plugins/testhelper/testhelper.xml.in' |
3953 | --- tests/xorg-gtest/plugins/testhelper/testhelper.xml.in 1970-01-01 00:00:00 +0000 |
3954 | +++ tests/xorg-gtest/plugins/testhelper/testhelper.xml.in 2013-02-21 16:57:22 +0000 |
3955 | @@ -0,0 +1,6 @@ |
3956 | +<?xml version="1.0" encoding="UTF-8"?> |
3957 | +<compiz> |
3958 | + <plugin name="testhelper" useBcop="true"> |
3959 | + <options/> |
3960 | + </plugin> |
3961 | +</compiz> |
3962 | |
3963 | === removed file 'tests/xorg-gtest/src/CMakeLists.txt' |
3964 | --- tests/xorg-gtest/src/CMakeLists.txt 2013-02-15 11:28:27 +0000 |
3965 | +++ tests/xorg-gtest/src/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3966 | @@ -1,2 +0,0 @@ |
3967 | -add_executable (xorg_gtest_wrapper |
3968 | - ${CMAKE_CURRENT_SOURCE_DIR}/xorg_gtest_wrapper.cpp) |
3969 | |
3970 | === modified file 'tests/xorg-gtest/src/compiz-xorg-gtest-config.h.in' |
3971 | --- tests/xorg-gtest/src/compiz-xorg-gtest-config.h.in 2012-09-18 13:17:09 +0000 |
3972 | +++ tests/xorg-gtest/src/compiz-xorg-gtest-config.h.in 2013-02-21 16:57:22 +0000 |
3973 | @@ -25,8 +25,9 @@ |
3974 | |
3975 | namespace |
3976 | { |
3977 | - const std::string compizLDLibraryPath ("@COMPIZ_LD_LIBRARY_PATH@");//("/home/smspillaz/Source/Compiz/dev/dev/merges/compiz/proposed/compiz/build/src/"); |
3978 | - const std::string compizBinaryPath ("@COMPIZ_BINARY@");//("/home/smspillaz/Source/Compiz/dev/dev/merges/compiz/proposed/compiz/build/src/compiz"); |
3979 | + const std::string compizLDLibraryPath ("@COMPIZ_LD_LIBRARY_PATH@"); |
3980 | + const std::string compizBinaryPath ("@COMPIZ_BINARY@"); |
3981 | + const std::string compizOverridePluginPath ("@COMPIZ_OVERRIDE_PLUGIN_PATH@"); |
3982 | } |
3983 | |
3984 | #endif |
3985 | |
3986 | === modified file 'tests/xorg-gtest/src/compiz-xorg-gtest.cpp' |
3987 | --- tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-02-19 01:06:21 +0000 |
3988 | +++ tests/xorg-gtest/src/compiz-xorg-gtest.cpp 2013-02-21 16:57:22 +0000 |
3989 | @@ -22,12 +22,16 @@ |
3990 | */ |
3991 | #include <list> |
3992 | #include <stdexcept> |
3993 | +#include <sstream> |
3994 | #include <iomanip> |
3995 | #include <gtest/gtest.h> |
3996 | #include <gmock/gmock.h> |
3997 | #include <boost/shared_ptr.hpp> |
3998 | +#include <gtest_shared_tmpenv.h> |
3999 | +#include <gtest_shared_characterwrapper.h> |
4000 | #include <xorg/gtest/xorg-gtest.h> |
4001 | #include <compiz-xorg-gtest.h> |
4002 | +#include <compiz_xorg_gtest_communicator.h> |
4003 | #include <X11/Xlib.h> |
4004 | #include <X11/Xatom.h> |
4005 | #include <X11/extensions/shape.h> |
4006 | @@ -49,7 +53,6 @@ |
4007 | const unsigned int WINDOW_CLASS = InputOutput; |
4008 | Visual *WINDOW_VISUAL = CopyFromParent; |
4009 | |
4010 | - |
4011 | const long WINDOW_ATTRIB_VALUE_MASK = 0; |
4012 | |
4013 | void RemoveEventFromQueue (Display *dpy) |
4014 | @@ -142,6 +145,10 @@ |
4015 | return true; |
4016 | } |
4017 | |
4018 | + std::stringstream ss; |
4019 | + matcher.DescribeTo (&ss); |
4020 | + ADD_FAILURE () << "Expected event matching: " << ss.str (); |
4021 | + |
4022 | return false; |
4023 | } |
4024 | |
4025 | @@ -221,6 +228,54 @@ |
4026 | }; |
4027 | } |
4028 | |
4029 | +class ct::PrivateClientMessageXEventMatcher |
4030 | +{ |
4031 | + public: |
4032 | + |
4033 | + PrivateClientMessageXEventMatcher (Display *display, |
4034 | + Atom message, |
4035 | + Window target) : |
4036 | + display (display), |
4037 | + message (message), |
4038 | + target (target) |
4039 | + { |
4040 | + } |
4041 | + |
4042 | + Display *display; |
4043 | + Atom message; |
4044 | + Window target; |
4045 | +}; |
4046 | + |
4047 | +ct::ClientMessageXEventMatcher::ClientMessageXEventMatcher (Display *display, |
4048 | + Atom message, |
4049 | + Window target) : |
4050 | + priv (new ct::PrivateClientMessageXEventMatcher (display, message, target)) |
4051 | +{ |
4052 | +} |
4053 | + |
4054 | +bool |
4055 | +ct::ClientMessageXEventMatcher::MatchAndExplain (const XEvent &event, MatchResultListener *listener) const |
4056 | +{ |
4057 | + const XClientMessageEvent *xce = reinterpret_cast <const XClientMessageEvent *> (&event); |
4058 | + |
4059 | + if (xce->message_type == priv->message && |
4060 | + xce->window == priv->target) |
4061 | + return true; |
4062 | + |
4063 | + return false; |
4064 | +} |
4065 | + |
4066 | +void |
4067 | +ct::ClientMessageXEventMatcher::DescribeTo (std::ostream *os) const |
4068 | +{ |
4069 | + CharacterWrapper name (XGetAtomName (priv->display, |
4070 | + priv->message)); |
4071 | + *os << "matches ClientMessage with type " << name |
4072 | + << " on window " |
4073 | + << std::hex << static_cast <long> (priv->target) |
4074 | + << std::dec << std::endl; |
4075 | +} |
4076 | + |
4077 | class ct::PrivatePropertyNotifyXEventMatcher |
4078 | { |
4079 | public: |
4080 | @@ -268,13 +323,15 @@ |
4081 | int x, |
4082 | int y, |
4083 | unsigned int width, |
4084 | - unsigned int height) : |
4085 | + unsigned int height, |
4086 | + unsigned int mask) : |
4087 | mAbove (above), |
4088 | mBorder (border), |
4089 | mX (x), |
4090 | mY (y), |
4091 | mWidth (width), |
4092 | - mHeight (height) |
4093 | + mHeight (height), |
4094 | + mMask (mask) |
4095 | { |
4096 | } |
4097 | |
4098 | @@ -284,6 +341,7 @@ |
4099 | int mY; |
4100 | int mWidth; |
4101 | int mHeight; |
4102 | + unsigned int mMask; |
4103 | }; |
4104 | |
4105 | ct::ConfigureNotifyXEventMatcher::ConfigureNotifyXEventMatcher (Window above, |
4106 | @@ -291,13 +349,15 @@ |
4107 | int x, |
4108 | int y, |
4109 | unsigned int width, |
4110 | - unsigned int height) : |
4111 | + unsigned int height, |
4112 | + unsigned int mask) : |
4113 | priv (new ct::PrivateConfigureNotifyXEventMatcher (above, |
4114 | border, |
4115 | x, |
4116 | y, |
4117 | width, |
4118 | - height)) |
4119 | + height, |
4120 | + mask)) |
4121 | { |
4122 | } |
4123 | |
4124 | @@ -306,24 +366,58 @@ |
4125 | { |
4126 | const XConfigureEvent *ce = reinterpret_cast <const XConfigureEvent *> (&event); |
4127 | |
4128 | - return ce->above == priv->mAbove && |
4129 | - ce->border_width == priv->mBorder && |
4130 | - ce->x == priv->mX && |
4131 | - ce->y == priv->mY && |
4132 | - ce->width == priv->mWidth && |
4133 | - ce->height == priv->mHeight; |
4134 | + if (priv->mMask & CWSibling) |
4135 | + if (ce->above != priv->mAbove) |
4136 | + return false; |
4137 | + |
4138 | + if (priv->mMask & CWBorderWidth) |
4139 | + if (ce->border_width != priv->mBorder) |
4140 | + return false; |
4141 | + |
4142 | + if (priv->mMask & CWX) |
4143 | + if (ce->x != priv->mX) |
4144 | + return false; |
4145 | + |
4146 | + if (priv->mMask & CWY) |
4147 | + if (ce->y != priv->mY) |
4148 | + return false; |
4149 | + |
4150 | + if (priv->mMask & CWWidth) |
4151 | + if (ce->width != priv->mWidth) |
4152 | + return false; |
4153 | + |
4154 | + if (priv->mMask & CWHeight) |
4155 | + if (ce->height != priv->mHeight) |
4156 | + return false; |
4157 | + |
4158 | + return true; |
4159 | } |
4160 | |
4161 | void |
4162 | ct::ConfigureNotifyXEventMatcher::DescribeTo (std::ostream *os) const |
4163 | { |
4164 | + std::stringstream x, y, width, height, border, sibling; |
4165 | + |
4166 | + if (priv->mMask & CWX) |
4167 | + x << " x: " << priv->mX; |
4168 | + |
4169 | + if (priv->mMask & CWY) |
4170 | + y << " y: " << priv->mY; |
4171 | + |
4172 | + if (priv->mMask & CWWidth) |
4173 | + width << " width: " << priv->mWidth; |
4174 | + |
4175 | + if (priv->mMask & CWHeight) |
4176 | + height << " height: " << priv->mHeight; |
4177 | + |
4178 | + if (priv->mMask & CWBorderWidth) |
4179 | + border << " border: " << priv->mBorder; |
4180 | + |
4181 | + if (priv->mMask & CWSibling) |
4182 | + sibling << " above: " << std::hex << priv->mAbove << std::dec; |
4183 | + |
4184 | *os << "Matches ConfigureNotify with parameters : " << std::endl << |
4185 | - " x: " << priv->mX << |
4186 | - " y: " << priv->mY << |
4187 | - " width: " << priv->mWidth << |
4188 | - " height: " << priv->mHeight << |
4189 | - " border: " << priv->mBorder << |
4190 | - " above: " << std::hex << priv->mAbove << std::dec; |
4191 | + x.str () << y.str () << width.str () << height.str () << border.str () << sibling.str (); |
4192 | } |
4193 | |
4194 | class ct::PrivateShapeNotifyXEventMatcher |
4195 | @@ -450,9 +544,10 @@ |
4196 | XSelectInput (dpy, root, attrib.your_event_mask); |
4197 | } |
4198 | |
4199 | -ct::CompizProcess::CompizProcess (::Display *dpy, |
4200 | - ct::CompizProcess::StartupFlags flags, |
4201 | - unsigned int waitTimeout) : |
4202 | +ct::CompizProcess::CompizProcess (::Display *dpy, |
4203 | + ct::CompizProcess::StartupFlags flags, |
4204 | + const ct::CompizProcess::PluginList &plugins, |
4205 | + unsigned int waitTimeout) : |
4206 | priv (new PrivateCompizProcess (flags)) |
4207 | { |
4208 | xorg::testing::Process::SetEnv ("LD_LIBRARY_PATH", compizLDLibraryPath, true); |
4209 | @@ -464,6 +559,12 @@ |
4210 | |
4211 | args.push_back ("--send-startup-message"); |
4212 | |
4213 | + /* Copy in plugin list */ |
4214 | + for (ct::CompizProcess::PluginList::const_iterator it = plugins.begin (); |
4215 | + it != plugins.end (); |
4216 | + ++it) |
4217 | + args.push_back (*it); |
4218 | + |
4219 | priv->mProcess.Start (compizBinaryPath, args); |
4220 | EXPECT_EQ (priv->mProcess.GetState (), xorg::testing::Process::RUNNING); |
4221 | |
4222 | @@ -508,7 +609,7 @@ |
4223 | const unsigned int USEC_TO_MSEC = 1000; |
4224 | const unsigned int SLEEP_TIME = 50 * USEC_TO_MSEC; |
4225 | |
4226 | - unsigned int connectionAttemptsRemaining = MAX_CONNECTION_ATTEMPTS; |
4227 | + int connectionAttemptsRemaining = MAX_CONNECTION_ATTEMPTS; |
4228 | |
4229 | /* Work around an inherent race condition in XOpenDisplay |
4230 | * |
4231 | @@ -527,8 +628,11 @@ |
4232 | * to work around that by simply re-trying our connection to the server |
4233 | * once every 50ms or so, and we're trying about 10 times before giving up |
4234 | * and assuming there is a problem with the server. |
4235 | + * |
4236 | + * The predecrement here is so that connectionAttemptsRemaining will be 0 |
4237 | + * on failure |
4238 | */ |
4239 | - while (connectionAttemptsRemaining--) |
4240 | + while (--connectionAttemptsRemaining) |
4241 | { |
4242 | try |
4243 | { |
4244 | @@ -571,16 +675,136 @@ |
4245 | } |
4246 | |
4247 | void |
4248 | -ct::CompizXorgSystemTest::StartCompiz (ct::CompizProcess::StartupFlags flags) |
4249 | -{ |
4250 | - priv->mProcess.reset (new ct::CompizProcess (Display (), flags, 3000)); |
4251 | +ct::CompizXorgSystemTest::StartCompiz (ct::CompizProcess::StartupFlags flags, |
4252 | + const ct::CompizProcess::PluginList &plugins) |
4253 | +{ |
4254 | + priv->mProcess.reset (new ct::CompizProcess (Display (), flags, plugins, 3000)); |
4255 | +} |
4256 | + |
4257 | +class ct::PrivateAutostartCompizXorgSystemTest |
4258 | +{ |
4259 | + public: |
4260 | + |
4261 | + PrivateAutostartCompizXorgSystemTest () : |
4262 | + overridePluginDirEnv ("COMPIZ_PLUGIN_DIR", compizOverridePluginPath.c_str ()) |
4263 | + { |
4264 | + } |
4265 | + |
4266 | + TmpEnv overridePluginDirEnv; |
4267 | +}; |
4268 | + |
4269 | +ct::AutostartCompizXorgSystemTest::AutostartCompizXorgSystemTest () : |
4270 | + priv (new ct::PrivateAutostartCompizXorgSystemTest ()) |
4271 | +{ |
4272 | +} |
4273 | + |
4274 | +ct::CompizProcess::StartupFlags |
4275 | +ct::AutostartCompizXorgSystemTest::GetStartupFlags () |
4276 | +{ |
4277 | + return static_cast <ct::CompizProcess::StartupFlags> ( |
4278 | + ct::CompizProcess::ReplaceCurrentWM | |
4279 | + ct::CompizProcess::WaitForStartupMessage); |
4280 | +} |
4281 | + |
4282 | +int |
4283 | +ct::AutostartCompizXorgSystemTest::GetEventMask () |
4284 | +{ |
4285 | + return 0; |
4286 | +} |
4287 | + |
4288 | +ct::CompizProcess::PluginList |
4289 | +ct::AutostartCompizXorgSystemTest::GetPluginList () |
4290 | +{ |
4291 | + return ct::CompizProcess::PluginList (); |
4292 | } |
4293 | |
4294 | void |
4295 | ct::AutostartCompizXorgSystemTest::SetUp () |
4296 | { |
4297 | ct::CompizXorgSystemTest::SetUp (); |
4298 | - StartCompiz (static_cast <ct::CompizProcess::StartupFlags> ( |
4299 | - ct::CompizProcess::ReplaceCurrentWM | |
4300 | - ct::CompizProcess::WaitForStartupMessage)); |
4301 | + |
4302 | + ::Display *display = Display (); |
4303 | + XSelectInput (display, DefaultRootWindow (display), |
4304 | + GetEventMask ()); |
4305 | + |
4306 | + StartCompiz (GetStartupFlags (), |
4307 | + GetPluginList ()); |
4308 | +} |
4309 | + |
4310 | +class ct::PrivateAutostartCompizXorgSystemTestWithTestHelper |
4311 | +{ |
4312 | + public: |
4313 | + |
4314 | + std::auto_ptr <ct::MessageAtoms> mMessages; |
4315 | +}; |
4316 | + |
4317 | +void |
4318 | +ct::AutostartCompizXorgSystemTestWithTestHelper::WaitForWindowCreation (Window w) |
4319 | +{ |
4320 | + ::Display *dpy = Display (); |
4321 | + |
4322 | + XEvent event; |
4323 | + |
4324 | + bool requestAcknowledged = false; |
4325 | + while (ct::ReceiveMessage (dpy, |
4326 | + FetchAtom (ct::messages::TEST_HELPER_WINDOW_READY), |
4327 | + event)) |
4328 | + { |
4329 | + requestAcknowledged = |
4330 | + w == static_cast <unsigned long> (event.xclient.data.l[0]); |
4331 | + |
4332 | + if (requestAcknowledged) |
4333 | + break; |
4334 | + |
4335 | + } |
4336 | + |
4337 | + ASSERT_TRUE (requestAcknowledged); |
4338 | +} |
4339 | + |
4340 | +Atom |
4341 | +ct::AutostartCompizXorgSystemTestWithTestHelper::FetchAtom (const char *message) |
4342 | +{ |
4343 | + return priv->mMessages->FetchForString (message); |
4344 | +} |
4345 | + |
4346 | +ct::AutostartCompizXorgSystemTestWithTestHelper::AutostartCompizXorgSystemTestWithTestHelper () : |
4347 | + priv (new ct::PrivateAutostartCompizXorgSystemTestWithTestHelper) |
4348 | +{ |
4349 | +} |
4350 | + |
4351 | +int |
4352 | +ct::AutostartCompizXorgSystemTestWithTestHelper::GetEventMask () |
4353 | +{ |
4354 | + return AutostartCompizXorgSystemTest::GetEventMask () | |
4355 | + StructureNotifyMask; |
4356 | +} |
4357 | + |
4358 | +void |
4359 | +ct::AutostartCompizXorgSystemTestWithTestHelper::SetUp () |
4360 | +{ |
4361 | + ct::AutostartCompizXorgSystemTest::SetUp (); |
4362 | + priv->mMessages.reset (new ct::MessageAtoms (Display ())); |
4363 | + |
4364 | + ::Display *dpy = Display (); |
4365 | + Window root = DefaultRootWindow (dpy); |
4366 | + |
4367 | + Atom ready = priv->mMessages->FetchForString (ct::messages::TEST_HELPER_READY_MSG); |
4368 | + ct::ClientMessageXEventMatcher matcher (dpy, ready, root); |
4369 | + |
4370 | + ASSERT_TRUE (ct::AdvanceToNextEventOnSuccess ( |
4371 | + dpy, |
4372 | + ct::WaitForEventOfTypeOnWindowMatching (dpy, |
4373 | + root, |
4374 | + ClientMessage, |
4375 | + -1, |
4376 | + -1, |
4377 | + matcher))); |
4378 | +} |
4379 | + |
4380 | +ct::CompizProcess::PluginList |
4381 | +ct::AutostartCompizXorgSystemTestWithTestHelper::GetPluginList () |
4382 | +{ |
4383 | + ct::CompizProcess::PluginList list; |
4384 | + list.push_back ("testhelper"); |
4385 | + return list; |
4386 | } |
FAILED: Continuous integration, rev:3530 jenkins. qa.ubuntu. com/job/ compiz- ci/308/ jenkins. qa.ubuntu. com/job/ compiz- ci/./build= pbuilder, distribution= quantal, flavor= amd64/308/ console
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild: jenkins. qa.ubuntu. com/job/ compiz- ci/308/ /rebuild/?
http://