767
767
PrivateWindow::updateFrameWindow ()
770
unsigned int valueMask = CWX | CWY | CWWidth | CWHeight;
769
772
if (!serverFrame)
775
/* Flush any changes made to serverFrameGeometry or serverGeometry to the server
776
* since there is a race condition where geometries will go out-of-sync with
779
window->syncPosition ();
772
780
if (serverInput.left || serverInput.right || serverInput.top || serverInput.bottom)
774
int x, y, width, height;
775
782
int bw = serverGeometry.border () * 2;
777
x = serverGeometry.x () - serverInput.left;
778
y = serverGeometry.y () - serverInput.top;
779
width = serverGeometry.width () + serverInput.left + serverInput.right + bw;
780
height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;
784
xwc.x = serverGeometry.x () - serverInput.left;
785
xwc.y = serverGeometry.y () - serverInput.top;
786
xwc.width = serverGeometry.width () + serverInput.left + serverInput.right + bw;
787
xwc.height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;
783
790
height = serverInput.top + serverInput.bottom;
792
if (serverFrameGeometry.x () == xwc.x)
795
serverFrameGeometry.setX (xwc.x);
797
if (serverFrameGeometry.y () == xwc.y)
800
serverFrameGeometry.setY (xwc.y);
802
if (serverFrameGeometry.width () == xwc.width)
803
valueMask &= ~(CWWidth);
805
serverFrameGeometry.setWidth (xwc.width);
807
if (serverFrameGeometry.height () == xwc.height)
808
valueMask &= ~(CWHeight);
810
serverFrameGeometry.setHeight (xwc.height);
812
addPendingConfigure (xwc, valueMask);
785
815
/* Geometry is the same, so we're not going to get a ConfigureNotify
786
816
* event when the window is configured, which means that other plugins
787
817
* won't know that the client, frame and wrapper windows got shifted
788
818
* around (and might result in display corruption, eg in OpenGL */
789
if (geometry.x () - input.left == x &&
790
geometry.y () - input.top == y &&
791
geometry.width () + input.left + input.right + bw == width &&
792
geometry.height () + input.top + input.bottom + bw == height)
794
821
XConfigureEvent xev;
795
822
XWindowAttributes attrib;
870
int x, y, width, height;
871
896
int bw = serverGeometry.border () * 2;
873
x = serverGeometry.x ();
874
y = serverGeometry.y ();
875
width = serverGeometry.width () + bw;
876
height = serverGeometry.height () + bw;
898
xwc.x = serverGeometry.x ();
899
xwc.y = serverGeometry.y ();
900
xwc.width = serverGeometry.width () + bw;
901
xwc.height = serverGeometry.height () + bw;
906
if (serverFrameGeometry.x () == xwc.x)
909
serverFrameGeometry.setX (xwc.x);
911
if (serverFrameGeometry.y () == xwc.y)
914
serverFrameGeometry.setY (xwc.y);
916
if (serverFrameGeometry.width () == xwc.width)
917
valueMask &= ~(CWWidth);
919
serverFrameGeometry.setWidth (xwc.width);
921
if (serverFrameGeometry.height () == xwc.height)
922
valueMask &= ~(CWHeight);
924
serverFrameGeometry.setHeight (xwc.height);
926
addPendingConfigure (xwc, valueMask);
881
929
/* Geometry is the same, so we're not going to get a ConfigureNotify
882
930
* event when the window is configured, which means that other plugins
883
931
* won't know that the client, frame and wrapper windows got shifted
884
932
* around (and might result in display corruption, eg in OpenGL */
885
if (geometry.x () - input.left == x &&
886
geometry.y () - input.top == y &&
887
geometry.width () + input.left + input.right + bw == width &&
888
geometry.height () + input.top + input.bottom + bw == height)
890
935
XConfigureEvent xev;
891
936
XWindowAttributes attrib;
1876
1931
PrivateWindow::configure (XConfigureEvent *ce)
1933
unsigned int valueMask = 0;
1878
1935
if (priv->frame)
1938
/* remove configure event from pending configures */
1939
if (priv->geometry.x () != ce->x)
1942
if (priv->geometry.y () != ce->y)
1945
if (priv->geometry.width () != ce->width)
1946
valueMask |= CWWidth;
1948
if (priv->geometry.height () != ce->height)
1949
valueMask |= CWHeight;
1951
if (priv->geometry.border () != ce->border_width)
1952
valueMask |= CWBorderWidth;
1954
if (ROOTPARENT (window->prev) != ce->above)
1955
valueMask |= CWSibling | CWStackMode;
1881
1957
priv->attrib.override_redirect = ce->override_redirect;
1959
priv->frameGeometry.set (ce->x, ce->y, ce->width,
1960
ce->height, ce->border_width);
1883
1962
if (priv->syncWait)
1884
1963
priv->syncGeometry.set (ce->x, ce->y, ce->width, ce->height,
1885
1964
ce->border_width);
1904
1983
int x, y, width, height;
1905
1984
CompWindow *above;
1985
unsigned int valueMask = 0;
1986
bool handled = false;
1907
1988
if (!priv->frame)
1991
/* remove configure event from pending configures */
1992
if (priv->frameGeometry.x () != ce->x)
1995
if (priv->frameGeometry.y () != ce->y)
1998
if (priv->frameGeometry.width () != ce->width)
1999
valueMask |= CWWidth;
2001
if (priv->frameGeometry.height () != ce->height)
2002
valueMask |= CWHeight;
2004
if (priv->frameGeometry.border () != ce->border_width)
2005
valueMask |= CWBorderWidth;
2007
if (ROOTPARENT (window->prev) != ce->above)
2008
valueMask |= CWSibling | CWStackMode;
2010
for (std::list <XWCValueMask>::iterator it = pendingConfigures.begin ();
2011
it != pendingConfigures.end (); it++)
2013
XWCValueMask &xwcvm = (*it);
2016
if (xwcvm.second != valueMask)
2018
/* For stacking cases, if a client wants to raise or lower a window
2019
* then they don't need to specify CWSibling, so allow that to be
2020
* excluded in those cases */
2022
if (ce->above == ROOTPARENT (screen->windows ().back ()) ||
2025
if ((xwcvm.second & ~(CWSibling)) != valueMask)
2032
if (xwcvm.second & CWX && xwcvm.first.x != ce->x)
2035
if (xwcvm.second & CWY && xwcvm.first.y != ce->y)
2038
if (xwcvm.second & CWWidth && xwcvm.first.width != ce->width)
2041
if (xwcvm.second & CWHeight && xwcvm.first.height != ce->height)
2044
if (xwcvm.second & (CWStackMode | CWSibling) && xwcvm.first.sibling != ce->above)
2047
/* Matched ConfigureWindow request to ConfigureNotify event
2048
* remove it from the list */
2052
pendingConfigures.erase (it);
2058
compLogMessage ("core", CompLogLevelWarn, "unhandled ConfigureNotify on 0x%x!", serverFrame);
2059
compLogMessage ("core", CompLogLevelWarn, "this should never happen. you should"\
2060
"probably file a bug about this.");
2064
pendingConfigures.clear ();
1910
2068
/* subtract the input extents last sent to the
1911
2069
* server to calculate the client size and then
1912
2070
* re-sync the input extents and extents last
1917
2075
width = ce->width - priv->serverGeometry.border () * 2 - priv->serverInput.left - priv->serverInput.right;
1918
2076
height = ce->height - priv->serverGeometry.border () * 2 - priv->serverInput.top - priv->serverInput.bottom;
2078
/* set the frame geometry */
2079
priv->frameGeometry.set (ce->x, ce->y, ce->width, ce->height, ce->border_width);
1920
2082
if (priv->syncWait)
1922
2083
priv->syncGeometry.set (x, y, width, height, ce->border_width);
1926
if (ce->override_redirect)
1928
priv->serverGeometry.set (x, y, width, height, ce->border_width);
1931
2085
window->resize (x, y, width, height, ce->border_width);
1934
2087
if (priv->restack (ce->above))
1935
2088
priv->updatePassiveButtonGrabs ();
1964
priv->attrib.x += dx;
1965
priv->attrib.y += dy;
1967
priv->geometry.setX (priv->geometry.x () + dx);
1968
priv->geometry.setY (priv->geometry.y () + dy);
1970
priv->region.translate (dx, dy);
1971
priv->inputRegion.translate (dx, dy);
1972
if (!priv->frameRegion.isEmpty ())
1973
priv->frameRegion.translate (dx, dy);
1975
priv->invisible = WINDOW_INVISIBLE (priv);
1977
moveNotify (dx, dy, immediate);
2137
/* Don't allow window movement to overwrite working geometries
2138
* last received from the server if we know there are pending
2139
* ConfigureNotify events on this window. That's a clunky workaround
2140
* and a FIXME in any case, however, until we can break the API
2141
* and remove CompWindow::move, this will need to be the case */
2143
if (!priv->pendingConfigures.size ())
2145
priv->geometry.setX (priv->geometry.x () + dx);
2146
priv->geometry.setY (priv->geometry.y () + dy);
2147
priv->frameGeometry.setX (priv->frameGeometry.x () + dx);
2148
priv->frameGeometry.setY (priv->frameGeometry.y () + dy);
2150
priv->pendingPositionUpdates = true;
2152
priv->region.translate (dx, dy);
2153
priv->inputRegion.translate (dx, dy);
2154
if (!priv->frameRegion.isEmpty ())
2155
priv->frameRegion.translate (dx, dy);
2157
priv->invisible = WINDOW_INVISIBLE (priv);
2159
moveNotify (dx, dy, immediate);
2164
unsigned int valueMask = CWX | CWY;
2165
struct timeval tv, old;
2166
compLogMessage ("core", CompLogLevelDebug, "pending configure notifies on 0x%x,"\
2167
"moving window asyncrhonously!", (unsigned int) priv->serverId);
2169
old = priv->lastConfigureRequest;
2170
gettimeofday (&tv, NULL);
2172
xwc.x = priv->serverGeometry.x () + dx;
2173
xwc.y = priv->serverGeometry.y () + dy;
2175
configureXWindow (valueMask, &xwc);
2177
priv->lastConfigureRequest = old;
2179
/* FIXME: This is a hack to avoid performance regressions
2180
* and must be removed in 0.9.6 */
2181
if (tv.tv_usec - priv->lastConfigureRequest.tv_usec > 30000)
2183
compLogMessage ("core", CompLogLevelWarn, "failed to receive ConfigureNotify event from request at %i (now: %i)\n",
2184
priv->lastConfigureRequest.tv_usec, tv.tv_usec);
2185
priv->pendingConfigures.clear ();
2192
PrivateWindow::addPendingConfigure (XWindowChanges &xwc, unsigned int valueMask)
2194
CompOption::Vector options;
2195
CompOption::Value v;
2197
options.push_back (CompOption ("window", CompOption::TypeInt));
2199
options.back ().set (v);
2200
options.push_back (CompOption ("active", CompOption::TypeInt));
2202
options.back ().set (v);
2204
gettimeofday (&lastConfigureRequest, NULL);
2206
/* Notify other plugins that it is unsafe to change geometry or serverGeometry
2207
* FIXME: That API should not be accessible to plugins, this is a hack to avoid
2210
screen->handleCompizEvent ("core", "lock_position", options);
2212
priv->pendingConfigures.push_back (XWCValueMask (xwc, valueMask));
1982
2216
CompWindow::syncPosition ()
1984
priv->serverGeometry.setX (priv->geometry.x ());
1985
priv->serverGeometry.setY (priv->geometry.y ());
1987
XMoveWindow (screen->dpy (), ROOTPARENT (this),
1988
priv->serverGeometry.x () - priv->serverInput.left,
1989
priv->serverGeometry.y () - priv->serverInput.top);
1991
if (priv->serverFrame)
2218
unsigned int valueMask = CWX | CWY;
2221
if (priv->pendingPositionUpdates && priv->pendingConfigures.empty ())
1993
XMoveWindow (screen->dpy (), priv->wrapper,
1994
priv->serverInput.left, priv->serverInput.top);
1995
sendConfigureNotify ();
2223
if (priv->serverFrameGeometry.x () == priv->frameGeometry.x ())
2224
valueMask &= ~(CWX);
2225
if (priv->serverFrameGeometry.y () == priv->frameGeometry.y ())
2226
valueMask &= ~(CWY);
2228
/* Because CompWindow::move can update the geometry last
2229
* received from the server, we must indicate that no values
2230
* changed, because when the ConfigureNotify comes around
2231
* the values are going to be the same. That's obviously
2232
* broken behaviour and worthy of a FIXME, but requires
2233
* larger changes to the window movement system. */
2236
priv->addPendingConfigure (xwc, 0);
2238
priv->serverGeometry.setX (priv->geometry.x ());
2239
priv->serverGeometry.setY (priv->geometry.y ());
2240
priv->serverFrameGeometry.setX (priv->frameGeometry.x ());
2241
priv->serverFrameGeometry.setY (priv->frameGeometry.y ());
2243
xwc.x = priv->serverFrameGeometry.x ();
2244
xwc.y = priv->serverFrameGeometry.y ();
2246
XConfigureWindow (screen->dpy (), ROOTPARENT (this), valueMask, &xwc);
2248
if (priv->serverFrame)
2250
XMoveWindow (screen->dpy (), priv->wrapper,
2251
priv->serverInput.left, priv->serverInput.top);
2252
sendConfigureNotify ();
2255
priv->pendingPositionUpdates = false;
2709
3045
PrivateWindow::reconfigureXWindow (unsigned int valueMask,
2710
3046
XWindowChanges *xwc)
3048
unsigned int frameValueMask = valueMask;
3050
/* Immediately sync window position
3051
* if plugins were updating w->geometry () directly
3052
* in order to avoid a race condition */
3054
window->syncPosition ();
3056
/* Remove redundant bits */
3058
if (serverGeometry.x () == xwc->x)
3059
valueMask &= ~(CWX);
3061
if (serverGeometry.y () == xwc->y)
3062
valueMask &= ~(CWY);
3064
if (serverGeometry.width () == xwc->width)
3065
valueMask &= ~(CWWidth);
3067
if (serverGeometry.height () == xwc->height)
3068
valueMask &= ~(CWHeight);
3070
if (serverGeometry.border () == xwc->border_width)
3071
valueMask &= ~(CWBorderWidth);
3073
if (window->serverPrev && ROOTPARENT (window->serverPrev) == xwc->sibling)
3075
/* check if the sibling is also pending a restack,
3076
* if not, then setting this bit is useless */
3078
bool pendingRestack = false;
3080
foreach (XWCValueMask &xwcvm, window->serverPrev->priv->pendingConfigures)
3082
if (xwcvm.second & (CWSibling | CWStackMode))
3084
pendingRestack = true;
3089
if (!pendingRestack)
3090
valueMask &= ~(CWSibling | CWStackMode);
3093
if (valueMask & CWBorderWidth)
3094
serverGeometry.setBorder (xwc->border_width);
2712
3096
if (valueMask & CWX)
2713
3097
serverGeometry.setX (xwc->x);
2735
3116
if (xwc->sibling)
2737
CompWindow *w = screen->findWindow (id);
2739
screen->unhookServerWindow (w);
2740
screen->insertServerWindow (w, xwc->sibling);
3118
screen->unhookServerWindow (window);
3119
screen->insertServerWindow (window, xwc->sibling);
2744
3123
compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");
3126
if (serverFrameGeometry.x () == xwc->x - serverGeometry.border () - serverInput.left)
3127
frameValueMask &= ~(CWX);
3129
if (serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top)
3130
frameValueMask &= ~(CWY);
3132
if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
3133
+ serverInput.left + serverInput.right)
3134
frameValueMask &= ~(CWWidth);
3136
if (serverFrameGeometry.height () == xwc->height + serverGeometry.border () * 2
3137
+ serverInput.top + serverInput.bottom)
3138
frameValueMask &= ~(CWHeight);
3140
/* Can't set the border width of frame windows */
3141
frameValueMask &= ~(CWBorderWidth);
3143
if (frameValueMask & CWX)
3144
serverFrameGeometry.setX (xwc->x - serverGeometry.border () - serverInput.left);
3146
if (frameValueMask & CWY)
3147
serverFrameGeometry.setY (xwc->y -serverGeometry.border () - serverInput.top);
3149
if (frameValueMask & CWWidth)
3150
serverFrameGeometry.setWidth (xwc->width + serverGeometry.border () * 2
3151
+ serverInput.left + serverInput.right);
3153
if (frameValueMask & CWHeight)
3154
serverFrameGeometry.setHeight (xwc->height + serverGeometry.border () * 2
3155
+ serverInput.top + serverInput.bottom);
2747
3158
if (serverFrame)
2749
XWindowChanges wc = *xwc;
2751
wc.x -= serverInput.left - serverGeometry.border ();
2752
wc.y -= serverInput.top - serverGeometry.border ();
2753
wc.width += serverInput.left + serverInput.right + serverGeometry.border ();
2754
wc.height += serverInput.top + serverInput.bottom + serverGeometry.border ();
2756
XConfigureWindow (screen->dpy (), serverFrame, valueMask, &wc);
3162
XWindowChanges wc = *xwc;
3164
wc.x = serverFrameGeometry.x ();
3165
wc.y = serverFrameGeometry.y ();
3166
wc.width = serverFrameGeometry.width ();
3167
wc.height = serverFrameGeometry.height ();
3169
addPendingConfigure (wc, frameValueMask);
3171
XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc);
2757
3173
valueMask &= ~(CWSibling | CWStackMode);
2759
xwc->x = serverInput.left;
2760
xwc->y = serverInput.top;
2761
XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);
3177
xwc->x = serverInput.left;
3178
xwc->y = serverInput.top;
3179
XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);
2766
3185
window->sendConfigureNotify ();
2769
XConfigureWindow (screen->dpy (), id, valueMask, xwc);
3189
XConfigureWindow (screen->dpy (), id, valueMask, xwc);
3432
3848
* if serverPrev was recently restacked */
3433
3849
if (window->serverPrev)
3437
XLowerWindow (screen->dpy (), ROOTPARENT (window));
3851
bool pendingRestacks = false;
3853
foreach (XWCValueMask &xwcvm, sibling->priv->pendingConfigures)
3855
if (xwcvm.second & (CWSibling | CWStackMode))
3857
pendingRestacks = true;
3862
if (!sibling && window->serverPrev)
3865
unsigned int valueMask = CWStackMode;
3867
xwc.stack_mode = Below;
3869
/* Below with no sibling puts the window at the bottom
3871
XConfigureWindow (screen->dpy (), ROOTPARENT (window), valueMask, &xwc);
3874
priv->addPendingConfigure (xwc, CWStackMode);
3439
3876
/* Update the list of windows last sent to the server */
3440
3877
screen->unhookServerWindow (window);
3441
3878
screen->insertServerWindow (window, 0);
3443
3880
else if (sibling->priv->id != window->serverPrev->priv->id ||
3444
(window->serverPrev->serverPrev != window->serverPrev->prev ||
3445
window->serverPrev->serverNext != window->serverPrev->next))
3447
3883
mask |= CWSibling | CWStackMode;
5519
5954
dbg->overrideRedirectRestack (priv->id, aboveId);
5956
gettimeofday (&priv->lastConfigureRequest, NULL);
5521
5958
priv->attrib = wa;
5522
5959
priv->serverGeometry.set (priv->attrib.x, priv->attrib.y,
5523
5960
priv->attrib.width, priv->attrib.height,
5524
5961
priv->attrib.border_width);
5525
priv->syncGeometry.set (priv->attrib.x, priv->attrib.y,
5526
priv->attrib.width, priv->attrib.height,
5527
priv->attrib.border_width);
5528
priv->geometry.set (priv->attrib.x, priv->attrib.y,
5529
priv->attrib.width, priv->attrib.height,
5530
priv->attrib.border_width);
5962
priv->serverFrameGeometry = priv->frameGeometry = priv->syncGeometry
5963
= priv->geometry = priv->serverGeometry;
5532
5965
priv->width = priv->attrib.width + priv->attrib.border_width * 2;
5533
5966
priv->height = priv->attrib.height + priv->attrib.border_width * 2;
6281
6719
SubstructureNotifyMask | EnterWindowMask |
6282
6720
LeaveWindowMask;
6722
serverFrameGeometry = serverGeometry;
6724
XMoveResizeWindow (dpy, serverFrame, serverFrameGeometry.x (), serverFrameGeometry.y (),
6725
serverFrameGeometry.width (), serverFrameGeometry.height ());
6727
XSelectInput (dpy, screen->root (),
6728
SubstructureRedirectMask |
6729
SubstructureNotifyMask |
6730
StructureNotifyMask |
6731
PropertyChangeMask |
6284
6741
XChangeWindowAttributes (dpy, serverFrame, CWEventMask, &attr);
6285
6742
XChangeWindowAttributes (dpy, wrapper, CWEventMask, &attr);
6287
XSelectInput (dpy, screen->root (),
6288
SubstructureRedirectMask |
6289
SubstructureNotifyMask |
6290
StructureNotifyMask |
6291
PropertyChangeMask |
6301
6744
XUngrabServer (dpy);
6302
6745
XSync (dpy, false);
6304
XMoveResizeWindow (dpy, serverFrame, wa.x, wa.y,
6305
wa.width, wa.height);
6307
6747
window->windowNotify (CompWindowNotifyReparent);