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
=== modified file 'plugins/move/src/move.cpp'
--- plugins/move/src/move.cpp 2011-06-23 03:22:47 +0000
+++ plugins/move/src/move.cpp 2011-09-27 15:45:28 +0000
@@ -488,7 +488,8 @@
488 wY + dy - w->geometry ().y (), false);488 wY + dy - w->geometry ().y (), false);
489489
490 if (ms->optionGetLazyPositioning () &&490 if (ms->optionGetLazyPositioning () &&
491 MoveScreen::get (screen)->hasCompositing)491 ms->hasCompositing &&
492 !MoveWindow::get (ms->w)->mLocked)
492 {493 {
493 /* FIXME: This form of lazy positioning is broken and should494 /* FIXME: This form of lazy positioning is broken and should
494 be replaced asap. Current code exists just to avoid a495 be replaced asap. Current code exists just to avoid a
@@ -507,6 +508,32 @@
507 }508 }
508}509}
509510
511/* FIXME: This is a hack to prevent a race condition
512 * when core is processing ConfigureNotify events. It
513 * MUST be removed after 0.9.6 when we can break ABI
514 * and do lazy positioning correctly ! */
515
516void
517MoveScreen::handleCompizEvent (const char *plugin, const char *event, CompOption::Vector &options)
518{
519 if (w)
520 {
521 if (std::string ("core") == std::string (plugin))
522 {
523 if (std::string ("lock_position") == std::string (event))
524 {
525 Window xid = CompOption::getIntOptionNamed (options, "window", 0);
526 int lock = CompOption::getIntOptionNamed (options, "active", 0);
527
528 if (xid == w->id ())
529 MoveWindow::get (w)->mLocked = lock ? true : false;
530 }
531 }
532 }
533
534 screen->handleCompizEvent (plugin, event, options);
535}
536
510void537void
511MoveScreen::handleEvent (XEvent *event)538MoveScreen::handleEvent (XEvent *event)
512{539{
513540
=== modified file 'plugins/move/src/move.h'
--- plugins/move/src/move.h 2009-12-25 19:49:23 +0000
+++ plugins/move/src/move.h 2011-09-27 15:45:28 +0000
@@ -61,6 +61,9 @@
61 void updateOpacity ();61 void updateOpacity ();
6262
63 void handleEvent (XEvent *);63 void handleEvent (XEvent *);
64 void handleCompizEvent (const char *plugin,
65 const char *event,
66 CompOption::Vector &options);
6467
65 CompWindow *w;68 CompWindow *w;
66 int savedX;69 int savedX;
@@ -98,7 +101,8 @@
98 PluginClassHandler<MoveWindow,CompWindow> (window),101 PluginClassHandler<MoveWindow,CompWindow> (window),
99 window (window),102 window (window),
100 gWindow (GLWindow::get (window)),103 gWindow (GLWindow::get (window)),
101 cWindow (CompositeWindow::get (window))104 cWindow (CompositeWindow::get (window)),
105 mLocked (false)
102 {106 {
103 if (gWindow)107 if (gWindow)
104 GLWindowInterface::setHandler (gWindow, false);108 GLWindowInterface::setHandler (gWindow, false);
@@ -110,6 +114,8 @@
110 CompWindow *window;114 CompWindow *window;
111 GLWindow *gWindow;115 GLWindow *gWindow;
112 CompositeWindow *cWindow;116 CompositeWindow *cWindow;
117
118 bool mLocked;
113};119};
114120
115#define MOVE_SCREEN(s) \121#define MOVE_SCREEN(s) \
116122
=== modified file 'src/privatewindow.h'
--- src/privatewindow.h 2011-09-25 04:16:18 +0000
+++ src/privatewindow.h 2011-09-27 15:45:28 +0000
@@ -211,6 +211,8 @@
211211
212 void readIconHint ();212 void readIconHint ();
213213
214 void addPendingConfigure (XWindowChanges &, unsigned int);
215
214 public:216 public:
215217
216 PrivateWindow *priv;218 PrivateWindow *priv;
@@ -235,6 +237,8 @@
235 XWindowAttributes attrib;237 XWindowAttributes attrib;
236 CompWindow::Geometry geometry;238 CompWindow::Geometry geometry;
237 CompWindow::Geometry serverGeometry;239 CompWindow::Geometry serverGeometry;
240 CompWindow::Geometry frameGeometry;
241 CompWindow::Geometry serverFrameGeometry;
238 Window transientFor;242 Window transientFor;
239 Window clientLeader;243 Window clientLeader;
240 XSizeHints sizeHints;244 XSizeHints sizeHints;
@@ -286,6 +290,11 @@
286 int pendingUnmaps;290 int pendingUnmaps;
287 int pendingMaps;291 int pendingMaps;
288292
293 typedef std::pair <XWindowChanges, unsigned int> XWCValueMask;
294
295 std::list <XWCValueMask> pendingConfigures;
296 bool pendingPositionUpdates;
297
289 char *startupId;298 char *startupId;
290 char *resName;299 char *resName;
291 char *resClass;300 char *resClass;
292301
=== modified file 'src/screen.cpp'
--- src/screen.cpp 2011-09-25 04:16:18 +0000
+++ src/screen.cpp 2011-09-27 15:45:28 +0000
@@ -765,7 +765,7 @@
765 compLogMessage ("core", CompLogLevelDebug, "however, this may be a false positive");765 compLogMessage ("core", CompLogLevelDebug, "however, this may be a false positive");
766 }766 }
767767
768 if (dbg->serverWindowsChanged () && dbg->checkSanity (priv->serverWindows))768 if (dbg->serverWindowsChanged () && dbg->checkSanity (priv->windows))
769 compLogMessage ("core", CompLogLevelDebug, "windows are stacked incorrectly");769 compLogMessage ("core", CompLogLevelDebug, "windows are stacked incorrectly");
770 }770 }
771}771}
@@ -1756,8 +1756,13 @@
17561756
1757 if (moveX != 0 || moveY != 0)1757 if (moveX != 0 || moveY != 0)
1758 {1758 {
1759 w->move (moveX, moveY, true);1759 unsigned int valueMask = CWX | CWY;
1760 w->syncPosition ();1760 XWindowChanges xwc;
1761
1762 xwc.x = w->serverGeometry ().x () + moveX;
1763 xwc.y = w->serverGeometry ().y () + moveY;
1764
1765 w->configureXWindow (valueMask, &xwc);
1761 }1766 }
1762 }1767 }
1763 }1768 }
@@ -3502,6 +3507,9 @@
35023507
3503 foreach (CompWindow *w, priv->windows)3508 foreach (CompWindow *w, priv->windows)
3504 {3509 {
3510 unsigned int valueMask = CWX | CWY;
3511 XWindowChanges xwc;
3512
3505 if (w->onAllViewports ())3513 if (w->onAllViewports ())
3506 continue;3514 continue;
35073515
@@ -3513,11 +3521,10 @@
3513 if (w->saveMask () & CWY)3521 if (w->saveMask () & CWY)
3514 w->saveWc ().y += pnt.y ();3522 w->saveWc ().y += pnt.y ();
35153523
3516 /* move */3524 xwc.x = w->serverGeometry ().x () + pnt.x ();
3517 w->move (pnt.x (), pnt.y ());3525 xwc.y = w->serverGeometry ().y () + pnt.y ();
35183526
3519 if (sync)3527 w->configureXWindow (valueMask, &xwc);
3520 w->syncPosition ();
3521 }3528 }
35223529
3523 if (sync)3530 if (sync)
35243531
=== modified file 'src/stackdebugger.cpp'
--- src/stackdebugger.cpp 2011-09-25 04:16:18 +0000
+++ src/stackdebugger.cpp 2011-09-27 15:45:28 +0000
@@ -330,6 +330,10 @@
330 if (!w->managed ())330 if (!w->managed ())
331 continue;331 continue;
332332
333 /* ignore any windows that just got created */
334 if (!w->mapNum ())
335 continue;
336
333 /* determine the current layer */337 /* determine the current layer */
334 if (w->type () == CompWindowTypeDockMask)338 if (w->type () == CompWindowTypeDockMask)
335 {339 {
336340
=== modified file 'src/window.cpp'
--- src/window.cpp 2011-09-25 04:16:18 +0000
+++ src/window.cpp 2011-09-27 15:45:28 +0000
@@ -792,32 +792,60 @@
792void792void
793PrivateWindow::updateFrameWindow ()793PrivateWindow::updateFrameWindow ()
794{794{
795 XWindowChanges xwc;
796 unsigned int valueMask = CWX | CWY | CWWidth | CWHeight;
797
795 if (!serverFrame)798 if (!serverFrame)
796 return;799 return;
797800
801
798 gettimeofday (&lastConfigureRequest, NULL);802 gettimeofday (&lastConfigureRequest, NULL);
803 /* Flush any changes made to serverFrameGeometry or serverGeometry to the server
804 * since there is a race condition where geometries will go out-of-sync with
805 * window movement */
806
807 window->syncPosition ();
799808
800 if (serverInput.left || serverInput.right || serverInput.top || serverInput.bottom)809 if (serverInput.left || serverInput.right || serverInput.top || serverInput.bottom)
801 {810 {
802 int x, y, width, height;
803 int bw = serverGeometry.border () * 2;811 int bw = serverGeometry.border () * 2;
804812
805 x = serverGeometry.x () - serverInput.left;813 xwc.x = serverGeometry.x () - serverInput.left;
806 y = serverGeometry.y () - serverInput.top;814 xwc.y = serverGeometry.y () - serverInput.top;
807 width = serverGeometry.width () + serverInput.left + serverInput.right + bw;815 xwc.width = serverGeometry.width () + serverInput.left + serverInput.right + bw;
808 height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;816 xwc.height = serverGeometry.height () + serverInput.top + serverInput.bottom + bw;
809817
810 if (shaded)818 if (shaded)
811 height = serverInput.top + serverInput.bottom;819 height = serverInput.top + serverInput.bottom;
812820
821 if (serverFrameGeometry.x () == xwc.x)
822 valueMask &= ~(CWX);
823 else
824 serverFrameGeometry.setX (xwc.x);
825
826 if (serverFrameGeometry.y () == xwc.y)
827 valueMask &= ~(CWY);
828 else
829 serverFrameGeometry.setY (xwc.y);
830
831 if (serverFrameGeometry.width () == xwc.width)
832 valueMask &= ~(CWWidth);
833 else
834 serverFrameGeometry.setWidth (xwc.width);
835
836 if (serverFrameGeometry.height () == xwc.height)
837 valueMask &= ~(CWHeight);
838 else
839 serverFrameGeometry.setHeight (xwc.height);
840
841 addPendingConfigure (xwc, valueMask);
842
843
813 /* Geometry is the same, so we're not going to get a ConfigureNotify844 /* Geometry is the same, so we're not going to get a ConfigureNotify
814 * event when the window is configured, which means that other plugins845 * event when the window is configured, which means that other plugins
815 * won't know that the client, frame and wrapper windows got shifted846 * won't know that the client, frame and wrapper windows got shifted
816 * around (and might result in display corruption, eg in OpenGL */847 * around (and might result in display corruption, eg in OpenGL */
817 if (geometry.x () - input.left == x &&848 if (valueMask == 0)
818 geometry.y () - input.top == y &&
819 geometry.width () + input.left + input.right + bw == width &&
820 geometry.height () + input.top + input.bottom + bw == height)
821 {849 {
822 XConfigureEvent xev;850 XConfigureEvent xev;
823 XWindowAttributes attrib;851 XWindowAttributes attrib;
@@ -876,8 +904,7 @@
876 XSync (screen->dpy (), false);904 XSync (screen->dpy (), false);
877 }905 }
878 else906 else
879 XMoveResizeWindow (screen->dpy (), serverFrame, x, y, width, height);907 XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
880
881 if (shaded)908 if (shaded)
882 {909 {
883 XUnmapWindow (screen->dpy (), wrapper);910 XUnmapWindow (screen->dpy (), wrapper);
@@ -895,25 +922,44 @@
895 }922 }
896 else923 else
897 {924 {
898 int x, y, width, height;
899 int bw = serverGeometry.border () * 2;925 int bw = serverGeometry.border () * 2;
900926
901 x = serverGeometry.x ();927 xwc.x = serverGeometry.x ();
902 y = serverGeometry.y ();928 xwc.y = serverGeometry.y ();
903 width = serverGeometry.width () + bw;929 xwc.width = serverGeometry.width () + bw;
904 height = serverGeometry.height () + bw;930 xwc.height = serverGeometry.height () + bw;
905931
906 if (shaded)932 if (shaded)
907 height = 0;933 height = 0;
908934
935 if (serverFrameGeometry.x () == xwc.x)
936 valueMask &= ~(CWX);
937 else
938 serverFrameGeometry.setX (xwc.x);
939
940 if (serverFrameGeometry.y () == xwc.y)
941 valueMask &= ~(CWY);
942 else
943 serverFrameGeometry.setY (xwc.y);
944
945 if (serverFrameGeometry.width () == xwc.width)
946 valueMask &= ~(CWWidth);
947 else
948 serverFrameGeometry.setWidth (xwc.width);
949
950 if (serverFrameGeometry.height () == xwc.height)
951 valueMask &= ~(CWHeight);
952 else
953 serverFrameGeometry.setHeight (xwc.height);
954
955 addPendingConfigure (xwc, valueMask);
956
957
909 /* Geometry is the same, so we're not going to get a ConfigureNotify958 /* Geometry is the same, so we're not going to get a ConfigureNotify
910 * event when the window is configured, which means that other plugins959 * event when the window is configured, which means that other plugins
911 * won't know that the client, frame and wrapper windows got shifted960 * won't know that the client, frame and wrapper windows got shifted
912 * around (and might result in display corruption, eg in OpenGL */961 * around (and might result in display corruption, eg in OpenGL */
913 if (geometry.x () - input.left == x &&962 if (valueMask == 0)
914 geometry.y () - input.top == y &&
915 geometry.width () + input.left + input.right + bw == width &&
916 geometry.height () + input.top + input.bottom + bw == height)
917 {963 {
918 XConfigureEvent xev;964 XConfigureEvent xev;
919 XWindowAttributes attrib;965 XWindowAttributes attrib;
@@ -972,7 +1018,7 @@
972 XSync (screen->dpy (), false);1018 XSync (screen->dpy (), false);
973 }1019 }
974 else1020 else
975 XMoveResizeWindow (screen->dpy (), serverFrame, x, y, width, height);1021 XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
9761022
977 if (shaded)1023 if (shaded)
978 {1024 {
@@ -1753,8 +1799,6 @@
1753 dwidth = gm.width () - priv->geometry.width ();1799 dwidth = gm.width () - priv->geometry.width ();
1754 dheight = gm.height () - priv->geometry.height ();1800 dheight = gm.height () - priv->geometry.height ();
17551801
1756 gettimeofday (&priv->lastGeometryUpdate, NULL);
1757
1758 priv->geometry.set (gm.x (), gm.y (),1802 priv->geometry.set (gm.x (), gm.y (),
1759 gm.width (), gm.height (),1803 gm.width (), gm.height (),
1760 gm.border ());1804 gm.border ());
@@ -1776,13 +1820,17 @@
1776 dx = gm.x () - priv->geometry.x ();1820 dx = gm.x () - priv->geometry.x ();
1777 dy = gm.y () - priv->geometry.y ();1821 dy = gm.y () - priv->geometry.y ();
17781822
1779 /* Don't move the window here if a plugin has already updated1823 priv->geometry.setX (gm.x ());
1780 * the geometry of that window after the last time the server1824 priv->geometry.setY (gm.y ());
1781 * was sent a configure request since the configureNotify we1825
1782 * receieve here will be out of date. Instead wait for the plugin1826 priv->region.translate (dx, dy);
1783 * to call syncPosition again */1827 priv->inputRegion.translate (dx, dy);
1784 if (TIMEVALDIFF (&priv->lastConfigureRequest, &priv->lastGeometryUpdate))1828 if (!priv->frameRegion.isEmpty ())
1785 move (dx, dy);1829 priv->frameRegion.translate (dx, dy);
1830
1831 priv->invisible = WINDOW_INVISIBLE (priv);
1832
1833 moveNotify (dx, dy, true);
1786 }1834 }
17871835
1788 updateFrameRegion ();1836 updateFrameRegion ();
@@ -1911,11 +1959,35 @@
1911void1959void
1912PrivateWindow::configure (XConfigureEvent *ce)1960PrivateWindow::configure (XConfigureEvent *ce)
1913{1961{
1962 unsigned int valueMask = 0;
1963
1914 if (priv->frame)1964 if (priv->frame)
1915 return;1965 return;
19161966
1967 /* remove configure event from pending configures */
1968 if (priv->geometry.x () != ce->x)
1969 valueMask |= CWX;
1970
1971 if (priv->geometry.y () != ce->y)
1972 valueMask |= CWY;
1973
1974 if (priv->geometry.width () != ce->width)
1975 valueMask |= CWWidth;
1976
1977 if (priv->geometry.height () != ce->height)
1978 valueMask |= CWHeight;
1979
1980 if (priv->geometry.border () != ce->border_width)
1981 valueMask |= CWBorderWidth;
1982
1983 if (ROOTPARENT (window->prev) != ce->above)
1984 valueMask |= CWSibling | CWStackMode;
1985
1917 priv->attrib.override_redirect = ce->override_redirect;1986 priv->attrib.override_redirect = ce->override_redirect;
19181987
1988 priv->frameGeometry.set (ce->x, ce->y, ce->width,
1989 ce->height, ce->border_width);
1990
1919 if (priv->syncWait)1991 if (priv->syncWait)
1920 priv->syncGeometry.set (ce->x, ce->y, ce->width, ce->height,1992 priv->syncGeometry.set (ce->x, ce->y, ce->width, ce->height,
1921 ce->border_width);1993 ce->border_width);
@@ -1939,10 +2011,89 @@
1939{2011{
1940 int x, y, width, height;2012 int x, y, width, height;
1941 CompWindow *above;2013 CompWindow *above;
2014 unsigned int valueMask = 0;
2015 bool handled = false;
19422016
1943 if (!priv->frame)2017 if (!priv->frame)
1944 return;2018 return;
19452019
2020 /* remove configure event from pending configures */
2021 if (priv->frameGeometry.x () != ce->x)
2022 valueMask |= CWX;
2023
2024 if (priv->frameGeometry.y () != ce->y)
2025 valueMask |= CWY;
2026
2027 if (priv->frameGeometry.width () != ce->width)
2028 valueMask |= CWWidth;
2029
2030 if (priv->frameGeometry.height () != ce->height)
2031 valueMask |= CWHeight;
2032
2033 if (priv->frameGeometry.border () != ce->border_width)
2034 valueMask |= CWBorderWidth;
2035
2036 if (ROOTPARENT (window->prev) != ce->above)
2037 valueMask |= CWSibling | CWStackMode;
2038
2039 for (std::list <XWCValueMask>::iterator it = pendingConfigures.begin ();
2040 it != pendingConfigures.end (); it++)
2041 {
2042 XWCValueMask &xwcvm = (*it);
2043
2044
2045 if (xwcvm.second != valueMask)
2046 {
2047 /* For stacking cases, if a client wants to raise or lower a window
2048 * then they don't need to specify CWSibling, so allow that to be
2049 * excluded in those cases */
2050
2051 if (ce->above == ROOTPARENT (screen->windows ().back ()) ||
2052 ce->above == 0)
2053 {
2054 if ((xwcvm.second & ~(CWSibling) != valueMask))
2055 continue;
2056 }
2057 else
2058 continue;
2059 }
2060
2061 if (xwcvm.second & CWX && xwcvm.first.x != ce->x)
2062 continue;
2063
2064 if (xwcvm.second & CWY && xwcvm.first.y != ce->y)
2065 continue;
2066
2067 if (xwcvm.second & CWWidth && xwcvm.first.width != ce->width)
2068 continue;
2069
2070 if (xwcvm.second & CWHeight && xwcvm.first.height != ce->height)
2071 continue;
2072
2073 if (xwcvm.second & (CWStackMode | CWSibling) && xwcvm.first.sibling != ce->above)
2074 continue;
2075
2076 /* Matched ConfigureWindow request to ConfigureNotify event
2077 * remove it from the list */
2078
2079 handled = true;
2080
2081 pendingConfigures.erase (it);
2082 break;
2083 }
2084
2085 if (!handled)
2086 {
2087 compLogMessage ("core", CompLogLevelWarn, "unhandled ConfigureNotify on 0x%x!", serverFrame);
2088 compLogMessage ("core", CompLogLevelWarn, "this should never happen. you should"\
2089 "probably file a bug about this.");
2090#ifdef DEBUG
2091 abort ();
2092#else
2093 pendingConfigures.clear ();
2094#endif
2095 }
2096
1946 /* subtract the input extents last sent to the2097 /* subtract the input extents last sent to the
1947 * server to calculate the client size and then2098 * server to calculate the client size and then
1948 * re-sync the input extents and extents last2099 * re-sync the input extents and extents last
@@ -1953,19 +2104,14 @@
1953 width = ce->width - priv->serverGeometry.border () * 2 - priv->serverInput.left - priv->serverInput.right;2104 width = ce->width - priv->serverGeometry.border () * 2 - priv->serverInput.left - priv->serverInput.right;
1954 height = ce->height - priv->serverGeometry.border () * 2 - priv->serverInput.top - priv->serverInput.bottom;2105 height = ce->height - priv->serverGeometry.border () * 2 - priv->serverInput.top - priv->serverInput.bottom;
19552106
2107 /* set the frame geometry */
2108 priv->frameGeometry.set (ce->x, ce->y, ce->width, ce->height, ce->border_width);
2109
2110
1956 if (priv->syncWait)2111 if (priv->syncWait)
1957 {
1958 priv->syncGeometry.set (x, y, width, height, ce->border_width);2112 priv->syncGeometry.set (x, y, width, height, ce->border_width);
1959 }
1960 else2113 else
1961 {
1962 if (ce->override_redirect)
1963 {
1964 priv->serverGeometry.set (x, y, width, height, ce->border_width);
1965 }
1966
1967 window->resize (x, y, width, height, ce->border_width);2114 window->resize (x, y, width, height, ce->border_width);
1968 }
19692115
1970 if (priv->restack (ce->above))2116 if (priv->restack (ce->above))
1971 priv->updatePassiveButtonGrabs ();2117 priv->updatePassiveButtonGrabs ();
@@ -1974,6 +2120,27 @@
19742120
1975 if (above)2121 if (above)
1976 above->priv->updatePassiveButtonGrabs ();2122 above->priv->updatePassiveButtonGrabs ();
2123
2124 if (pendingConfigures.empty ())
2125 {
2126 /* Tell plugins its ok to start doing stupid things again but
2127 * obviously FIXME */
2128 CompOption::Vector options;
2129 CompOption::Value v;
2130
2131 options.push_back (CompOption ("window", CompOption::TypeInt));
2132 v.set ((int) id);
2133 options.back ().set (v);
2134 options.push_back (CompOption ("active", CompOption::TypeInt));
2135 v.set ((int) 0);
2136 options.back ().set (v);
2137
2138 /* Notify other plugins that it is unsafe to change geometry or serverGeometry
2139 * FIXME: That API should not be accessible to plugins, this is a hack to avoid
2140 * breaking ABI */
2141
2142 screen->handleCompizEvent ("core", "lock_position", options);
2143 }
1977}2144}
19782145
1979void2146void
@@ -1996,43 +2163,129 @@
1996{2163{
1997 if (dx || dy)2164 if (dx || dy)
1998 {2165 {
1999 /*
2000 priv->attrib.x += dx;
2001 priv->attrib.y += dy;
2002 */
2003 priv->geometry.setX (priv->geometry.x () + dx);
2004 priv->geometry.setY (priv->geometry.y () + dy);
2005
2006 gettimeofday (&priv->lastGeometryUpdate, NULL);2166 gettimeofday (&priv->lastGeometryUpdate, NULL);
20072167
2008 priv->region.translate (dx, dy);2168 /* Don't allow window movement to overwrite working geometries
2009 priv->inputRegion.translate (dx, dy);2169 * last received from the server if we know there are pending
2010 if (!priv->frameRegion.isEmpty ())2170 * ConfigureNotify events on this window. That's a clunky workaround
2011 priv->frameRegion.translate (dx, dy);2171 * and a FIXME in any case, however, until we can break the API
20122172 * and remove CompWindow::move, this will need to be the case */
2013 priv->invisible = WINDOW_INVISIBLE (priv);2173
20142174 if (!priv->pendingConfigures.size ())
2015 moveNotify (dx, dy, immediate);2175 {
2176 priv->geometry.setX (priv->geometry.x () + dx);
2177 priv->geometry.setY (priv->geometry.y () + dy);
2178 priv->frameGeometry.setX (priv->frameGeometry.x () + dx);
2179 priv->frameGeometry.setY (priv->frameGeometry.y () + dy);
2180
2181 priv->pendingPositionUpdates = true;
2182
2183 priv->region.translate (dx, dy);
2184 priv->inputRegion.translate (dx, dy);
2185 if (!priv->frameRegion.isEmpty ())
2186 priv->frameRegion.translate (dx, dy);
2187
2188 priv->invisible = WINDOW_INVISIBLE (priv);
2189
2190 moveNotify (dx, dy, immediate);
2191 }
2192 else
2193 {
2194 XWindowChanges xwc;
2195 unsigned int valueMask = CWX | CWY;
2196 struct timeval tv, old;
2197 compLogMessage ("core", CompLogLevelDebug, "pending configure notifies on 0x%x,"\
2198 "moving window asyncrhonously!", (unsigned int) priv->serverId);
2199
2200 old = priv->lastConfigureRequest;
2201 gettimeofday (&tv, NULL);
2202
2203 xwc.x = priv->serverGeometry.x () + dx;
2204 xwc.y = priv->serverGeometry.y () + dy;
2205
2206 configureXWindow (valueMask, &xwc);
2207
2208 priv->lastConfigureRequest = old;
2209
2210 /* FIXME: This is a hack to avoid performance regressions
2211 * and must be removed in 0.9.6 */
2212 if (tv.tv_usec - priv->lastConfigureRequest.tv_usec > 30000)
2213 {
2214 compLogMessage ("core", CompLogLevelWarn, "failed to receive ConfigureNotify event from request at %i (now: %i)\n",
2215 priv->lastConfigureRequest.tv_usec, tv.tv_usec);
2216 priv->pendingConfigures.clear ();
2217 }
2218 }
2016 }2219 }
2017}2220}
20182221
2019void2222void
2223PrivateWindow::addPendingConfigure (XWindowChanges &xwc, unsigned int valueMask)
2224{
2225 CompOption::Vector options;
2226 CompOption::Value v;
2227
2228 options.push_back (CompOption ("window", CompOption::TypeInt));
2229 v.set ((int) id);
2230 options.back ().set (v);
2231 options.push_back (CompOption ("active", CompOption::TypeInt));
2232 v.set ((int) 1);
2233 options.back ().set (v);
2234
2235 gettimeofday (&lastConfigureRequest, NULL);
2236
2237 /* Notify other plugins that it is unsafe to change geometry or serverGeometry
2238 * FIXME: That API should not be accessible to plugins, this is a hack to avoid
2239 * breaking ABI */
2240
2241 screen->handleCompizEvent ("core", "lock_position", options);
2242
2243 priv->pendingConfigures.push_back (XWCValueMask (xwc, valueMask));
2244}
2245
2246void
2020CompWindow::syncPosition ()2247CompWindow::syncPosition ()
2021{2248{
2022 priv->serverGeometry.setX (priv->geometry.x ());
2023 priv->serverGeometry.setY (priv->geometry.y ());
2024
2025 gettimeofday (&priv->lastConfigureRequest, NULL);2249 gettimeofday (&priv->lastConfigureRequest, NULL);
20262250
2027 XMoveWindow (screen->dpy (), ROOTPARENT (this),2251 unsigned int valueMask = CWX | CWY;
2028 priv->serverGeometry.x () - priv->serverInput.left,2252 XWindowChanges xwc;
2029 priv->serverGeometry.y () - priv->serverInput.top);
20302253
2031 if (priv->serverFrame)2254 if (priv->pendingPositionUpdates && priv->pendingConfigures.empty ())
2032 {2255 {
2033 XMoveWindow (screen->dpy (), priv->wrapper,2256 if (priv->serverFrameGeometry.x () == priv->frameGeometry.x ())
2034 priv->serverInput.left, priv->serverInput.top);2257 valueMask &= ~(CWX);
2035 sendConfigureNotify ();2258 if (priv->serverFrameGeometry.y () == priv->frameGeometry.y ())
2259 valueMask &= ~(CWY);
2260
2261 /* Because CompWindow::move can update the geometry last
2262 * received from the server, we must indicate that no values
2263 * changed, because when the ConfigureNotify comes around
2264 * the values are going to be the same. That's obviously
2265 * broken behaviour and worthy of a FIXME, but requires
2266 * larger changes to the window movement system. */
2267 if (valueMask)
2268 {
2269 priv->addPendingConfigure (xwc, 0);
2270
2271 priv->serverGeometry.setX (priv->geometry.x ());
2272 priv->serverGeometry.setY (priv->geometry.y ());
2273 priv->serverFrameGeometry.setX (priv->frameGeometry.x ());
2274 priv->serverFrameGeometry.setY (priv->frameGeometry.y ());
2275
2276 xwc.x = priv->serverFrameGeometry.x ();
2277 xwc.y = priv->serverFrameGeometry.y ();
2278
2279 XConfigureWindow (screen->dpy (), ROOTPARENT (this), valueMask, &xwc);
2280
2281 if (priv->serverFrame)
2282 {
2283 XMoveWindow (screen->dpy (), priv->wrapper,
2284 priv->serverInput.left, priv->serverInput.top);
2285 sendConfigureNotify ();
2286 }
2287 }
2288 priv->pendingPositionUpdates = false;
2036 }2289 }
2037}2290}
20382291
@@ -2185,11 +2438,13 @@
2185 vp = defaultViewport ();2438 vp = defaultViewport ();
2186 if (screen->vp () != vp)2439 if (screen->vp () != vp)
2187 {2440 {
2188 int moveX = (screen->vp ().x () - vp.x ()) * screen->width ();2441 unsigned int valueMask = CWX | CWY;
2189 int moveY = (screen->vp ().y () - vp.y ()) * screen->height ();2442 XWindowChanges xwc;
21902443
2191 move (moveX, moveY, TRUE);2444 xwc.x = serverGeometry ().x () + (screen->vp ().x () - vp.x ()) * screen->width ();
2192 syncPosition ();2445 xwc.y = serverGeometry ().y () + (screen->vp ().y () - vp.y ()) * screen->height ();
2446
2447 configureXWindow (valueMask, &xwc);
2193 }2448 }
2194 }2449 }
2195}2450}
@@ -2749,6 +3004,54 @@
2749PrivateWindow::reconfigureXWindow (unsigned int valueMask,3004PrivateWindow::reconfigureXWindow (unsigned int valueMask,
2750 XWindowChanges *xwc)3005 XWindowChanges *xwc)
2751{3006{
3007 unsigned int frameValueMask = valueMask;
3008
3009 /* Immediately sync window position
3010 * if plugins were updating w->geometry () directly
3011 * in order to avoid a race condition */
3012
3013 window->syncPosition ();
3014
3015 /* Remove redundant bits */
3016
3017 if (serverGeometry.x () == xwc->x)
3018 valueMask &= ~(CWX);
3019
3020 if (serverGeometry.y () == xwc->y)
3021 valueMask &= ~(CWY);
3022
3023 if (serverGeometry.width () == xwc->width)
3024 valueMask &= ~(CWWidth);
3025
3026 if (serverGeometry.height () == xwc->height)
3027 valueMask &= ~(CWHeight);
3028
3029 if (serverGeometry.border () == xwc->border_width)
3030 valueMask &= ~(CWBorderWidth);
3031
3032 if (window->serverPrev && ROOTPARENT (window->serverPrev) == xwc->sibling)
3033 {
3034 /* check if the sibling is also pending a restack,
3035 * if not, then setting this bit is useless */
3036
3037 bool pendingRestack = false;
3038
3039 foreach (XWCValueMask &xwcvm, window->serverPrev->priv->pendingConfigures)
3040 {
3041 if (xwcvm.second & (CWSibling | CWStackMode))
3042 {
3043 pendingRestack = true;
3044 break;
3045 }
3046 }
3047
3048 if (!pendingRestack)
3049 valueMask &= ~(CWSibling | CWStackMode);
3050 }
3051
3052 if (valueMask & CWBorderWidth)
3053 serverGeometry.setBorder (xwc->border_width);
3054
2752 if (valueMask & CWX)3055 if (valueMask & CWX)
2753 serverGeometry.setX (xwc->x);3056 serverGeometry.setX (xwc->x);
27543057
@@ -2761,9 +3064,6 @@
2761 if (valueMask & CWHeight)3064 if (valueMask & CWHeight)
2762 serverGeometry.setHeight (xwc->height);3065 serverGeometry.setHeight (xwc->height);
27633066
2764 if (valueMask & CWBorderWidth)
2765 serverGeometry.setBorder (xwc->border_width);
2766
2767 /* Update the server side window list on raise, lower and restack functions.3067 /* Update the server side window list on raise, lower and restack functions.
2768 * This function should only recieve stack_mode == Above3068 * This function should only recieve stack_mode == Above
2769 * but warn incase something else does get through, to make the cause3069 * but warn incase something else does get through, to make the cause
@@ -2774,41 +3074,80 @@
2774 {3074 {
2775 if (xwc->sibling)3075 if (xwc->sibling)
2776 {3076 {
2777 CompWindow *w = screen->findWindow (id);3077 screen->unhookServerWindow (window);
27783078 screen->insertServerWindow (window, xwc->sibling);
2779 screen->unhookServerWindow (w);
2780 screen->insertServerWindow (w, xwc->sibling);
2781 }3079 }
2782 }3080 }
2783 else3081 else
2784 compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");3082 compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");
2785 }3083 }
27863084
3085 if (serverFrameGeometry.x () == xwc->x - serverGeometry.border () - serverInput.left)
3086 frameValueMask &= ~(CWX);
3087
3088 if (serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top)
3089 frameValueMask &= ~(CWY);
3090
3091 if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
3092 + serverInput.left + serverInput.right)
3093 frameValueMask &= ~(CWWidth);
3094
3095 if (serverFrameGeometry.height () == xwc->height + serverGeometry.border () * 2
3096 + serverInput.top + serverInput.bottom)
3097 frameValueMask &= ~(CWHeight);
3098
3099 /* Can't set the border width of frame windows */
3100 frameValueMask &= ~(CWBorderWidth);
3101
3102 if (frameValueMask & CWX)
3103 serverFrameGeometry.setX (xwc->x - serverGeometry.border () - serverInput.left);
3104
3105 if (frameValueMask & CWY)
3106 serverFrameGeometry.setY (xwc->y -serverGeometry.border () - serverInput.top);
3107
3108 if (frameValueMask & CWWidth)
3109 serverFrameGeometry.setWidth (xwc->width + serverGeometry.border () * 2
3110 + serverInput.left + serverInput.right);
3111
3112 if (frameValueMask & CWHeight)
3113 serverFrameGeometry.setHeight (xwc->height + serverGeometry.border () * 2
3114 + serverInput.top + serverInput.bottom);
3115
3116
2787 if (serverFrame)3117 if (serverFrame)
2788 {3118 {
2789 XWindowChanges wc = *xwc;
2790
2791 gettimeofday (&lastConfigureRequest, NULL);3119 gettimeofday (&lastConfigureRequest, NULL);
27923120
2793 wc.x -= serverInput.left - serverGeometry.border ();3121 if (frameValueMask)
2794 wc.y -= serverInput.top - serverGeometry.border ();3122 {
2795 wc.width += serverInput.left + serverInput.right + serverGeometry.border ();3123 XWindowChanges wc = *xwc;
2796 wc.height += serverInput.top + serverInput.bottom + serverGeometry.border ();3124
27973125 wc.x = serverFrameGeometry.x ();
2798 XConfigureWindow (screen->dpy (), serverFrame, valueMask, &wc);3126 wc.y = serverFrameGeometry.y ();
3127 wc.width = serverFrameGeometry.width ();
3128 wc.height = serverFrameGeometry.height ();
3129
3130 addPendingConfigure (wc, frameValueMask);
3131
3132 XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc);
3133 }
2799 valueMask &= ~(CWSibling | CWStackMode);3134 valueMask &= ~(CWSibling | CWStackMode);
28003135
2801 xwc->x = serverInput.left;3136 if (valueMask)
2802 xwc->y = serverInput.top;3137 {
2803 XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);3138 xwc->x = serverInput.left;
3139 xwc->y = serverInput.top;
3140 XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);
28043141
2805 xwc->x = 0;3142 xwc->x = 0;
2806 xwc->y = 0;3143 xwc->y = 0;
3144 }
28073145
2808 window->sendConfigureNotify ();3146 window->sendConfigureNotify ();
2809 }3147 }
28103148
2811 XConfigureWindow (screen->dpy (), id, valueMask, xwc);3149 if (valueMask)
3150 XConfigureWindow (screen->dpy (), id, valueMask, xwc);
2812}3151}
28133152
2814bool3153bool
@@ -3574,9 +3913,30 @@
3574 * if serverPrev was recently restacked */3913 * if serverPrev was recently restacked */
3575 if (window->serverPrev)3914 if (window->serverPrev)
3576 {3915 {
3577 if (!sibling)3916 bool pendingRestacks = false;
3578 {3917
3579 XLowerWindow (screen->dpy (), ROOTPARENT (window));3918 foreach (XWCValueMask &xwcvm, sibling->priv->pendingConfigures)
3919 {
3920 if (xwcvm.second & (CWSibling | CWStackMode))
3921 {
3922 pendingRestacks = true;
3923 break;
3924 }
3925 }
3926
3927 if (!sibling && window->serverPrev)
3928 {
3929 XWindowChanges xwc;
3930 unsigned int valueMask = CWStackMode;
3931
3932 xwc.stack_mode = Below;
3933
3934 /* Below with no sibling puts the window at the bottom
3935 * of the stack */
3936 XConfigureWindow (screen->dpy (), ROOTPARENT (window), valueMask, &xwc);
3937
3938 if (serverFrame)
3939 priv->addPendingConfigure (xwc, CWStackMode);
35803940
3581 /* Update the list of windows last sent to the server */3941 /* Update the list of windows last sent to the server */
3582 screen->unhookServerWindow (window);3942 screen->unhookServerWindow (window);
@@ -5410,6 +5770,8 @@
54105770
5411 if (tx || ty)5771 if (tx || ty)
5412 {5772 {
5773 unsigned int valueMask = CWX | CWY;
5774 XWindowChanges xwc;
5413 int m, wx, wy;5775 int m, wx, wy;
54145776
5415 if (!priv->managed)5777 if (!priv->managed)
@@ -5450,10 +5812,10 @@
5450 if (priv->saveMask & CWY)5812 if (priv->saveMask & CWY)
5451 priv->saveWc.y += wy;5813 priv->saveWc.y += wy;
54525814
5453 move (wx, wy);5815 xwc.x = serverGeometry ().x () + wx;
5816 xwc.y = serverGeometry ().y () + wy;
54545817
5455 if (sync)5818 configureXWindow (valueMask, &xwc);
5456 syncPosition ();
5457 }5819 }
5458}5820}
54595821
@@ -5659,18 +6021,14 @@
5659 if (dbg)6021 if (dbg)
5660 dbg->overrideRedirectRestack (priv->id, aboveId);6022 dbg->overrideRedirectRestack (priv->id, aboveId);
56616023
5662 gettimeofday (&priv->lastGeometryUpdate, NULL);6024 gettimeofday (&priv->lastConfigureRequest, NULL);
56636025
5664 priv->attrib = wa;6026 priv->attrib = wa;
5665 priv->serverGeometry.set (priv->attrib.x, priv->attrib.y,6027 priv->serverGeometry.set (priv->attrib.x, priv->attrib.y,
5666 priv->attrib.width, priv->attrib.height,6028 priv->attrib.width, priv->attrib.height,
5667 priv->attrib.border_width);6029 priv->attrib.border_width);
5668 priv->syncGeometry.set (priv->attrib.x, priv->attrib.y,6030 priv->serverFrameGeometry = priv->frameGeometry = priv->syncGeometry
5669 priv->attrib.width, priv->attrib.height,6031 = priv->geometry = priv->serverGeometry;
5670 priv->attrib.border_width);
5671 priv->geometry.set (priv->attrib.x, priv->attrib.y,
5672 priv->attrib.width, priv->attrib.height,
5673 priv->attrib.border_width);
56746032
5675 priv->width = priv->attrib.width + priv->attrib.border_width * 2;6033 priv->width = priv->attrib.width + priv->attrib.border_width * 2;
5676 priv->height = priv->attrib.height + priv->attrib.border_width * 2;6034 priv->height = priv->attrib.height + priv->attrib.border_width * 2;
@@ -5982,6 +6340,7 @@
59826340
5983 pendingUnmaps (0),6341 pendingUnmaps (0),
5984 pendingMaps (0),6342 pendingMaps (0),
6343 pendingPositionUpdates (false),
59856344
5986 startupId (0),6345 startupId (0),
5987 resName (0),6346 resName (0),
@@ -6278,7 +6637,6 @@
6278 XSync (dpy, false);6637 XSync (dpy, false);
6279 return false;6638 return false;
6280 }6639 }
6281 gettimeofday (&lastConfigureRequest, NULL);
62826640
6283 if (wa.override_redirect)6641 if (wa.override_redirect)
6284 return false;6642 return false;
@@ -6309,7 +6667,7 @@
63096667
6310 priv->serverGeometry.setBorder (0);6668 priv->serverGeometry.setBorder (0);
63116669
6312 mask = CWBorderPixel | CWColormap | CWBackPixmap;6670 mask = CWBorderPixel | CWColormap | CWBackPixmap | CWOverrideRedirect;
63136671
6314 if (wa.depth == 32)6672 if (wa.depth == 32)
6315 {6673 {
@@ -6427,6 +6785,11 @@
6427 SubstructureNotifyMask | EnterWindowMask |6785 SubstructureNotifyMask | EnterWindowMask |
6428 LeaveWindowMask;6786 LeaveWindowMask;
64296787
6788 serverFrameGeometry = serverGeometry;
6789
6790 XMoveResizeWindow (dpy, serverFrame, serverFrameGeometry.x (), serverFrameGeometry.y (),
6791 serverFrameGeometry.width (), serverFrameGeometry.height ());
6792
6430 XChangeWindowAttributes (dpy, serverFrame, CWEventMask, &attr);6793 XChangeWindowAttributes (dpy, serverFrame, CWEventMask, &attr);
6431 XChangeWindowAttributes (dpy, wrapper, CWEventMask, &attr);6794 XChangeWindowAttributes (dpy, wrapper, CWEventMask, &attr);
64326795
@@ -6447,9 +6810,6 @@
6447 XUngrabServer (dpy);6810 XUngrabServer (dpy);
6448 XSync (dpy, false);6811 XSync (dpy, false);
64496812
6450 XMoveResizeWindow (dpy, serverFrame, wa.x, wa.y,
6451 wa.width, wa.height);
6452
6453 window->windowNotify (CompWindowNotifyReparent);6813 window->windowNotify (CompWindowNotifyReparent);
64546814
6455 return true;6815 return true;
@@ -6508,6 +6868,14 @@
6508 /* Wait for the reparent to finish */6868 /* Wait for the reparent to finish */
6509 XSync (dpy, false);6869 XSync (dpy, false);
65106870
6871 xwc.x = serverGeometry.x () - serverGeometry.border ();
6872 xwc.y = serverGeometry.y () - serverGeometry.border ();
6873 xwc.width = serverGeometry.width () + serverGeometry.border () * 2;
6874 xwc.height = serverGeometry.height () + serverGeometry.border () * 2;
6875
6876 XConfigureWindow (dpy, serverFrame, CWX | CWY | CWWidth | CWHeight, &xwc);
6877
6878
6511 xwc.stack_mode = Below;6879 xwc.stack_mode = Below;
6512 xwc.sibling = serverFrame;6880 xwc.sibling = serverFrame;
6513 XConfigureWindow (dpy, id, CWSibling | CWStackMode, &xwc);6881 XConfigureWindow (dpy, id, CWSibling | CWStackMode, &xwc);

Subscribers

People subscribed via source and target branches