Blob Blame History Raw
Description: Fix window edge behaviour
Author: https://bugs.launchpad.net/bugs/103306

--- a/metadata/wall.xml.in
+++ b/metadata/wall.xml.in
@@ -280,6 +280,7 @@
 						<_short>Flip Left</_short>
 						<_long>Flip left</_long>
 						<nodelay>true</nodelay>
+  						<passive_grab>false</passive_grab>
 						<default>
 							<edge name="Left"/>
 						</default>
@@ -289,6 +290,7 @@
 						<_short>Flip Right</_short>
 						<_long>Flip right</_long>
 						<nodelay>true</nodelay>
+  						<passive_grab>false</passive_grab>
 						<default>
 							<edge name="Right"/>
 						</default>
@@ -298,6 +300,7 @@
 						<_short>Flip Up</_short>
 						<_long>Flip up</_long>
 						<nodelay>true</nodelay>
+  						<passive_grab>false</passive_grab>
 						<default>
 							<edge name="Top"/>
 						</default>
@@ -307,6 +310,7 @@
 						<_short>Flip Down</_short>
 						<_long>Flip down</_long>
 						<nodelay>true</nodelay>
+  						<passive_grab>false</passive_grab>
 						<default>
 							<edge name="Bottom"/>
 						</default>
--- a/src/wall/wall.c
+++ b/src/wall/wall.c
@@ -111,6 +111,8 @@ typedef struct _WallScreen
     WindowUngrabNotifyProc       windowUngrabNotify;
     ActivateWindowProc           activateWindow;
 
+    int grabCount;
+
     Bool moving; /* Used to track miniview movement */
     Bool showPreview;
 
@@ -178,6 +180,38 @@ typedef struct _WallWindow
 
 
 static void
+wallScreenOptionChangeNotify (CompScreen *s, CompOption *opt,
+			      WallScreenOptions num)
+{
+    WALL_SCREEN (s);
+
+    if (ws->grabCount == -1 || ws->grabCount > 0)
+    {
+	removeScreenAction (s, wallGetFlipLeftEdge(s->display));
+	removeScreenAction (s, wallGetFlipRightEdge(s->display));
+	removeScreenAction (s, wallGetFlipUpEdge(s->display));
+	removeScreenAction (s, wallGetFlipDownEdge(s->display));
+    }
+
+    if (wallGetEdgeflipPointer (s) || wallGetEdgeflipMove (s) ||
+	wallGetEdgeflipDnd (s))
+    {
+	if (!wallGetEdgeflipPointer (s) && !wallGetEdgeflipDnd (s))
+	    ws->grabCount = 0;
+	else
+	{
+	    ws->grabCount = -1;
+	    addScreenAction (s, wallGetFlipLeftEdge(s->display));
+	    addScreenAction (s, wallGetFlipRightEdge(s->display));
+	    addScreenAction (s, wallGetFlipUpEdge(s->display));
+	    addScreenAction (s, wallGetFlipDownEdge(s->display));
+	}
+    }
+    else
+	ws->grabCount = -2;
+}
+
+static void
 wallClearCairoLayer (cairo_t *cr)
 {
     cairo_save (cr);
@@ -1903,11 +1937,25 @@ wallWindowGrabNotify (CompWindow   *w,
 		      unsigned int state,
 		      unsigned int mask)
 {
-    WALL_SCREEN (w->screen);
+    CompScreen *s = w->screen;
+    WALL_SCREEN (s);
 
     if (!ws->grabWindow)
 	ws->grabWindow = w;
 
+    if (ws->grabCount >= 0)
+    {
+	if (!ws->grabCount)
+	{
+	    addScreenAction (s, wallGetFlipLeftEdge(s->display));
+	    addScreenAction (s, wallGetFlipRightEdge(s->display));
+	    addScreenAction (s, wallGetFlipUpEdge(s->display));
+	    addScreenAction (s, wallGetFlipDownEdge(s->display));
+	}
+
+	ws->grabCount++;
+    }
+
     UNWRAP (ws, w->screen, windowGrabNotify);
     (*w->screen->windowGrabNotify) (w, x, y, state, mask);
     WRAP (ws, w->screen, windowGrabNotify, wallWindowGrabNotify);
@@ -1916,11 +1964,25 @@ wallWindowGrabNotify (CompWindow   *w,
 static void
 wallWindowUngrabNotify (CompWindow *w)
 {
-    WALL_SCREEN (w->screen);
+    CompScreen *s = w->screen;
+    WALL_SCREEN (s);
 
     if (w == ws->grabWindow)
 	ws->grabWindow = NULL;
 
+    if (ws->grabCount >= 0)
+    {
+	ws->grabCount--;
+
+	if (!ws->grabCount)
+	{
+	    removeScreenAction (s, wallGetFlipLeftEdge(s->display));
+	    removeScreenAction (s, wallGetFlipRightEdge(s->display));
+	    removeScreenAction (s, wallGetFlipUpEdge(s->display));
+	    removeScreenAction (s, wallGetFlipDownEdge(s->display));
+	}
+    }
+
     UNWRAP (ws, w->screen, windowUngrabNotify);
     (*w->screen->windowUngrabNotify) (w);
     WRAP (ws, w->screen, windowUngrabNotify, wallWindowUngrabNotify);
@@ -2122,6 +2184,8 @@ wallInitScreen (CompPlugin *p,
     ws->transform  = NoTransformation;
     ws->direction  = -1;
 
+    ws->grabCount = 0;
+
     memset (&ws->switcherContext, 0, sizeof (WallCairoContext));
     memset (&ws->thumbContext, 0, sizeof (WallCairoContext));
     memset (&ws->highlightContext, 0, sizeof (WallCairoContext));
@@ -2137,6 +2201,27 @@ wallInitScreen (CompPlugin *p,
     WRAP (ws, s, windowUngrabNotify, wallWindowUngrabNotify);
     WRAP (ws, s, activateWindow, wallActivateWindow);
 
+    wallSetEdgeflipPointerNotify (s, wallScreenOptionChangeNotify);
+    wallSetEdgeflipMoveNotify (s, wallScreenOptionChangeNotify);
+    wallSetEdgeflipDndNotify (s, wallScreenOptionChangeNotify);
+
+    if (wallGetEdgeflipPointer (s) || wallGetEdgeflipMove (s) ||
+	wallGetEdgeflipDnd (s))
+    {
+	if (!wallGetEdgeflipPointer (s) && !wallGetEdgeflipDnd (s))
+	    ws->grabCount = 0;
+	else
+	{
+	    ws->grabCount = -1;
+	    addScreenAction (s, wallGetFlipLeftEdge(s->display));
+	    addScreenAction (s, wallGetFlipRightEdge(s->display));
+	    addScreenAction (s, wallGetFlipUpEdge(s->display));
+	    addScreenAction (s, wallGetFlipDownEdge(s->display));
+	}
+    }
+    else
+	ws->grabCount = -2;
+
     s->base.privates[wd->screenPrivateIndex].ptr = ws;
 
     wallCreateCairoContexts (s, TRUE);
@@ -2170,6 +2255,14 @@ wallFiniScreen (CompPlugin *p,
     
     freeWindowPrivateIndex (s, ws->windowPrivateIndex);
 
+    if (ws->grabCount > 0 || ws->grabCount == -1)
+    {
+	removeScreenAction (s, wallGetFlipLeftEdge(s->display));
+	removeScreenAction (s, wallGetFlipRightEdge(s->display));
+	removeScreenAction (s, wallGetFlipUpEdge(s->display));
+	removeScreenAction (s, wallGetFlipDownEdge(s->display));
+    }
+
     free(ws);
 }