Merge lp:~compiz-team/compiz-core/compiz-core.fix_860304 into lp:compiz-core/0.9.5

Proposed by Sam Spilsbury
Status: Merged
Merged at revision: 2842
Proposed branch: lp:~compiz-team/compiz-core/compiz-core.fix_860304
Merge into: lp:compiz-core/0.9.5
Diff against target: 1020 lines (+538/-117)
6 files modified
plugins/move/src/move.cpp (+28/-1)
plugins/move/src/move.h (+7/-1)
src/privatewindow.h (+9/-0)
src/screen.cpp (+14/-7)
src/stackdebugger.cpp (+4/-0)
src/window.cpp (+476/-108)
To merge this branch: bzr merge lp:~compiz-team/compiz-core/compiz-core.fix_860304
Reviewer Review Type Date Requested Status
Robert Carr (community) Approve
Review via email: mp+77156@code.launchpad.net

Description of the change

To post a comment you must log in.
Revision history for this message
Robert Carr (robertcarr) wrote :

+1

review: Approve
Revision history for this message
David Barth (dbarth) wrote :

The code changes are massive: is that some parts that you've taken from elsewhere and can be trusted to be well tested already? Or is it all brand new code? The worst would be to add crashers.

2840. By Sam Spilsbury

Fix typoes

2841. By Sam Spilsbury

Added a workaround to ensure that we don't end up with stale configure requests
causing windows to always be moved asynchronously (slow)

Revision history for this message
Carey Underwood (cwillu) wrote :

