All pastes #431515 Raw Edit

Stuff

public text v1 · immutable
·published 2007-04-09 18:47 UTC
rendered paste body
diff --git a/include/compiz.h b/include/compiz.h
index 027a0e3..8ed0668 100644
--- a/include/compiz.h
+++ b/include/compiz.h
@@ -26,7 +26,7 @@
 #ifndef _COMPIZ_H
 #define _COMPIZ_H
 
-#define ABIVERSION 20070403
+#define ABIVERSION 20070405
 
 #include <stdio.h>
 #include <sys/time.h>
@@ -1150,6 +1150,12 @@ typedef void (*DonePaintScreenProc) (CompScreen *screen);
 #define PAINT_SCREEN_TRANSFORMED_MASK		   (1 << 2)
 #define PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK (1 << 3)
 #define PAINT_SCREEN_CLEAR_MASK			   (1 << 4)
+#define PAINT_SCREEN_ORDER_BACK_TO_FRONT_MASK	   (1 << 5)
+#define PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK	   (1 << 6)
+/* A plugin that sets PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK will get reversed painting.
+   A plugin that sets  both PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK and PAINT_SCREEN_ORDER_BACK_TO_FRONT_MASK
+   will get both normal and reversed painting one after the other,
+   and will check paint window mask to avoid painting the window twice. This allows more complex drawing order.*/
 
 typedef Bool (*PaintScreenProc) (CompScreen		 *screen,
 				 const ScreenPaintAttrib *sAttrib,
@@ -1215,6 +1221,13 @@ typedef void (*ApplyScreenTransformProc) (CompScreen		  *screen,
 */
 #define PAINT_WINDOW_BLEND_MASK			(1 << 19)
 
+/*
+ flags that indicate the painting order which is used
+ in paintScreen when drawing the window.
+*/
+#define PAINT_WINDOW_BACK_TO_FRONT_MASK		(1 << 20)
+#define PAINT_WINDOW_FRONT_TO_BACK_MASK		(1 << 21)
+
 
 typedef Bool (*PaintWindowProc) (CompWindow		 *window,
 				 const WindowPaintAttrib *attrib,
@@ -1252,6 +1265,10 @@ typedef void (*PaintBackgroundProc) (CompScreen   *screen,
 				     Region	  region,
 				     unsigned int mask);
 
+typedef void (*SetClipPlanesProc) (CompScreen *screen, Region region, int output);
+
+void setClipPlanes (CompScreen *screen, Region region, int output);
+
 void
 preparePaintScreen (CompScreen *screen,
 		    int	       msSinceLastPaint);
@@ -1922,6 +1939,7 @@ struct _CompScreen {
     GetOutputExtentsForWindowProc  getOutputExtentsForWindow;
     GetAllowedActionsForWindowProc getAllowedActionsForWindow;
     FocusWindowProc		   focusWindow;
+    SetClipPlanesProc		   setClipPlanes;
 
     PaintCursorProc      paintCursor;
     DamageCursorRectProc damageCursorRect;
diff --git a/plugins/cube.c b/plugins/cube.c
index 6784a45..eed6310 100644
--- a/plugins/cube.c
+++ b/plugins/cube.c
@@ -108,6 +108,8 @@ typedef struct _CubeDisplay {
     int		    screenPrivateIndex;
 
     CompOption opt[CUBE_DISPLAY_OPTION_NUM];
+    
+    HandleCompizEventProc handleCompizEvent;
 } CubeDisplay;
 
 #define CUBE_SCREEN_OPTION_COLOR	      0
@@ -133,6 +135,9 @@ typedef struct _CubeScreen {
     ApplyScreenTransformProc   applyScreenTransform;
     SetScreenOptionProc	       setScreenOption;
     OutputChangeNotifyProc     outputChangeNotify;
+    SetClipPlanesProc          setClipPlanes;
+    PaintBackgroundProc        paintBackground;
+    PaintWindowProc            paintWindow;
 
     CompOption opt[CUBE_SCREEN_OPTION_NUM];
 
@@ -178,6 +183,11 @@ typedef struct _CubeScreen {
     float outputYScale;
     float outputXOffset;
     float outputYOffset;
+    
+    Bool disableCaps;
+    Bool paintAllViewports;
+    
+    float desktopOpacity;
 
 #ifdef USE_LIBRSVG
     cairo_t	    *cr;
@@ -1217,6 +1227,76 @@ cubeDonePaintScreen (CompScreen *s)
 }
 
 static void
+cubePaintBackground(CompScreen * s, Region region, unsigned int mask)
+{
+    CUBE_SCREEN(s);
+
+    if (cs->desktopOpacity != OPAQUE)
+    {
+	if (s->desktopWindowCount)
+	{
+	    glColor4us(0, 0, 0, 0);
+	    glEnable(GL_BLEND);
+	}
+	else
+	{
+	    glColor4us(0xffff, 0xffff, 0xffff, cs->desktopOpacity);
+	    glEnable(GL_BLEND);
+	    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	}
+    }
+
+    UNWRAP (cs, s, paintBackground);
+    (*s->paintBackground) (s, region, mask);
+    WRAP (cs, s, paintBackground, cubePaintBackground);
+
+    if (cs->desktopOpacity != OPAQUE)
+    {
+	if (s->desktopWindowCount)
+	{
+	    glColor3usv(defaultColor);
+	    glDisable(GL_BLEND);
+	}
+	else
+	{
+	    glColor3usv(defaultColor);
+	    glDisable(GL_BLEND);
+	    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+	    screenTexEnvMode(s, GL_REPLACE);
+	}
+    }
+}
+
+static Bool
+cubePaintWindow (CompWindow		  *w,
+		 const WindowPaintAttrib  *attrib,
+		 const CompTransform	  *transform,
+		 Region			  region,
+		 unsigned int		  mask)
+{
+    Bool status;
+    CompScreen* s = w->screen;
+    CUBE_SCREEN(s);
+    
+    WindowPaintAttrib wa = *attrib;
+
+    if (w->type & CompWindowTypeDesktopMask)
+    {
+	if (cs->desktopOpacity == 0)
+	    return TRUE;
+	wa.opacity = cs->desktopOpacity;
+    }
+
+
+    UNWRAP (cs, s, paintWindow);
+    status = (*s->paintWindow) (w, &wa, transform, region, mask);
+    WRAP (cs, s, paintWindow, cubePaintWindow);
+    
+    return status;
+}
+
+static void
 cubeMoveViewportAndPaint (CompScreen		  *s,
 			  const ScreenPaintAttrib *sAttrib,
 			  const CompTransform	  *transform,
@@ -1225,7 +1305,22 @@ cubeMoveViewportAndPaint (CompScreen		  *s,
 			  int			  dx)
 {
     CUBE_SCREEN (s);
-
+    
+    float angle = sAttrib->xRotate + sAttrib->yRotate;
+    
+    // fix angle to be between -180 and 180
+    while (angle < -180.0f || angle > 180.0f)
+    {
+    	if (angle < -180.0f)
+    		angle += 360.0f;
+    	else
+    		angle -= 360.0f;
+    }
+    
+    // Don't paint if the viewport isn't visible.
+    if ((angle > 90.0f || angle < -90.0f) && !cs->paintAllViewports && cs->desktopOpacity == OPAQUE)
+	return;
+    
     if (cs->nOutput > 1)
     {
 	int cubeOutput, dView;
@@ -1277,12 +1372,20 @@ cubePaintTransformedScreen (CompScreen		    *s,
     int		      hsize, xMove = 0;
     float	      size;
     Bool	      clear;
+    Bool wasCulled;
 
     CUBE_SCREEN (s);
 
     hsize = s->hsize * cs->nOutput;
     size  = hsize;
 
+    if (cs->desktopOpacity != OPAQUE)
+    {
+	wasCulled = glIsEnabled(GL_CULL_FACE);
+	if (wasCulled)
+	    glDisable(GL_CULL_FACE);
+    }
+
     if (!cs->fullscreenOutput)
     {
 	cs->outputXScale = (float) s->width / s->outputDev[output].width;
@@ -1386,21 +1489,16 @@ cubePaintTransformedScreen (CompScreen		    *s,
 
 	sa.zTranslate = -cs->invert * cs->distance;
 	sa.xRotate = sAttrib->xRotate * cs->invert;
+	
 	if (sa.xRotate > 0.0f)
-	{
-	    cs->xrotations = (int) (size * sa.xRotate) / 360;
-	    sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / size;
-	}
+		cs->xrotations = (int) (size * sa.xRotate + 180) / 360;
 	else
-	{
-	    cs->xrotations = (int) (size * sa.xRotate) / 360;
-	    sa.xRotate = sa.xRotate -
-		(360.0f * cs->xrotations) / size + 360.0f / size;
-	    cs->xrotations--;
-	}
+		cs->xrotations = (int) (size * sa.xRotate - 180) / 360;
+	
+	sa.xRotate -= (360.0f * cs->xrotations) / size;
     }
 
-    if (!clear && cs->grabIndex == 0 && hsize > 2 &&
+    if (!clear && cs->grabIndex == 0 && hsize > 2 && !cs->disableCaps &&
 	(cs->invert != 1 || sa.vRotate != 0.0f || sa.yTranslate != 0.0f))
     {
 	CompTransform sTransform = *transform;
@@ -1462,7 +1560,7 @@ cubePaintTransformedScreen (CompScreen		    *s,
     /* outside cube */
     if (cs->invert == 1)
     {
-	if (cs->grabIndex || hsize > 4)
+	if (cs->grabIndex)
 	{
 	    GLenum filter;
 	    int    i;
@@ -1487,19 +1585,52 @@ cubePaintTransformedScreen (CompScreen		    *s,
 	}
 	else
 	{
-	    if (sAttrib->xRotate != 0.0f)
+	    int i;
+	    
+	    // xrotations ==> dx for the viewport which is the nearest to the viewer in z axis.
+	    // xrotations +/- hsize / 2 ==> dx for the viewport which is the farest to the viewer in z axis.
+	    
+	    if (sa.xRotate < 0.0f)
 	    {
-		xMove = cs->xrotations;
-
-		cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
-					  xMove);
-
-		xMove++;
+		for (i = 0; i <= hsize / 2; i++)
+		{
+		    xMove = cs->xrotations + hsize / 2 + i;
+		    sa.yRotate -= (hsize / 2 + i) * 360.0f / size;
+		    cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
+					      xMove);
+		    sa.yRotate += (hsize / 2 + i) * 360.0f / size;
+		
+		    if (i == 0 || i * 2 == hsize)	// same viewport.
+			continue;
+		
+		    xMove = cs->xrotations + hsize / 2 - i;
+		    sa.yRotate -= (hsize / 2 - i) * 360.0f / size;
+		    cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
+					      xMove);
+		    sa.yRotate += (hsize / 2 - i) * 360.0f / size;
+		}
+	    }
+	    
+	    else
+	    {
+		for (i = 0; i <= hsize / 2; i++)
+		{
+		    xMove = cs->xrotations - hsize / 2 - i;
+		    sa.yRotate -= (-hsize / 2 - i) * 360.0f / size;
+		    cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
+					      xMove);
+		    sa.yRotate += (-hsize / 2 - i) * 360.0f / size;
+		
+		    if (i == 0 || i * 2 == hsize)	// same viewport.
+			continue;
+		
+		    xMove = cs->xrotations - hsize / 2 + i;
+		    sa.yRotate -= (-hsize / 2 + i) * 360.0f / size;
+		    cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
+					      xMove);
+		    sa.yRotate += (-hsize / 2 + i) * 360.0f / size;
+		}
 	    }
-
-	    sa.yRotate -= 360.0f / size;
-
-	    cubeMoveViewportAndPaint (s, &sa, transform, output, mask, xMove);
 	}
     }
     else
@@ -1561,6 +1692,45 @@ cubePaintTransformedScreen (CompScreen		    *s,
     }
 
     WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
+    
+    if (cs->desktopOpacity != OPAQUE && wasCulled)
+	glEnable(GL_CULL_FACE);
+}
+
+static void cubeSetClipPlanes (CompScreen *s, Region region, int output)
+{
+    CUBE_SCREEN(s);
+
+    glTranslatef(cs->outputXOffset, -cs->outputYOffset, 0.0f);
+    glScalef( cs->outputXScale, cs->outputYScale, 1.0f);
+
+    UNWRAP(cs, s, setClipPlanes);
+    (*s->setClipPlanes) (s, region, output);
+    WRAP(cs, s, setClipPlanes, cubeSetClipPlanes);
+
+	
+    if (cs->invert == 1)
+    {
+	GLdouble clipPlane0[] = { 1.0, 0.0, 0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane1[] = { -1.0,  0.0, 0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane2[] = { 0.0,  -1.0, 0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane3[] = { 0.0,  1.0, 0.5 / cs->distance, 0.0 };
+	glClipPlane (GL_CLIP_PLANE0, clipPlane0);
+	glClipPlane (GL_CLIP_PLANE1, clipPlane1);
+	glClipPlane (GL_CLIP_PLANE2, clipPlane2);
+	glClipPlane (GL_CLIP_PLANE3, clipPlane3);
+    }
+    else
+    {
+	GLdouble clipPlane0[] = { -1.0, 0.0, -0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane1[] = { 1.0,  0.0, -0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane2[] = { 0.0,  1.0, -0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane3[] = { 0.0,  -1.0, -0.5 / cs->distance, 0.0 };
+	glClipPlane (GL_CLIP_PLANE0, clipPlane0);
+	glClipPlane (GL_CLIP_PLANE1, clipPlane1);
+	glClipPlane (GL_CLIP_PLANE2, clipPlane2);
+	glClipPlane (GL_CLIP_PLANE3, clipPlane3);
+    }
 }
 
 static void
@@ -1583,6 +1753,62 @@ cubeApplyScreenTransform (CompScreen		  *s,
     matrixTranslate (transform, -cs->outputXOffset, cs->outputYOffset, 0.0f);
 }
 
+static void cubeHandleCompizEvent(CompDisplay * d, char *pluginName,
+				 char *eventName, CompOption * option, int nOption)
+{
+    CUBE_DISPLAY(d);
+
+    UNWRAP (cd, d, handleCompizEvent);
+    (*d->handleCompizEvent) (d, pluginName, eventName, option, nOption);
+    WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent);
+	
+    if (strcmp(pluginName, "cube") == 0)
+    {
+	if (strcmp(eventName, "disableCapsEvent") == 0)
+	{
+	    Window xid = getIntOptionNamed(option, nOption, "root", 0);
+	    CompScreen *s = findScreenAtDisplay(d, xid);
+
+	    if (s)
+	    {
+		CUBE_SCREEN(s);
+		cs->disableCaps = getBoolOptionNamed(option, nOption, "disableCaps", FALSE);
+	    }
+	}
+	
+	else if (strcmp(eventName, "paintAllViewportsEvent") == 0)
+	{
+	    Window xid = getIntOptionNamed(option, nOption, "root", 0);
+	    CompScreen *s = findScreenAtDisplay(d, xid);
+
+	    if (s)
+	    {
+		CUBE_SCREEN(s);
+		cs->paintAllViewports = getBoolOptionNamed(option, nOption, "paintAllViewports", FALSE);
+	    }
+	}
+    }
+}
+
+static void
+cubeFoldEvent(CompScreen *s, Bool unfolded)
+{
+    CompOption o[2];
+
+    o[0].type = CompOptionTypeInt;
+    o[0].name = "root";
+    o[0].value.i = s->root;
+
+    o[1].type = CompOptionTypeBool;
+    o[1].name = "unfolded";
+    o[1].value.b = unfolded;
+
+    (*s->display->handleCompizEvent) (s->display, 
+				      "cube", 
+				      "unfoldEvent", 
+				      o, 2);
+}
+
 static Bool
 cubeUnfold (CompDisplay     *d,
 	    CompAction      *action,
@@ -1611,6 +1837,7 @@ cubeUnfold (CompDisplay     *d,
 
 	if (cs->grabIndex)
 	{
+	    cubeFoldEvent (s, TRUE);
 	    cs->unfolded = TRUE;
 	    damageScreen (s);
 	}
@@ -1646,6 +1873,7 @@ cubeFold (CompDisplay     *d,
 
 	if (cs->grabIndex)
 	{
+	    cubeFoldEvent (s, FALSE);
 	    cs->unfolded = FALSE;
 	    damageScreen (s);
 	}
@@ -1869,6 +2097,8 @@ cubeInitDisplay (CompPlugin  *p,
     cubeDisplayInitOptions (cd, d->display);
 
     d->privates[displayPrivateIndex].ptr = cd;
+    
+    WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent);
 
     return TRUE;
 }
@@ -1883,6 +2113,7 @@ cubeFiniDisplay (CompPlugin  *p,
 #endif
 
     CUBE_DISPLAY (d);
+    UNWRAP (cd, d, handleCompizEvent);
 
     freeScreenPrivateIndex (d, cd->screenPrivateIndex);
 
@@ -1941,6 +2172,11 @@ cubeInitScreen (CompPlugin *p,
     cs->unfoldVelocity = 0.0f;
 
     cs->fullscreenOutput = TRUE;
+    
+    cs->disableCaps = FALSE;
+    cs->paintAllViewports = FALSE;
+    
+    cs->desktopOpacity = OPAQUE / 2;
 
     memset (cs->cleared, 0, sizeof (cs->cleared));
 
@@ -1958,6 +2194,9 @@ cubeInitScreen (CompPlugin *p,
     WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
     WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
     WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
+    WRAP (cs, s, setClipPlanes, cubeSetClipPlanes);
+    WRAP (cs, s, paintBackground, cubePaintBackground);
+    WRAP (cs, s, paintWindow, cubePaintWindow);
 
     cubeUpdateOutputs (s);
 
@@ -1992,6 +2231,9 @@ cubeFiniScreen (CompPlugin *p,
     UNWRAP (cs, s, applyScreenTransform);
     UNWRAP (cs, s, setScreenOption);
     UNWRAP (cs, s, outputChangeNotify);
+    UNWRAP (cs, s, setClipPlanes);
+    UNWRAP (cs, s, paintBackground);
+    UNWRAP (cs, s, paintWindow);
 
     finiTexture (s, &cs->texture);
     finiTexture (s, &cs->sky);
diff --git a/plugins/rotate.c b/plugins/rotate.c
index c19030b..b74c40c 100644
--- a/plugins/rotate.c
+++ b/plugins/rotate.c
@@ -400,6 +400,30 @@ rotateReleaseMoveWindow (CompScreen *s)
     rs->moveWindow = None;
 }
 
+static void rotateEvent(CompScreen *s, 
+			Bool       rotating, 
+			Bool       manual)
+{
+    CompOption o[3];
+
+    o[0].type = CompOptionTypeInt;
+    o[0].name = "root";
+    o[0].value.i = s->root;
+
+    o[1].type = CompOptionTypeBool;
+    o[1].name = "rotating";
+    o[1].value.b = rotating;
+
+    o[2].type = CompOptionTypeBool;
+    o[2].name = "manual";
+    o[2].value.b = manual;
+
+    (*s->display->handleCompizEvent)(s->display, 
+				     "rotate", 
+				     "rotateEvent", 
+				     o, 3);
+}
+
 static void
 rotatePreparePaintScreen (CompScreen *s,
 			  int	     msSinceLastPaint)
@@ -485,6 +509,8 @@ rotatePreparePaintScreen (CompScreen *s,
 		    else
 			tx = (s->hsize * xrot / 360.0f) + 0.5f;
 
+		    rotateEvent (s, FALSE, FALSE);
+
 		    moveScreenViewport (s, tx, 0, TRUE);
 
 		    rs->xrot = 0.0f;
@@ -638,6 +664,10 @@ rotateInitiate (CompDisplay     *d,
 	rs->moving = FALSE;
 	rs->slow   = FALSE;
 
+	/* notify other plugins that rotation starts - if action is
+	   non-NULL, we are called from the 'Initiate rotate' binding */
+	rotateEvent (s, TRUE, (action != NULL));
+
 	if (!rs->grabIndex)
 	{
 	    rs->grabIndex = pushScreenGrab (s, s->invisibleCursor, "rotate");
diff --git a/src/paint.c b/src/paint.c
index a618328..9c0e252 100644
--- a/src/paint.c
+++ b/src/paint.c
@@ -157,7 +157,9 @@ paintScreenRegion (CompScreen	       *screen,
     static Region tmpRegion = NULL;
     CompWindow    *w;
     CompCursor	  *c;
-    int		  count, windowMask, backgroundMask;
+    int		  count, windowMask, backgroundMask, occlusionMask;
+    Bool ftb = (mask & PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK) && 
+	      !(mask & PAINT_SCREEN_ORDER_BACK_TO_FRONT_MASK);	// Do FTB drawing only if FTB flag is set and BTF flag isn't
 
     if (!tmpRegion)
     {
@@ -179,10 +181,29 @@ paintScreenRegion (CompScreen	       *screen,
 	count	       = 0;
     }
 
+    if (ftb)
+    {
+	windowMask |= PAINT_WINDOW_FRONT_TO_BACK_MASK;
+	occlusionMask = PAINT_WINDOW_OCCLUSION_DETECTION_MASK | 
+	               PAINT_WINDOW_FRONT_TO_BACK_MASK;
+    }
+    else
+    {
+	windowMask |= PAINT_WINDOW_BACK_TO_FRONT_MASK;
+	occlusionMask = PAINT_WINDOW_OCCLUSION_DETECTION_MASK | 
+	               PAINT_WINDOW_BACK_TO_FRONT_MASK;
+    }
+    
+
     XSubtractRegion (region, &emptyRegion, tmpRegion);
 
-    /* detect occlusions */
-    for (w = screen->reverseWindows; w; w = w->prev)
+    /* detect occlusions (order is reversed from true painting order). */
+    if (ftb)
+	w = screen->windows;
+    else
+	w = screen->reverseWindows;
+
+    for (; w; w = (ftb)? w->next: w->prev)
     {
 	if (w->destroyed)
 	    continue;
@@ -197,7 +218,7 @@ paintScreenRegion (CompScreen	       *screen,
 	XSubtractRegion (tmpRegion, &emptyRegion, w->clip);
 
 	if ((*screen->paintWindow) (w, &w->paint, transform, tmpRegion,
-				    PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
+				   occlusionMask))
 	{
 	    /* unredirect top most fullscreen windows. */
 	    if (count == 0					      &&
@@ -216,8 +237,13 @@ paintScreenRegion (CompScreen	       *screen,
 
     (*screen->paintBackground) (screen, tmpRegion, backgroundMask);
 
-    /* paint all windows from bottom to top */
-    for (w = screen->windows; w; w = w->next)
+    /* paint all windows with the order specified by the masks. */
+    if (ftb)
+	w = screen->reverseWindows;
+    else
+	w = screen->windows;
+
+    for (; w; w = (ftb)? w->prev: w->next)
     {
 	if (w->destroyed)
 	    continue;
@@ -231,9 +257,22 @@ paintScreenRegion (CompScreen	       *screen,
 	(*screen->paintWindow) (w, &w->paint, transform, w->clip, windowMask);
     }
 
-    /* paint cursors */
-    for (c = screen->cursors; c; c = c->next)
-	(*screen->paintCursor) (c, transform, tmpRegion, 0);
+    if ((mask & PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK) &&
+	(mask & PAINT_SCREEN_ORDER_BACK_TO_FRONT_MASK))
+    {
+	/* when both modes are set, we first paint in Back-To-Front mode (already done), 
+           and after that we paint the screen in Front-To-Back mode, by removing the 
+           Back-To-Front mask. 
+           Painting the cursors will be done after the Front-To-Back drawing*/
+	paintScreenRegion (screen, transform, region, output, 
+	                   mask & (~PAINT_SCREEN_ORDER_BACK_TO_FRONT_MASK));	
+    }
+    else
+    {
+	/* paint cursors */
+	for (c = screen->cursors; c; c = c->next)
+	    (*screen->paintCursor) (c, transform, tmpRegion, 0);
+    }
 }
 
 
@@ -259,29 +298,10 @@ paintTransformedScreen (CompScreen		*screen,
 
     if ((mask & CLIP_PLANE_MASK) == CLIP_PLANE_MASK)
     {
-	GLdouble h = screen->height;
-
-	GLdouble p1[2] = { region->extents.x1, h - region->extents.y2 };
-	GLdouble p2[2] = { region->extents.x2, h - region->extents.y1 };
-
-	GLdouble halfW = screen->outputDev[output].width / 2.0;
-	GLdouble halfH = screen->outputDev[output].height / 2.0;
-
-	GLdouble cx = screen->outputDev[output].region.extents.x1 + halfW;
-	GLdouble cy = (h - screen->outputDev[output].region.extents.y2) + halfH;
-
-	GLdouble top[4]    = { 0.0, halfH / (cy - p1[1]), 0.0, 0.5 };
-	GLdouble bottom[4] = { 0.0, halfH / (cy - p2[1]), 0.0, 0.5 };
-	GLdouble left[4]   = { halfW / (cx - p1[0]), 0.0, 0.0, 0.5 };
-	GLdouble right[4]  = { halfW / (cx - p2[0]), 0.0, 0.0, 0.5 };
-
 	glPushMatrix ();
 	glLoadMatrixf (sTransform.m);
 
-	glClipPlane (GL_CLIP_PLANE0, top);
-	glClipPlane (GL_CLIP_PLANE1, bottom);
-	glClipPlane (GL_CLIP_PLANE2, left);
-	glClipPlane (GL_CLIP_PLANE3, right);
+	(*screen->setClipPlanes) (screen, region, output);
 
 	glEnable (GL_CLIP_PLANE0);
 	glEnable (GL_CLIP_PLANE1);
@@ -1154,3 +1174,27 @@ paintBackground (CompScreen   *s,
 
     free (data);
 }
+
+void setClipPlanes (CompScreen *screen, Region region, int output)
+{
+    GLdouble h = screen->height;
+
+    GLdouble p1[2] = { region->extents.x1, h - region->extents.y2 };
+    GLdouble p2[2] = { region->extents.x2, h - region->extents.y1 };
+
+    GLdouble halfW = screen->outputDev[output].width / 2.0;
+    GLdouble halfH = screen->outputDev[output].height / 2.0;
+
+    GLdouble cx = screen->outputDev[output].region.extents.x1 + halfW;
+    GLdouble cy = (h - screen->outputDev[output].region.extents.y2) + halfH;
+
+    GLdouble top[4]    = { 0.0, halfH / (cy - p1[1]), 0.0, 0.5 };
+    GLdouble bottom[4] = { 0.0, halfH / (cy - p2[1]), 0.0, 0.5 };
+    GLdouble left[4]   = { halfW / (cx - p1[0]), 0.0, 0.0, 0.5 };
+    GLdouble right[4]  = { halfW / (cx - p2[0]), 0.0, 0.0, 0.5 };
+
+    glClipPlane (GL_CLIP_PLANE0, top);
+    glClipPlane (GL_CLIP_PLANE1, bottom);
+    glClipPlane (GL_CLIP_PLANE2, left);
+    glClipPlane (GL_CLIP_PLANE3, right);
+}
diff --git a/src/screen.c b/src/screen.c
index 63d7189..482f0da 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -1688,6 +1688,7 @@ addScreen (CompDisplay *display,
     s->getOutputExtentsForWindow  = getOutputExtentsForWindow;
     s->getAllowedActionsForWindow = getAllowedActionsForWindow;
     s->focusWindow		  = focusWindow;
+    s->setClipPlanes		  = setClipPlanes;
 
     s->paintCursor      = paintCursor;
     s->damageCursorRect	= damageCursorRect;