2
* Copyright © 2012 Sam Spilsbury
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Canonical Ltd. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Canonical Ltd. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Authored by: Sam Spilsbury <smspillaz@gmail.com>
27
#include <boost/foreach.hpp>
28
#include <boost/weak_ptr.hpp>
29
#include <boost/bind.hpp>
30
#include "asyncserverwindow.h"
31
#include "configurerequestbuffer-impl.h"
34
#define foreach BOOST_FOREACH
37
namespace crb = compiz::window::configure_buffers;
38
namespace cw = compiz::window;
40
class crb::ConfigureRequestBuffer::Private
44
typedef crb::Lockable::Weak LockObserver;
46
Private (cw::AsyncServerWindow *asyncServerWindow,
47
cw::SyncServerWindow *syncServerWindow,
48
const crb::ConfigureRequestBuffer::LockFactory &lockFactory) :
50
wrapperChangeMask (0),
52
sendSyntheticConfigure (false),
54
asyncServerWindow (asyncServerWindow),
55
syncServerWindow (syncServerWindow),
56
lockFactory (lockFactory)
60
void dispatchConfigure (bool force = false);
62
XWindowChanges clientChanges;
63
unsigned int clientChangeMask;
65
XWindowChanges wrapperChanges;
66
unsigned int wrapperChangeMask;
68
XWindowChanges frameChanges;
69
unsigned int frameChangeMask;
71
bool sendSyntheticConfigure;
73
unsigned int lockCount;
75
cw::AsyncServerWindow *asyncServerWindow;
76
cw::SyncServerWindow *syncServerWindow;
78
crb::ConfigureRequestBuffer::LockFactory lockFactory;
79
std::vector <LockObserver> locks;
83
crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force)
85
const unsigned int allEventMasks = 0x7f;
86
bool immediate = frameChangeMask & (CWStackMode | CWSibling);
88
/* This is a stop-gap solution for not having a plugin API to
89
* query the window shape. Once we have that, we can safely
90
* remove these and require the queue to be unlocked when that
91
* happens. Its a separate unit of work for improving resize
92
* performance anyways.
94
immediate |= (frameChangeMask & (CWWidth | CWHeight | CWBorderWidth));
95
immediate |= (wrapperChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
96
immediate |= (clientChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
99
bool clientDispatch = (clientChangeMask & allEventMasks);
100
bool wrapperDispatch = (wrapperChangeMask & allEventMasks);
101
bool frameDispatch = (frameChangeMask & allEventMasks);
103
bool dispatch = !lockCount && (clientDispatch ||
106
sendSyntheticConfigure);
108
if (dispatch || immediate)
112
asyncServerWindow->requestConfigureOnFrame (frameChanges,
119
asyncServerWindow->requestConfigureOnWrapper (wrapperChanges,
121
wrapperChangeMask = 0;
126
asyncServerWindow->requestConfigureOnClient (clientChanges,
128
clientChangeMask = 0;
131
if (sendSyntheticConfigure)
133
asyncServerWindow->sendSyntheticConfigureNotify ();
134
sendSyntheticConfigure = false;
137
foreach (const LockObserver &lock, locks)
139
crb::Lockable::Ptr strongLock (lock.lock ());
141
/* We might be in a lock's destructor so check
142
* if this can really be re-locked, if not, its
143
* no big deal as the lock is going away anyways
152
crb::ConfigureRequestBuffer::freeze ()
156
assert (priv->lockCount <= priv->locks.size ());
160
crb::ConfigureRequestBuffer::release ()
162
assert (priv->lockCount);
166
priv->dispatchConfigure ();
171
void applyChangeToXWC (const XWindowChanges &from,
182
to.width = from.width;
185
to.height = from.height;
187
if (mask & CWBorderWidth)
188
to.border_width = from.border_width;
190
if (mask & CWSibling)
191
to.sibling = from.sibling;
193
if (mask & CWStackMode)
194
to.stack_mode = from.stack_mode;
199
crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc,
202
applyChangeToXWC (xwc, priv->clientChanges, mask);
203
priv->clientChangeMask |= mask;
205
priv->dispatchConfigure ();
209
crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc,
212
applyChangeToXWC (xwc, priv->wrapperChanges, mask);
213
priv->wrapperChangeMask |= mask;
215
priv->dispatchConfigure ();
219
crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc,
222
applyChangeToXWC (xwc, priv->frameChanges, mask);
223
priv->frameChangeMask |= mask;
225
priv->dispatchConfigure ();
229
crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify ()
231
priv->sendSyntheticConfigure = true;
233
priv->dispatchConfigure ();
237
crb::ConfigureRequestBuffer::obtainLock ()
239
crb::BufferLock::Ptr lock (priv->lockFactory (this));
241
priv->locks.push_back (crb::Lockable::Weak (lock));
249
bool isLock (const crb::Lockable::Weak &lockable,
250
crb::BufferLock *lock)
252
crb::Lockable::Ptr strongLockable (lockable.lock ());
254
/* Asserting that the lock did not go away without telling
256
assert (strongLockable.get ());
258
if (strongLockable.get () == lock)
266
crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock)
268
std::remove_if (priv->locks.begin (),
270
boost::bind (isLock, _1, lock));
273
bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib)
275
priv->dispatchConfigure (true);
276
return priv->syncServerWindow->queryAttributes (attrib);
279
bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib)
281
priv->dispatchConfigure (true);
282
return priv->syncServerWindow->queryFrameAttributes (attrib);
285
/* This is more or less of a stop-gap for the fact that
286
* when resizing window we re-query the window shape
287
* and apply that to the frame. That's a separate unit of
288
* work and should be dealt with separately. For now, force
289
* a release of the queue whenever we do that so that
290
* XShapeGetRectangles doesn't return an unexpected value
293
crb::ConfigureRequestBuffer::queryShapeRectangles (int kind,
297
priv->dispatchConfigure (true);
298
return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering);
301
void crb::ConfigureRequestBuffer::forceRelease ()
303
priv->dispatchConfigure (true);
306
crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
307
SyncServerWindow *syncServerWindow,
308
const crb::ConfigureRequestBuffer::LockFactory &factory) :
309
priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory))
313
compiz::window::configure_buffers::Buffer::Ptr
314
crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow,
315
SyncServerWindow *syncServerWindow,
316
const LockFactory &factory)
318
return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow,
323
class crb::ConfigureBufferLock::Private
327
Private (crb::CountedFreeze *freezable) :
328
freezable (freezable),
333
crb::CountedFreeze *freezable;
337
crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) :
338
priv (new crb::ConfigureBufferLock::Private (freezable))
342
crb::ConfigureBufferLock::~ConfigureBufferLock ()
348
crb::ConfigureBufferLock::lock ()
351
priv->freezable->freeze ();
357
crb::ConfigureBufferLock::release ()
360
priv->freezable->release ();