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 #include @@ -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..999bc6d 100644 --- a/plugins/cube.c +++ b/plugins/cube.c @@ -52,6 +52,14 @@ #define CUBE_IN_DEFAULT FALSE +typedef enum _RotationMode +{ + NoRotation = 0, + RotationChange, + RotationManual +} RotationMode; + + static char *cubeImages[] = { "freedesktop" }; @@ -85,6 +93,21 @@ static char *cubeImages[] = { #define CUBE_ACCELERATION_MAX 20.0f #define CUBE_ACCELERATION_PRECISION 0.1f +#define CUBE_FADE_TIME_DEFAULT 1.0 +#define CUBE_FADE_TIME_MAX 10.0 +#define CUBE_FADE_TIME_MIN 0.0 +#define CUBE_FADE_TIME_PRECISION 0.1 + +#define CUBE_OPACITY_MIN 0.0 +#define CUBE_OPACITY_MAX 100.0 +#define CUBE_OPACITY_PRECISION 1.0 + +#define CUBE_TRANSPARENT_MANUAL_ONLY_DEFAULT FALSE + +#define CUBE_ACTIVE_OPACITY_DEFAULT 30 + +#define CUBE_INACTIVE_OPACITY_DEFAULT 100 + #define CUBE_SPEED_DEFAULT 1.5f #define CUBE_SPEED_MIN 0.1f #define CUBE_SPEED_MAX 50.0f @@ -108,22 +131,28 @@ typedef struct _CubeDisplay { int screenPrivateIndex; CompOption opt[CUBE_DISPLAY_OPTION_NUM]; + + HandleCompizEventProc handleCompizEvent; } CubeDisplay; -#define CUBE_SCREEN_OPTION_COLOR 0 -#define CUBE_SCREEN_OPTION_IN 1 -#define CUBE_SCREEN_OPTION_SCALE_IMAGE 2 -#define CUBE_SCREEN_OPTION_IMAGES 3 -#define CUBE_SCREEN_OPTION_SKYDOME 4 -#define CUBE_SCREEN_OPTION_SKYDOME_IMG 5 -#define CUBE_SCREEN_OPTION_SKYDOME_ANIM 6 -#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_START 7 -#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_END 8 -#define CUBE_SCREEN_OPTION_ACCELERATION 9 -#define CUBE_SCREEN_OPTION_SPEED 10 -#define CUBE_SCREEN_OPTION_TIMESTEP 11 -#define CUBE_SCREEN_OPTION_MIPMAP 12 -#define CUBE_SCREEN_OPTION_NUM 13 +#define CUBE_SCREEN_OPTION_COLOR 0 +#define CUBE_SCREEN_OPTION_IN 1 +#define CUBE_SCREEN_OPTION_SCALE_IMAGE 2 +#define CUBE_SCREEN_OPTION_IMAGES 3 +#define CUBE_SCREEN_OPTION_SKYDOME 4 +#define CUBE_SCREEN_OPTION_SKYDOME_IMG 5 +#define CUBE_SCREEN_OPTION_SKYDOME_ANIM 6 +#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_START 7 +#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_END 8 +#define CUBE_SCREEN_OPTION_ACCELERATION 9 +#define CUBE_SCREEN_OPTION_SPEED 10 +#define CUBE_SCREEN_OPTION_TIMESTEP 11 +#define CUBE_SCREEN_OPTION_MIPMAP 12 +#define CUBE_SCREEN_OPTION_ACTIVE_OPACITY 13 +#define CUBE_SCREEN_OPTION_INACTIVE_OPACITY 14 +#define CUBE_SCREEN_OPTION_FADE_TIME 15 +#define CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY 16 +#define CUBE_SCREEN_OPTION_NUM 17 typedef struct _CubeScreen { PreparePaintScreenProc preparePaintScreen; @@ -133,6 +162,9 @@ typedef struct _CubeScreen { ApplyScreenTransformProc applyScreenTransform; SetScreenOptionProc setScreenOption; OutputChangeNotifyProc outputChangeNotify; + SetClipPlanesProc setClipPlanes; + PaintBackgroundProc paintBackground; + PaintWindowProc paintWindow; CompOption opt[CUBE_SCREEN_OPTION_NUM]; @@ -173,11 +205,18 @@ typedef struct _CubeScreen { Bool cleared[64]; Bool fullscreenOutput; + RotationMode rotationMode; float outputXScale; float outputYScale; float outputXOffset; float outputYOffset; + + Bool disableCaps; + Bool paintAllViewports; + + float desktopOpacity; + float toOpacity; #ifdef USE_LIBRSVG cairo_t *cr; @@ -971,8 +1010,14 @@ cubeSetScreenOption (CompPlugin *plugin, } break; case CUBE_SCREEN_OPTION_MIPMAP: + case CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY: if (compSetBoolOption (o, value)) return TRUE; + case CUBE_SCREEN_OPTION_FADE_TIME: + case CUBE_SCREEN_OPTION_ACTIVE_OPACITY: + case CUBE_SCREEN_OPTION_INACTIVE_OPACITY: + if (compSetFloatOption (o,value)) + return TRUE; default: break; } @@ -1106,6 +1151,46 @@ cubeScreenInitOptions (CubeScreen *cs, o->longDesc = N_("Generate mipmaps when possible for higher quality scaling"); o->type = CompOptionTypeBool; o->value.b = CUBE_MIPMAP_DEFAULT; + + o = &cs->opt[CUBE_SCREEN_OPTION_FADE_TIME]; + o->name = "fade_time"; + o->shortDesc = N_("Fade Time"); + o->longDesc = N_("Desktop Window Opacity Fade Time."); + o->type = CompOptionTypeFloat; + o->value.f = CUBE_FADE_TIME_DEFAULT; + o->rest.f.min = CUBE_FADE_TIME_MIN; + o->rest.f.max = CUBE_FADE_TIME_MAX; + o->rest.f.precision = CUBE_FADE_TIME_PRECISION; + + o = &cs->opt[CUBE_SCREEN_OPTION_ACTIVE_OPACITY]; + o->name = "active_opacity"; + o->shortDesc = N_("Opacity During Rotation"); + o->longDesc = N_("Opacity of desktop window during rotation."); + o->type = CompOptionTypeFloat; + o->value.f = CUBE_ACTIVE_OPACITY_DEFAULT; + o->rest.f.min = CUBE_OPACITY_MIN; + o->rest.f.max = CUBE_OPACITY_MAX; + o->rest.f.precision = CUBE_OPACITY_PRECISION; + + + o = &cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY]; + o->name = "inactive_opacity"; + o->shortDesc = N_("Opacity When Not Rotating"); + o->longDesc = N_("Opacity of desktop window when not rotating."); + o->type = CompOptionTypeFloat; + o->value.f = CUBE_INACTIVE_OPACITY_DEFAULT; + o->rest.f.min = CUBE_OPACITY_MIN; + o->rest.f.max = CUBE_OPACITY_MAX; + o->rest.f.precision = CUBE_OPACITY_PRECISION; + + o = &cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY]; + o->name = "transparent_manual_only"; + o->shortDesc = N_("Transparency Only\non Mouse Rotate"); + o->longDesc = + N_ + ("Initiates Cube transparency only if rotation is mouse driven."); + o->type = CompOptionTypeBool; + o->value.b = CUBE_TRANSPARENT_MANUAL_ONLY_DEFAULT; } static int @@ -1172,6 +1257,41 @@ cubePreparePaintScreen (CompScreen *s, memset (cs->cleared, 0, sizeof (Bool) * s->nOutputDev); + //transparency, mostly copied/ported from beryl's cube.c, orig. by onestone + /* if (cs->rotationMode != NoRotation && ((cs->rotationMode == RotationManual) || + !(cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY].value.b))) + { + cs->toOpacity = + (cs->opt[CUBE_SCREEN_OPTION_ACTIVE_OPACITY].value.i / 100.0f) * OPAQUE; + } + else + cs->toOpacity = + (cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.i / 100.0f) * OPAQUE; + + if (cs->opt[CUBE_SCREEN_OPTION_FADE_TIME].value.f == 0.0f) + { + cs->desktopOpacity = cs->toOpacity; + } + else if (cs->desktopOpacity != cs->toOpacity) + { + float steps = (msSinceLastPaint * OPAQUE / 1000.0) / + cs->opt[CUBE_SCREEN_OPTION_FADE_TIME].value.f; + if (steps < 12) + steps = 12; + + if (cs->toOpacity > cs->desktopOpacity) + { + cs->desktopOpacity += steps; + cs->desktopOpacity = MIN(cs->toOpacity, cs->desktopOpacity); + } + if (cs->toOpacity < cs->desktopOpacity) + { + cs->desktopOpacity -= steps; + cs->desktopOpacity = MAX(cs->toOpacity, cs->desktopOpacity); + } + }*/ + cs->desktopOpacity = OPAQUE / 2; + UNWRAP (cs, s, preparePaintScreen); (*s->preparePaintScreen) (s, msSinceLastPaint); WRAP (cs, s, preparePaintScreen, cubePreparePaintScreen); @@ -1217,6 +1337,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 +1415,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 +1482,20 @@ cubePaintTransformedScreen (CompScreen *s, int hsize, xMove = 0; float size; Bool clear; + Bool wasCulled = FALSE; 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 +1599,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 +1670,7 @@ cubePaintTransformedScreen (CompScreen *s, /* outside cube */ if (cs->invert == 1) { - if (cs->grabIndex || hsize > 4) + if (cs->grabIndex) { GLenum filter; int i; @@ -1487,19 +1695,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 +1802,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 +1863,85 @@ 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); + } + } + } + if (strcmp(pluginName, "rotate") == 0) + { + if (strcmp(eventName, "rotateEvent") == 0) + { + Window xid = getIntOptionNamed(option, nOption, "root", 0); + CompScreen *s = findScreenAtDisplay(d, xid); + + if (s) + { + CUBE_SCREEN(s); + Bool rotate = getBoolOptionNamed(option, nOption, "rotating", FALSE); + Bool manual = getBoolOptionNamed(option, nOption, "manual", FALSE); + + if (rotate && manual) + cs->rotationMode = RotationManual; + else if (rotate) + cs->rotationMode = RotationChange; + else + cs->rotationMode = NoRotation; + damageScreen(s); + } + } + } +} + +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 +1970,7 @@ cubeUnfold (CompDisplay *d, if (cs->grabIndex) { + cubeFoldEvent (s, TRUE); cs->unfolded = TRUE; damageScreen (s); } @@ -1646,6 +2006,7 @@ cubeFold (CompDisplay *d, if (cs->grabIndex) { + cubeFoldEvent (s, FALSE); cs->unfolded = FALSE; damageScreen (s); } @@ -1869,6 +2230,8 @@ cubeInitDisplay (CompPlugin *p, cubeDisplayInitOptions (cd, d->display); d->privates[displayPrivateIndex].ptr = cd; + + WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent); return TRUE; } @@ -1883,6 +2246,7 @@ cubeFiniDisplay (CompPlugin *p, #endif CUBE_DISPLAY (d); + UNWRAP (cd, d, handleCompizEvent); freeScreenPrivateIndex (d, cd->screenPrivateIndex); @@ -1941,6 +2305,12 @@ cubeInitScreen (CompPlugin *p, cs->unfoldVelocity = 0.0f; cs->fullscreenOutput = TRUE; + + cs->disableCaps = FALSE; + cs->paintAllViewports = FALSE; + cs->rotationMode = NoRotation; + + cs->desktopOpacity = CUBE_ACTIVE_OPACITY_DEFAULT; memset (cs->cleared, 0, sizeof (cs->cleared)); @@ -1958,6 +2328,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 +2365,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); @@ -2067,3 +2443,4 @@ getCompPluginInfo (void) { return &cubeVTable; } + 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;