diff --git a/include/compiz.h b/include/compiz.h index 496bfaf..62544fc 100644 --- a/include/compiz.h +++ b/include/compiz.h @@ -1154,6 +1154,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, @@ -1219,6 +1225,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, diff --git a/src/paint.c b/src/paint.c index a618328..c9e540d 100644 --- a/src/paint.c +++ b/src/paint.c @@ -157,7 +157,10 @@ 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) { @@ -178,11 +181,29 @@ paintScreenRegion (CompScreen *screen, windowMask = 0; 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->windows; + else + w = screen->reverseWindows; + + for (; w; w = (ftb)? w->next: w->prev) { 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); + } }