Merge lp:~smspillaz/compiz-core/compiz-core.work_923683 into lp:compiz-core/0.9.5

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/compiz-core/compiz-core.work_923683
Merge into: lp:compiz-core/0.9.5
Diff against target: 1316 lines (+247/-559)
9 files modified
include/core/window.h (+2/-2)
plugins/composite/src/window.cpp (+16/-16)
plugins/decor/src/decor.cpp (+15/-15)
plugins/move/src/move.cpp (+1/-11)
plugins/opengl/src/window.cpp (+2/-2)
src/event.cpp (+2/-2)
src/privatewindow.h (+10/-12)
src/window.cpp (+195/-495)
src/windowgeometry.cpp (+4/-4)
To merge this branch: bzr merge lp:~smspillaz/compiz-core/compiz-core.work_923683
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Resubmitting
Alan Griffiths Needs Fixing
Review via email: mp+90906@code.launchpad.net

This proposal has been superseded by a proposal from 2012-02-06.

Description of the change

A lot of the work that I've wanted to do in order to properly fix this, but in a far more condensed form. (bug 923683). Proposing early so that ~vanvugt will see it :)

Always use the asynchronous codepaths in core. This commit changes the following:

 * CompWindow::move is now just a wrapper around CompWindow::configureXWindow
 * CompWindow::configureXWindow will always call through to moveNotify
 * moveNotify is only ever called pre-request to the server in the case of
   managed windows (SubstructureRedirectMask guaruntees they will end up in
   the right place) and post ConfigureNotify for override redirect windows
 * resizeNotify is always called post ConfigureNotify regardless of whether
   or not the window is managed or not
 * composite and opengl now use the geometry last sent to the server in order
   to compute display matrices and window positions as well as damage regions
 * decor now also does the above
 * const correctness in include/core/window.h
 * removed priv->width and priv->height , which was just redundant data used for
   window shading and honestly, is a ticking time bomb for future maintainers.
 * CompWindow::syncPosition is now deprecated and a no-op
 * Removed the majority of PrivateWindow::updateFrameWindow - this function had a lot
   of redundant code which PrivateWindow::reconfigureXWindow had anyways - the big work
   there was to send synthetic ConfigureNotify events to ourselves to notify about windows
   moving within frame windows that don't move themselves. Its safer to use reconfigureXWindow
   in this case and probably more sane too. We should look into removing the other update* functions.

Caveats:

 0) There are no tests yet
 1) Window movement performance will regress with this branch. This is *probably* due to the fact that for every slight movement, we send a full ConfigureWindow request to the X Server and it has to post back to us a full ConfigureNotify, for pretty much every pixel the window moves. In the case that we're not doing compositing thats fine, but in every other case its *super* chatty and largely unnecessary. This can probably be optimized a lot, but that will require work to gather up requests that we want to send to the X server - combine them (eg, merging the stack of requests based on the change mask and using the latest values where appropriate). Thats a lot of work and probably not appropriate in this branch
 2) The diff is a little big
 3) No tests
 4) Window shading is more than likely going to break again, mostly because I haven't tested it yet, but also because shading does some strange things and manipulated geometry values in strange ways
 5) No tests

Testing plan?

I would imagine here that the PendingConfigureRequests object can probably be split out into something testable, as can the logic to strip flags from frame window geometry and client window geometry updates.

We'll need to get CompRegion into a testable state though, which is probably easily done.

To post a comment you must log in.
2977. By Sam Spilsbury

Dump a bunch of debugging code

2978. By Sam Spilsbury

Dump more code nobody cares about

2979. By Sam Spilsbury

Dump more hacks

Revision history for this message
Sam Spilsbury (smspillaz) wrote :
Download full text (10.3 KiB)

The diff is big and scary, but its not too complicated. I'll explain each separate part

1 === modified file 'include/core/window.h'
2 --- include/core/window.h 2012-01-20 15:20:44 +0000
3 +++ include/core/window.h 2012-01-31 17:12:59 +0000
4 @@ -398,9 +398,9 @@
5
6 bool hasUnmapReference ();
7
8 - bool resize (XWindowAttributes);
9 + bool resize (const XWindowAttributes &);
10
11 - bool resize (Geometry);
12 + bool resize (const Geometry &);
13
14 bool resize (int x, int y, int width, int height,
15 int border = 0);

const correctness

31 int x1, x2, y1, y2;
32
33 - CompWindow::Geometry geom = priv->window->geometry ();
34 - CompWindowExtents output = priv->window->output ();
35 + const CompWindow::Geometry &geom = priv->window->serverGeometry ();
36 + const CompWindowExtents &output = priv->window->output ();

more const correctness

35 + const CompWindow::Geometry &geom = priv->window->serverGeometry ();
36 + const CompWindowExtents &output = priv->window->output ();

Lots of this - in paint code we want to use serverFoo because it was the last thing sent to the server. And this is always guarunteed to come back to us.

166 - unsigned int width = window->size ().width ();
167 - unsigned int height = window->size ().height ();
168 + unsigned int width = window->geometry ().width ();
169 + unsigned int height = window->geometry ().height ();

CompWindow::size was just returning CompSize (priv->width, priv->height) which was just redundant data which should be removed. Replaced it with geometry () for clarity

299 + void move (int dx, int dy, bool sync);
300 + bool resize (int dx, int dy, int dwidth, int dheight, int dborder);
301 + bool resize (const CompWindow::Geometry &g);
302 + bool resize (const XWindowAttributes &attrib);
303 +