Something in this appears to have made moving windows quite slow, and frequently preventing the window (or any other windows for that matter) from updating while the mouse is still moving. Enabling sync to vrefresh makes it much worse. Disabling the unityshell plugin temporarily immediately restores silky smooth behaviour.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/move/src/move.cpp'
2--- plugins/move/src/move.cpp 2011-06-23 03:22:47 +0000
3+++ plugins/move/src/move.cpp 2011-09-27 15:45:28 +0000
4@@ -488,7 +488,8 @@
5 wY + dy - w->geometry ().y (), false);
6
7 if (ms->optionGetLazyPositioning () &&
8- MoveScreen::get (screen)->hasCompositing)
9+ ms->hasCompositing &&
10+ !MoveWindow::get (ms->w)->mLocked)
11 {
12 /* FIXME: This form of lazy positioning is broken and should
13 be replaced asap. Current code exists just to avoid a
14@@ -507,6 +508,32 @@
15 }
16 }
17
18+/* FIXME: This is a hack to prevent a race condition
19+ * when core is processing ConfigureNotify events. It
20+ * MUST be removed after 0.9.6 when we can break ABI
21+ * and do lazy positioning correctly ! */
22+
23+void
24+MoveScreen::handleCompizEvent (const char *plugin, const char *event, CompOption::Vector &options)
25+{
26+ if (w)
27+ {
28+ if (std::string ("core") == std::string (plugin))
29+ {
30+ if (std::string ("lock_position") == std::string (event))
31+ {
32+ Window xid = CompOption::getIntOptionNamed (options, "window", 0);
33+ int lock = CompOption::getIntOptionNamed (options, "active", 0);
34+
35+ if (xid == w->id ())
36+ MoveWindow::get (w)->mLocked = lock ? true : false;
37+ }
38+ }
39+ }
40+
41+ screen->handleCompizEvent (plugin, event, options);
42+}
43+
44 void
45 MoveScreen::handleEvent (XEvent *event)
46 {
47
48=== modified file 'plugins/move/src/move.h'
49--- plugins/move/src/move.h 2009-12-25 19:49:23 +0000
50+++ plugins/move/src/move.h 2011-09-27 15:45:28 +0000
51@@ -61,6 +61,9 @@
52 void updateOpacity ();
53
54 void handleEvent (XEvent *);
55+ void handleCompizEvent (const char *plugin,
56+ const char *event,
57+ CompOption::Vector &options);
58
59 CompWindow *w;
60 int savedX;
61@@ -98,7 +101,8 @@
62 PluginClassHandler<MoveWindow,CompWindow> (window),
63 window (window),
64 gWindow (GLWindow::get (window)),
65- cWindow (CompositeWindow::get (window))
66+ cWindow (CompositeWindow::get (window)),
67+ mLocked (false)
68 {
69 if (gWindow)
70 GLWindowInterface::setHandler (gWindow, false);
71@@ -110,6 +114,8 @@
72 CompWindow *window;
73 GLWindow *gWindow;
74 CompositeWindow *cWindow;
75+
76+ bool mLocked;
77 };
78
79 #define MOVE_SCREEN(s) \
80
81=== modified file 'src/privatewindow.h'
82--- src/privatewindow.h 2011-09-25 04:16:18 +0000
83+++ src/privatewindow.h 2011-09-27 15:45:28 +0000
84@@ -211,6 +211,8 @@
85
86 void readIconHint ();
87
88+ void addPendingConfigure (XWindowChanges &, unsigned int);
89+
90 public:
91
92 PrivateWindow *priv;
93@@ -235,6 +237,8 @@
94 XWindowAttributes attrib;
95 CompWindow::Geometry geometry;
96 CompWindow::Geometry serverGeometry;
97+ CompWindow::Geometry frameGeometry;
98+ CompWindow::Geometry serverFrameGeometry;
99 Window transientFor;
100 Window clientLeader;
101 XSizeHints sizeHints;
102@@ -286,6 +290,11 @@
103 int pendingUnmaps;
104 int pendingMaps;
105
106+ typedef std::pair <XWindowChanges, unsigned int> XWCValueMask;
107+
108+ std::list <XWCValueMask> pendingConfigures;
109+ bool pendingPositionUpdates;
110+
111 char *startupId;
112 char *resName;
113 char *resClass;
114
115=== modified file 'src/screen.cpp'
116--- src/screen.cpp 2011-09-25 04:16:18 +0000
117+++ src/screen.cpp 2011-09-27 15:45:28 +0000
118@@ -765,7 +765,7 @@
119 compLogMessage ("core", CompLogLevelDebug, "however, this may be a false positive");
120 }
121
122- if (dbg->serverWindowsChanged () && dbg->checkSanity (priv->serverWindows))
123+ if (dbg->serverWindowsChanged () && dbg->checkSanity (priv->windows))
124 compLogMessage ("core", CompLogLevelDebug, "windows are stacked incorrectly");
125 }
126 }
127@@ -1756,8 +1756,13 @@
128
129 if (moveX != 0 || moveY != 0)
130 {
131- w->move (moveX, moveY, true);
132- w->syncPosition ();
133+ unsigned int valueMask = CWX | CWY;
134+ XWindowChanges xwc;
135+
136+ xwc.x = w->serverGeometry ().x () + moveX;
137+ xwc.y = w->serverGeometry ().y () + moveY;
138+
139+ w->configureXWindow (valueMask, &xwc);
140 }
141 }
142 }
143@@ -3502,6 +3507,9 @@
144
145 foreach (CompWindow *w, priv->windows)
146 {
147+ unsigned int valueMask = CWX | CWY;
148+ XWindowChanges xwc;
149+
150 if (w->onAllViewports ())
151 continue;
152
153@@ -3513,11 +3521,10 @@
154 if (w->saveMask () & CWY)
155 w->saveWc ().y += pnt.y ();
156
157- /* move */
158- w->move (pnt.x (), pnt.y ());
159+ xwc.x = w->serverGeometry ().x () + pnt.x ();
160+ xwc.y = w->serverGeometry ().y () + pnt.y ();
161
162- if (sync)
163- w->syncPosition ();
164+ w->configureXWindow (valueMask, &xwc);
165 }
166
167 if (sync)
168
169=== modified file 'src/stackdebugger.cpp'
170--- src/stackdebugger.cpp 2011-09-25 04:16:18 +0000
171+++ src/stackdebugger.cpp 2011-09-27 15:45:28 +0000
172@@ -330,6 +330,10 @@
173 if (!w->managed ())
174 continue;
175
176+ /* ignore any windows that just got created */
177+ if (!w->mapNum ())
178+ continue;
179+
180 /* determine the current layer */
181 if (w->type () == CompWindowTypeDockMask)
182 {
183
184=== modified file 'src/window.cpp'
185--- src/window.cpp 2011-09-25 04:16:18 +0000
186+++ src/window.cpp 2011-09-27 15:45:28 +0000
187@@ -792,32 +792,60 @@
188 void
189 PrivateWindow::updateFrameWindow ()
190 {
191+ XWindowChanges xwc;
192+ unsigned int valueMask = CWX | CWY | CWWidth | CWHeight;
193+
194 if (!serverFrame)
195 return;
196
197+
198 gettimeofday (&lastConfigureRequest, NULL);
199+ /* Flush any changes made to serverFrameGeometry or serverGeometry to the server
200+ * since there is a race condition where geometries will go out-of-sync with
201+ * window movement */
202+
203+ window->syncPosition ();
204
205 if (serverInput.left || serverInput.right || serverInput.top || serverInput.bottom)
206 {
207- int x, y, width, height;
208 int bw = serverGeometry.border () * 2;
209
210- x = serverGeometry.x () - serverInput.left;
211- y = serverGeometry.y () - serverInput.top;
212- width = serverGeometry.width () + serverInput.left + serverInput.right + bw;
213- height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;
214+ xwc.x = serverGeometry.x () - serverInput.left;
215+ xwc.y = serverGeometry.y () - serverInput.top;
216+ xwc.width = serverGeometry.width () + serverInput.left + serverInput.right + bw;
217+ xwc.height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;
218
219 if (shaded)
220 height = serverInput.top + serverInput.bottom;
221
222+ if (serverFrameGeometry.x () == xwc.x)
223+ valueMask &= ~(CWX);
224+ else
225+ serverFrameGeometry.setX (xwc.x);
226+
227+ if (serverFrameGeometry.y () == xwc.y)
228+ valueMask &= ~(CWY);
229+ else
230+ serverFrameGeometry.setY (xwc.y);
231+
232+ if (serverFrameGeometry.width () == xwc.width)
233+ valueMask &= ~(CWWidth);
234+ else
235+ serverFrameGeometry.setWidth (xwc.width);
236+
237+ if (serverFrameGeometry.height () == xwc.height)
238+ valueMask &= ~(CWHeight);
239+ else
240+ serverFrameGeometry.setHeight (xwc.height);
241+
242+ addPendingConfigure (xwc, valueMask);
243+
244+
245 /* Geometry is the same, so we're not going to get a ConfigureNotify
246 * event when the window is configured, which means that other plugins
247 * won't know that the client, frame and wrapper windows got shifted
248 * around (and might result in display corruption, eg in OpenGL */
249- if (geometry.x () - input.left == x &&
250- geometry.y () - input.top == y &&
251- geometry.width () + input.left + input.right + bw == width &&
252- geometry.height () + input.top + input.bottom + bw == height)
253+ if (valueMask == 0)
254 {
255 XConfigureEvent xev;
256 XWindowAttributes attrib;
257@@ -876,8 +904,7 @@
258 XSync (screen->dpy (), false);
259 }
260 else
261- XMoveResizeWindow (screen->dpy (), serverFrame, x, y, width, height);
262-
263+ XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
264 if (shaded)
265 {
266 XUnmapWindow (screen->dpy (), wrapper);
267@@ -895,25 +922,44 @@
268 }
269 else
270 {
271- int x, y, width, height;
272 int bw = serverGeometry.border () * 2;
273
274- x = serverGeometry.x ();
275- y = serverGeometry.y ();
276- width = serverGeometry.width () + bw;
277- height = serverGeometry.height () + bw;
278+ xwc.x = serverGeometry.x ();
279+ xwc.y = serverGeometry.y ();
280+ xwc.width = serverGeometry.width () + bw;
281+ xwc.height = serverGeometry.height () + bw;
282
283 if (shaded)
284 height = 0;
285
286+ if (serverFrameGeometry.x () == xwc.x)
287+ valueMask &= ~(CWX);
288+ else
289+ serverFrameGeometry.setX (xwc.x);
290+
291+ if (serverFrameGeometry.y () == xwc.y)
292+ valueMask &= ~(CWY);
293+ else
294+ serverFrameGeometry.setY (xwc.y);
295+
296+ if (serverFrameGeometry.width () == xwc.width)
297+ valueMask &= ~(CWWidth);
298+ else
299+ serverFrameGeometry.setWidth (xwc.width);
300+
301+ if (serverFrameGeometry.height () == xwc.height)
302+ valueMask &= ~(CWHeight);
303+ else
304+ serverFrameGeometry.setHeight (xwc.height);
305+
306+ addPendingConfigure (xwc, valueMask);
307+
308+
309 /* Geometry is the same, so we're not going to get a ConfigureNotify
310 * event when the window is configured, which means that other plugins
311 * won't know that the client, frame and wrapper windows got shifted
312 * around (and might result in display corruption, eg in OpenGL */
313- if (geometry.x () - input.left == x &&
314- geometry.y () - input.top == y &&
315- geometry.width () + input.left + input.right + bw == width &&
316- geometry.height () + input.top + input.bottom + bw == height)
317+ if (valueMask == 0)
318 {
319 XConfigureEvent xev;
320 XWindowAttributes attrib;
321@@ -972,7 +1018,7 @@
322 XSync (screen->dpy (), false);
323 }
324 else
325- XMoveResizeWindow (screen->dpy (), serverFrame, x, y, width, height);
326+ XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
327
328 if (shaded)
329 {
330@@ -1753,8 +1799,6 @@
331 dwidth = gm.width () - priv->geometry.width ();
332 dheight = gm.height () - priv->geometry.height ();
333
334- gettimeofday (&priv->lastGeometryUpdate, NULL);
335-
336 priv->geometry.set (gm.x (), gm.y (),
337 gm.width (), gm.height (),
338 gm.border ());
339@@ -1776,13 +1820,17 @@
340 dx = gm.x () - priv->geometry.x ();
341 dy = gm.y () - priv->geometry.y ();
342
343- /* Don't move the window here if a plugin has already updated
344- * the geometry of that window after the last time the server
345- * was sent a configure request since the configureNotify we
346- * receieve here will be out of date. Instead wait for the plugin
347- * to call syncPosition again */
348- if (TIMEVALDIFF (&priv->lastConfigureRequest, &priv->lastGeometryUpdate))
349- move (dx, dy);
350+ priv->geometry.setX (gm.x ());
351+ priv->geometry.setY (gm.y ());
352+
353+ priv->region.translate (dx, dy);
354+ priv->inputRegion.translate (dx, dy);
355+ if (!priv->frameRegion.isEmpty ())
356+ priv->frameRegion.translate (dx, dy);
357+
358+ priv->invisible = WINDOW_INVISIBLE (priv);
359+
360+ moveNotify (dx, dy, true);
361 }
362
363 updateFrameRegion ();
364@@ -1911,11 +1959,35 @@
365 void
366 PrivateWindow::configure (XConfigureEvent *ce)
367 {
368+ unsigned int valueMask = 0;
369+
370 if (priv->frame)
371 return;
372
373+ /* remove configure event from pending configures */
374+ if (priv->geometry.x () != ce->x)
375+ valueMask |= CWX;
376+
377+ if (priv->geometry.y () != ce->y)
378+ valueMask |= CWY;
379+
380+ if (priv->geometry.width () != ce->width)
381+ valueMask |= CWWidth;
382+
383+ if (priv->geometry.height () != ce->height)
384+ valueMask |= CWHeight;
385+
386+ if (priv->geometry.border () != ce->border_width)
387+ valueMask |= CWBorderWidth;
388+
389+ if (ROOTPARENT (window->prev) != ce->above)
390+ valueMask |= CWSibling | CWStackMode;
391+
392 priv->attrib.override_redirect = ce->override_redirect;
393
394+ priv->frameGeometry.set (ce->x, ce->y, ce->width,
395+ ce->height, ce->border_width);
396+
397 if (priv->syncWait)
398 priv->syncGeometry.set (ce->x, ce->y, ce->width, ce->height,
399 ce->border_width);
400@@ -1939,10 +2011,89 @@
401 {
402 int x, y, width, height;
403 CompWindow *above;
404+ unsigned int valueMask = 0;
405+ bool handled = false;
406
407 if (!priv->frame)
408 return;
409
410+ /* remove configure event from pending configures */
411+ if (priv->frameGeometry.x () != ce->x)
412+ valueMask |= CWX;
413+
414+ if (priv->frameGeometry.y () != ce->y)
415+ valueMask |= CWY;
416+
417+ if (priv->frameGeometry.width () != ce->width)
418+ valueMask |= CWWidth;
419+
420+ if (priv->frameGeometry.height () != ce->height)
421+ valueMask |= CWHeight;
422+
423+ if (priv->frameGeometry.border () != ce->border_width)
424+ valueMask |= CWBorderWidth;
425+
426+ if (ROOTPARENT (window->prev) != ce->above)
427+ valueMask |= CWSibling | CWStackMode;
428+
429+ for (std::list <XWCValueMask>::iterator it = pendingConfigures.begin ();
430+ it != pendingConfigures.end (); it++)
431+ {
432+ XWCValueMask &xwcvm = (*it);
433+
434+
435+ if (xwcvm.second != valueMask)
436+ {
437+ /* For stacking cases, if a client wants to raise or lower a window
438+ * then they don't need to specify CWSibling, so allow that to be
439+ * excluded in those cases */
440+
441+ if (ce->above == ROOTPARENT (screen->windows ().back ()) ||
442+ ce->above == 0)
443+ {
444+ if ((xwcvm.second & ~(CWSibling) != valueMask))
445+ continue;
446+ }
447+ else
448+ continue;
449+ }
450+
451+ if (xwcvm.second & CWX && xwcvm.first.x != ce->x)
452+ continue;
453+
454+ if (xwcvm.second & CWY && xwcvm.first.y != ce->y)
455+ continue;
456+
457+ if (xwcvm.second & CWWidth && xwcvm.first.width != ce->width)
458+ continue;
459+
460+ if (xwcvm.second & CWHeight && xwcvm.first.height != ce->height)
461+ continue;
462+
463+ if (xwcvm.second & (CWStackMode | CWSibling) && xwcvm.first.sibling != ce->above)
464+ continue;
465+
466+ /* Matched ConfigureWindow request to ConfigureNotify event
467+ * remove it from the list */
468+
469+ handled = true;
470+
471+ pendingConfigures.erase (it);
472+ break;
473+ }
474+
475+ if (!handled)
476+ {
477+ compLogMessage ("core", CompLogLevelWarn, "unhandled ConfigureNotify on 0x%x!", serverFrame);
478+ compLogMessage ("core", CompLogLevelWarn, "this should never happen. you should"\
479+ "probably file a bug about this.");
480+#ifdef DEBUG
481+ abort ();
482+#else
483+ pendingConfigures.clear ();
484+#endif
485+ }
486+
487 /* subtract the input extents last sent to the
488 * server to calculate the client size and then
489 * re-sync the input extents and extents last
490@@ -1953,19 +2104,14 @@
491 width = ce->width - priv->serverGeometry.border () * 2 - priv->serverInput.left - priv->serverInput.right;
492 height = ce->height - priv->serverGeometry.border () * 2 - priv->serverInput.top - priv->serverInput.bottom;
493
494+ /* set the frame geometry */
495+ priv->frameGeometry.set (ce->x, ce->y, ce->width, ce->height, ce->border_width);
496+
497+
498 if (priv->syncWait)
499- {
500 priv->syncGeometry.set (x, y, width, height, ce->border_width);
501- }
502 else
503- {
504- if (ce->override_redirect)
505- {
506- priv->serverGeometry.set (x, y, width, height, ce->border_width);
507- }
508-
509 window->resize (x, y, width, height, ce->border_width);
510- }
511
512 if (priv->restack (ce->above))
513 priv->updatePassiveButtonGrabs ();
514@@ -1974,6 +2120,27 @@
515
516 if (above)
517 above->priv->updatePassiveButtonGrabs ();
518+
519+ if (pendingConfigures.empty ())
520+ {
521+ /* Tell plugins its ok to start doing stupid things again but
522+ * obviously FIXME */
523+ CompOption::Vector options;
524+ CompOption::Value v;
525+
526+ options.push_back (CompOption ("window", CompOption::TypeInt));
527+ v.set ((int) id);
528+ options.back ().set (v);
529+ options.push_back (CompOption ("active", CompOption::TypeInt));
530+ v.set ((int) 0);
531+ options.back ().set (v);
532+
533+ /* Notify other plugins that it is unsafe to change geometry or serverGeometry
534+ * FIXME: That API should not be accessible to plugins, this is a hack to avoid
535+ * breaking ABI */
536+
537+ screen->handleCompizEvent ("core", "lock_position", options);
538+ }
539 }
540
541 void
542@@ -1996,43 +2163,129 @@
543 {
544 if (dx || dy)
545 {
546- /*
547- priv->attrib.x += dx;
548- priv->attrib.y += dy;
549- */
550- priv->geometry.setX (priv->geometry.x () + dx);
551- priv->geometry.setY (priv->geometry.y () + dy);
552-
553 gettimeofday (&priv->lastGeometryUpdate, NULL);
554
555- priv->region.translate (dx, dy);
556- priv->inputRegion.translate (dx, dy);
557- if (!priv->frameRegion.isEmpty ())
558- priv->frameRegion.translate (dx, dy);
559-
560- priv->invisible = WINDOW_INVISIBLE (priv);
561-
562- moveNotify (dx, dy, immediate);
563+ /* Don't allow window movement to overwrite working geometries
564+ * last received from the server if we know there are pending
565+ * ConfigureNotify events on this window. That's a clunky workaround
566+ * and a FIXME in any case, however, until we can break the API
567+ * and remove CompWindow::move, this will need to be the case */
568+
569+ if (!priv->pendingConfigures.size ())
570+ {
571+ priv->geometry.setX (priv->geometry.x () + dx);
572+ priv->geometry.setY (priv->geometry.y () + dy);
573+ priv->frameGeometry.setX (priv->frameGeometry.x () + dx);
574+ priv->frameGeometry.setY (priv->frameGeometry.y () + dy);
575+
576+ priv->pendingPositionUpdates = true;
577+
578+ priv->region.translate (dx, dy);
579+ priv->inputRegion.translate (dx, dy);
580+ if (!priv->frameRegion.isEmpty ())
581+ priv->frameRegion.translate (dx, dy);
582+
583+ priv->invisible = WINDOW_INVISIBLE (priv);
584+
585+ moveNotify (dx, dy, immediate);
586+ }
587+ else
588+ {
589+ XWindowChanges xwc;
590+ unsigned int valueMask = CWX | CWY;
591+ struct timeval tv, old;
592+ compLogMessage ("core", CompLogLevelDebug, "pending configure notifies on 0x%x,"\
593+ "moving window asyncrhonously!", (unsigned int) priv->serverId);
594+
595+ old = priv->lastConfigureRequest;
596+ gettimeofday (&tv, NULL);
597+
598+ xwc.x = priv->serverGeometry.x () + dx;
599+ xwc.y = priv->serverGeometry.y () + dy;
600+
601+ configureXWindow (valueMask, &xwc);
602+
603+ priv->lastConfigureRequest = old;
604+
605+ /* FIXME: This is a hack to avoid performance regressions
606+ * and must be removed in 0.9.6 */
607+ if (tv.tv_usec - priv->lastConfigureRequest.tv_usec > 30000)
608+ {
609+ compLogMessage ("core", CompLogLevelWarn, "failed to receive ConfigureNotify event from request at %i (now: %i)\n",
610+ priv->lastConfigureRequest.tv_usec, tv.tv_usec);
611+ priv->pendingConfigures.clear ();
612+ }
613+ }
614 }
615 }
616
617 void
618+PrivateWindow::addPendingConfigure (XWindowChanges &xwc, unsigned int valueMask)
619+{
620+ CompOption::Vector options;
621+ CompOption::Value v;
622+
623+ options.push_back (CompOption ("window", CompOption::TypeInt));
624+ v.set ((int) id);
625+ options.back ().set (v);
626+ options.push_back (CompOption ("active", CompOption::TypeInt));
627+ v.set ((int) 1);
628+ options.back ().set (v);
629+
630+ gettimeofday (&lastConfigureRequest, NULL);
631+
632+ /* Notify other plugins that it is unsafe to change geometry or serverGeometry
633+ * FIXME: That API should not be accessible to plugins, this is a hack to avoid
634+ * breaking ABI */
635+
636+ screen->handleCompizEvent ("core", "lock_position", options);
637+
638+ priv->pendingConfigures.push_back (XWCValueMask (xwc, valueMask));
639+}
640+
641+void
642 CompWindow::syncPosition ()
643 {
644- priv->serverGeometry.setX (priv->geometry.x ());
645- priv->serverGeometry.setY (priv->geometry.y ());
646-
647 gettimeofday (&priv->lastConfigureRequest, NULL);
648
649- XMoveWindow (screen->dpy (), ROOTPARENT (this),
650- priv->serverGeometry.x () - priv->serverInput.left,
651- priv->serverGeometry.y () - priv->serverInput.top);
652+ unsigned int valueMask = CWX | CWY;
653+ XWindowChanges xwc;
654
655- if (priv->serverFrame)
656+ if (priv->pendingPositionUpdates && priv->pendingConfigures.empty ())
657 {
658- XMoveWindow (screen->dpy (), priv->wrapper,
659- priv->serverInput.left, priv->serverInput.top);
660- sendConfigureNotify ();
661+ if (priv->serverFrameGeometry.x () == priv->frameGeometry.x ())
662+ valueMask &= ~(CWX);
663+ if (priv->serverFrameGeometry.y () == priv->frameGeometry.y ())
664+ valueMask &= ~(CWY);
665+
666+ /* Because CompWindow::move can update the geometry last
667+ * received from the server, we must indicate that no values
668+ * changed, because when the ConfigureNotify comes around
669+ * the values are going to be the same. That's obviously
670+ * broken behaviour and worthy of a FIXME, but requires
671+ * larger changes to the window movement system. */
672+ if (valueMask)
673+ {
674+ priv->addPendingConfigure (xwc, 0);
675+
676+ priv->serverGeometry.setX (priv->geometry.x ());
677+ priv->serverGeometry.setY (priv->geometry.y ());
678+ priv->serverFrameGeometry.setX (priv->frameGeometry.x ());
679+ priv->serverFrameGeometry.setY (priv->frameGeometry.y ());
680+
681+ xwc.x = priv->serverFrameGeometry.x ();
682+ xwc.y = priv->serverFrameGeometry.y ();
683+
684+ XConfigureWindow (screen->dpy (), ROOTPARENT (this), valueMask, &xwc);
685+
686+ if (priv->serverFrame)
687+ {
688+ XMoveWindow (screen->dpy (), priv->wrapper,
689+ priv->serverInput.left, priv->serverInput.top);
690+ sendConfigureNotify ();
691+ }
692+ }
693+ priv->pendingPositionUpdates = false;
694 }
695 }
696
697@@ -2185,11 +2438,13 @@
698 vp = defaultViewport ();
699 if (screen->vp () != vp)
700 {
701- int moveX = (screen->vp ().x () - vp.x ()) * screen->width ();
702- int moveY = (screen->vp ().y () - vp.y ()) * screen->height ();
703-
704- move (moveX, moveY, TRUE);
705- syncPosition ();
706+ unsigned int valueMask = CWX | CWY;
707+ XWindowChanges xwc;
708+
709+ xwc.x = serverGeometry ().x () + (screen->vp ().x () - vp.x ()) * screen->width ();
710+ xwc.y = serverGeometry ().y () + (screen->vp ().y () - vp.y ()) * screen->height ();
711+
712+ configureXWindow (valueMask, &xwc);
713 }
714 }
715 }
716@@ -2749,6 +3004,54 @@
717 PrivateWindow::reconfigureXWindow (unsigned int valueMask,
718 XWindowChanges *xwc)
719 {
720+ unsigned int frameValueMask = valueMask;
721+
722+ /* Immediately sync window position
723+ * if plugins were updating w->geometry () directly
724+ * in order to avoid a race condition */
725+
726+ window->syncPosition ();
727+
728+ /* Remove redundant bits */
729+
730+ if (serverGeometry.x () == xwc->x)
731+ valueMask &= ~(CWX);
732+
733+ if (serverGeometry.y () == xwc->y)
734+ valueMask &= ~(CWY);
735+
736+ if (serverGeometry.width () == xwc->width)
737+ valueMask &= ~(CWWidth);
738+
739+ if (serverGeometry.height () == xwc->height)
740+ valueMask &= ~(CWHeight);
741+
742+ if (serverGeometry.border () == xwc->border_width)
743+ valueMask &= ~(CWBorderWidth);
744+
745+ if (window->serverPrev && ROOTPARENT (window->serverPrev) == xwc->sibling)
746+ {
747+ /* check if the sibling is also pending a restack,
748+ * if not, then setting this bit is useless */
749+
750+ bool pendingRestack = false;
751+
752+ foreach (XWCValueMask &xwcvm, window->serverPrev->priv->pendingConfigures)
753+ {
754+ if (xwcvm.second & (CWSibling | CWStackMode))
755+ {
756+ pendingRestack = true;
757+ break;
758+ }
759+ }
760+
761+ if (!pendingRestack)
762+ valueMask &= ~(CWSibling | CWStackMode);
763+ }
764+
765+ if (valueMask & CWBorderWidth)
766+ serverGeometry.setBorder (xwc->border_width);
767+
768 if (valueMask & CWX)
769 serverGeometry.setX (xwc->x);
770
771@@ -2761,9 +3064,6 @@
772 if (valueMask & CWHeight)
773 serverGeometry.setHeight (xwc->height);
774
775- if (valueMask & CWBorderWidth)
776- serverGeometry.setBorder (xwc->border_width);
777-
778 /* Update the server side window list on raise, lower and restack functions.
779 * This function should only recieve stack_mode == Above
780 * but warn incase something else does get through, to make the cause
781@@ -2774,41 +3074,80 @@
782 {
783 if (xwc->sibling)
784 {
785- CompWindow *w = screen->findWindow (id);
786-
787- screen->unhookServerWindow (w);
788- screen->insertServerWindow (w, xwc->sibling);
789+ screen->unhookServerWindow (window);
790+ screen->insertServerWindow (window, xwc->sibling);
791 }
792 }
793 else
794 compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");
795 }
796
797+ if (serverFrameGeometry.x () == xwc->x - serverGeometry.border () - serverInput.left)
798+ frameValueMask &= ~(CWX);
799+
800+ if (serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top)
801+ frameValueMask &= ~(CWY);
802+
803+ if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
804+ + serverInput.left + serverInput.right)
805+ frameValueMask &= ~(CWWidth);
806+
807+ if (serverFrameGeometry.height () == xwc->height + serverGeometry.border () * 2
808+ + serverInput.top + serverInput.bottom)
809+ frameValueMask &= ~(CWHeight);
810+
811+ /* Can't set the border width of frame windows */
812+ frameValueMask &= ~(CWBorderWidth);
813+
814+ if (frameValueMask & CWX)
815+ serverFrameGeometry.setX (xwc->x - serverGeometry.border () - serverInput.left);
816+
817+ if (frameValueMask & CWY)
818+ serverFrameGeometry.setY (xwc->y -serverGeometry.border () - serverInput.top);
819+
820+ if (frameValueMask & CWWidth)
821+ serverFrameGeometry.setWidth (xwc->width + serverGeometry.border () * 2
822+ + serverInput.left + serverInput.right);
823+
824+ if (frameValueMask & CWHeight)
825+ serverFrameGeometry.setHeight (xwc->height + serverGeometry.border () * 2
826+ + serverInput.top + serverInput.bottom);
827+
828+
829 if (serverFrame)
830 {
831- XWindowChanges wc = *xwc;
832-
833 gettimeofday (&lastConfigureRequest, NULL);
834
835- wc.x -= serverInput.left - serverGeometry.border ();
836- wc.y -= serverInput.top - serverGeometry.border ();
837- wc.width += serverInput.left + serverInput.right + serverGeometry.border ();
838- wc.height += serverInput.top + serverInput.bottom + serverGeometry.border ();
839-
840- XConfigureWindow (screen->dpy (), serverFrame, valueMask, &wc);
841+ if (frameValueMask)
842+ {
843+ XWindowChanges wc = *xwc;
844+
845+ wc.x = serverFrameGeometry.x ();
846+ wc.y = serverFrameGeometry.y ();
847+ wc.width = serverFrameGeometry.width ();
848+ wc.height = serverFrameGeometry.height ();
849+
850+ addPendingConfigure (wc, frameValueMask);
851+
852+ XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc);
853+ }
854 valueMask &= ~(CWSibling | CWStackMode);
855
856- xwc->x = serverInput.left;
857- xwc->y = serverInput.top;
858- XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);
859+ if (valueMask)
860+ {
861+ xwc->x = serverInput.left;
862+ xwc->y = serverInput.top;
863+ XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);
864
865- xwc->x = 0;
866- xwc->y = 0;
867+ xwc->x = 0;
868+ xwc->y = 0;
869+ }
870
871 window->sendConfigureNotify ();
872 }
873
874- XConfigureWindow (screen->dpy (), id, valueMask, xwc);
875+ if (valueMask)
876+ XConfigureWindow (screen->dpy (), id, valueMask, xwc);
877 }
878
879 bool
880@@ -3574,9 +3913,30 @@
881 * if serverPrev was recently restacked */
882 if (window->serverPrev)
883 {
884- if (!sibling)
885- {
886- XLowerWindow (screen->dpy (), ROOTPARENT (window));
887+ bool pendingRestacks = false;
888+
889+ foreach (XWCValueMask &xwcvm, sibling->priv->pendingConfigures)
890+ {
891+ if (xwcvm.second & (CWSibling | CWStackMode))
892+ {
893+ pendingRestacks = true;
894+ break;
895+ }
896+ }
897+
898+ if (!sibling && window->serverPrev)
899+ {
900+ XWindowChanges xwc;
901+ unsigned int valueMask = CWStackMode;
902+
903+ xwc.stack_mode = Below;
904+
905+ /* Below with no sibling puts the window at the bottom
906+ * of the stack */
907+ XConfigureWindow (screen->dpy (), ROOTPARENT (window), valueMask, &xwc);
908+
909+ if (serverFrame)
910+ priv->addPendingConfigure (xwc, CWStackMode);
911
912 /* Update the list of windows last sent to the server */
913 screen->unhookServerWindow (window);
914@@ -5410,6 +5770,8 @@
915
916 if (tx || ty)
917 {
918+ unsigned int valueMask = CWX | CWY;
919+ XWindowChanges xwc;
920 int m, wx, wy;
921
922 if (!priv->managed)
923@@ -5450,10 +5812,10 @@
924 if (priv->saveMask & CWY)
925 priv->saveWc.y += wy;
926
927- move (wx, wy);
928+ xwc.x = serverGeometry ().x () + wx;
929+ xwc.y = serverGeometry ().y () + wy;
930
931- if (sync)
932- syncPosition ();
933+ configureXWindow (valueMask, &xwc);
934 }
935 }
936
937@@ -5659,18 +6021,14 @@
938 if (dbg)
939 dbg->overrideRedirectRestack (priv->id, aboveId);
940
941- gettimeofday (&priv->lastGeometryUpdate, NULL);
942+ gettimeofday (&priv->lastConfigureRequest, NULL);
943
944 priv->attrib = wa;
945 priv->serverGeometry.set (priv->attrib.x, priv->attrib.y,
946 priv->attrib.width, priv->attrib.height,
947 priv->attrib.border_width);
948- priv->syncGeometry.set (priv->attrib.x, priv->attrib.y,
949- priv->attrib.width, priv->attrib.height,
950- priv->attrib.border_width);
951- priv->geometry.set (priv->attrib.x, priv->attrib.y,
952- priv->attrib.width, priv->attrib.height,
953- priv->attrib.border_width);
954+ priv->serverFrameGeometry = priv->frameGeometry = priv->syncGeometry
955+ = priv->geometry = priv->serverGeometry;
956
957 priv->width = priv->attrib.width + priv->attrib.border_width * 2;
958 priv->height = priv->attrib.height + priv->attrib.border_width * 2;
959@@ -5982,6 +6340,7 @@
960
961 pendingUnmaps (0),
962 pendingMaps (0),
963+ pendingPositionUpdates (false),
964
965 startupId (0),
966 resName (0),
967@@ -6278,7 +6637,6 @@
968 XSync (dpy, false);
969 return false;
970 }
971- gettimeofday (&lastConfigureRequest, NULL);
972
973 if (wa.override_redirect)
974 return false;
975@@ -6309,7 +6667,7 @@
976
977 priv->serverGeometry.setBorder (0);
978
979- mask = CWBorderPixel | CWColormap | CWBackPixmap;
980+ mask = CWBorderPixel | CWColormap | CWBackPixmap | CWOverrideRedirect;
981
982 if (wa.depth == 32)
983 {
984@@ -6427,6 +6785,11 @@
985 SubstructureNotifyMask | EnterWindowMask |
986 LeaveWindowMask;
987
988+ serverFrameGeometry = serverGeometry;
989+
990+ XMoveResizeWindow (dpy, serverFrame, serverFrameGeometry.x (), serverFrameGeometry.y (),
991+ serverFrameGeometry.width (), serverFrameGeometry.height ());
992+
993 XChangeWindowAttributes (dpy, serverFrame, CWEventMask, &attr);
994 XChangeWindowAttributes (dpy, wrapper, CWEventMask, &attr);
995
996@@ -6447,9 +6810,6 @@
997 XUngrabServer (dpy);
998 XSync (dpy, false);
999
1000- XMoveResizeWindow (dpy, serverFrame, wa.x, wa.y,
1001- wa.width, wa.height);
1002-
1003 window->windowNotify (CompWindowNotifyReparent);
1004
1005 return true;
1006@@ -6508,6 +6868,14 @@
1007 /* Wait for the reparent to finish */
1008 XSync (dpy, false);
1009
1010+ xwc.x = serverGeometry.x () - serverGeometry.border ();
1011+ xwc.y = serverGeometry.y () - serverGeometry.border ();
1012+ xwc.width = serverGeometry.width () + serverGeometry.border () * 2;
1013+ xwc.height = serverGeometry.height () + serverGeometry.border () * 2;
1014+
1015+ XConfigureWindow (dpy, serverFrame, CWX | CWY | CWWidth | CWHeight, &xwc);
1016+
1017+
1018 xwc.stack_mode = Below;
1019 xwc.sibling = serverFrame;
1020 XConfigureWindow (dpy, id, CWSibling | CWStackMode, &xwc);

Subscribers

People subscribed via source and target branches