Merge lp:~compiz-team/compiz/compiz.performance_1027211.2 into lp:compiz/0.9.9
- compiz.performance_1027211.2
- Merge into 0.9.9
| Status: | Superseded |
|---|---|
| Proposed branch: | lp:~compiz-team/compiz/compiz.performance_1027211.2 |
| Merge into: | lp:compiz/0.9.9 |
| Diff against target: |
2047 lines (+1631/-70) 20 files modified
include/core/CMakeLists.txt (+1/-0) include/core/configurerequestbuffer.h (+73/-0) include/core/window.h (+26/-7) 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 (+3/-0) 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 (+354/-0) src/event.cpp (+1/-1) src/privatewindow.h (+45/-1) src/syncserverwindow.h (+49/-0) src/tests/CMakeLists.txt (+11/-0) src/tests/test_configurerequestbuffer.cpp (+647/-0) src/window.cpp (+196/-49) |
| To merge this branch: | bzr merge lp:~compiz-team/compiz/compiz.performance_1027211.2 |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| PS Jenkins bot | continuous-integration | Needs Fixing on 2012-12-07 | |
| Compiz Maintainers | 2012-12-07 | Pending | |
|
Review via email:
|
|||
This proposal has been superseded by a proposal from 2012-12-07.
Commit Message
Allow plugins to throttle delivery of ConfigureWindow requests within reason (LP: #1027211)
Description of the Change
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.
| PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3534
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
- 3535. By Sam Spilsbury on 2012-12-07
-
Put lock in the list before freezing the buffer to avoid an assertion failure
- 3536. By Sam Spilsbury on 2012-12-07
-
Fix assertion failures
Unmerged revisions
- 3536. By Sam Spilsbury on 2012-12-07
-
Fix assertion failures
- 3535. By Sam Spilsbury on 2012-12-07
-
Put lock in the list before freezing the buffer to avoid an assertion failure
- 3534. By Sam Spilsbury on 2012-12-07
-
Revert an accidental change due to f'n'r
- 3533. By Sam Spilsbury on 2012-12-07
-
Update client code to take advantage of ConfigureBuffer wrapping
queryShapeRectangles - 3532. By Sam Spilsbury on 2012-12-07
-
Fix broken assert
- 3531. By Sam Spilsbury on 2012-12-07
-
Merge lp:compiz
- 3530. By Sam Spilsbury on 2012-12-07
-
Bring back lazy positioning, make it off by default.
This basically "fixes" the various problems with nvidia being slow at
handling ConfigureWindow requests at the same time as doing synchronized
compositing, however it could come at the cost of some weird bugs. Keep
it off for now, and lets turn it on if there aren't any in testing - 3529. By Sam Spilsbury on 2012-12-07
-
Handle XShapeQueryRect
angles too and work around races with that - 3528. By Sam Spilsbury on 2012-12-07
-
Remove const promise, be a little smarter about calling XConfigureWindow
the other times - 3527. By Sam Spilsbury on 2012-12-07
-
Refactor the test code into test fixtures, remove lots of duplicated code
Preview Diff
| 1 | === modified file 'include/core/CMakeLists.txt' |
| 2 | --- include/core/CMakeLists.txt 2012-10-17 06:25:59 +0000 |
| 3 | +++ include/core/CMakeLists.txt 2012-12-07 17:16:21 +0000 |
| 4 | @@ -1,6 +1,7 @@ |
| 5 | set (_headers |
| 6 | action.h |
| 7 | atoms.h |
| 8 | + configurerequestbuffer.h |
| 9 | core.h |
| 10 | countedlist.h |
| 11 | global.h |
| 12 | |
| 13 | === added file 'include/core/configurerequestbuffer.h' |
| 14 | --- include/core/configurerequestbuffer.h 1970-01-01 00:00:00 +0000 |
| 15 | +++ include/core/configurerequestbuffer.h 2012-12-07 17:16:21 +0000 |
| 16 | @@ -0,0 +1,73 @@ |
| 17 | +/* |
| 18 | + * Copyright © 2012 Sam Spilsbury |
| 19 | + * |
| 20 | + * Permission to use, copy, modify, distribute, and sell this software |
| 21 | + * and its documentation for any purpose is hereby granted without |
| 22 | + * fee, provided that the above copyright notice appear in all copies |
| 23 | + * and that both that copyright notice and this permission notice |
| 24 | + * appear in supporting documentation, and that the name of |
| 25 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
| 26 | + * distribution of the software without specific, written prior permission. |
| 27 | + * Canonical Ltd. makes no representations about the suitability of this |
| 28 | + * software for any purpose. It is provided "as is" without express or |
| 29 | + * implied warranty. |
| 30 | + * |
| 31 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 32 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
| 33 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 34 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
| 35 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
| 36 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
| 37 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 38 | + * |
| 39 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
| 40 | + */ |
| 41 | +#ifndef _COMPIZ_CONFIGURE_REQUEST_BUFFER_H |
| 42 | +#define _COMPIZ_CONFIGURE_REQUEST_BUFFER_H |
| 43 | + |
| 44 | +#include <boost/shared_ptr.hpp> |
| 45 | +#include <X11/Xlib.h> |
| 46 | +#include <syncserverwindow.h> |
| 47 | + |
| 48 | +namespace compiz |
| 49 | +{ |
| 50 | +namespace window |
| 51 | +{ |
| 52 | +namespace configure_buffers |
| 53 | +{ |
| 54 | +class Releasable |
| 55 | +{ |
| 56 | + public: |
| 57 | + |
| 58 | + typedef boost::shared_ptr <Releasable> Ptr; |
| 59 | + |
| 60 | + virtual void release () = 0; |
| 61 | +}; |
| 62 | + |
| 63 | +class Buffer : |
| 64 | + public SyncServerWindow |
| 65 | +{ |
| 66 | + public: |
| 67 | + |
| 68 | + typedef boost::shared_ptr <Buffer> Ptr; |
| 69 | + |
| 70 | + virtual ~Buffer () {} |
| 71 | + |
| 72 | + virtual void pushClientRequest (const XWindowChanges &xwc, unsigned int mask) = 0; |
| 73 | + virtual void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask) = 0; |
| 74 | + virtual void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask) = 0; |
| 75 | + |
| 76 | + virtual void pushSyntheticConfigureNotify () = 0; |
| 77 | + |
| 78 | + virtual Releasable::Ptr obtainLock () = 0; |
| 79 | + |
| 80 | + /* This API will all configure requests to be |
| 81 | + * released. It should only be used in situations |
| 82 | + * where you have a server grab and need |
| 83 | + * to have complete sync with the server */ |
| 84 | + virtual void forceRelease () = 0; |
| 85 | +}; |
| 86 | +} |
| 87 | +} |
| 88 | +} |
| 89 | +#endif |
| 90 | |
| 91 | === modified file 'include/core/window.h' |
| 92 | --- include/core/window.h 2012-12-07 09:28:03 +0000 |
| 93 | +++ include/core/window.h 2012-12-07 17:16:21 +0000 |
| 94 | @@ -53,13 +53,26 @@ |
| 95 | class PrivateWindow; |
| 96 | struct CompStartupSequence; |
| 97 | |
| 98 | -namespace compiz { namespace private_screen { |
| 99 | - class Ping; |
| 100 | - class GrabManager; |
| 101 | - class OutputDevices; |
| 102 | - class WindowManager; |
| 103 | - class StartupSequence; |
| 104 | -}} |
| 105 | +namespace compiz |
| 106 | +{ |
| 107 | +namespace window |
| 108 | +{ |
| 109 | +namespace configure_buffers |
| 110 | +{ |
| 111 | +class Releasable; |
| 112 | +typedef boost::shared_ptr <Releasable> ReleasablePtr; |
| 113 | +} |
| 114 | +} |
| 115 | + |
| 116 | +namespace private_screen |
| 117 | +{ |
| 118 | +class Ping; |
| 119 | +class GrabManager; |
| 120 | +class OutputDevices; |
| 121 | +class WindowManager; |
| 122 | +class StartupSequence; |
| 123 | +} |
| 124 | +} |
| 125 | |
| 126 | #define ROOTPARENT(x) (((x)->frame ()) ? (x)->frame () : (x)->id ()) |
| 127 | |
| 128 | @@ -524,6 +537,12 @@ |
| 129 | bool updateStruts (); |
| 130 | const CompStruts *struts () const; |
| 131 | |
| 132 | + bool queryAttributes (XWindowAttributes &); |
| 133 | + bool queryFrameAttributes (XWindowAttributes &); |
| 134 | + |
| 135 | + compiz::window::configure_buffers::ReleasablePtr |
| 136 | + obtainLockOnConfigureRequests (); |
| 137 | + |
| 138 | WRAPABLE_HND (0, WindowInterface, void, getOutputExtents, |
| 139 | CompWindowExtents&); |
| 140 | WRAPABLE_HND (1, WindowInterface, void, getAllowedActions, |
| 141 | |
| 142 | === modified file 'plugins/composite/src/window.cpp' |
| 143 | --- plugins/composite/src/window.cpp 2012-11-18 00:16:47 +0000 |
| 144 | +++ plugins/composite/src/window.cpp 2012-12-07 17:16:21 +0000 |
| 145 | @@ -181,11 +181,7 @@ |
| 146 | bool |
| 147 | PrivateCompositeWindow::getAttributes (XWindowAttributes &attr) |
| 148 | { |
| 149 | - if (XGetWindowAttributes (screen->dpy (), |
| 150 | - ROOTPARENT (window), &attr)) |
| 151 | - return true; |
| 152 | - |
| 153 | - return false; |
| 154 | + return window->queryFrameAttributes (attr); |
| 155 | } |
| 156 | |
| 157 | bool |
| 158 | |
| 159 | === modified file 'plugins/move/move.xml.in' |
| 160 | --- plugins/move/move.xml.in 2012-10-15 10:31:51 +0000 |
| 161 | +++ plugins/move/move.xml.in 2012-12-07 17:16:21 +0000 |
| 162 | @@ -42,7 +42,7 @@ |
| 163 | <option name="lazy_positioning" type="bool"> |
| 164 | <_short>Lazy Positioning</_short> |
| 165 | <_long>Do not update the server-side position of windows until finished moving</_long> |
| 166 | - <default>true</default> |
| 167 | + <default>false</default> |
| 168 | </option> |
| 169 | </options> |
| 170 | </plugin> |
| 171 | |
| 172 | === modified file 'plugins/move/src/move.cpp' |
| 173 | --- plugins/move/src/move.cpp 2012-12-05 09:38:59 +0000 |
| 174 | +++ plugins/move/src/move.cpp 2012-12-07 17:16:21 +0000 |
| 175 | @@ -158,6 +158,14 @@ |
| 176 | if (mw->gWindow) |
| 177 | mw->gWindow->glPaintSetEnabled (mw, true); |
| 178 | } |
| 179 | + |
| 180 | + if (ms->optionGetLazyPositioning ()) |
| 181 | + { |
| 182 | + MOVE_WINDOW (w); |
| 183 | + |
| 184 | + if (mw->gWindow) |
| 185 | + mw->releasable = w->obtainLockOnConfigureRequests (); |
| 186 | + } |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | @@ -173,6 +181,8 @@ |
| 191 | |
| 192 | if (ms->w) |
| 193 | { |
| 194 | + MOVE_WINDOW (ms->w); |
| 195 | + |
| 196 | if (state & CompAction::StateCancel) |
| 197 | ms->w->move (ms->savedX - ms->w->geometry ().x (), |
| 198 | ms->savedY - ms->w->geometry ().y (), false); |
| 199 | @@ -194,14 +204,14 @@ |
| 200 | |
| 201 | if (ms->moveOpacity != OPAQUE) |
| 202 | { |
| 203 | - MOVE_WINDOW (ms->w); |
| 204 | - |
| 205 | if (mw->cWindow) |
| 206 | mw->cWindow->addDamage (); |
| 207 | if (mw->gWindow) |
| 208 | mw->gWindow->glPaintSetEnabled (mw, false); |
| 209 | } |
| 210 | |
| 211 | + mw->releasable.reset (); |
| 212 | + |
| 213 | ms->w = 0; |
| 214 | ms->releaseButton = 0; |
| 215 | } |
| 216 | @@ -489,9 +499,6 @@ |
| 217 | w->move (wX + dx - w->geometry ().x (), |
| 218 | wY + dy - w->geometry ().y (), false); |
| 219 | |
| 220 | - if (!ms->optionGetLazyPositioning ()) |
| 221 | - w->syncPosition (); |
| 222 | - |
| 223 | ms->x -= dx; |
| 224 | ms->y -= dy; |
| 225 | } |
| 226 | |
| 227 | === modified file 'plugins/move/src/move.h' |
| 228 | --- plugins/move/src/move.h 2012-09-07 22:48:26 +0000 |
| 229 | +++ plugins/move/src/move.h 2012-12-07 17:16:21 +0000 |
| 230 | @@ -27,6 +27,7 @@ |
| 231 | |
| 232 | #include <core/screen.h> |
| 233 | #include <core/pluginclasshandler.h> |
| 234 | +#include <core/configurerequestbuffer.h> |
| 235 | |
| 236 | #include <composite/composite.h> |
| 237 | #include <opengl/opengl.h> |
| 238 | @@ -117,6 +118,7 @@ |
| 239 | CompWindow *window; |
| 240 | GLWindow *gWindow; |
| 241 | CompositeWindow *cWindow; |
| 242 | + compiz::window::configure_buffers::Releasable::Ptr releasable; |
| 243 | }; |
| 244 | |
| 245 | #define MOVE_SCREEN(s) \ |
| 246 | |
| 247 | === modified file 'plugins/opengl/src/paint.cpp' |
| 248 | --- plugins/opengl/src/paint.cpp 2012-12-04 08:47:32 +0000 |
| 249 | +++ plugins/opengl/src/paint.cpp 2012-12-07 17:16:21 +0000 |
| 250 | @@ -1283,6 +1283,9 @@ |
| 251 | !priv->cWindow->damaged ()) |
| 252 | return true; |
| 253 | |
| 254 | + /* Release any queued ConfigureWindow requests now */ |
| 255 | + priv->configureLock->release (); |
| 256 | + |
| 257 | if (textures ().empty () && !bind ()) |
| 258 | return false; |
| 259 | |
| 260 | |
| 261 | === modified file 'plugins/opengl/src/privates.h' |
| 262 | --- plugins/opengl/src/privates.h 2012-11-08 09:29:42 +0000 |
| 263 | +++ plugins/opengl/src/privates.h 2012-12-07 17:16:21 +0000 |
| 264 | @@ -33,6 +33,7 @@ |
| 265 | #include <composite/composite.h> |
| 266 | #include <opengl/opengl.h> |
| 267 | #include <core/atoms.h> |
| 268 | +#include <core/configurerequestbuffer.h> |
| 269 | |
| 270 | #ifdef USE_GLES |
| 271 | #include <opengl/framebufferobject.h> |
| 272 | @@ -276,6 +277,8 @@ |
| 273 | GLVertexBuffer::AutoProgram *autoProgram; |
| 274 | |
| 275 | std::list<GLIcon> icons; |
| 276 | + |
| 277 | + compiz::window::configure_buffers::Releasable::Ptr configureLock; |
| 278 | }; |
| 279 | |
| 280 | #endif |
| 281 | |
| 282 | === modified file 'plugins/opengl/src/window.cpp' |
| 283 | --- plugins/opengl/src/window.cpp 2012-10-16 04:49:19 +0000 |
| 284 | +++ plugins/opengl/src/window.cpp 2012-12-07 17:16:21 +0000 |
| 285 | @@ -86,7 +86,8 @@ |
| 286 | bindFailed (false), |
| 287 | vertexBuffer (new GLVertexBuffer ()), |
| 288 | autoProgram(new GLWindowAutoProgram(this)), |
| 289 | - icons () |
| 290 | + icons (), |
| 291 | + configureLock (w->obtainLockOnConfigureRequests ()) |
| 292 | { |
| 293 | paint.xScale = 1.0f; |
| 294 | paint.yScale = 1.0f; |
| 295 | |
| 296 | === modified file 'src/CMakeLists.txt' |
| 297 | --- src/CMakeLists.txt 2012-11-26 07:13:04 +0000 |
| 298 | +++ src/CMakeLists.txt 2012-12-07 17:16:21 +0000 |
| 299 | @@ -160,6 +160,12 @@ |
| 300 | compiz_window_geometry |
| 301 | ) |
| 302 | |
| 303 | +add_library (compiz_configurerequestbuffer STATIC |
| 304 | + configurerequestbuffer.cpp) |
| 305 | + |
| 306 | +target_link_libraries (compiz_configurerequestbuffer |
| 307 | + compiz_window_geometry) |
| 308 | + |
| 309 | # workaround for build race |
| 310 | add_dependencies (compiz core-xml-file) |
| 311 | |
| 312 | @@ -192,6 +198,7 @@ |
| 313 | compiz_servergrab |
| 314 | compiz_output |
| 315 | compiz_outputdevices |
| 316 | + compiz_configurerequestbuffer |
| 317 | -Wl,-no-whole-archive |
| 318 | # ${CORE_MOD_LIBRARIES} |
| 319 | ) |
| 320 | |
| 321 | === added file 'src/asyncserverwindow.h' |
| 322 | --- src/asyncserverwindow.h 1970-01-01 00:00:00 +0000 |
| 323 | +++ src/asyncserverwindow.h 2012-12-07 17:16:21 +0000 |
| 324 | @@ -0,0 +1,52 @@ |
| 325 | +/* |
| 326 | + * Copyright © 2012 Sam Spilsbury |
| 327 | + * |
| 328 | + * Permission to use, copy, modify, distribute, and sell this software |
| 329 | + * and its documentation for any purpose is hereby granted without |
| 330 | + * fee, provided that the above copyright notice appear in all copies |
| 331 | + * and that both that copyright notice and this permission notice |
| 332 | + * appear in supporting documentation, and that the name of |
| 333 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
| 334 | + * distribution of the software without specific, written prior permission. |
| 335 | + * Canonical Ltd. makes no representations about the suitability of this |
| 336 | + * software for any purpose. It is provided "as is" without express or |
| 337 | + * implied warranty. |
| 338 | + * |
| 339 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 340 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
| 341 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 342 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
| 343 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
| 344 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
| 345 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 346 | + * |
| 347 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
| 348 | + */ |
| 349 | +#ifndef _COMPIZ_ASYNC_SERVER_WINDOW_H |
| 350 | +#define _COMPIZ_ASYNC_SERVER_WINDOW_H |
| 351 | + |
| 352 | +#include <X11/Xlib.h> |
| 353 | + |
| 354 | +namespace compiz |
| 355 | +{ |
| 356 | +namespace window |
| 357 | +{ |
| 358 | +class AsyncServerWindow |
| 359 | +{ |
| 360 | + public: |
| 361 | + |
| 362 | + virtual ~AsyncServerWindow () {}; |
| 363 | + |
| 364 | + virtual int requestConfigureOnClient (const XWindowChanges &xwc, |
| 365 | + unsigned int valueMask) = 0; |
| 366 | + virtual int requestConfigureOnWrapper (const XWindowChanges &xwc, |
| 367 | + unsigned int valueMask) = 0; |
| 368 | + virtual int requestConfigureOnFrame (const XWindowChanges &xwc, |
| 369 | + unsigned int valueMask) = 0; |
| 370 | + virtual void sendSyntheticConfigureNotify () = 0; |
| 371 | + virtual bool hasCustomShape () const = 0; |
| 372 | +}; |
| 373 | +} |
| 374 | +} |
| 375 | + |
| 376 | +#endif |
| 377 | |
| 378 | === added file 'src/configurerequestbuffer-impl.h' |
| 379 | --- src/configurerequestbuffer-impl.h 1970-01-01 00:00:00 +0000 |
| 380 | +++ src/configurerequestbuffer-impl.h 2012-12-07 17:16:21 +0000 |
| 381 | @@ -0,0 +1,145 @@ |
| 382 | +/* |
| 383 | + * Copyright © 2012 Sam Spilsbury |
| 384 | + * |
| 385 | + * Permission to use, copy, modify, distribute, and sell this software |
| 386 | + * and its documentation for any purpose is hereby granted without |
| 387 | + * fee, provided that the above copyright notice appear in all copies |
| 388 | + * and that both that copyright notice and this permission notice |
| 389 | + * appear in supporting documentation, and that the name of |
| 390 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
| 391 | + * distribution of the software without specific, written prior permission. |
| 392 | + * Canonical Ltd. makes no representations about the suitability of this |
| 393 | + * software for any purpose. It is provided "as is" without express or |
| 394 | + * implied warranty. |
| 395 | + * |
| 396 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 397 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
| 398 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 399 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
| 400 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
| 401 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
| 402 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 403 | + * |
| 404 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
| 405 | + */ |
| 406 | +#ifndef _COMPIZ_GEOMETRY_UPDATE_QUEUE_H |
| 407 | +#define _COMPIZ_GEOMETRY_UPDATE_QUEUE_H |
| 408 | + |
| 409 | +#include <memory> |
| 410 | +#include <vector> |
| 411 | +#include <boost/weak_ptr.hpp> |
| 412 | +#include <boost/shared_ptr.hpp> |
| 413 | +#include <boost/function.hpp> |
| 414 | +#include <X11/Xlib.h> |
| 415 | + |
| 416 | +#include <core/configurerequestbuffer.h> |
| 417 | + |
| 418 | +namespace compiz |
| 419 | +{ |
| 420 | +namespace window |
| 421 | +{ |
| 422 | +class AsyncServerWindow; |
| 423 | +namespace configure_buffers |
| 424 | +{ |
| 425 | + |
| 426 | +class Lockable |
| 427 | +{ |
| 428 | + public: |
| 429 | + |
| 430 | + typedef boost::shared_ptr <Lockable> Ptr; |
| 431 | + typedef boost::weak_ptr <Lockable> Weak; |
| 432 | + |
| 433 | + virtual ~Lockable () {} |
| 434 | + |
| 435 | + virtual void lock () = 0; |
| 436 | +}; |
| 437 | + |
| 438 | +class BufferLock : |
| 439 | + public Lockable, |
| 440 | + public Releasable |
| 441 | +{ |
| 442 | + public: |
| 443 | + typedef boost::shared_ptr <BufferLock> Ptr; |
| 444 | + |
| 445 | + virtual ~BufferLock () {} |
| 446 | +}; |
| 447 | + |
| 448 | +class CountedFreeze |
| 449 | +{ |
| 450 | + public: |
| 451 | + |
| 452 | + virtual ~CountedFreeze () {} |
| 453 | + |
| 454 | + virtual void freeze () = 0; |
| 455 | + virtual void release () = 0; |
| 456 | + |
| 457 | + virtual void untrackLock (compiz::window::configure_buffers::BufferLock *lock) = 0; |
| 458 | +}; |
| 459 | + |
| 460 | +class ConfigureRequestBuffer : |
| 461 | + public CountedFreeze, |
| 462 | + public Buffer |
| 463 | +{ |
| 464 | + public: |
| 465 | + |
| 466 | + typedef boost::function <BufferLock::Ptr (CountedFreeze *)> LockFactory; |
| 467 | + |
| 468 | + void freeze (); |
| 469 | + void release (); |
| 470 | + |
| 471 | + void untrackLock (compiz::window::configure_buffers::BufferLock *lock); |
| 472 | + |
| 473 | + void pushClientRequest (const XWindowChanges &xwc, unsigned int mask); |
| 474 | + void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask); |
| 475 | + void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask); |
| 476 | + void pushSyntheticConfigureNotify (); |
| 477 | + compiz::window::configure_buffers::Releasable::Ptr obtainLock (); |
| 478 | + |
| 479 | + /* Implement getAttributes and require that |
| 480 | + * the queue is released before calling through |
| 481 | + * to the SyncServerWindow */ |
| 482 | + bool queryAttributes (XWindowAttributes &attrib); |
| 483 | + bool queryFrameAttributes (XWindowAttributes &attrib); |
| 484 | + XRectangle * queryShapeRectangles (int kind, |
| 485 | + int *count, |
| 486 | + int *ordering); |
| 487 | + |
| 488 | + void forceRelease (); |
| 489 | + |
| 490 | + static compiz::window::configure_buffers::Buffer::Ptr |
| 491 | + Create (AsyncServerWindow *asyncServerWindow, |
| 492 | + SyncServerWindow *syncServerWindow, |
| 493 | + const LockFactory &factory); |
| 494 | + |
| 495 | + private: |
| 496 | + |
| 497 | + ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow, |
| 498 | + SyncServerWindow *syncServerWindow, |
| 499 | + const LockFactory &factory); |
| 500 | + |
| 501 | + class Private; |
| 502 | + std::auto_ptr <Private> priv; |
| 503 | +}; |
| 504 | + |
| 505 | +class ConfigureBufferLock : |
| 506 | + public compiz::window::configure_buffers::BufferLock |
| 507 | +{ |
| 508 | + public: |
| 509 | + |
| 510 | + typedef boost::shared_ptr <ConfigureBufferLock> Ptr; |
| 511 | + |
| 512 | + ConfigureBufferLock (CountedFreeze *); |
| 513 | + ~ConfigureBufferLock (); |
| 514 | + |
| 515 | + void lock (); |
| 516 | + void release (); |
| 517 | + |
| 518 | + private: |
| 519 | + |
| 520 | + class Private; |
| 521 | + std::auto_ptr <Private> priv; |
| 522 | +}; |
| 523 | +} |
| 524 | +} |
| 525 | +} |
| 526 | +#endif |
| 527 | |
| 528 | === added file 'src/configurerequestbuffer.cpp' |
| 529 | --- src/configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000 |
| 530 | +++ src/configurerequestbuffer.cpp 2012-12-07 17:16:21 +0000 |
| 531 | @@ -0,0 +1,354 @@ |
| 532 | +/* |
| 533 | + * Copyright © 2012 Sam Spilsbury |
| 534 | + * |
| 535 | + * Permission to use, copy, modify, distribute, and sell this software |
| 536 | + * and its documentation for any purpose is hereby granted without |
| 537 | + * fee, provided that the above copyright notice appear in all copies |
| 538 | + * and that both that copyright notice and this permission notice |
| 539 | + * appear in supporting documentation, and that the name of |
| 540 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
| 541 | + * distribution of the software without specific, written prior permission. |
| 542 | + * Canonical Ltd. makes no representations about the suitability of this |
| 543 | + * software for any purpose. It is provided "as is" without express or |
| 544 | + * implied warranty. |
| 545 | + * |
| 546 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 547 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
| 548 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 549 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
| 550 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
| 551 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
| 552 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 553 | + * |
| 554 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
| 555 | + */ |
| 556 | +#include <cassert> |
| 557 | +#include <boost/foreach.hpp> |
| 558 | +#include <boost/weak_ptr.hpp> |
| 559 | +#include <boost/bind.hpp> |
| 560 | +#include "asyncserverwindow.h" |
| 561 | +#include "configurerequestbuffer-impl.h" |
| 562 | + |
| 563 | +#ifndef foreach |
| 564 | +#define foreach BOOST_FOREACH |
| 565 | +#endif |
| 566 | + |
| 567 | +namespace crb = compiz::window::configure_buffers; |
| 568 | +namespace cw = compiz::window; |
| 569 | + |
| 570 | +class crb::ConfigureRequestBuffer::Private |
| 571 | +{ |
| 572 | + public: |
| 573 | + |
| 574 | + typedef crb::Lockable::Weak LockObserver; |
| 575 | + |
| 576 | + Private (cw::AsyncServerWindow *asyncServerWindow, |
| 577 | + cw::SyncServerWindow *syncServerWindow, |
| 578 | + const crb::ConfigureRequestBuffer::LockFactory &lockFactory) : |
| 579 | + clientChangeMask (0), |
| 580 | + wrapperChangeMask (0), |
| 581 | + frameChangeMask (0), |
| 582 | + sendSyntheticConfigure (false), |
| 583 | + lockCount (0), |
| 584 | + asyncServerWindow (asyncServerWindow), |
| 585 | + syncServerWindow (syncServerWindow), |
| 586 | + lockFactory (lockFactory) |
| 587 | + { |
| 588 | + } |
| 589 | + |
| 590 | + void dispatchConfigure (bool force = false); |
| 591 | + |
| 592 | + XWindowChanges clientChanges; |
| 593 | + unsigned int clientChangeMask; |
| 594 | + |
| 595 | + XWindowChanges wrapperChanges; |
| 596 | + unsigned int wrapperChangeMask; |
| 597 | + |
| 598 | + XWindowChanges frameChanges; |
| 599 | + unsigned int frameChangeMask; |
| 600 | + |
| 601 | + bool sendSyntheticConfigure; |
| 602 | + |
| 603 | + unsigned int lockCount; |
| 604 | + |
| 605 | + cw::AsyncServerWindow *asyncServerWindow; |
| 606 | + cw::SyncServerWindow *syncServerWindow; |
| 607 | + |
| 608 | + crb::ConfigureRequestBuffer::LockFactory lockFactory; |
| 609 | + std::vector <LockObserver> locks; |
| 610 | +}; |
| 611 | + |
| 612 | +void |
| 613 | +crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force) |
| 614 | +{ |
| 615 | + const unsigned int allEventMasks = 0x7f; |
| 616 | + bool immediate = frameChangeMask & (CWStackMode | CWSibling); |
| 617 | + immediate |= (frameChangeMask & (CWWidth | CWHeight)) && |
| 618 | + asyncServerWindow->hasCustomShape (); |
| 619 | + immediate |= force; |
| 620 | + |
| 621 | + bool clientDispatch = (clientChangeMask & allEventMasks); |
| 622 | + bool wrapperDispatch = (wrapperChangeMask & allEventMasks); |
| 623 | + bool frameDispatch = (frameChangeMask & allEventMasks); |
| 624 | + |
| 625 | + bool dispatch = !lockCount && (clientDispatch || |
| 626 | + wrapperDispatch || |
| 627 | + frameDispatch || |
| 628 | + sendSyntheticConfigure); |
| 629 | + |
| 630 | + if (dispatch || immediate) |
| 631 | + { |
| 632 | + if (frameDispatch) |
| 633 | + { |
| 634 | + asyncServerWindow->requestConfigureOnFrame (frameChanges, |
| 635 | + frameChangeMask); |
| 636 | + frameChangeMask = 0; |
| 637 | + } |
| 638 | + |
| 639 | + if (wrapperDispatch) |
| 640 | + { |
| 641 | + asyncServerWindow->requestConfigureOnWrapper (wrapperChanges, |
| 642 | + wrapperChangeMask); |
| 643 | + wrapperChangeMask = 0; |
| 644 | + } |
| 645 | + |
| 646 | + if (clientDispatch) |
| 647 | + { |
| 648 | + asyncServerWindow->requestConfigureOnClient (clientChanges, |
| 649 | + clientChangeMask); |
| 650 | + clientChangeMask = 0; |
| 651 | + } |
| 652 | + |
| 653 | + if (sendSyntheticConfigure) |
| 654 | + { |
| 655 | + asyncServerWindow->sendSyntheticConfigureNotify (); |
| 656 | + sendSyntheticConfigure = false; |
| 657 | + } |
| 658 | + |
| 659 | + foreach (const LockObserver &lock, locks) |
| 660 | + { |
| 661 | + crb::Lockable::Ptr strongLock (lock.lock ()); |
| 662 | + |
| 663 | + /* We might be in a lock's destructor so check |
| 664 | + * if this can really be re-locked, if not, its |
| 665 | + * no big deal as the lock is going away anyways |
| 666 | + */ |
| 667 | + if (strongLock) |
| 668 | + strongLock->lock (); |
| 669 | + } |
| 670 | + } |
| 671 | +} |
| 672 | + |
| 673 | +void |
| 674 | +crb::ConfigureRequestBuffer::freeze () |
| 675 | +{ |
| 676 | + priv->lockCount++; |
| 677 | + |
| 678 | + assert (priv->lockCount <= priv->locks.size ()); |
| 679 | +} |
| 680 | + |
| 681 | +void |
| 682 | +crb::ConfigureRequestBuffer::release () |
| 683 | +{ |
| 684 | + assert (priv->lockCount); |
| 685 | + |
| 686 | + priv->lockCount--; |
| 687 | + |
| 688 | + priv->dispatchConfigure (); |
| 689 | +} |
| 690 | + |
| 691 | +namespace |
| 692 | +{ |
| 693 | +void applyChangeToXWC (const XWindowChanges &from, |
| 694 | + XWindowChanges &to, |
| 695 | + unsigned int mask) |
| 696 | +{ |
| 697 | + if (mask & CWX) |
| 698 | + to.x = from.x; |
| 699 | + |
| 700 | + if (mask & CWY) |
| 701 | + to.y = from.y; |
| 702 | + |
| 703 | + if (mask & CWWidth) |
| 704 | + to.width = from.width; |
| 705 | + |
| 706 | + if (mask & CWHeight) |
| 707 | + to.height = from.height; |
| 708 | + |
| 709 | + if (mask & CWBorderWidth) |
| 710 | + to.border_width = from.border_width; |
| 711 | + |
| 712 | + if (mask & CWSibling) |
| 713 | + to.sibling = from.sibling; |
| 714 | + |
| 715 | + if (mask & CWStackMode) |
| 716 | + to.stack_mode = from.stack_mode; |
| 717 | +} |
| 718 | +} |
| 719 | + |
| 720 | +void |
| 721 | +crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc, |
| 722 | + unsigned int mask) |
| 723 | +{ |
| 724 | + applyChangeToXWC (xwc, priv->clientChanges, mask); |
| 725 | + priv->clientChangeMask |= mask; |
| 726 | + |
| 727 | + priv->dispatchConfigure (); |
| 728 | +} |
| 729 | + |
| 730 | +void |
| 731 | +crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc, |
| 732 | + unsigned int mask) |
| 733 | +{ |
| 734 | + applyChangeToXWC (xwc, priv->wrapperChanges, mask); |
| 735 | + priv->wrapperChangeMask |= mask; |
| 736 | + |
| 737 | + priv->dispatchConfigure (); |
| 738 | +} |
| 739 | + |
| 740 | +void |
| 741 | +crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc, |
| 742 | + unsigned int mask) |
| 743 | +{ |
| 744 | + applyChangeToXWC (xwc, priv->frameChanges, mask); |
| 745 | + priv->frameChangeMask |= mask; |
| 746 | + |
| 747 | + priv->dispatchConfigure (); |
| 748 | +} |
| 749 | + |
| 750 | +void |
| 751 | +crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify () |
| 752 | +{ |
| 753 | + priv->sendSyntheticConfigure = true; |
| 754 | + |
| 755 | + priv->dispatchConfigure (); |
| 756 | +} |
| 757 | + |
| 758 | +crb::Releasable::Ptr |
| 759 | +crb::ConfigureRequestBuffer::obtainLock () |
| 760 | +{ |
| 761 | + crb::BufferLock::Ptr lock (priv->lockFactory (this)); |
| 762 | + |
| 763 | + priv->locks.push_back (crb::Lockable::Weak (lock)); |
| 764 | + lock->lock (); |
| 765 | + |
| 766 | + return lock; |
| 767 | +} |
| 768 | + |
| 769 | +namespace |
| 770 | +{ |
| 771 | +bool isLock (const crb::Lockable::Weak &lockable, |
| 772 | + crb::BufferLock *lock) |
| 773 | +{ |
| 774 | + crb::Lockable::Ptr strongLockable (lockable.lock ()); |
| 775 | + |
| 776 | + /* Asserting that the lock did not go away without telling |
| 777 | + * us first */ |
| 778 | + assert (strongLockable.get ()); |
| 779 | + |
| 780 | + if (strongLockable.get () == lock) |
| 781 | + return true; |
| 782 | + |
| 783 | + return false; |
| 784 | +} |
| 785 | +} |
| 786 | + |
| 787 | +void |
| 788 | +crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock) |
| 789 | +{ |
| 790 | + std::remove_if (priv->locks.begin (), |
| 791 | + priv->locks.end (), |
| 792 | + boost::bind (isLock, _1, lock)); |
| 793 | +} |
| 794 | + |
| 795 | +bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib) |
| 796 | +{ |
| 797 | + priv->dispatchConfigure (true); |
| 798 | + return priv->syncServerWindow->queryAttributes (attrib); |
| 799 | +} |
| 800 | + |
| 801 | +bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib) |
| 802 | +{ |
| 803 | + priv->dispatchConfigure (true); |
| 804 | + return priv->syncServerWindow->queryFrameAttributes (attrib); |
| 805 | +} |
| 806 | + |
| 807 | +/* This is more or less of a stop-gap for the fact that |
| 808 | + * when resizing window we re-query the window shape |
| 809 | + * and apply that to the frame. That's a separate unit of |
| 810 | + * work and should be dealt with separately. For now, force |
| 811 | + * a release of the queue whenever we do that so that |
| 812 | + * XShapeGetRectangles doesn't return an unexpected value |
| 813 | + */ |
| 814 | +XRectangle * |
| 815 | +crb::ConfigureRequestBuffer::queryShapeRectangles (int kind, |
| 816 | + int *count, |
| 817 | + int *ordering) |
| 818 | +{ |
| 819 | + priv->dispatchConfigure (true); |
| 820 | + return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering); |
| 821 | +} |
| 822 | + |
| 823 | +void crb::ConfigureRequestBuffer::forceRelease () |
| 824 | +{ |
| 825 | + priv->dispatchConfigure (true); |
| 826 | +} |
| 827 | + |
| 828 | +crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow, |
| 829 | + SyncServerWindow *syncServerWindow, |
| 830 | + const crb::ConfigureRequestBuffer::LockFactory &factory) : |
| 831 | + priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory)) |
| 832 | +{ |
| 833 | +} |
| 834 | + |
| 835 | +compiz::window::configure_buffers::Buffer::Ptr |
| 836 | +crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow, |
| 837 | + SyncServerWindow *syncServerWindow, |
| 838 | + const LockFactory &factory) |
| 839 | +{ |
| 840 | + return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow, |
| 841 | + syncServerWindow, |
| 842 | + factory)); |
| 843 | +} |
| 844 | + |
| 845 | +class crb::ConfigureBufferLock::Private |
| 846 | +{ |
| 847 | + public: |
| 848 | + |
| 849 | + Private (crb::CountedFreeze *freezable) : |
| 850 | + freezable (freezable), |
| 851 | + armed (false) |
| 852 | + { |
| 853 | + } |
| 854 | + |
| 855 | + crb::CountedFreeze *freezable; |
| 856 | + bool armed; |
| 857 | +}; |
| 858 | + |
| 859 | +crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) : |
| 860 | + priv (new crb::ConfigureBufferLock::Private (freezable)) |
| 861 | +{ |
| 862 | +} |
| 863 | + |
| 864 | +crb::ConfigureBufferLock::~ConfigureBufferLock () |
| 865 | +{ |
| 866 | + release (); |
| 867 | +} |
| 868 | + |
| 869 | +void |
| 870 | +crb::ConfigureBufferLock::lock () |
| 871 | +{ |
| 872 | + if (!priv->armed) |
| 873 | + priv->freezable->freeze (); |
| 874 | + |
| 875 | + priv->armed = true; |
| 876 | +} |
| 877 | + |
| 878 | +void |
| 879 | +crb::ConfigureBufferLock::release () |
| 880 | +{ |
| 881 | + if (priv->armed) |
| 882 | + priv->freezable->release (); |
| 883 | + |
| 884 | + priv->armed = false; |
| 885 | +} |
| 886 | |
| 887 | === modified file 'src/event.cpp' |
| 888 | --- src/event.cpp 2012-12-04 15:11:42 +0000 |
| 889 | +++ src/event.cpp 2012-12-07 17:16:21 +0000 |
| 890 | @@ -1928,7 +1928,7 @@ |
| 891 | |
| 892 | /* We should check the override_redirect flag here, because the |
| 893 | client might have changed it while being unmapped. */ |
| 894 | - if (XGetWindowAttributes (privateScreen.dpy, w->id (), &attr)) |
| 895 | + if (w->queryAttributes (attr)) |
| 896 | w->priv->setOverrideRedirect (attr.override_redirect != 0); |
| 897 | |
| 898 | if (w->state () & CompWindowStateHiddenMask) |
| 899 | |
| 900 | === modified file 'src/privatewindow.h' |
| 901 | --- src/privatewindow.h 2012-11-28 18:14:56 +0000 |
| 902 | +++ src/privatewindow.h 2012-12-07 17:16:21 +0000 |
| 903 | @@ -35,6 +35,11 @@ |
| 904 | |
| 905 | #include <boost/shared_ptr.hpp> |
| 906 | |
| 907 | +#include <core/configurerequestbuffer.h> |
| 908 | + |
| 909 | +#include "syncserverwindow.h" |
| 910 | +#include "asyncserverwindow.h" |
| 911 | + |
| 912 | #define XWINDOWCHANGES_INIT {0, 0, 0, 0, 0, None, 0} |
| 913 | |
| 914 | namespace compiz {namespace X11 |
| 915 | @@ -107,12 +112,47 @@ |
| 916 | |
| 917 | typedef CompWindowExtents CompFullscreenMonitorSet; |
| 918 | |
| 919 | -class PrivateWindow { |
| 920 | +class X11SyncServerWindow : |
| 921 | + public compiz::window::SyncServerWindow |
| 922 | +{ |
| 923 | + public: |
| 924 | + |
| 925 | + X11SyncServerWindow (Display *dpy, |
| 926 | + const Window *w, |
| 927 | + const Window *frame); |
| 928 | + |
| 929 | + bool queryAttributes (XWindowAttributes &attrib); |
| 930 | + bool queryFrameAttributes (XWindowAttributes &attrib); |
| 931 | + XRectangle * queryShapeRectangles(int kind, int *count, int *ordering); |
| 932 | + |
| 933 | + private: |
| 934 | + |
| 935 | + Display *mDpy; |
| 936 | + const Window *mWindow; |
| 937 | + const Window *mFrame; |
| 938 | +}; |
| 939 | + |
| 940 | +class PrivateWindow : |
| 941 | + public compiz::window::SyncServerWindow, |
| 942 | + public compiz::window::AsyncServerWindow |
| 943 | +{ |
| 944 | |
| 945 | public: |
| 946 | PrivateWindow (); |
| 947 | ~PrivateWindow (); |
| 948 | |
| 949 | + bool queryAttributes (XWindowAttributes &attrib); |
| 950 | + bool queryFrameAttributes (XWindowAttributes &attrib); |
| 951 | + XRectangle * queryShapeRectangles (int kind, int *count, int *ordering); |
| 952 | + int requestConfigureOnClient (const XWindowChanges &xwc, |
| 953 | + unsigned int valueMask); |
| 954 | + int requestConfigureOnWrapper (const XWindowChanges &xwc, |
| 955 | + unsigned int valueMask); |
| 956 | + int requestConfigureOnFrame (const XWindowChanges &xwc, |
| 957 | + unsigned int valueMask); |
| 958 | + void sendSyntheticConfigureNotify (); |
| 959 | + bool hasCustomShape () const; |
| 960 | + |
| 961 | void recalcNormalHints (); |
| 962 | |
| 963 | void updateFrameWindow (); |
| 964 | @@ -373,6 +413,7 @@ |
| 965 | |
| 966 | CompWindowExtents input; |
| 967 | CompWindowExtents serverInput; |
| 968 | + CompWindowExtents lastServerInput; |
| 969 | CompWindowExtents border; |
| 970 | CompWindowExtents output; |
| 971 | |
| 972 | @@ -398,6 +439,9 @@ |
| 973 | Time lastCloseRequestTime; |
| 974 | |
| 975 | bool nextMoveImmediate; |
| 976 | + |
| 977 | + X11SyncServerWindow syncServerWindow; |
| 978 | + compiz::window::configure_buffers::Buffer::Ptr configureBuffer; |
| 979 | }; |
| 980 | |
| 981 | #endif |
| 982 | |
| 983 | === added file 'src/serverwindow.h' |
| 984 | === added file 'src/syncserverwindow.h' |
| 985 | --- src/syncserverwindow.h 1970-01-01 00:00:00 +0000 |
| 986 | +++ src/syncserverwindow.h 2012-12-07 17:16:21 +0000 |
| 987 | @@ -0,0 +1,49 @@ |
| 988 | +/* |
| 989 | + * Copyright © 2012 Sam Spilsbury |
| 990 | + * |
| 991 | + * Permission to use, copy, modify, distribute, and sell this software |
| 992 | + * and its documentation for any purpose is hereby granted without |
| 993 | + * fee, provided that the above copyright notice appear in all copies |
| 994 | + * and that both that copyright notice and this permission notice |
| 995 | + * appear in supporting documentation, and that the name of |
| 996 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
| 997 | + * distribution of the software without specific, written prior permission. |
| 998 | + * Canonical Ltd. makes no representations about the suitability of this |
| 999 | + * software for any purpose. It is provided "as is" without express or |
| 1000 | + * implied warranty. |
| 1001 | + * |
| 1002 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 1003 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
| 1004 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 1005 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
| 1006 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
| 1007 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
| 1008 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 1009 | + * |
| 1010 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
| 1011 | + */ |
| 1012 | +#ifndef _COMPIZ_SYNC_SERVER_WINDOW_H |
| 1013 | +#define _COMPIZ_SYNC_SERVER_WINDOW_H |
| 1014 | + |
| 1015 | +#include <X11/Xlib.h> |
| 1016 | + |
| 1017 | +namespace compiz |
| 1018 | +{ |
| 1019 | +namespace window |
| 1020 | +{ |
| 1021 | +class SyncServerWindow |
| 1022 | +{ |
| 1023 | + public: |
| 1024 | + |
| 1025 | + virtual ~SyncServerWindow () {} |
| 1026 | + |
| 1027 | + virtual bool queryAttributes (XWindowAttributes &attrib) = 0; |
| 1028 | + virtual bool queryFrameAttributes (XWindowAttributes &attrib) = 0; |
| 1029 | + virtual XRectangle * queryShapeRectangles (int kind, |
| 1030 | + int *count, |
| 1031 | + int *ordering) = 0; |
| 1032 | +}; |
| 1033 | +} |
| 1034 | +} |
| 1035 | + |
| 1036 | +#endif |
| 1037 | |
| 1038 | === modified file 'src/tests/CMakeLists.txt' |
| 1039 | --- src/tests/CMakeLists.txt 2012-11-26 07:13:04 +0000 |
| 1040 | +++ src/tests/CMakeLists.txt 2012-12-07 17:16:21 +0000 |
| 1041 | @@ -29,3 +29,14 @@ |
| 1042 | |
| 1043 | compiz_discover_tests(compiz_test_outputdevices COVERAGE compiz_core) |
| 1044 | |
| 1045 | +add_executable (compiz_test_configurerequestbuffer |
| 1046 | + test_configurerequestbuffer.cpp) |
| 1047 | + |
| 1048 | +target_link_libraries (compiz_test_configurerequestbuffer |
| 1049 | + compiz_configurerequestbuffer |
| 1050 | + ${GTEST_BOTH_LIBRARIES} |
| 1051 | + ${GMOCK_MAIN_LIBRARY} |
| 1052 | + ${GMOCK_LIBRARY} |
| 1053 | +) |
| 1054 | + |
| 1055 | +compiz_discover_tests(compiz_test_configurerequestbuffer COVERAGE compiz_configurerequestbuffer) |
| 1056 | |
| 1057 | === added file 'src/tests/test_configurerequestbuffer.cpp' |
| 1058 | --- src/tests/test_configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000 |
| 1059 | +++ src/tests/test_configurerequestbuffer.cpp 2012-12-07 17:16:21 +0000 |
| 1060 | @@ -0,0 +1,647 @@ |
| 1061 | +/* |
| 1062 | + * Copyright © 2012 Sam Spilsbury |
| 1063 | + * |
| 1064 | + * Permission to use, copy, modify, distribute, and sell this software |
| 1065 | + * and its documentation for any purpose is hereby granted without |
| 1066 | + * fee, provided that the above copyright notice appear in all copies |
| 1067 | + * and that both that copyright notice and this permission notice |
| 1068 | + * appear in supporting documentation, and that the name of |
| 1069 | + * Canonical Ltd. not be used in advertising or publicity pertaining to |
| 1070 | + * distribution of the software without specific, written prior permission. |
| 1071 | + * Canonical Ltd. makes no representations about the suitability of this |
| 1072 | + * software for any purpose. It is provided "as is" without express or |
| 1073 | + * implied warranty. |
| 1074 | + * |
| 1075 | + * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 1076 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN |
| 1077 | + * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 1078 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
| 1079 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
| 1080 | + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION |
| 1081 | + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 1082 | + * |
| 1083 | + * Authored by: Sam Spilsbury <smspillaz@gmail.com> |
| 1084 | + */ |
| 1085 | +#include <deque> |
| 1086 | +#include <boost/shared_ptr.hpp> |
| 1087 | +#include <boost/make_shared.hpp> |
| 1088 | +#include <boost/bind.hpp> |
| 1089 | +#include <gmock/gmock.h> |
| 1090 | +#include <gtest/gtest.h> |
| 1091 | +#include <X11/Xlib.h> |
| 1092 | + |
| 1093 | +#include "configurerequestbuffer-impl.h" |
| 1094 | +#include "asyncserverwindow.h" |
| 1095 | + |
| 1096 | +namespace crb = compiz::window::configure_buffers; |
| 1097 | +namespace cw = compiz::window; |
| 1098 | + |
| 1099 | +using testing::_; |
| 1100 | +using testing::NiceMock; |
| 1101 | +using testing::Return; |
| 1102 | +using testing::Invoke; |
| 1103 | +using testing::WithArgs; |
| 1104 | +using testing::SetArgReferee; |
| 1105 | +using testing::DoAll; |
| 1106 | +using testing::InSequence; |
| 1107 | +using testing::ReturnNull; |
| 1108 | +using testing::IsNull; |
| 1109 | + |
| 1110 | +class MockAsyncServerWindow : |
| 1111 | + public cw::AsyncServerWindow |
| 1112 | +{ |
| 1113 | + public: |
| 1114 | + |
| 1115 | + MOCK_METHOD2 (requestConfigureOnClient, int (const XWindowChanges &, unsigned int)); |
| 1116 | + MOCK_METHOD2 (requestConfigureOnFrame, int (const XWindowChanges &, unsigned int)); |
| 1117 | + MOCK_METHOD2 (requestConfigureOnWrapper, int (const XWindowChanges &, unsigned int)); |
| 1118 | + MOCK_METHOD0 (sendSyntheticConfigureNotify, void ()); |
| 1119 | + MOCK_CONST_METHOD0 (hasCustomShape, bool ()); |
| 1120 | +}; |
| 1121 | + |
| 1122 | +class MockSyncServerWindow : |
| 1123 | + public cw::SyncServerWindow |
| 1124 | +{ |
| 1125 | + public: |
| 1126 | + |
| 1127 | + MOCK_METHOD1 (queryAttributes, bool (XWindowAttributes &)); |
| 1128 | + MOCK_METHOD1 (queryFrameAttributes, bool (XWindowAttributes &)); |
| 1129 | + MOCK_METHOD3 (queryShapeRectangles, XRectangle * (int, int *, int *)); |
| 1130 | +}; |
| 1131 | + |
| 1132 | +namespace |
| 1133 | +{ |
| 1134 | +int REQUEST_X = 1; |
| 1135 | +int REQUEST_Y = 2; |
| 1136 | +int REQUEST_WIDTH = 3; |
| 1137 | +int REQUEST_HEIGHT = 4; |
| 1138 | +int REQUEST_BORDER = 5; |
| 1139 | + |
| 1140 | +Window REQUEST_ABOVE = 6; |
| 1141 | +unsigned int REQUEST_MODE = 7; |
| 1142 | + |
| 1143 | +crb::BufferLock::Ptr |
| 1144 | +CreateNormalLock (crb::CountedFreeze *cf) |
| 1145 | +{ |
| 1146 | + return boost::make_shared <crb::ConfigureBufferLock> (cf); |
| 1147 | +} |
| 1148 | + |
| 1149 | +} |
| 1150 | + |
| 1151 | +MATCHER_P2 (MaskXWC, xwc, vm, "Matches XWindowChanges") |
| 1152 | +{ |
| 1153 | + if (vm & CWX) |
| 1154 | + if (xwc.x != arg.x) |
| 1155 | + return false; |
| 1156 | + |
| 1157 | + if (vm & CWY) |
| 1158 | + if (xwc.y != arg.y) |
| 1159 | + return false; |
| 1160 | + |
| 1161 | + if (vm & CWWidth) |
| 1162 | + if (xwc.width != arg.width) |
| 1163 | + return false; |
| 1164 | + |
| 1165 | + if (vm & CWHeight) |
| 1166 | + if (xwc.height != arg.height) |
| 1167 | + return false; |
| 1168 | + |
| 1169 | + if (vm & CWBorderWidth) |
| 1170 | + if (xwc.border_width != arg.border_width) |
| 1171 | + return false; |
| 1172 | + |
| 1173 | + if (vm & CWStackMode) |
| 1174 | + if (xwc.stack_mode != arg.stack_mode) |
| 1175 | + return false; |
| 1176 | + |
| 1177 | + if (vm & CWSibling) |
| 1178 | + if (xwc.sibling != arg.sibling) |
| 1179 | + return false; |
| 1180 | + |
| 1181 | + return true; |
| 1182 | +} |
| 1183 | + |
| 1184 | +class ConfigureRequestBuffer : |
| 1185 | + public testing::Test |
| 1186 | +{ |
| 1187 | + public: |
| 1188 | + |
| 1189 | + ConfigureRequestBuffer () |
| 1190 | + { |
| 1191 | + /* Initialize xwc, we control it |
| 1192 | + * through the value masks */ |
| 1193 | + xwc.x = REQUEST_X; |
| 1194 | + xwc.y = REQUEST_Y; |
| 1195 | + xwc.width = REQUEST_WIDTH; |
| 1196 | + xwc.height = REQUEST_HEIGHT; |
| 1197 | + xwc.border_width = REQUEST_BORDER; |
| 1198 | + xwc.sibling = REQUEST_ABOVE; |
| 1199 | + xwc.stack_mode = REQUEST_MODE; |
| 1200 | + } |
| 1201 | + |
| 1202 | + protected: |
| 1203 | + |
| 1204 | + XWindowChanges xwc; |
| 1205 | + MockAsyncServerWindow asyncServerWindow; |
| 1206 | + MockSyncServerWindow syncServerWindow; |
| 1207 | +}; |
| 1208 | + |
| 1209 | +class ConfigureRequestBufferDispatch : |
| 1210 | + public ConfigureRequestBuffer |
| 1211 | +{ |
| 1212 | + protected: |
| 1213 | + |
| 1214 | + ConfigureRequestBufferDispatch () : |
| 1215 | + ConfigureRequestBuffer (), |
| 1216 | + factory (boost::bind (CreateNormalLock, _1)), |
| 1217 | + buffer ( |
| 1218 | + crb::ConfigureRequestBuffer::Create (&asyncServerWindow, |
| 1219 | + &syncServerWindow, |
| 1220 | + factory)) |
| 1221 | + { |
| 1222 | + } |
| 1223 | + |
| 1224 | + crb::ConfigureRequestBuffer::LockFactory factory; |
| 1225 | + crb::Buffer::Ptr buffer; |
| 1226 | +}; |
| 1227 | + |
| 1228 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectSyntheticConfigureNotify) |
| 1229 | +{ |
| 1230 | + EXPECT_CALL (asyncServerWindow, sendSyntheticConfigureNotify ()); |
| 1231 | + |
| 1232 | + buffer->pushSyntheticConfigureNotify (); |
| 1233 | +} |
| 1234 | + |
| 1235 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectClientUpdate) |
| 1236 | +{ |
| 1237 | + unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth | |
| 1238 | + CWSibling | CWStackMode; |
| 1239 | + |
| 1240 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask), |
| 1241 | + valueMask)); |
| 1242 | + |
| 1243 | + buffer->pushClientRequest (xwc, valueMask); |
| 1244 | +} |
| 1245 | + |
| 1246 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectWrapperUpdate) |
| 1247 | +{ |
| 1248 | + unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth | |
| 1249 | + CWSibling | CWStackMode; |
| 1250 | + |
| 1251 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask), |
| 1252 | + valueMask)); |
| 1253 | + |
| 1254 | + buffer->pushWrapperRequest (xwc, valueMask); |
| 1255 | +} |
| 1256 | + |
| 1257 | +TEST_F (ConfigureRequestBufferDispatch, PushDirectFrameUpdate) |
| 1258 | +{ |
| 1259 | + unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth | |
| 1260 | + CWSibling | CWStackMode; |
| 1261 | + |
| 1262 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillOnce (Return (false)); |
| 1263 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
| 1264 | + valueMask)); |
| 1265 | + |
| 1266 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1267 | +} |
| 1268 | + |
| 1269 | +TEST_F (ConfigureRequestBufferDispatch, PushUpdateLocked) |
| 1270 | +{ |
| 1271 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
| 1272 | + |
| 1273 | + unsigned int valueMask = 0; |
| 1274 | + |
| 1275 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1276 | + |
| 1277 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1278 | +} |
| 1279 | + |
| 1280 | +TEST_F (ConfigureRequestBufferDispatch, PushCombinedUpdateLocked) |
| 1281 | +{ |
| 1282 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
| 1283 | + |
| 1284 | + unsigned int valueMask = CWX | CWY; |
| 1285 | + |
| 1286 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1287 | + |
| 1288 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1289 | + |
| 1290 | + valueMask |= CWWidth | CWHeight; |
| 1291 | + |
| 1292 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillRepeatedly (Return (false)); |
| 1293 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1294 | + |
| 1295 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1296 | + |
| 1297 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
| 1298 | + valueMask)); |
| 1299 | + |
| 1300 | + lock->release (); |
| 1301 | +} |
| 1302 | + |
| 1303 | +TEST_F (ConfigureRequestBufferDispatch, PushUpdateLockedReleaseInOrder) |
| 1304 | +{ |
| 1305 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
| 1306 | + |
| 1307 | + unsigned int valueMask = CWX | CWY; |
| 1308 | + |
| 1309 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillRepeatedly (Return (false)); |
| 1310 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1311 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (_, _)).Times (0); |
| 1312 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (_, _)).Times (0); |
| 1313 | + |
| 1314 | + buffer->pushClientRequest (xwc, valueMask); |
| 1315 | + buffer->pushWrapperRequest (xwc, valueMask); |
| 1316 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1317 | + |
| 1318 | + InSequence s; |
| 1319 | + |
| 1320 | + /* Always frame -> wrapper -> client */ |
| 1321 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
| 1322 | + valueMask)); |
| 1323 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask), |
| 1324 | + valueMask)); |
| 1325 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask), |
| 1326 | + valueMask)); |
| 1327 | + |
| 1328 | + lock->release (); |
| 1329 | +} |
| 1330 | + |
| 1331 | +TEST_F (ConfigureRequestBufferDispatch, UnlockBuffer) |
| 1332 | +{ |
| 1333 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
| 1334 | + |
| 1335 | + unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; |
| 1336 | + |
| 1337 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillRepeatedly (Return (false)); |
| 1338 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1339 | + |
| 1340 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1341 | + |
| 1342 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
| 1343 | + valueMask)); |
| 1344 | + |
| 1345 | + lock->release (); |
| 1346 | +} |
| 1347 | + |
| 1348 | +TEST_F (ConfigureRequestBufferDispatch, ImplicitUnlockBuffer) |
| 1349 | +{ |
| 1350 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
| 1351 | + |
| 1352 | + unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; |
| 1353 | + |
| 1354 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillRepeatedly (Return (false)); |
| 1355 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1356 | + |
| 1357 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1358 | + |
| 1359 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
| 1360 | + valueMask)); |
| 1361 | +} |
| 1362 | + |
| 1363 | +TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnRestack) |
| 1364 | +{ |
| 1365 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
| 1366 | + |
| 1367 | + unsigned int valueMask = CWStackMode | CWSibling; |
| 1368 | + |
| 1369 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
| 1370 | + valueMask)); |
| 1371 | + |
| 1372 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1373 | +} |
| 1374 | + |
| 1375 | +TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnShapedWindowSizeChange) |
| 1376 | +{ |
| 1377 | + crb::Releasable::Ptr lock (buffer->obtainLock ()); |
| 1378 | + |
| 1379 | + unsigned int valueMask = CWWidth | CWHeight; |
| 1380 | + |
| 1381 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillOnce (Return (true)); |
| 1382 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask), |
| 1383 | + valueMask)); |
| 1384 | + |
| 1385 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1386 | +} |
| 1387 | + |
| 1388 | +namespace |
| 1389 | +{ |
| 1390 | +class MockLock : |
| 1391 | + public crb::BufferLock |
| 1392 | +{ |
| 1393 | + public: |
| 1394 | + |
| 1395 | + /* We're currently importing the locks statefulness and coupling |
| 1396 | + * the caller with that */ |
| 1397 | + MockLock () : |
| 1398 | + armed (false) |
| 1399 | + { |
| 1400 | + ON_CALL (*this, lock ()).WillByDefault ( |
| 1401 | + Invoke (this, &MockLock::FreezeIfUnarmed)); |
| 1402 | + ON_CALL (*this, release ()).WillByDefault ( |
| 1403 | + Invoke (this, &MockLock::ReleaseIfArmed)); |
| 1404 | + } |
| 1405 | + |
| 1406 | + void OperateOver (crb::CountedFreeze *cf) |
| 1407 | + { |
| 1408 | + countedFreeze = cf; |
| 1409 | + } |
| 1410 | + |
| 1411 | + void FreezeIfUnarmed () |
| 1412 | + { |
| 1413 | + if (!armed) |
| 1414 | + { |
| 1415 | + countedFreeze->freeze (); |
| 1416 | + armed = true; |
| 1417 | + } |
| 1418 | + } |
| 1419 | + |
| 1420 | + void ReleaseIfArmed () |
| 1421 | + { |
| 1422 | + if (armed) |
| 1423 | + { |
| 1424 | + countedFreeze->release (); |
| 1425 | + armed = false; |
| 1426 | + } |
| 1427 | + } |
| 1428 | + |
| 1429 | + typedef boost::shared_ptr <MockLock> Ptr; |
| 1430 | + |
| 1431 | + MOCK_METHOD0 (lock, void ()); |
| 1432 | + MOCK_METHOD0 (release, void ()); |
| 1433 | + |
| 1434 | + private: |
| 1435 | + |
| 1436 | + crb::CountedFreeze *countedFreeze; |
| 1437 | + bool armed; |
| 1438 | +}; |
| 1439 | + |
| 1440 | +class MockLockFactory |
| 1441 | +{ |
| 1442 | + public: |
| 1443 | + |
| 1444 | + crb::BufferLock::Ptr |
| 1445 | + CreateMockLock (crb::CountedFreeze *cf) |
| 1446 | + { |
| 1447 | + MockLock::Ptr mockLock (locks.front ()); |
| 1448 | + mockLock->OperateOver (cf); |
| 1449 | + |
| 1450 | + locks.pop_front (); |
| 1451 | + |
| 1452 | + return mockLock; |
| 1453 | + } |
| 1454 | + |
| 1455 | + void |
| 1456 | + QueueLockForCreation (const MockLock::Ptr &lock) |
| 1457 | + { |
| 1458 | + locks.push_back (lock); |
| 1459 | + } |
| 1460 | + |
| 1461 | + private: |
| 1462 | + |
| 1463 | + std::deque <MockLock::Ptr> locks; |
| 1464 | +}; |
| 1465 | +} |
| 1466 | + |
| 1467 | +class ConfigureRequestBufferLockBehaviour : |
| 1468 | + public ConfigureRequestBuffer |
| 1469 | +{ |
| 1470 | + public: |
| 1471 | + |
| 1472 | + ConfigureRequestBufferLockBehaviour () : |
| 1473 | + ConfigureRequestBuffer (), |
| 1474 | + lock (boost::make_shared <MockLock> ()), |
| 1475 | + factory ( |
| 1476 | + boost::bind (&MockLockFactory::CreateMockLock, |
| 1477 | + &mockLockFactory, |
| 1478 | + _1)), |
| 1479 | + buffer ( |
| 1480 | + crb::ConfigureRequestBuffer::Create ( |
| 1481 | + &asyncServerWindow, |
| 1482 | + &syncServerWindow, |
| 1483 | + factory)) |
| 1484 | + |
| 1485 | + { |
| 1486 | + mockLockFactory.QueueLockForCreation (lock); |
| 1487 | + } |
| 1488 | + |
| 1489 | + protected: |
| 1490 | + |
| 1491 | + typedef NiceMock <MockAsyncServerWindow> NiceServerWindow; |
| 1492 | + typedef crb::ConfigureRequestBuffer::LockFactory LockFactory; |
| 1493 | + |
| 1494 | + MockLock::Ptr lock; |
| 1495 | + MockLockFactory mockLockFactory; |
| 1496 | + |
| 1497 | + LockFactory factory; |
| 1498 | + crb::Buffer::Ptr buffer; |
| 1499 | +}; |
| 1500 | + |
| 1501 | +TEST_F (ConfigureRequestBufferLockBehaviour, RearmBufferLockOnRelease) |
| 1502 | +{ |
| 1503 | + EXPECT_CALL (*lock, lock ()); |
| 1504 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1505 | + |
| 1506 | + unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; |
| 1507 | + |
| 1508 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillRepeatedly (Return (false)); |
| 1509 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1510 | + |
| 1511 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1512 | + |
| 1513 | + /* We are releasing this lock */ |
| 1514 | + EXPECT_CALL (*lock, release ()); |
| 1515 | + |
| 1516 | + /* Now the buffer will dispatch is configure request */ |
| 1517 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
| 1518 | + |
| 1519 | + /* Rearm locks on release */ |
| 1520 | + EXPECT_CALL (*lock, lock ()); |
| 1521 | + |
| 1522 | + /* Directly release the queue */ |
| 1523 | + releasable->release (); |
| 1524 | +} |
| 1525 | + |
| 1526 | +TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockNoReleaseRequired) |
| 1527 | +{ |
| 1528 | + /* Locks get armed on construction */ |
| 1529 | + EXPECT_CALL (*lock, lock ()); |
| 1530 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1531 | + |
| 1532 | + /* No call to requestConfigureOnFrame if there's nothing to be configured */ |
| 1533 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1534 | + |
| 1535 | + /* We are releasing this lock */ |
| 1536 | + EXPECT_CALL (*lock, release ()); |
| 1537 | + |
| 1538 | + /* No rearm - we haven't released the whole buffer */ |
| 1539 | + EXPECT_CALL (*lock, lock ()).Times (0); |
| 1540 | + |
| 1541 | + /* Directly release the queue */ |
| 1542 | + releasable->release (); |
| 1543 | +} |
| 1544 | + |
| 1545 | +TEST_F (ConfigureRequestBufferLockBehaviour, RearmWhenPushReady) |
| 1546 | +{ |
| 1547 | + /* Locks get armed on construction */ |
| 1548 | + EXPECT_CALL (*lock, lock ()); |
| 1549 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1550 | + |
| 1551 | + /* We are releasing this lock */ |
| 1552 | + EXPECT_CALL (*lock, release ()); |
| 1553 | + |
| 1554 | + /* No call to requestConfigureOnFrame if there's nothing to be configured */ |
| 1555 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1556 | + |
| 1557 | + /* No rearm - we haven't released it */ |
| 1558 | + EXPECT_CALL (*lock, lock ()).Times (0); |
| 1559 | + |
| 1560 | + /* Directly release the queue */ |
| 1561 | + releasable->release (); |
| 1562 | + |
| 1563 | + /* Since we're now going to push something to a queue |
| 1564 | + * that's effectively not locked, the locks should now |
| 1565 | + * be released */ |
| 1566 | + unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; |
| 1567 | + |
| 1568 | + /* Now rearm it */ |
| 1569 | + EXPECT_CALL (asyncServerWindow, hasCustomShape ()).WillOnce (Return (false)); |
| 1570 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
| 1571 | + EXPECT_CALL (*lock, lock ()); |
| 1572 | + |
| 1573 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1574 | +} |
| 1575 | + |
| 1576 | +TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockOnNoRelease) |
| 1577 | +{ |
| 1578 | + MockLock::Ptr second (boost::make_shared <MockLock> ()); |
| 1579 | + mockLockFactory.QueueLockForCreation (second); |
| 1580 | + |
| 1581 | + /* Locks get armed on construction */ |
| 1582 | + EXPECT_CALL (*lock, lock ()); |
| 1583 | + EXPECT_CALL (*second, lock ()); |
| 1584 | + |
| 1585 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1586 | + crb::Releasable::Ptr otherReleasable (buffer->obtainLock ()); |
| 1587 | + |
| 1588 | + /* We are releasing this lock */ |
| 1589 | + EXPECT_CALL (*lock, release ()); |
| 1590 | + |
| 1591 | + /* No call to requestConfigureOnFrame if there's nothing to be configured */ |
| 1592 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1593 | + |
| 1594 | + /* No rearm - we haven't released it */ |
| 1595 | + EXPECT_CALL (*lock, lock ()).Times (0); |
| 1596 | + |
| 1597 | + releasable->release (); |
| 1598 | +} |
| 1599 | + |
| 1600 | +TEST_F (ConfigureRequestBufferLockBehaviour, QueryAttributesDispatchAndRearm) |
| 1601 | +{ |
| 1602 | + /* Locks get armed on construction */ |
| 1603 | + EXPECT_CALL (*lock, lock ()); |
| 1604 | + |
| 1605 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1606 | + |
| 1607 | + unsigned int valueMask = CWX | CWY; |
| 1608 | + |
| 1609 | + /* Queue locked */ |
| 1610 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1611 | + |
| 1612 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1613 | + |
| 1614 | + /* Queue forceably unlocked, locks rearmed */ |
| 1615 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
| 1616 | + EXPECT_CALL (*lock, lock ()); |
| 1617 | + |
| 1618 | + /* Expect a call to XGetWindowAttributes */ |
| 1619 | + EXPECT_CALL (syncServerWindow, queryShapeRectangles (_, _, _)) |
| 1620 | + .WillOnce ( |
| 1621 | + ReturnNull ()); |
| 1622 | + |
| 1623 | + int a, b; |
| 1624 | + |
| 1625 | + EXPECT_THAT (buffer->queryShapeRectangles (0, &a, &b), IsNull ()); |
| 1626 | +} |
| 1627 | + |
| 1628 | +TEST_F (ConfigureRequestBufferLockBehaviour, QueryFrameAttributesDispatchAndRearm) |
| 1629 | +{ |
| 1630 | + /* Locks get armed on construction */ |
| 1631 | + EXPECT_CALL (*lock, lock ()); |
| 1632 | + |
| 1633 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1634 | + |
| 1635 | + unsigned int valueMask = CWX | CWY; |
| 1636 | + |
| 1637 | + /* Queue locked */ |
| 1638 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1639 | + |
| 1640 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1641 | + |
| 1642 | + /* Queue forceably unlocked, locks rearmed */ |
| 1643 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
| 1644 | + EXPECT_CALL (*lock, lock ()); |
| 1645 | + |
| 1646 | + /* Expect a call to XGetWindowAttributes */ |
| 1647 | + XWindowAttributes xwa; |
| 1648 | + EXPECT_CALL (syncServerWindow, queryFrameAttributes (_)) |
| 1649 | + .WillOnce ( |
| 1650 | + DoAll ( |
| 1651 | + SetArgReferee <0> (xwa), |
| 1652 | + Return (true))); |
| 1653 | + |
| 1654 | + buffer->queryFrameAttributes (xwa); |
| 1655 | +} |
| 1656 | + |
| 1657 | +TEST_F (ConfigureRequestBufferLockBehaviour, QueryShapeRectanglesDispatchAndRearm) |
| 1658 | +{ |
| 1659 | + /* Locks get armed on construction */ |
| 1660 | + EXPECT_CALL (*lock, lock ()); |
| 1661 | + |
| 1662 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1663 | + |
| 1664 | + unsigned int valueMask = CWX | CWY; |
| 1665 | + |
| 1666 | + /* Queue locked */ |
| 1667 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1668 | + |
| 1669 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1670 | + |
| 1671 | + /* Queue forceably unlocked, locks rearmed */ |
| 1672 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
| 1673 | + EXPECT_CALL (*lock, lock ()); |
| 1674 | + |
| 1675 | + /* Expect a call to XGetWindowAttributes */ |
| 1676 | + XWindowAttributes xwa; |
| 1677 | + EXPECT_CALL (syncServerWindow, queryFrameAttributes (_)) |
| 1678 | + .WillOnce ( |
| 1679 | + DoAll ( |
| 1680 | + SetArgReferee <0> (xwa), |
| 1681 | + Return (true))); |
| 1682 | + |
| 1683 | + buffer->queryFrameAttributes (xwa); |
| 1684 | +} |
| 1685 | + |
| 1686 | +TEST_F (ConfigureRequestBufferLockBehaviour, ForceReleaseDispatchAndRearm) |
| 1687 | +{ |
| 1688 | + /* Locks get armed on construction */ |
| 1689 | + EXPECT_CALL (*lock, lock ()); |
| 1690 | + |
| 1691 | + crb::Releasable::Ptr releasable (buffer->obtainLock ()); |
| 1692 | + |
| 1693 | + unsigned int valueMask = CWX | CWY; |
| 1694 | + |
| 1695 | + /* Queue locked */ |
| 1696 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0); |
| 1697 | + |
| 1698 | + buffer->pushFrameRequest (xwc, valueMask); |
| 1699 | + |
| 1700 | + /* Queue forceably unlocked, locks rearmed */ |
| 1701 | + EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)); |
| 1702 | + EXPECT_CALL (*lock, lock ()); |
| 1703 | + |
| 1704 | + /* Force release */ |
| 1705 | + buffer->forceRelease (); |
| 1706 | +} |
| 1707 | + |
| 1708 | |
| 1709 | === modified file 'src/window.cpp' |
| 1710 | --- src/window.cpp 2012-12-07 09:28:03 +0000 |
| 1711 | +++ src/window.cpp 2012-12-07 17:16:21 +0000 |
| 1712 | @@ -37,6 +37,7 @@ |
| 1713 | #include <math.h> |
| 1714 | |
| 1715 | #include <boost/bind.hpp> |
| 1716 | +#include <boost/make_shared.hpp> |
| 1717 | |
| 1718 | #include <core/icon.h> |
| 1719 | #include <core/atoms.h> |
| 1720 | @@ -45,8 +46,13 @@ |
| 1721 | #include "privatescreen.h" |
| 1722 | #include "privatestackdebugger.h" |
| 1723 | |
| 1724 | +#include "configurerequestbuffer-impl.h" |
| 1725 | + |
| 1726 | #include <boost/scoped_array.hpp> |
| 1727 | |
| 1728 | +namespace crb = compiz::window::configure_buffers; |
| 1729 | +namespace cw = compiz::window; |
| 1730 | + |
| 1731 | template class WrapableInterface<CompWindow, WindowInterface>; |
| 1732 | |
| 1733 | PluginClassStorage::Indices windowPluginClassIndices (0); |
| 1734 | @@ -912,10 +918,12 @@ |
| 1735 | /* We should update the server here */ |
| 1736 | XSync (screen->dpy (), false); |
| 1737 | |
| 1738 | - boundingShapeRects = XShapeGetRectangles (screen->dpy (), priv->id, |
| 1739 | - ShapeBounding, &nBounding, &order); |
| 1740 | - inputShapeRects = XShapeGetRectangles (screen->dpy (), priv->id, |
| 1741 | - ShapeInput, &nInput, &order); |
| 1742 | + boundingShapeRects = priv->queryShapeRectangles (ShapeBounding, |
| 1743 | + &nBounding, |
| 1744 | + &order); |
| 1745 | + inputShapeRects = priv->queryShapeRectangles (ShapeInput, |
| 1746 | + &nBounding, |
| 1747 | + &order); |
| 1748 | } |
| 1749 | |
| 1750 | r.x = -geom.border (); |
| 1751 | @@ -2961,6 +2969,80 @@ |
| 1752 | return pc->matchRequest (xwc, valueMask); |
| 1753 | } |
| 1754 | |
| 1755 | +bool |
| 1756 | +PrivateWindow::queryAttributes (XWindowAttributes &attrib) |
| 1757 | +{ |
| 1758 | + return configureBuffer->queryAttributes (attrib); |
| 1759 | +} |
| 1760 | + |
| 1761 | +bool |
| 1762 | +PrivateWindow::queryFrameAttributes (XWindowAttributes &attrib) |
| 1763 | +{ |
| 1764 | + return configureBuffer->queryFrameAttributes (attrib); |
| 1765 | +} |
| 1766 | + |
| 1767 | +XRectangle * |
| 1768 | +PrivateWindow::queryShapeRectangles (int kind, int *count, int *ordering) |
| 1769 | +{ |
| 1770 | + return configureBuffer->queryShapeRectangles (kind, count, ordering); |
| 1771 | +} |
| 1772 | + |
| 1773 | +int |
| 1774 | +PrivateWindow::requestConfigureOnClient (const XWindowChanges &xwc, |
| 1775 | + unsigned int valueMask) |
| 1776 | +{ |
| 1777 | + int ret = XConfigureWindow (screen->dpy (), |
| 1778 | + id, |
| 1779 | + valueMask, |
| 1780 | + const_cast <XWindowChanges *> (&xwc)); |
| 1781 | + |
| 1782 | + return ret; |
| 1783 | +} |
| 1784 | + |
| 1785 | +int |
| 1786 | +PrivateWindow::requestConfigureOnWrapper (const XWindowChanges &xwc, |
| 1787 | + unsigned int valueMask) |
| 1788 | +{ |
| 1789 | + return XConfigureWindow (screen->dpy (), |
| 1790 | + wrapper, |
| 1791 | + valueMask, |
| 1792 | + const_cast <XWindowChanges *> (&xwc)); |
| 1793 | +} |
| 1794 | + |
| 1795 | +int |
| 1796 | +PrivateWindow::requestConfigureOnFrame (const XWindowChanges &xwc, |
| 1797 | + unsigned int frameValueMask) |
| 1798 | +{ |
| 1799 | + XWindowChanges wc = xwc; |
| 1800 | + |
| 1801 | + wc.x = serverFrameGeometry.x (); |
| 1802 | + wc.y = serverFrameGeometry.y (); |
| 1803 | + wc.width = serverFrameGeometry.width (); |
| 1804 | + wc.height = serverFrameGeometry.height (); |
| 1805 | + |
| 1806 | + compiz::X11::PendingEvent::Ptr pc ( |
| 1807 | + new compiz::X11::PendingConfigureEvent ( |
| 1808 | + screen->dpy (), |
| 1809 | + priv->serverFrame, |
| 1810 | + frameValueMask, &wc)); |
| 1811 | + |
| 1812 | + pendingConfigures.add (pc); |
| 1813 | + |
| 1814 | + return XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc); |
| 1815 | +} |
| 1816 | + |
| 1817 | +void |
| 1818 | +PrivateWindow::sendSyntheticConfigureNotify () |
| 1819 | +{ |
| 1820 | + window->sendConfigureNotify (); |
| 1821 | +} |
| 1822 | + |
| 1823 | +bool |
| 1824 | +PrivateWindow::hasCustomShape () const |
| 1825 | +{ |
| 1826 | + return false; |
| 1827 | +} |
| 1828 | + |
| 1829 | void |
| 1830 | PrivateWindow::reconfigureXWindow (unsigned int valueMask, |
| 1831 | XWindowChanges *xwc) |
| 1832 | @@ -3173,47 +3255,41 @@ |
| 1833 | if (serverFrame) |
| 1834 | { |
| 1835 | if (frameValueMask) |
| 1836 | - { |
| 1837 | - XWindowChanges wc = *xwc; |
| 1838 | - |
| 1839 | - wc.x = serverFrameGeometry.x (); |
| 1840 | - wc.y = serverFrameGeometry.y (); |
| 1841 | - wc.width = serverFrameGeometry.width (); |
| 1842 | - wc.height = serverFrameGeometry.height (); |
| 1843 | - |
| 1844 | - compiz::X11::PendingEvent::Ptr pc = |
| 1845 | - boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr ( |
| 1846 | - new compiz::X11::PendingConfigureEvent ( |
| 1847 | - screen->dpy (), priv->serverFrame, frameValueMask, &wc))); |
| 1848 | - |
| 1849 | - pendingConfigures.add (pc); |
| 1850 | - |
| 1851 | - XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc); |
| 1852 | - } |
| 1853 | - |
| 1854 | - valueMask &= ~(CWSibling | CWStackMode); |
| 1855 | + priv->configureBuffer->pushFrameRequest (*xwc, frameValueMask); |
| 1856 | + |
| 1857 | + valueMask = frameValueMask & (CWWidth | CWHeight); |
| 1858 | |
| 1859 | /* If the frame has changed position (eg, serverInput.top |
| 1860 | * or serverInput.left have changed) then we also need to |
| 1861 | * update the client and wrapper position */ |
| 1862 | - if (!(valueMask & CWX)) |
| 1863 | - valueMask |= frameValueMask & CWX; |
| 1864 | - if (!(valueMask & CWY)) |
| 1865 | - valueMask |= frameValueMask & CWY; |
| 1866 | + if (lastServerInput.left != serverInput.left) |
| 1867 | + valueMask |= CWX; |
| 1868 | + if (lastServerInput.top != serverInput.top) |
| 1869 | + valueMask |= CWY; |
| 1870 | + |
| 1871 | + if (lastServerInput.right != serverInput.right) |
| 1872 | + valueMask |= CWWidth; |
| 1873 | + if (lastServerInput.bottom != serverInput.bottom) |
| 1874 | + valueMask |= CWHeight; |
| 1875 | |
| 1876 | if (valueMask) |
| 1877 | { |
| 1878 | xwc->x = serverInput.left; |
| 1879 | xwc->y = serverInput.top; |
| 1880 | - XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc); |
| 1881 | - |
| 1882 | - xwc->x = 0; |
| 1883 | - xwc->y = 0; |
| 1884 | + |
| 1885 | + lastServerInput = serverInput; |
| 1886 | + |
| 1887 | + priv->configureBuffer->pushWrapperRequest (*xwc, valueMask); |
| 1888 | } |
| 1889 | } |
| 1890 | |
| 1891 | + /* Client is reparented, the only things that can change |
| 1892 | + * are the width, height and border width */ |
| 1893 | + if (serverFrame) |
| 1894 | + valueMask &= (CWWidth | CWHeight | CWBorderWidth); |
| 1895 | + |
| 1896 | if (valueMask) |
| 1897 | - XConfigureWindow (screen->dpy (), id, valueMask, xwc); |
| 1898 | + priv->configureBuffer->pushClientRequest (*xwc, valueMask); |
| 1899 | |
| 1900 | /* Send the synthetic configure notify |
| 1901 | * after the real configure notify arrives |
| 1902 | @@ -5655,6 +5731,24 @@ |
| 1903 | return priv->struts; |
| 1904 | } |
| 1905 | |
| 1906 | +bool |
| 1907 | +CompWindow::queryAttributes (XWindowAttributes &attrib) |
| 1908 | +{ |
| 1909 | + return priv->queryAttributes (attrib); |
| 1910 | +} |
| 1911 | + |
| 1912 | +bool |
| 1913 | +CompWindow::queryFrameAttributes (XWindowAttributes &attrib) |
| 1914 | +{ |
| 1915 | + return priv->queryFrameAttributes (attrib); |
| 1916 | +} |
| 1917 | + |
| 1918 | +crb::Releasable::Ptr |
| 1919 | +CompWindow::obtainLockOnConfigureRequests () |
| 1920 | +{ |
| 1921 | + return priv->configureBuffer->obtainLock (); |
| 1922 | +} |
| 1923 | + |
| 1924 | int & |
| 1925 | CompWindow::saveMask () const |
| 1926 | { |
| 1927 | @@ -6193,6 +6287,55 @@ |
| 1928 | delete priv; |
| 1929 | } |
| 1930 | |
| 1931 | +X11SyncServerWindow::X11SyncServerWindow (Display *dpy, |
| 1932 | + const Window *w, |
| 1933 | + const Window *frame) : |
| 1934 | + mDpy (dpy), |
| 1935 | + mWindow (w), |
| 1936 | + mFrame (frame) |
| 1937 | +{ |
| 1938 | +} |
| 1939 | + |
| 1940 | +bool |
| 1941 | +X11SyncServerWindow::queryAttributes (XWindowAttributes &attrib) |
| 1942 | +{ |
| 1943 | + if (XGetWindowAttributes (mDpy, *mWindow, &attrib)) |
| 1944 | + return true; |
| 1945 | + |
| 1946 | + return false; |
| 1947 | +} |
| 1948 | + |
| 1949 | +bool |
| 1950 | +X11SyncServerWindow::queryFrameAttributes (XWindowAttributes &attrib) |
| 1951 | +{ |
| 1952 | + Window w = *mFrame ? *mFrame : *mWindow; |
| 1953 | + |
| 1954 | + if (XGetWindowAttributes (mDpy, w, &attrib)) |
| 1955 | + return true; |
| 1956 | + |
| 1957 | + return false; |
| 1958 | +} |
| 1959 | + |
| 1960 | +XRectangle * |
| 1961 | +X11SyncServerWindow::queryShapeRectangles (int kind, |
| 1962 | + int *count, |
| 1963 | + int *ordering) |
| 1964 | +{ |
| 1965 | + return XShapeGetRectangles (mDpy, *mWindow, |
| 1966 | + kind, |
| 1967 | + count, |
| 1968 | + ordering); |
| 1969 | +} |
| 1970 | + |
| 1971 | +namespace |
| 1972 | +{ |
| 1973 | +crb::BufferLock::Ptr |
| 1974 | +createConfigureBufferLock (crb::CountedFreeze *cf) |
| 1975 | +{ |
| 1976 | + return boost::make_shared <crb::ConfigureBufferLock> (cf); |
| 1977 | +} |
| 1978 | +} |
| 1979 | + |
| 1980 | PrivateWindow::PrivateWindow () : |
| 1981 | priv (this), |
| 1982 | refcnt (1), |
| 1983 | @@ -6264,27 +6407,27 @@ |
| 1984 | |
| 1985 | syncWait (false), |
| 1986 | closeRequests (false), |
| 1987 | - lastCloseRequestTime (0) |
| 1988 | + lastCloseRequestTime (0), |
| 1989 | + |
| 1990 | + syncServerWindow (screen->dpy (), |
| 1991 | + &id, |
| 1992 | + &serverFrame), |
| 1993 | + configureBuffer ( |
| 1994 | + crb::ConfigureRequestBuffer::Create ( |
| 1995 | + this, |
| 1996 | + &syncServerWindow, |
| 1997 | + boost::bind (createConfigureBufferLock, _1))) |
| 1998 | { |
| 1999 | input.left = 0; |
| 2000 | input.right = 0; |
| 2001 | input.top = 0; |
| 2002 | input.bottom = 0; |
| 2003 | |
| 2004 | - serverInput.left = 0; |
| 2005 | - serverInput.right = 0; |
| 2006 | - serverInput.top = 0; |
| 2007 | - serverInput.bottom = 0; |
| 2008 | - |
| 2009 | - border.top = 0; |
| 2010 | - border.bottom = 0; |
| 2011 | - border.left = 0; |
| 2012 | - border.right = 0; |
| 2013 | - |
| 2014 | - output.left = 0; |
| 2015 | - output.right = 0; |
| 2016 | - output.top = 0; |
| 2017 | - output.bottom = 0; |
| 2018 | + /* Zero initialize */ |
| 2019 | + serverInput = input; |
| 2020 | + lastServerInput = input; |
| 2021 | + border = input; |
| 2022 | + output = input; |
| 2023 | |
| 2024 | syncWaitTimer.setTimes (1000, 1200); |
| 2025 | syncWaitTimer.setCallback (boost::bind (&PrivateWindow::handleSyncAlarm, |
| 2026 | @@ -6554,7 +6697,11 @@ |
| 2027 | XSync (dpy, false); |
| 2028 | XGrabServer (dpy); |
| 2029 | |
| 2030 | - if (!XGetWindowAttributes (dpy, id, &wa)) |
| 2031 | + /* We need to flush all queued up requests */ |
| 2032 | + foreach (CompWindow *w, screen->windows ()) |
| 2033 | + w->priv->configureBuffer->forceRelease (); |
| 2034 | + |
| 2035 | + if (!window->priv->queryAttributes (wa)) |
| 2036 | { |
| 2037 | XUngrabServer (dpy); |
| 2038 | XSync (dpy, false); |
| 2039 | @@ -6841,7 +6988,7 @@ |
| 2040 | * a DestroyNotify for it yet, it is possible that restacking |
| 2041 | * operations could occurr relative to it so we need to hold it |
| 2042 | * in the stack for now. Ensure that it is marked override redirect */ |
| 2043 | - XGetWindowAttributes (screen->dpy (), serverFrame, &attrib); |
| 2044 | + window->priv->queryFrameAttributes (attrib); |
| 2045 | |
| 2046 | /* Put the frame window "above" the client window |
| 2047 | * in the stack */ |


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://