Added PrivateWindow::move and PrivateWindow::resize - to be called whenever a new position / size comes back from the server. (cut'n'paste code from CompWindow::move and CompWindow::resize

335 -
336 - gettimeofday (&lastConfigureRequest, NULL);
337 - /* Flush any changes made to serverFrameGeometry or serverGeometry to the server
338 - * since there is a race condition where geometries will go out-of-sync with
339 - * window movement */
340 -
341 - window->syncPosition ();
342 -
343 - if (serverInput.left || serverInput.right || serverInput.top || serverInput.bottom)
344 - {
345 - int bw = serverGeometry.border () * 2;
346 -
347 - xwc.x = serverGeometry.x () - serverInput.left;
348 - xwc.y = serverGeometry.y () - serverInput.top;
349 - xwc.width = serverGeometry.width () + serverInput.left + serverInput.right + bw;
350 - if (shaded)
351 - xwc.height = serverInput.top + serverInput.bottom + bw;
352 - else
353 - xwc.height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;
354 -
355 - if (shaded)
356 - height = serverInput.top + serverInput.bottom;
357 -
358 - if (serverFrameGeometry.x () == xwc.x)
359 - valueMask &= ~(CWX);
360 - else
361 - serverFrameGeometry.setX (xwc.x);
362 -
*snip*
616 - XMoveResizeWindow (screen->dpy (), id, 0, 0,
617 - serverGeometry.width (), serverGeometry.height ());
618 - window->sendConfigureNotify ();
619 - window->windowNotify (CompWindowNotifyFrameUpdate...

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

824 -
825 - if (!pendingConfigures.pending ())
826 - {
827 - /* Tell plugins its ok to start doing stupid things again but
828 - * obviously FIXME */
829 - CompOption::Vector options;
830 - CompOption::Value v;
831 -
832 - options.push_back (CompOption ("window", CompOption::TypeInt));
833 - v.set ((int) id);
834 - options.back ().set (v);
835 - options.push_back (CompOption ("active", CompOption::TypeInt));
836 - v.set ((int) 0);
837 - options.back ().set (v);
838 -
839 - /* Notify other plugins that it is unsafe to change geometry or serverGeometry
840 - * FIXME: That API should not be accessible to plugins, this is a hack to avoid
841 - * breaking ABI */
842 -
843 - screen->handleCompizEvent ("core", "lock_position", options);
844 - }

DIE

924 -bool
925 -PrivateWindow::checkClear ()
926 -{
927 - if (pendingConfigures.pending ())
928 - {
929 - /* FIXME: This is a hack to avoid performance regressions
930 - * and must be removed in 0.9.6 */
931 - compLogMessage ("core", CompLogLevelWarn, "failed to receive ConfigureNotify event on 0x%x\n",
932 - id);
933 - pendingConfigures.dump ();
934 - pendingConfigures.clear ();
935 - }
936 -
937 - return false;
938 -}
939 -
940 void
941 compiz::X11::PendingEventQueue::add (PendingEvent::Ptr p)
942 {
943 @@ -2454,21 +2148,6 @@
944 mValueMask (valueMask),
945 mXwc (*xwc)
946 {
947 - CompOption::Vector options;
948 - CompOption::Value v;
949 -
950 - options.push_back (CompOption ("window", CompOption::TypeInt));
951 - v.set ((int) w);
952 - options.back ().set (v);
953 - options.push_back (CompOption ("active", CompOption::TypeInt));
954 - v.set ((int) 1);
955 - options.back ().set (v);
956 -
957 - /* Notify other plugins that it is unsafe to change geometry or serverGeometry
958 - * FIXME: That API should not be accessible to plugins, this is a hack to avoid
959 - * breaking ABI */
960 -
961 - screen->handleCompizEvent ("core", "lock_position", options);
962 }

DIE

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

GOOD IN THEORY:

* Most of the description sounds like steps in the right direction.

* Simplified: Replacing 559 lines of code with 247.

UNSURE ABOUT THE THEORY:

* "composite and opengl now use the geometry last sent to the server"
This should give maximum performance, sure, but what if (for some reason) the server rejects the configure request as being somehow invalid? Would you ever encounter that, like moving a window to an invalid location?
For stability and correctness (which should be the primary goal right now) don't we want "composite and opengl now use the geometry last received from the server"?

* Caveat #1 is not really a caveat. It's the right (intended) design. But if you want to see a (buggy) example of how to solve the chattiness look at the timer code here:
https://code.launchpad.net/~vanvugt/compiz-core/fix-764330-trunk/+merge/86497
This was slightly buggy though as it broke keyboatrd-initiated moves (incorrect pointer warp). Simple to fix, probably.

* Still no XFlush's to ensure XConfigureWindow happens immediately. Or are there adequate XSyncs already?

BAD IN THEORY:

* The diff is too big for a mere mortal (who hasn't worked on all the code before) to fully load into their mental interpreter and evaluate its theoretical correctness. Please read that sentence again; it's important.

GOOD IN PRACTICE:

* Window movement is smooth and predictable, but not really better than in oneiric.

BAD IN PRACTICE:

* The bug introduced is worse than the bug being fixed; Window contents offset from the frame/decorations whenever a window is created or maximized.

* All that code, but we still haven't reduced the lag below oneiric-levels. Still not as good as Gnome Shell.

CONCLUSION:

The theory is mostly good but there is at least one serious bug that needs fixing. We probably shouldn't risk 0.9.7.0 any more with large changes like this. We should aim to get this code into a later release when it's more stable, not 0.9.7.0.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote :
Download full text (3.2 KiB)

> GOOD IN THEORY:
>
> * Most of the description sounds like steps in the right direction.
>
> * Simplified: Replacing 559 lines of code with 247.
>
>
> UNSURE ABOUT THE THEORY:
>
> * "composite and opengl now use the geometry last sent to the server"
> This should give maximum performance, sure, but what if (for some reason) the
> server rejects the configure request as being somehow invalid? Would you ever
> encounter that, like moving a window to an invalid location?
> For stability and correctness (which should be the primary goal right now)
> don't we want "composite and opengl now use the geometry last received from
> the server"?

See http://tronche.com/gui/x/xlib/window/XConfigureWindow.html

Since we have SubstructureRedirectMask, it is guarunteed that any ConfigureWindow request we make on a child of the root window is guarunteed to end up in that position (hence the event tracker).

The only error cases I can think of is where you ask for a window to be of a size < 0 or > MAXSHORT. Ideally we should check for that case.

>
> * Caveat #1 is not really a caveat. It's the right (intended) design. But if
> you want to see a (buggy) example of how to solve the chattiness look at the
> timer code here:
> https://code.launchpad.net/~vanvugt/compiz-core/fix-764330-trunk/+merge/86497
> This was slightly buggy though as it broke keyboatrd-initiated moves
> (incorrect pointer warp). Simple to fix, probably.
>

There are some optimizations that can be done here - for example, if a window is grabbed, you can withold sending positions to the server until it is ungrabbed, or there is some other reason why you would want to do that. When that happens you can send it all at once.

> * Still no XFlush's to ensure XConfigureWindow happens immediately. Or are
> there adequate XSyncs already?

The GLib mainloop work introduced an XFlush as soon as we have finished dispatching the X event source.

>
>
> BAD IN THEORY:
>
> * The diff is too big for a mere mortal (who hasn't worked on all the code
> before) to fully load into their mental interpreter and evaluate its
> theoretical correctness. Please read that sentence again; it's important.

Indeed. The good thing is that its mostly all deletion and consolidation.

>
>
> GOOD IN PRACTICE:
>
> * Window movement is smooth and predictable, but not really better than in
> oneiric.
>
>
> BAD IN PRACTICE:
>
> * The bug introduced is worse than the bug being fixed; Window contents offset
> from the frame/decorations whenever a window is created or maximized.

Alright. I haven't seen this yet, but I have an idea of what might cause it. Will have a look into it when I get some time.

>
> * All that code, but we still haven't reduced the lag below oneiric-levels.
> Still not as good as Gnome Shell.

This will be fixed once the chattyness goes away. (as above). Watch your X.org CPU usage as you move windows - it skyrockets because at the moment we flood it with requests.

>
>
> CONCLUSION:
>
> The theory is mostly good but there is at least one serious bug that needs
> fixing. We probably shouldn't risk 0.9.7.0 any more with large changes like
> this. We should aim to get this code into a later r...

Read more...

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

OK, I'm still wading through the changes. But I feel like a rant...

1307 CompSize
1308 CompWindow::size () const
1309 {
1310 - return CompSize (priv->width + priv->geometry.border () * 2,
1311 - priv->height + priv->geometry.border () * 2);
1312 + return CompSize (priv->geometry.width () + priv->geometry.border () * 2,
1313 + priv->geometry.height () + priv->geometry.border () * 2);
1314 }

As a change this doesn't look too bad - but it ignores a horrid design!

1. Chained operations like "priv->geometry.width ()" imply too muck knowledge of the details of "priv".
   That is "priv->width ()" would reflect less coupling.

2. You're tracing the path "priv->geometry..." many times, which suggests that the logic belongs in "geometry".
   "return priv->geometry.size ()" or "return CompSize(priv->geometry)" would reflect better coherence.

So, assuming (because borders may be optional?) that there's an unambiguous mapping from CompWindow::Geometry:

a. Add a constructor to CompSize: "explicit CompSize(CompWindow::Geometry const& g) : mWidth(g.width () + g.border () * 2) ..."
b. Add an inline method "CompSize PrivateWindow::size () const { return CompSize(priv->geometry); }"
c. Rewrite the above as "CompSize CompWindow::size () const { "return priv->size ()"; }"

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

264 - /* been shaded */
265 + /* been shaded
266 if (w->priv->height == 0)
267 {
268 if (w->id () == priv->activeWindow)
269 w->moveInputFocusTo ();
270 - }
271 + }*/

Comments are not for storing old versions of the code - that's what we use bzr for. ;)

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

There's a lot of "<blah>.width () + <blah>.border () * 2" and "<blah>.height () + <blah>.border () * 2" around. Surely CompWindow::Geometry could have a "widthWithBorders" method - or maybe a free function?

I'm tempted by

template<Typename T>
inline int heightWithBorders(T const& blah) { return blah.height () + blah.border () * 2; }

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> OK, I'm still wading through the changes. But I feel like a rant...
>
> 1307 CompSize
> 1308 CompWindow::size () const
> 1309 {
> 1310 - return CompSize (priv->width + priv->geometry.border () * 2,
> 1311 - priv->height + priv->geometry.border () * 2);
> 1312 + return CompSize (priv->geometry.width () + priv->geometry.border ()
> * 2,
> 1313 + priv->geometry.height () + priv->geometry.border () * 2);
> 1314 }
>
> As a change this doesn't look too bad - but it ignores a horrid design!
>
> 1. Chained operations like "priv->geometry.width ()" imply too muck knowledge
> of the details of "priv".
> That is "priv->width ()" would reflect less coupling.

Probably, although priv is just a private member with implementation details, I don't really see this as a large design problem.

>
> 2. You're tracing the path "priv->geometry..." many times, which suggests that
> the logic belongs in "geometry".
> "return priv->geometry.size ()" or "return CompSize(priv->geometry)" would
> reflect better coherence.
>
> So, assuming (because borders may be optional?) that there's an unambiguous
> mapping from CompWindow::Geometry:
>
> a. Add a constructor to CompSize: "explicit CompSize(CompWindow::Geometry
> const& g) : mWidth(g.width () + g.border () * 2) ..."
> b. Add an inline method "CompSize PrivateWindow::size () const { return
> CompSize(priv->geometry); }"
> c. Rewrite the above as "CompSize CompWindow::size () const { "return
> priv->size ()"; }"

+1 for all three

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> 264 - /* been shaded */
> 265 + /* been shaded
> 266 if (w->priv->height == 0)
> 267 {
> 268 if (w->id () == priv->activeWindow)
> 269 w->moveInputFocusTo ();
> 270 - }
> 271 + }*/
>
> Comments are not for storing old versions of the code - that's what we use bzr
> for. ;)

Indeed, this is a small portion of the code and I'm not yet sure what to do with it. When I get around to revisiting this section (when I actually get time to look at this again, wanted to get it up for review early) I'll see what can be done.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> There's a lot of "<blah>.width () + <blah>.border () * 2" and "<blah>.height
> () + <blah>.border () * 2" around. Surely CompWindow::Geometry could have a
> "widthWithBorders" method - or maybe a free function?
>
> I'm tempted by
>
> template<Typename T>
> inline int heightWithBorders(T const& blah) { return blah.height () +
> blah.border () * 2; }

I'm not really sure ?

The complexity here comes from a legacy part of the X Server coming into play - a window could have fixed dimentions, but also specify a "border" which would be exclusive of the fixed dimentions, so you'd have to take this into account for all positioning operations (Xterm comes to mind here).

I definitely agree that geom.width () + geom.border () * 2 feels fragile and indeed, that has tripped me up many times before. Maybe a default parameter with a bitflag makes sense here, eg IncludeBorder , IncludeBorderFirst , IncludeBorderSecond (as it is on both sides)

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

I'll note that the above isn't *really* all that relevant to this merge though, but good things to keep in mind in any case. I'd rather not see the diff get any better except for adding tests.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Please resubmit for target branch lp:compiz-core (0.9.7)

review: Needs Resubmitting
2980. By Sam Spilsbury

Use serverGeometry for rectsToRegion so that there isn't a race condition
when we fetch the shape rectangles from the server and remove a mostly useless
section of configureXWindow

2981. By Sam Spilsbury

Remove commented code, use serverGeometry where appropriate

2982. By Sam Spilsbury

Remove XSynchronize

2983. By Sam Spilsbury

Merged from lp:compiz-core

2984. By Sam Spilsbury

Fix a memory leak in the decor plugin ... use shared_ptr etc

2985. By Sam Spilsbury

Don't spuriously re-create decorations when we don't need to. Also handle the
race between the decorator and the decor plugin when attempting to bind a pixmap
that hasn't been fully formed yet. (Should really use XSync barriers in future)

2986. By Sam Spilsbury

Merged from lp:compiz-core

2987. By Sam Spilsbury

Update PrivateWindow::isInvisible

2988. By Sam Spilsbury

Also adjust the client position inside the frame whenever the frame value mask
indicates that it might have moved.

2989. By Sam Spilsbury

Added a note for a fixme

2990. By Sam Spilsbury

Also send moveNotify for override redirect windows

2991. By Sam Spilsbury

Cleanup, fix removal of XSynchronize and detect error conditions

2992. By Sam Spilsbury

Fix silly typo

2993. By Sam Spilsbury

Merge lp:compiz-core

2994. By Sam Spilsbury

Use reference

2995. By Sam Spilsbury

Merge trunk

2996. By Sam Spilsbury

Removed a lot of width () / height () + border () * 2 sillyness, replace with
more sturdy abstraction

2997. By Sam Spilsbury

Fix LP #932520 - Update regions correctly when sending geometry updates

Use information last sent to server to determine window regions and shape
regions, update regions for resizing when we send the information to the server
as the shape rectangles will be correct anyways (even though it costs us a
round trip).

2998. By Sam Spilsbury

Replace instances of geometry with serverGeoemtry where appropriate

2999. By Sam Spilsbury

Merge lp:compiz-core

3000. By Sam Spilsbury

Fix typoo

3001. By Sam Spilsbury

Merge trunk

3002. By Sam Spilsbury

Remove abi breaks

3003. By Sam Spilsbury

Don't break abi

3004. By Sam Spilsbury

Use geometry last sent to server to calculate damage rects

3005. By Sam Spilsbury

Use server side rects for calculating clip regions

3006. By Sam Spilsbury

Use serverGeometry

3007. By Sam Spilsbury

Damage the screen when windows are resized

3008. By Sam Spilsbury

Style issue

3009. By Sam Spilsbury

Merged trunk and fixed a number of problems with resize synchronization

3010. By Sam Spilsbury

Send resize notification immediately for windows that aren't override redirect

3011. By Sam Spilsbury

Fix jumping around on resize because we were rebinding way too much at the wrong time.

Only rebind on paints.

3012. By Sam Spilsbury

Don't not update decorations when we're grabbed for resizing

3013. By Sam Spilsbury

Null check

3014. By Sam Spilsbury

resize: unconditionally finish the resize operation when releasing the button

3015. By Sam Spilsbury

Merge trunk

3016. By Sam Spilsbury

Don't send a moveNotify and resizeNotify if the window was moved and resized

3017. By Sam Spilsbury

Cleanup wobbly model update code

3018. By Sam Spilsbury

Ensure that override redirect windows get their regions set correctly.
Also they can't have input extents.

3019. By Sam Spilsbury

Force all override redirect windows to use geometry last received from
server. Force all managed windows to use geometry last sent.

The difference between geometry and server* is now moot and can be
removed in a future release

3020. By Sam Spilsbury

Clean some cruft

3021. By Sam Spilsbury

Update decoration matrix of shaded windows

3022. By Sam Spilsbury

Send a resizeNotify to indicate to plugins when map operations have completed

3023. By Sam Spilsbury

Merge lp:compiz-core

3024. By Sam Spilsbury

Don't notify plugins of unreparent in the right place

3025. By Sam Spilsbury

Merged lp:~vanvugt/compiz-core/compiz-core/fix-981703-properly

3026. By Sam Spilsbury

updateState is bitwise, so never clobber it

3027. By Sam Spilsbury

Base decision to send notifications to plugins on absolute position
changes

3028. By Sam Spilsbury

Don't set height = 0 if the window still has a pixmap

3029. By Sam Spilsbury

Remove some unnecessary cahgnes in the wobbly plugin

3030. By Sam Spilsbury

Merge lp:compiz-core

3031. By Sam Spilsbury

Now that geometry and serverGeometry both return the same thing, the changes
in client code don't make any sense to keep

3032. By Sam Spilsbury

Fix logic errors

3033. By Sam Spilsbury

!= 0 not necessary

3034. By Sam Spilsbury

Merge lp:compiz-core

Unmerged revisions

3034. By Sam Spilsbury

Merge lp:compiz-core

3033. By Sam Spilsbury

!= 0 not necessary

3032. By Sam Spilsbury

Fix logic errors

3031. By Sam Spilsbury

Now that geometry and serverGeometry both return the same thing, the changes
in client code don't make any sense to keep

3030. By Sam Spilsbury

Merge lp:compiz-core

3029. By Sam Spilsbury

Remove some unnecessary cahgnes in the wobbly plugin

3028. By Sam Spilsbury

Don't set height = 0 if the window still has a pixmap

3027. By Sam Spilsbury

Base decision to send notifications to plugins on absolute position
changes

3026. By Sam Spilsbury

updateState is bitwise, so never clobber it

3025. By Sam Spilsbury

Merged lp:~vanvugt/compiz-core/compiz-core/fix-981703-properly

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/core/window.h'
2--- include/core/window.h 2012-01-20 15:20:44 +0000
3+++ include/core/window.h 2012-01-31 17:22:24 +0000
4@@ -398,9 +398,9 @@
5
6 bool hasUnmapReference ();
7
8- bool resize (XWindowAttributes);
9+ bool resize (const XWindowAttributes &);
10
11- bool resize (Geometry);
12+ bool resize (const Geometry &);
13
14 bool resize (int x, int y, int width, int height,
15 int border = 0);
16
17=== modified file 'plugins/composite/src/window.cpp'
18--- plugins/composite/src/window.cpp 2012-01-16 09:50:28 +0000
19+++ plugins/composite/src/window.cpp 2012-01-31 17:22:24 +0000
20@@ -250,7 +250,7 @@
21
22 if (x2 > x1 && y2 > y1)
23 {
24- CompWindow::Geometry geom = priv->window->geometry ();
25+ CompWindow::Geometry geom = priv->window->serverGeometry ();
26
27 x1 += geom.x () + geom.border ();
28 y1 += geom.y () + geom.border ();
29@@ -272,20 +272,20 @@
30 {
31 int x1, x2, y1, y2;
32
33- CompWindow::Geometry geom = priv->window->geometry ();
34- CompWindowExtents output = priv->window->output ();
35+ const CompWindow::Geometry &geom = priv->window->serverGeometry ();
36+ const CompWindowExtents &output = priv->window->output ();
37
38 /* top */
39 x1 = -output.left - geom.border ();
40 y1 = -output.top - geom.border ();
41- x2 = priv->window->size ().width () + output.right - geom.border ();
42+ x2 = priv->window->serverGeometry ().width () + geom.border () + output.right;
43 y2 = -geom.border ();
44
45 if (x1 < x2 && y1 < y2)
46 addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
47
48 /* bottom */
49- y1 = priv->window->size ().height () - geom.border ();
50+ y1 = priv->window->serverGeometry ().height () + geom.border ();
51 y2 = y1 + output.bottom - geom.border ();
52
53 if (x1 < x2 && y1 < y2)
54@@ -295,13 +295,13 @@
55 x1 = -output.left - geom.border ();
56 y1 = -geom.border ();
57 x2 = -geom.border ();
58- y2 = priv->window->size ().height () - geom.border ();
59+ y2 = priv->window->serverGeometry ().height () - geom.border ();
60
61 if (x1 < x2 && y1 < y2)
62 addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
63
64 /* right */
65- x1 = priv->window->size ().width () - geom.border ();
66+ x1 = priv->window->serverGeometry ().width () - geom.border ();
67 x2 = x1 + output.right - geom.border ();
68
69 if (x1 < x2 && y1 < y2)
70@@ -322,7 +322,7 @@
71 x = rect.x ();
72 y = rect.y ();
73
74- CompWindow::Geometry geom = priv->window->geometry ();
75+ const CompWindow::Geometry &geom = priv->window->serverGeometry ();
76 x += geom.x () + geom.border ();
77 y += geom.y () + geom.border ();
78
79@@ -341,16 +341,16 @@
80 if (priv->window->shaded () || force ||
81 (priv->window->isViewable ()))
82 {
83- int border = priv->window->geometry ().border ();
84+ int border = priv->window->serverGeometry ().border ();
85
86 int x1 = -MAX (priv->window->output ().left,
87 priv->window->input ().left) - border;
88 int y1 = -MAX (priv->window->output ().top,
89 priv->window->input ().top) - border;
90- int x2 = priv->window->size ().width () +
91+ int x2 = priv->window->serverGeometry ().width () +
92 MAX (priv->window->output ().right,
93 priv->window->input ().right) ;
94- int y2 = priv->window->size ().height () +
95+ int y2 = priv->window->serverGeometry ().height () +
96 MAX (priv->window->output ().bottom,
97 priv->window->input ().bottom) ;
98 CompRect r (x1, y1, x2 - x1, y2 - y1);
99@@ -410,7 +410,7 @@
100
101 if (!w->damageRect (initial, CompRect (x, y, width, height)))
102 {
103- CompWindow::Geometry geom = w->priv->window->geometry ();
104+ CompWindow::Geometry geom = w->priv->window->serverGeometry ();
105
106 x += geom.x () + geom.border ();
107 y += geom.y () + geom.border ();
108@@ -622,14 +622,14 @@
109 {
110 int x, y, x1, x2, y1, y2;
111
112- x = window->geometry ().x ();
113- y = window->geometry ().y ();
114+ x = window->serverGeometry ().x ();
115+ y = window->serverGeometry ().y ();
116
117 x1 = x - window->output ().left - dx;
118 y1 = y - window->output ().top - dy;
119- x2 = x + window->size ().width () +
120+ x2 = x + window->serverGeometry ().width () +
121 window->output ().right - dx;
122- y2 = y + window->size ().height () +
123+ y2 = y + window->serverGeometry ().height () +
124 window->output ().bottom - dy;
125
126 cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
127
128=== modified file 'plugins/decor/src/decor.cpp'
129--- plugins/decor/src/decor.cpp 2012-01-21 19:05:23 +0000
130+++ plugins/decor/src/decor.cpp 2012-01-31 17:22:24 +0000
131@@ -91,7 +91,7 @@
132 void
133 DecorWindow::computeShadowRegion ()
134 {
135- shadowRegion = CompRegion (window->outputRect ());
136+ shadowRegion = CompRegion (window->serverOutputRect ());
137
138 if (window->type () == CompWindowTypeDropdownMenuMask ||
139 window->type () == CompWindowTypePopupMenuMask)
140@@ -142,11 +142,11 @@
141 if (window->type () == CompWindowTypeDropdownMenuMask &&
142 shadowRegion == CompRegion (window->outputRect ()))
143 {
144- CompRect area (window->outputRect ().x1 (),
145- window->outputRect ().y1 (),
146- window->outputRect ().width (),
147- window->inputRect ().y1 () -
148- window->outputRect ().y1 ());
149+ CompRect area (window->serverOutputRect ().x1 (),
150+ window->serverOutputRect ().y1 (),
151+ window->serverOutputRect ().width (),
152+ window->serverInputRect ().y1 () -
153+ window->serverOutputRect ().y1 ());
154
155 shadowRegion = shadowRegion.subtracted (area);
156 }
157@@ -1020,8 +1020,8 @@
158 for (i = 0; i < wd->nQuad; i++)
159 {
160 int x, y;
161- unsigned int width = window->size ().width ();
162- unsigned int height = window->size ().height ();
163+ unsigned int width = window->geometry ().width ();
164+ unsigned int height = window->geometry ().height ();
165
166 if (window->shaded ())
167 height = 0;
168@@ -1030,8 +1030,8 @@
169 &x1, &y1, &x2, &y2, &sx, &sy);
170
171 /* Translate by x and y points of this window */
172- x = window->geometry ().x ();
173- y = window->geometry ().y ();
174+ x = window->serverGeometry ().x ();
175+ y = window->serverGeometry ().y ();
176
177 wd->quad[i].box.x1 = x1 + x;
178 wd->quad[i].box.y1 = y1 + y;
179@@ -1059,8 +1059,8 @@
180 bool
181 DecorWindow::checkSize (Decoration *decoration)
182 {
183- return (decoration->minWidth <= (int) window->size ().width () &&
184- decoration->minHeight <= (int) window->size ().height ());
185+ return (decoration->minWidth <= (int) window->geometry ().width () &&
186+ decoration->minHeight <= (int) window->geometry ().height ());
187 }
188
189 /*
190@@ -2054,8 +2054,8 @@
191 {
192 int x, y;
193
194- x = window->geometry (). x ();
195- y = window->geometry (). y ();
196+ x = window->serverGeometry (). x ();
197+ y = window->serverGeometry (). y ();
198
199 region += frameRegion.translated (x - wd->decor->input.left,
200 y - wd->decor->input.top);
201@@ -2076,7 +2076,7 @@
202 void
203 DecorWindow::updateWindowRegions ()
204 {
205- const CompRect &input (window->inputRect ());
206+ const CompRect &input (window->serverInputRect ());
207
208 if (regions.size () != gWindow->textures ().size ())
209 regions.resize (gWindow->textures ().size ());
210
211=== modified file 'plugins/move/src/move.cpp'
212--- plugins/move/src/move.cpp 2012-01-20 14:42:53 +0000
213+++ plugins/move/src/move.cpp 2012-01-31 17:22:24 +0000
214@@ -487,18 +487,8 @@
215 w->move (wX + dx - w->geometry ().x (),
216 wY + dy - w->geometry ().y (), false);
217
218- if (ms->optionGetLazyPositioning () && ms->hasCompositing)
219- {
220- /* FIXME: This form of lazy positioning is broken and should
221- be replaced asap. Current code exists just to avoid a
222- major performance regression in the 0.5.2 release. */
223- w->serverGeometry ().setX (w->geometry ().x ());
224- w->serverGeometry ().setY (w->geometry ().y ());
225- }
226- else
227- {
228+ if (!ms->optionGetLazyPositioning ())
229 w->syncPosition ();
230- }
231
232 ms->x -= dx;
233 ms->y -= dy;
234
235=== modified file 'plugins/opengl/src/window.cpp'
236--- plugins/opengl/src/window.cpp 2011-03-11 12:15:30 +0000
237+++ plugins/opengl/src/window.cpp 2012-01-31 17:22:24 +0000
238@@ -76,7 +76,7 @@
239 void
240 PrivateGLWindow::setWindowMatrix ()
241 {
242- CompRect input (window->inputRect ());
243+ CompRect input (window->serverInputRect ());
244
245 if (textures.size () != matrices.size ())
246 matrices.resize (textures.size ());
247@@ -344,7 +344,7 @@
248 void
249 PrivateGLWindow::updateWindowRegions ()
250 {
251- CompRect input (window->inputRect ());
252+ CompRect input (window->serverInputRect ());
253
254 if (regions.size () != textures.size ())
255 regions.resize (textures.size ());
256
257=== modified file 'src/event.cpp'
258--- src/event.cpp 2012-01-19 18:12:31 +0000
259+++ src/event.cpp 2012-01-31 17:22:24 +0000
260@@ -1179,12 +1179,12 @@
261 w->priv->managed = true;
262 }
263
264- /* been shaded */
265+ /* been shaded
266 if (w->priv->height == 0)
267 {
268 if (w->id () == priv->activeWindow)
269 w->moveInputFocusTo ();
270- }
271+ }*/
272
273 w->map ();
274 }
275
276=== modified file 'src/privatewindow.h'
277--- src/privatewindow.h 2011-10-10 14:56:06 +0000
278+++ src/privatewindow.h 2012-01-31 17:22:24 +0000
279@@ -36,8 +36,8 @@
280
281 #define WINDOW_INVISIBLE(w) \
282 ((w)->attrib.map_state != IsViewable || \
283- (w)->attrib.x + (w)->width + (w)->output.right <= 0 || \
284- (w)->attrib.y + (w)->height + (w)->output.bottom <= 0 || \
285+ (w)->attrib.x + (w)->geometry.width () + (w)->output.right <= 0 || \
286+ (w)->attrib.y + (w)->geometry.height () + (w)->output.bottom <= 0 || \
287 (w)->attrib.x - (w)->output.left >= (int) screen->width () || \
288 (w)->attrib.y - (w)->output.top >= (int) screen->height () )
289
290@@ -171,6 +171,11 @@
291
292 bool handleSyncAlarm ();
293
294+ void move (int dx, int dy, bool sync);
295+ bool resize (int dx, int dy, int dwidth, int dheight, int dborder);
296+ bool resize (const CompWindow::Geometry &g);
297+ bool resize (const XWindowAttributes &attrib);
298+
299 void configure (XConfigureEvent *ce);
300
301 void configureFrame (XConfigureEvent *ce);
302@@ -211,8 +216,6 @@
303
304 void readIconHint ();
305
306- bool checkClear ();
307-
308 public:
309
310 PrivateWindow *priv;
311@@ -244,13 +247,8 @@
312 XSizeHints sizeHints;
313 XWMHints *hints;
314
315- struct timeval lastGeometryUpdate;
316- struct timeval lastConfigureRequest;
317-
318 bool inputHint;
319- bool alpha;
320- int width;
321- int height;
322+ bool alpha;;
323 CompRegion region;
324 CompRegion inputRegion;
325 CompRegion frameRegion;
326@@ -293,8 +291,6 @@
327 typedef std::pair <XWindowChanges, unsigned int> XWCValueMask;
328
329 compiz::X11::PendingEventQueue pendingConfigures;
330- CompTimer mClearCheckTimeout;
331- bool pendingPositionUpdates;
332
333 char *startupId;
334 char *resName;
335@@ -330,6 +326,8 @@
336
337 bool closeRequests;
338 Time lastCloseRequestTime;
339+
340+ bool nextMoveImmediate;
341 };
342
343 class CoreWindow
344
345=== modified file 'src/window.cpp'
346--- src/window.cpp 2012-01-25 09:20:47 +0000
347+++ src/window.cpp 2012-01-31 17:22:24 +0000
348@@ -798,292 +798,14 @@
349 if (!serverFrame)
350 return;
351
352-
353- gettimeofday (&lastConfigureRequest, NULL);
354- /* Flush any changes made to serverFrameGeometry or serverGeometry to the server
355- * since there is a race condition where geometries will go out-of-sync with
356- * window movement */
357-
358- window->syncPosition ();
359-
360- if (serverInput.left || serverInput.right || serverInput.top || serverInput.bottom)
361- {
362- int bw = serverGeometry.border () * 2;
363-
364- xwc.x = serverGeometry.x () - serverInput.left;
365- xwc.y = serverGeometry.y () - serverInput.top;
366- xwc.width = serverGeometry.width () + serverInput.left + serverInput.right + bw;
367- if (shaded)
368- xwc.height = serverInput.top + serverInput.bottom + bw;
369- else
370- xwc.height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;
371-
372- if (shaded)
373- height = serverInput.top + serverInput.bottom;
374-
375- if (serverFrameGeometry.x () == xwc.x)
376- valueMask &= ~(CWX);
377- else
378- serverFrameGeometry.setX (xwc.x);
379-
380- if (serverFrameGeometry.y () == xwc.y)
381- valueMask &= ~(CWY);
382- else
383- serverFrameGeometry.setY (xwc.y);
384-
385- if (serverFrameGeometry.width () == xwc.width)
386- valueMask &= ~(CWWidth);
387- else
388- serverFrameGeometry.setWidth (xwc.width);
389-
390- if (serverFrameGeometry.height () == xwc.height)
391- valueMask &= ~(CWHeight);
392- else
393- serverFrameGeometry.setHeight (xwc.height);
394-
395- /* Geometry is the same, so we're not going to get a ConfigureNotify
396- * event when the window is configured, which means that other plugins
397- * won't know that the client, frame and wrapper windows got shifted
398- * around (and might result in display corruption, eg in OpenGL */
399- if (valueMask == 0)
400- {
401- XConfigureEvent xev;
402- XWindowAttributes attrib;
403- unsigned int nchildren = 0;
404- Window rootRet = 0, parentRet = 0;
405- Window *children = NULL;
406-
407- xev.type = ConfigureNotify;
408- xev.event = screen->root ();
409- xev.window = priv->serverFrame;
410-
411- XGrabServer (screen->dpy ());
412-
413- if (XGetWindowAttributes (screen->dpy (), priv->serverFrame, &attrib))
414- {
415- xev.x = attrib.x;
416- xev.y = attrib.y;
417- xev.width = attrib.width;
418- xev.height = attrib.height;
419- xev.border_width = attrib.border_width;
420- xev.above = None;
421-
422- /* We need to ensure that the stacking order is
423- * based on the current server stacking order so
424- * find the sibling to this window's frame in the
425- * server side stack and stack above that */
426- XQueryTree (screen->dpy (), screen->root (), &rootRet, &parentRet, &children, &nchildren);
427-
428- if (nchildren)
429- {
430- for (unsigned int i = 0; i < nchildren; i++)
431- {
432- if (i + 1 == nchildren ||
433- children[i + 1] == ROOTPARENT (window))
434- {
435- xev.above = children[i];
436- break;
437- }
438- }
439- }
440-
441- if (children)
442- XFree (children);
443-
444- if (!xev.above)
445- xev.above = (window->serverPrev) ? ROOTPARENT (window->serverPrev) : None;
446-
447- xev.override_redirect = priv->attrib.override_redirect;
448-
449- }
450-
451- compiz::X11::PendingEvent::Ptr pc =
452- boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
453- new compiz::X11::PendingConfigureEvent (
454- screen->dpy (), serverFrame, valueMask, &xwc)));
455-
456- pendingConfigures.add (pc);
457- if (priv->mClearCheckTimeout.active ())
458- priv->mClearCheckTimeout.stop ();
459- priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
460- 2000, 2500);
461-
462- XSendEvent (screen->dpy (), screen->root (), false,
463- SubstructureNotifyMask, (XEvent *) &xev);
464-
465- XUngrabServer (screen->dpy ());
466- XSync (screen->dpy (), false);
467- }
468- else
469- {
470- compiz::X11::PendingEvent::Ptr pc =
471- boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
472- new compiz::X11::PendingConfigureEvent (
473- screen->dpy (), serverFrame, valueMask, &xwc)));
474-
475- pendingConfigures.add (pc);
476- if (priv->mClearCheckTimeout.active ())
477- priv->mClearCheckTimeout.stop ();
478- priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
479- 2000, 2500);
480- XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
481- }
482-
483- if (shaded)
484- {
485- XUnmapWindow (screen->dpy (), wrapper);
486- }
487- else
488- {
489- XMapWindow (screen->dpy (), wrapper);
490- XMoveResizeWindow (screen->dpy (), wrapper, serverInput.left, serverInput.top,
491- serverGeometry.width (), serverGeometry.height ());
492- }
493- XMoveResizeWindow (screen->dpy (), id, 0, 0,
494- serverGeometry.width (), serverGeometry.height ());
495- window->sendConfigureNotify ();
496- window->windowNotify (CompWindowNotifyFrameUpdate);
497- }
498- else
499- {
500- int bw = serverGeometry.border () * 2;
501-
502- xwc.x = serverGeometry.x ();
503- xwc.y = serverGeometry.y ();
504- xwc.width = serverGeometry.width () + bw;
505-
506- /* FIXME: It doesn't make much sense to allow undecorated windows to be
507- * shaded */
508- if (shaded)
509- xwc.height = bw;
510- else
511- xwc.height = serverGeometry.height () + bw;
512-
513- if (serverFrameGeometry.x () == xwc.x)
514- valueMask &= ~(CWX);
515- else
516- serverFrameGeometry.setX (xwc.x);
517-
518- if (serverFrameGeometry.y () == xwc.y)
519- valueMask &= ~(CWY);
520- else
521- serverFrameGeometry.setY (xwc.y);
522-
523- if (serverFrameGeometry.width () == xwc.width)
524- valueMask &= ~(CWWidth);
525- else
526- serverFrameGeometry.setWidth (xwc.width);
527-
528- if (serverFrameGeometry.height () == xwc.height)
529- valueMask &= ~(CWHeight);
530- else
531- serverFrameGeometry.setHeight (xwc.height);
532-
533- /* Geometry is the same, so we're not going to get a ConfigureNotify
534- * event when the window is configured, which means that other plugins
535- * won't know that the client, frame and wrapper windows got shifted
536- * around (and might result in display corruption, eg in OpenGL */
537- if (valueMask == 0)
538- {
539- XConfigureEvent xev;
540- XWindowAttributes attrib;
541- unsigned int nchildren = 0;
542- Window rootRet = 0, parentRet = 0;
543- Window *children = NULL;
544-
545- xev.type = ConfigureNotify;
546- xev.event = screen->root ();
547- xev.window = priv->serverFrame;
548-
549- XGrabServer (screen->dpy ());
550-
551- if (XGetWindowAttributes (screen->dpy (), priv->serverFrame, &attrib))
552- {
553- xev.x = attrib.x;
554- xev.y = attrib.y;
555- xev.width = attrib.width;
556- xev.height = attrib.height;
557- xev.border_width = attrib.border_width;
558- xev.above = None;
559-
560- /* We need to ensure that the stacking order is
561- * based on the current server stacking order so
562- * find the sibling to this window's frame in the
563- * server side stack and stack above that */
564- XQueryTree (screen->dpy (), screen->root (), &rootRet, &parentRet, &children, &nchildren);
565-
566- if (nchildren)
567- {
568- for (unsigned int i = 0; i < nchildren; i++)
569- {
570- if (i + 1 == nchildren ||
571- children[i + 1] == ROOTPARENT (window))
572- {
573- xev.above = children[i];
574- break;
575- }
576- }
577- }
578-
579- if (children)
580- XFree (children);
581-
582- if (!xev.above)
583- xev.above = (window->serverPrev) ? ROOTPARENT (window->serverPrev) : None;
584-
585- xev.override_redirect = priv->attrib.override_redirect;
586-
587- }
588-
589- compiz::X11::PendingEvent::Ptr pc =
590- boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
591- new compiz::X11::PendingConfigureEvent (
592- screen->dpy (), serverFrame, valueMask, &xwc)));
593-
594- pendingConfigures.add (pc);
595- if (priv->mClearCheckTimeout.active ())
596- priv->mClearCheckTimeout.stop ();
597- priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
598- 2000, 2500);
599-
600- XSendEvent (screen->dpy (), screen->root (), false,
601- SubstructureNotifyMask, (XEvent *) &xev);
602-
603- XUngrabServer (screen->dpy ());
604- XSync (screen->dpy (), false);
605- }
606- else
607- {
608- compiz::X11::PendingEvent::Ptr pc =
609- boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
610- new compiz::X11::PendingConfigureEvent (
611- screen->dpy (), serverFrame, valueMask, &xwc)));
612-
613- pendingConfigures.add (pc);
614- if (priv->mClearCheckTimeout.active ())
615- priv->mClearCheckTimeout.stop ();
616- priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
617- 2000, 2500);
618-
619- XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
620- }
621-
622- if (shaded)
623- {
624- XUnmapWindow (screen->dpy (), wrapper);
625- }
626- else
627- {
628- XMapWindow (screen->dpy (), wrapper);
629- XMoveResizeWindow (screen->dpy (), wrapper, 0, 0,
630- serverGeometry.width (), serverGeometry.height ());
631- }
632-
633- XMoveResizeWindow (screen->dpy (), id, 0, 0,
634- serverGeometry.width (), serverGeometry.height ());
635- window->sendConfigureNotify ();
636- window->windowNotify (CompWindowNotifyFrameUpdate);
637- }
638+ xwc.x = serverGeometry.x ();
639+ xwc.y = serverGeometry.y ();
640+ xwc.width = serverGeometry.width ();
641+ xwc.height = serverGeometry.height ();
642+ xwc.border_width = serverGeometry.border ();
643+
644+ window->configureXWindow (valueMask, &xwc);
645+ window->windowNotify (CompWindowNotifyFrameUpdate);
646 window->recalcActions ();
647 }
648
649@@ -1135,10 +857,10 @@
650 x1 = 0;
651 if (y1 < 0)
652 y1 = 0;
653- if (x2 > priv->width)
654- x2 = priv->width;
655- if (y2 > priv->height)
656- y2 = priv->height;
657+ if (x2 > priv->geometry.width ())
658+ x2 = priv->geometry.height ();
659+ if (y2 > priv->geometry.width ())
660+ y2 = priv->geometry.height ();
661
662 if (y1 < y2 && x1 < x2)
663 {
664@@ -1182,8 +904,8 @@
665
666 r.x = -priv->geometry.border ();
667 r.y = -priv->geometry.border ();
668- r.width = priv->width + priv->geometry.border ();
669- r.height = priv->height + priv->geometry.border ();
670+ r.width = priv->geometry.width () + priv->geometry.border ();
671+ r.height = priv->geometry.height () + priv->geometry.border ();
672
673 if (nBounding < 1)
674 {
675@@ -1716,7 +1438,7 @@
676 priv->attrib.map_state = IsUnmapped;
677 priv->invisible = true;
678
679- if (priv->shaded && priv->height)
680+ if (priv->shaded && priv->geometry.height ())
681 {
682 priv->updateFrameWindow ();
683 }
684@@ -1784,7 +1506,7 @@
685 }
686
687 bool
688-CompWindow::resize (XWindowAttributes attr)
689+CompWindow::resize (const XWindowAttributes &attr)
690 {
691 return resize (Geometry (attr.x, attr.y, attr.width, attr.height,
692 attr.border_width));
693@@ -1801,7 +1523,7 @@
694 }
695
696 bool
697-CompWindow::resize (CompWindow::Geometry gm)
698+PrivateWindow::resize (const CompWindow::Geometry &gm)
699 {
700 /* Input extents are now the last thing sent
701 * from the server. This might not work in some
702@@ -1818,12 +1540,8 @@
703 priv->geometry.height () != gm.height () ||
704 priv->geometry.border () != gm.border ())
705 {
706- int pw, ph;
707 int dx, dy, dwidth, dheight;
708
709- pw = gm.width () + gm.border () * 2;
710- ph = gm.height () + gm.border () * 2;
711-
712 dx = gm.x () - priv->geometry.x ();
713 dy = gm.y () - priv->geometry.y ();
714 dwidth = gm.width () - priv->geometry.width ();
715@@ -1833,37 +1551,60 @@
716 gm.width (), gm.height (),
717 gm.border ());
718
719- priv->width = pw;
720- priv->height = ph;
721+ if (priv->attrib.override_redirect)
722+ {
723+ priv->serverGeometry = priv->geometry;
724+ priv->serverFrameGeometry = priv->frameGeometry;
725+ }
726
727 if (priv->mapNum)
728 priv->updateRegion ();
729
730- resizeNotify (dx, dy, dwidth, dheight);
731+ window->resizeNotify (dx, dy, dwidth, dheight);
732
733 priv->invisible = WINDOW_INVISIBLE (priv);
734 }
735 else if (priv->geometry.x () != gm.x () || priv->geometry.y () != gm.y ())
736 {
737- int dx, dy;
738-
739- dx = gm.x () - priv->geometry.x ();
740- dy = gm.y () - priv->geometry.y ();
741-
742- priv->geometry.setX (gm.x ());
743- priv->geometry.setY (gm.y ());
744-
745- priv->region.translate (dx, dy);
746- priv->inputRegion.translate (dx, dy);
747- if (!priv->frameRegion.isEmpty ())
748- priv->frameRegion.translate (dx, dy);
749-
750- priv->invisible = WINDOW_INVISIBLE (priv);
751-
752- moveNotify (dx, dy, true);
753+ move (gm.x () - priv->geometry.x (),
754+ gm.y () - priv->geometry.y (), true);
755 }
756
757- updateFrameRegion ();
758+ window->updateFrameRegion ();
759+
760+ return true;
761+}
762+
763+bool
764+PrivateWindow::resize (const XWindowAttributes &attr)
765+{
766+ return resize (CompWindow::Geometry (attr.x, attr.y, attr.width, attr.height,
767+ attr.border_width));
768+}
769+
770+bool
771+PrivateWindow::resize (int x,
772+ int y,
773+ int width,
774+ int height,
775+ int border)
776+{
777+ return resize (CompWindow::Geometry (x, y, width, height, border));
778+}
779+
780+bool
781+CompWindow::resize (const CompWindow::Geometry &gm)
782+{
783+ XWindowChanges xwc = XWINDOWCHANGES_INIT;
784+ unsigned int valueMask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
785+
786+ xwc.x = gm.x ();
787+ xwc.y = gm.y ();
788+ xwc.width = gm.width ();
789+ xwc.height = gm.height ();
790+ xwc.border_width = gm.border ();
791+
792+ configureXWindow (valueMask, &xwc);
793
794 return true;
795 }
796@@ -2031,13 +1772,7 @@
797 ce->border_width);
798 else
799 {
800- if (ce->override_redirect)
801- {
802- priv->serverGeometry.set (ce->x, ce->y, ce->width, ce->height,
803- ce->border_width);
804- }
805-
806- window->resize (ce->x, ce->y, ce->width, ce->height, ce->border_width);
807+ resize (ce->x, ce->y, ce->width, ce->height, ce->border_width);
808 }
809
810 if (ce->event == screen->root ())
811@@ -2118,7 +1853,7 @@
812 if (priv->syncWait)
813 priv->syncGeometry.set (x, y, width, height, ce->border_width);
814 else
815- window->resize (x, y, width, height, ce->border_width);
816+ resize (x, y, width, height, ce->border_width);
817
818 if (priv->restack (ce->above))
819 priv->updatePassiveButtonGrabs ();
820@@ -2127,27 +1862,6 @@
821
822 if (above)
823 above->priv->updatePassiveButtonGrabs ();
824-
825- if (!pendingConfigures.pending ())
826- {
827- /* Tell plugins its ok to start doing stupid things again but
828- * obviously FIXME */
829- CompOption::Vector options;
830- CompOption::Value v;
831-
832- options.push_back (CompOption ("window", CompOption::TypeInt));
833- v.set ((int) id);
834- options.back ().set (v);
835- options.push_back (CompOption ("active", CompOption::TypeInt));
836- v.set ((int) 0);
837- options.back ().set (v);
838-
839- /* Notify other plugins that it is unsafe to change geometry or serverGeometry
840- * FIXME: That API should not be accessible to plugins, this is a hack to avoid
841- * breaking ABI */
842-
843- screen->handleCompizEvent ("core", "lock_position", options);
844- }
845 }
846
847 void
848@@ -2170,43 +1884,39 @@
849 {
850 if (dx || dy)
851 {
852- gettimeofday (&priv->lastGeometryUpdate, NULL);
853-
854- /* Don't allow window movement to overwrite working geometries
855- * last received from the server if we know there are pending
856- * ConfigureNotify events on this window. That's a clunky workaround
857- * and a FIXME in any case, however, until we can break the API
858- * and remove CompWindow::move, this will need to be the case */
859-
860- if (!priv->pendingConfigures.pending ())
861+ XWindowChanges xwc = XWINDOWCHANGES_INIT;
862+ unsigned int valueMask = CWX | CWY;
863+
864+ xwc.x = priv->serverGeometry.x () + dx;
865+ xwc.y = priv->serverGeometry.y () + dy;
866+
867+ priv->nextMoveImmediate = immediate;
868+
869+ configureXWindow (valueMask, &xwc);
870+ }
871+}
872+
873+void
874+PrivateWindow::move (int dx,
875+ int dy,
876+ bool immediate)
877+{
878+ if (dx || dy)
879+ {
880+ priv->geometry.setX (priv->geometry.x () + dx);
881+ priv->geometry.setY (priv->geometry.y () + dy);
882+ priv->frameGeometry.setX (priv->frameGeometry.x () + dx);
883+ priv->frameGeometry.setY (priv->frameGeometry.y () + dy);
884+
885+ if (priv->attrib.override_redirect)
886 {
887- priv->geometry.setX (priv->geometry.x () + dx);
888- priv->geometry.setY (priv->geometry.y () + dy);
889- priv->frameGeometry.setX (priv->frameGeometry.x () + dx);
890- priv->frameGeometry.setY (priv->frameGeometry.y () + dy);
891-
892- priv->pendingPositionUpdates = true;
893-
894+ priv->serverGeometry = priv->geometry;
895+ priv->serverFrameGeometry = priv->frameGeometry;
896 priv->region.translate (dx, dy);
897 priv->inputRegion.translate (dx, dy);
898 if (!priv->frameRegion.isEmpty ())
899 priv->frameRegion.translate (dx, dy);
900-
901- priv->invisible = WINDOW_INVISIBLE (priv);
902-
903- moveNotify (dx, dy, immediate);
904- }
905- else
906- {
907- XWindowChanges xwc = XWINDOWCHANGES_INIT;
908- unsigned int valueMask = CWX | CWY;
909- compLogMessage ("core", CompLogLevelDebug, "pending configure notifies on 0x%x, "\
910- "moving window asyncrhonously!", (unsigned int) priv->serverId);
911-
912- xwc.x = priv->serverGeometry.x () + dx;
913- xwc.y = priv->serverGeometry.y () + dy;
914-
915- configureXWindow (valueMask, &xwc);
916+ priv->window->moveNotify (dx, dy, immediate);
917 }
918 }
919 }
920@@ -2217,22 +1927,6 @@
921 return !mEvents.empty ();
922 }
923
924-bool
925-PrivateWindow::checkClear ()
926-{
927- if (pendingConfigures.pending ())
928- {
929- /* FIXME: This is a hack to avoid performance regressions
930- * and must be removed in 0.9.6 */
931- compLogMessage ("core", CompLogLevelWarn, "failed to receive ConfigureNotify event on 0x%x\n",
932- id);
933- pendingConfigures.dump ();
934- pendingConfigures.clear ();
935- }
936-
937- return false;
938-}
939-
940 void
941 compiz::X11::PendingEventQueue::add (PendingEvent::Ptr p)
942 {
943@@ -2454,21 +2148,6 @@
944 mValueMask (valueMask),
945 mXwc (*xwc)
946 {
947- CompOption::Vector options;
948- CompOption::Value v;
949-
950- options.push_back (CompOption ("window", CompOption::TypeInt));
951- v.set ((int) w);
952- options.back ().set (v);
953- options.push_back (CompOption ("active", CompOption::TypeInt));
954- v.set ((int) 1);
955- options.back ().set (v);
956-
957- /* Notify other plugins that it is unsafe to change geometry or serverGeometry
958- * FIXME: That API should not be accessible to plugins, this is a hack to avoid
959- * breaking ABI */
960-
961- screen->handleCompizEvent ("core", "lock_position", options);
962 }
963
964 compiz::X11::PendingConfigureEvent::~PendingConfigureEvent ()
965@@ -2478,57 +2157,6 @@
966 void
967 CompWindow::syncPosition ()
968 {
969- gettimeofday (&priv->lastConfigureRequest, NULL);
970-
971- unsigned int valueMask = CWX | CWY;
972- XWindowChanges xwc = XWINDOWCHANGES_INIT;
973-
974- if (priv->pendingPositionUpdates && !priv->pendingConfigures.pending ())
975- {
976- if (priv->serverFrameGeometry.x () == priv->frameGeometry.x ())
977- valueMask &= ~(CWX);
978- if (priv->serverFrameGeometry.y () == priv->frameGeometry.y ())
979- valueMask &= ~(CWY);
980-
981- /* Because CompWindow::move can update the geometry last
982- * received from the server, we must indicate that no values
983- * changed, because when the ConfigureNotify comes around
984- * the values are going to be the same. That's obviously
985- * broken behaviour and worthy of a FIXME, but requires
986- * larger changes to the window movement system. */
987- if (valueMask)
988- {
989- priv->serverGeometry.setX (priv->geometry.x ());
990- priv->serverGeometry.setY (priv->geometry.y ());
991- priv->serverFrameGeometry.setX (priv->frameGeometry.x ());
992- priv->serverFrameGeometry.setY (priv->frameGeometry.y ());
993-
994- xwc.x = priv->serverFrameGeometry.x ();
995- xwc.y = priv->serverFrameGeometry.y ();
996-
997- compiz::X11::PendingEvent::Ptr pc =
998- boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
999- new compiz::X11::PendingConfigureEvent (
1000- screen->dpy (), priv->serverFrame, 0, &xwc)));
1001-
1002- priv->pendingConfigures.add (pc);
1003-
1004- /* Got 3 seconds to get its stuff together */
1005- if (priv->mClearCheckTimeout.active ())
1006- priv->mClearCheckTimeout.stop ();
1007- priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
1008- 2000, 2500);
1009- XConfigureWindow (screen->dpy (), ROOTPARENT (this), valueMask, &xwc);
1010-
1011- if (priv->serverFrame)
1012- {
1013- XMoveWindow (screen->dpy (), priv->wrapper,
1014- priv->serverInput.left, priv->serverInput.top);
1015- sendConfigureNotify ();
1016- }
1017- }
1018- priv->pendingPositionUpdates = false;
1019- }
1020 }
1021
1022 bool
1023@@ -3350,6 +2978,12 @@
1024
1025 /* Remove redundant bits */
1026
1027+ xwc->x = valueMask & CWX ? xwc->x : serverGeometry.x ();
1028+ xwc->y = valueMask & CWY ? xwc->y : serverGeometry.y ();
1029+ xwc->width = valueMask & CWWidth ? xwc->width : serverGeometry.width ();
1030+ xwc->height = valueMask & CWHeight ? xwc->height : serverGeometry.height ();
1031+ xwc->border_width = valueMask & CWBorderWidth ? xwc->border_width : serverGeometry.border ();
1032+
1033 if (valueMask & CWX && serverGeometry.x () == xwc->x)
1034 valueMask &= ~(CWX);
1035
1036@@ -3416,18 +3050,15 @@
1037 compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");
1038 }
1039
1040- frameValueMask = valueMask;
1041+ frameValueMask = CWX | CWY | CWWidth | CWHeight | (valueMask & (CWStackMode | CWSibling));
1042
1043- if (frameValueMask & CWX &&
1044- serverFrameGeometry.x () == xwc->x - serverGeometry.border () - serverInput.left)
1045+ if (serverFrameGeometry.x () == xwc->x - serverGeometry.border () - serverInput.left)
1046 frameValueMask &= ~(CWX);
1047
1048- if (frameValueMask & CWY &&
1049- serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top)
1050+ if (serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top)
1051 frameValueMask &= ~(CWY);
1052
1053- if (frameValueMask & CWWidth &&
1054- serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
1055+ if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
1056 + serverInput.left + serverInput.right)
1057 frameValueMask &= ~(CWWidth);
1058
1059@@ -3437,15 +3068,13 @@
1060
1061 if (shaded)
1062 {
1063- if (frameValueMask & CWHeight &&
1064- serverFrameGeometry.height () == serverGeometry.border () * 2
1065+ if (serverFrameGeometry.height () == serverGeometry.border () * 2
1066 + serverInput.top + serverInput.bottom)
1067 frameValueMask &= ~(CWHeight);
1068 }
1069 else
1070 {
1071- if (frameValueMask & CWHeight &&
1072- serverFrameGeometry.height () == xwc->height + serverGeometry.border () * 2
1073+ if (serverFrameGeometry.height () == xwc->height + serverGeometry.border () * 2
1074 + serverInput.top + serverInput.bottom)
1075 frameValueMask &= ~(CWHeight);
1076 }
1077@@ -3479,8 +3108,6 @@
1078
1079 if (serverFrame)
1080 {
1081- gettimeofday (&lastConfigureRequest, NULL);
1082-
1083 if (frameValueMask)
1084 {
1085 XWindowChanges wc = *xwc;
1086@@ -3496,13 +3123,83 @@
1087 screen->dpy (), priv->serverFrame, frameValueMask, &wc)));
1088
1089 pendingConfigures.add (pc);
1090- if (priv->mClearCheckTimeout.active ())
1091- priv->mClearCheckTimeout.stop ();
1092- priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
1093- 2000, 2500);
1094
1095 XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc);
1096 }
1097+ else
1098+ {
1099+ /* Craft an XConfigureWindow event to send to the frame window */
1100+ XConfigureEvent xev;
1101+ XWindowAttributes attrib;
1102+ unsigned int nchildren = 0;
1103+ Window rootRet = 0, parentRet = 0;
1104+ Window *children = NULL;
1105+
1106+ XWindowChanges wc = *xwc;
1107+
1108+ wc.x = serverFrameGeometry.x ();
1109+ wc.y = serverFrameGeometry.y ();
1110+ wc.width = serverFrameGeometry.width ();
1111+ wc.height = serverFrameGeometry.height ();
1112+
1113+ xev.type = ConfigureNotify;
1114+ xev.event = screen->root ();
1115+ xev.window = priv->serverFrame;
1116+
1117+ XGrabServer (screen->dpy ());
1118+
1119+ if (XGetWindowAttributes (screen->dpy (), priv->serverFrame, &attrib))
1120+ {
1121+ xev.x = attrib.x;
1122+ xev.y = attrib.y;
1123+ xev.width = attrib.width;
1124+ xev.height = attrib.height;
1125+ xev.border_width = attrib.border_width;
1126+ xev.above = None;
1127+
1128+ /* We need to ensure that the stacking order is
1129+ * based on the current server stacking order so
1130+ * find the sibling to this window's frame in the
1131+ * server side stack and stack above that */
1132+ XQueryTree (screen->dpy (), screen->root (), &rootRet, &parentRet, &children, &nchildren);
1133+
1134+ if (nchildren)
1135+ {
1136+ for (unsigned int i = 0; i < nchildren; i++)
1137+ {
1138+ if (i + 1 == nchildren ||
1139+ children[i + 1] == ROOTPARENT (window))
1140+ {
1141+ xev.above = children[i];
1142+ break;
1143+ }
1144+ }
1145+ }
1146+
1147+ if (children)
1148+ XFree (children);
1149+
1150+ if (!xev.above)
1151+ xev.above = (window->serverPrev) ? ROOTPARENT (window->serverPrev) : None;
1152+
1153+ xev.override_redirect = priv->attrib.override_redirect;
1154+
1155+ }
1156+
1157+ compiz::X11::PendingEvent::Ptr pc =
1158+ boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
1159+ new compiz::X11::PendingConfigureEvent (
1160+ screen->dpy (), serverFrame, valueMask, &wc)));
1161+
1162+ pendingConfigures.add (pc);
1163+
1164+ XSendEvent (screen->dpy (), screen->root (), false,
1165+ SubstructureNotifyMask, (XEvent *) &xev);
1166+
1167+ XUngrabServer (screen->dpy ());
1168+ XSync (screen->dpy (), false);
1169+ }
1170+
1171 valueMask &= ~(CWSibling | CWStackMode);
1172
1173 if (valueMask)
1174@@ -3692,6 +3389,9 @@
1175 CompWindow::configureXWindow (unsigned int valueMask,
1176 XWindowChanges *xwc)
1177 {
1178+ int dx = valueMask & CWX ? xwc->x - priv->serverGeometry.x () : 0;
1179+ int dy = valueMask & CWY ? xwc->y - priv->serverGeometry.y () : 0;
1180+
1181 if (priv->managed && (valueMask & (CWSibling | CWStackMode)))
1182 {
1183 CompWindowList transients;
1184@@ -3746,6 +3446,17 @@
1185 {
1186 priv->reconfigureXWindow (valueMask, xwc);
1187 }
1188+
1189+ if (!overrideRedirect () && (dx || dy))
1190+ {
1191+ priv->region.translate (dx, dy);
1192+ priv->inputRegion.translate (dx, dy);
1193+ if (!priv->frameRegion.isEmpty ())
1194+ priv->frameRegion.translate (dx, dy);
1195+ moveNotify (dx, dy, priv->nextMoveImmediate);
1196+
1197+ priv->nextMoveImmediate = true;
1198+ }
1199 }
1200
1201 int
1202@@ -4297,10 +4008,6 @@
1203 screen->dpy (), serverFrame, valueMask, &lxwc)));
1204
1205 pendingConfigures.add (pc);
1206- if (priv->mClearCheckTimeout.active ())
1207- priv->mClearCheckTimeout.stop ();
1208- priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
1209- 2000, 2500);
1210 }
1211
1212 /* Below with no sibling puts the window at the bottom
1213@@ -5472,7 +5179,7 @@
1214 m = priv->geometry.x () + offX;
1215 if (m - priv->input.left < (int) s->width () - vWidth)
1216 rv.setX (offX + vWidth);
1217- else if (m + priv->width + priv->input.right > vWidth)
1218+ else if (m + priv->geometry.width () + priv->input.right > vWidth)
1219 rv.setX (offX - vWidth);
1220 else
1221 rv.setX (offX);
1222@@ -5487,7 +5194,7 @@
1223 m = priv->geometry.y () + offY;
1224 if (m - priv->input.top < (int) s->height () - vHeight)
1225 rv.setY (offY + vHeight);
1226- else if (m + priv->height + priv->input.bottom > vHeight)
1227+ else if (m + priv->geometry.height () + priv->input.bottom > vHeight)
1228 rv.setY (offY - vHeight);
1229 else
1230 rv.setY (offY);
1231@@ -6063,7 +5770,7 @@
1232
1233 if (m - priv->output.left < (int) screen->width () - vWidth)
1234 wx = tx + vWidth;
1235- else if (m + priv->width + priv->output.right > vWidth)
1236+ else if (m + priv->geometry.width () + priv->output.right > vWidth)
1237 wx = tx - vWidth;
1238 }
1239
1240@@ -6073,7 +5780,7 @@
1241
1242 if (m - priv->output.top < (int) screen->height () - vHeight)
1243 wy = ty + vHeight;
1244- else if (m + priv->height + priv->output.bottom > vHeight)
1245+ else if (m + priv->geometry.height () + priv->output.bottom > vHeight)
1246 wy = ty - vHeight;
1247 }
1248
1249@@ -6299,9 +6006,6 @@
1250 priv->serverFrameGeometry = priv->frameGeometry = priv->syncGeometry
1251 = priv->geometry = priv->serverGeometry;
1252
1253- priv->width = priv->attrib.width + priv->attrib.border_width * 2;
1254- priv->height = priv->attrib.height + priv->attrib.border_width * 2;
1255-
1256 priv->sizeHints.flags = 0;
1257
1258 priv->recalcNormalHints ();
1259@@ -6323,8 +6027,7 @@
1260
1261 if (priv->attrib.c_class != InputOnly)
1262 {
1263- priv->region = CompRegion (priv->attrib.x, priv->attrib.y,
1264- priv->width, priv->height);
1265+ priv->region = CompRegion (static_cast <CompRect> (priv->serverGeometry));
1266 priv->inputRegion = priv->region;
1267
1268 /* need to check for DisplayModal state on all windows */
1269@@ -6569,8 +6272,6 @@
1270 hints (NULL),
1271 inputHint (true),
1272 alpha (false),
1273- width (0),
1274- height (0),
1275 region (),
1276 wmType (0),
1277 type (CompWindowTypeUnknownMask),
1278@@ -6605,7 +6306,6 @@
1279 pendingUnmaps (0),
1280 pendingMaps (0),
1281 pendingConfigures (screen->dpy ()),
1282- pendingPositionUpdates (false),
1283
1284 startupId (0),
1285 resName (0),
1286
1287=== modified file 'src/windowgeometry.cpp'
1288--- src/windowgeometry.cpp 2012-01-23 05:44:19 +0000
1289+++ src/windowgeometry.cpp 2012-01-31 17:22:24 +0000
1290@@ -61,22 +61,22 @@
1291 int
1292 CompWindow::width () const
1293 {
1294- return priv->width +
1295+ return priv->geometry.width () +
1296 priv->geometry.border () * 2;
1297 }
1298
1299 int
1300 CompWindow::height () const
1301 {
1302- return priv->height +
1303+ return priv->geometry.height () +
1304 priv->geometry.border () * 2;;
1305 }
1306
1307 CompSize
1308 CompWindow::size () const
1309 {
1310- return CompSize (priv->width + priv->geometry.border () * 2,
1311- priv->height + priv->geometry.border () * 2);
1312+ return CompSize (priv->geometry.width () + priv->geometry.border () * 2,
1313+ priv->geometry.height () + priv->geometry.border () * 2);
1314 }
1315
1316 int

Subscribers

People subscribed via source and target branches