/* * Copyright © 2005 Novell, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Authors: David Reveman * Mirco Müller (Skydome support) * Guillaume Seguin (Bottom caps, rotation stuff) * Dennis Kasprzyk (Transparent cube) */ #ifdef HAVE_CONFIG_H #include #endif #define _GNU_SOURCE #include #include #include #include #include #include #include #include #define CUBE_COLOR_RED_DEFAULT 0xefef #define CUBE_COLOR_GREEN_DEFAULT 0xebeb #define CUBE_COLOR_BLUE_DEFAULT 0xe7e7 typedef enum _ImagesRotateMode { ImagesRotateModeNever, ImagesRotateModeAfterMoving, ImagesRotateModeWhileMoving } ImagesRotateMode; char *imagesRotateModes[] = { N_("Never rotate caps"), N_("Rotate after moving"), N_("Rotate while moving") }; #define IMAGES_ROTATE_MODE_DEFAULT ImagesRotateModeNever #define NUM_IMAGES_ROTATE_MODES 3 typedef enum _MultiMonitorMode { Multiple, OneBig, } MultiMonitorMode; char *multiMonitorModes[] = { N_("Multiple cubes"), N_("One big cube") }; #define MULTIMONITOR_MODE_DEFAULT OneBig #define NUM_MULTIMONITOR_MODES 2 #define CUBE_IN_DEFAULT FALSE static char *cubeImages[] = { IMAGEDIR "/cubecaps.png" }; #define N_CUBE_IMAGES (sizeof (cubeImages) / sizeof (cubeImages[0])) #define CUBE_SCALE_IMAGE_TOP_DEFAULT FALSE #define CUBE_SCALE_IMAGE_BOTTOM_DEFAULT FALSE #define CUBE_NEXT_KEY_DEFAULT "Space" #define CUBE_NEXT_MODIFIERS_DEFAULT 0 #define CUBE_PREV_KEY_DEFAULT "BackSpace" #define CUBE_PREV_MODIFIERS_DEFAULT 0 #define CUBE_SKYDOME_DEFAULT FALSE #define CUBE_SKYDOME_ANIMATE_DEFAULT FALSE #define CUBE_SKYDOME_GRAD_START_RED_DEFAULT 0x0d0d #define CUBE_SKYDOME_GRAD_START_GREEN_DEFAULT 0xb1b1 #define CUBE_SKYDOME_GRAD_START_BLUE_DEFAULT 0xfdfd #define CUBE_SKYDOME_GRAD_END_RED_DEFAULT 0xfefe #define CUBE_SKYDOME_GRAD_END_GREEN_DEFAULT 0xffff #define CUBE_SKYDOME_GRAD_END_BLUE_DEFAULT 0xc7c7 #define CUBE_UNFOLD_KEY_DEFAULT "Next" #define CUBE_UNFOLD_MODIFIERS_DEFAULT (ControlMask | CompAltMask) #define CUBE_UNFOLD_ZOOM_DEFAULT 1.0f #define CUBE_UNFOLD_ZOOM_PRECISION 0.1f #define CUBE_UNFOLD_ZOOM_MIN 0.0f #define CUBE_UNFOLD_ZOOM_MAX 10.0f #define CUBE_ACCELERATION_DEFAULT 4.0f #define CUBE_ACCELERATION_MIN 1.0f #define CUBE_ACCELERATION_MAX 20.0f #define CUBE_ACCELERATION_PRECISION 0.1f #define CUBE_SPEED_DEFAULT 1.5f #define CUBE_SPEED_MIN 0.1f #define CUBE_SPEED_MAX 50.0f #define CUBE_SPEED_PRECISION 0.1f #define CUBE_TIMESTEP_DEFAULT 1.2f #define CUBE_TIMESTEP_MIN 0.1f #define CUBE_TIMESTEP_MAX 50.0f #define CUBE_TIMESTEP_PRECISION 0.1f #define CUBE_MIPMAP_DEFAULT FALSE #define CUBE_VIEWPORT_SLIDE_DEFAULT FALSE #define CUBE_VIEWPORT_SLIDE_NO3D_DEFAULT FALSE #define CUBE_DRAW_CAPS_DEFAULT TRUE #define CUBE_TRANSPARENT_DEFAULT FALSE #define CUBE_DISPLAY_OPTION_UNFOLD 0 #define CUBE_DISPLAY_OPTION_NEXT 1 #define CUBE_DISPLAY_OPTION_PREV 2 #define CUBE_DISPLAY_OPTION_NUM 3 #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_ACTIVE_OPACITY_DEFAULT 30 #define CUBE_INACTIVE_OPACITY_DEFAULT 100 #define CAP_TRANSPARENT_DEFAULT FALSE static int displayPrivateIndex; typedef struct _CubeDisplay { int screenPrivateIndex; CompOption opt[CUBE_DISPLAY_OPTION_NUM]; } CubeDisplay; #define CUBE_SCREEN_OPTION_COLOR 0 #define CUBE_SCREEN_OPTION_IN 1 #define CUBE_SCREEN_OPTION_DRAW_CAPS 2 #define CUBE_SCREEN_OPTION_IMAGES_ROTATE_MODE 3 #define CUBE_SCREEN_OPTION_SCALE_IMAGE_TOP 4 #define CUBE_SCREEN_OPTION_IMAGES_TOP 5 #define CUBE_SCREEN_OPTION_SCALE_IMAGE_BOTTOM 6 #define CUBE_SCREEN_OPTION_IMAGES_BOTTOM 7 #define CUBE_SCREEN_OPTION_SKYDOME 8 #define CUBE_SCREEN_OPTION_SKYDOME_IMG 9 #define CUBE_SCREEN_OPTION_SKYDOME_ANIM 10 #define CUBE_SCREEN_OPTION_SKYDOME_GRAD_START 11 #define CUBE_SCREEN_OPTION_SKYDOME_GRAD_END 12 #define CUBE_SCREEN_OPTION_ACCELERATION 13 #define CUBE_SCREEN_OPTION_SPEED 14 #define CUBE_SCREEN_OPTION_TIMESTEP 15 #define CUBE_SCREEN_OPTION_MIPMAP 16 #define CUBE_SCREEN_OPTION_VIEWPORT_SLIDE 17 #define CUBE_SCREEN_OPTION_VIEWPORT_SLIDE_NO3D 18 #define CUBE_SCREEN_OPTION_MULTIMONITOR 19 #define CUBE_SCREEN_OPTION_TRANSPARENT 20 #define CUBE_SCREEN_OPTION_FADE_TIME 21 #define CUBE_SCREEN_OPTION_ACTIVE_OPACITY 22 #define CUBE_SCREEN_OPTION_INACTIVE_OPACITY 23 #define CUBE_SCREEN_OPTION_CAP_TRANSPARENT 24 #define CUBE_TRANSPARENT_MANUALONLY 25 #define CUBE_SCREEN_OPTION_UNFOLD_ZOOM_DISTANCE 26 #define CUBE_SCREEN_OPTION_STUCK_TO_SCREEN 27 #define CUBE_SCREEN_OPTION_NUM 28 typedef struct _CubeCapInfo { CompTexture texture; GLfloat tc[12]; int imgNFile; int imgCurFile; CompOptionValue *imgFiles; Bool scale; } CubeCapInfo; typedef struct _CubeScreen { PreparePaintScreenProc preparePaintScreen; DonePaintScreenProc donePaintScreen; PaintScreenProc paintScreen; PaintTransformedScreenProc paintTransformedScreen; ApplyScreenTransformProc applyScreenTransform; PaintBackgroundProc paintBackground; PaintWindowProc paintWindow; SetScreenOptionProc setScreenOption; OutputChangeNotifyProc outputChangeNotify; SetClipPlanesProc setClipPlanes; CompOption opt[CUBE_SCREEN_OPTION_NUM]; int invert; int xrotations; GLfloat distance; Bool rotateImages; Bool neverRotateImages; int previousRotationAtom; Bool paintingCaps; int paintingCapsAtom; GLushort color[3]; int grabIndex; float acceleration; float speed; float timestep; Bool unfolded; GLfloat unfold, unfoldVelocity, unfoldDistance; GLfloat *vertices; int nvertices; GLuint skyListId; Bool animateSkyDome; GLushort skyGradStartColor[3]; GLushort skyGradEndColor[3]; CubeCapInfo cubeCapTop; CubeCapInfo cubeCapBottom; CompTexture sky; int nOutput; int output[64]; int outputMask[64]; Bool fullscreenOutput; int manualAtom; int unfoldedAtom; float outputXScale; float outputYScale; float outputXOffset; float outputYOffset; MultiMonitorMode mmMode; int mmModeAtom; int insideAtom; int snapTopBottomAtom; float desktopOpacity; float toOpacity; Bool noManaged; int zoomLevelAtom; Bool finalPaint; } CubeScreen; #define GET_CUBE_DISPLAY(d) \ ((CubeDisplay *) (d)->privates[displayPrivateIndex].ptr) #define CUBE_DISPLAY(d) \ CubeDisplay *cd = GET_CUBE_DISPLAY (d) #define GET_CUBE_SCREEN(s, cd) \ ((CubeScreen *) (s)->privates[(cd)->screenPrivateIndex].ptr) #define CUBE_SCREEN(s) \ CubeScreen *cs = GET_CUBE_SCREEN (s, GET_CUBE_DISPLAY (s->display)) #define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption)) static void cubeInitTextureCoords(CompScreen * s, CubeCapInfo * cubeCap, unsigned int width, unsigned int height) { float x1, x2, y1, y2; CompMatrix *matrix; if (!cubeCap) return; matrix = &cubeCap->texture.matrix; if (cubeCap->scale) { x1 = 0.0f; y1 = 0.0f; x2 = width; y2 = height; } else { int bigscr, i; int bigWidth, bigHeight; CUBE_SCREEN(s); bigWidth = s->width; bigHeight = s->height; /* Scale the texture in a sane way for multi head too */ if (s->nOutputDev > 1 && cs->mmMode != OneBig) { for (i = bigscr = 0; i < s->nOutputDev; i++) if (s->outputDev[i].width > s->outputDev[bigscr].width) bigscr = i; bigWidth = s->outputDev[bigscr].width; bigHeight = s->outputDev[bigscr].height; } x1 = width / 2.0f - bigWidth / 2.0f; y1 = height / 2.0f - bigHeight / 2.0f; x2 = width / 2.0f + bigWidth / 2.0f; y2 = height / 2.0f + bigHeight / 2.0f; } cubeCap->tc[0] = COMP_TEX_COORD_X(matrix, width / 2.0f); cubeCap->tc[1] = COMP_TEX_COORD_Y(matrix, height / 2.0f); cubeCap->tc[2] = COMP_TEX_COORD_X(matrix, x2); cubeCap->tc[3] = COMP_TEX_COORD_Y(matrix, y1); cubeCap->tc[4] = COMP_TEX_COORD_X(matrix, x1); cubeCap->tc[5] = COMP_TEX_COORD_Y(matrix, y1); cubeCap->tc[6] = COMP_TEX_COORD_X(matrix, x1); cubeCap->tc[7] = COMP_TEX_COORD_Y(matrix, y2); cubeCap->tc[8] = COMP_TEX_COORD_X(matrix, x2); cubeCap->tc[9] = COMP_TEX_COORD_Y(matrix, y2); cubeCap->tc[10] = COMP_TEX_COORD_X(matrix, x2); cubeCap->tc[11] = COMP_TEX_COORD_Y(matrix, y1); } static void cubeSetClipPlanes (CompScreen *s, int output) { CUBE_SCREEN(s); if (cs->mmMode == Multiple || s->nOutputDev == 1) { if (cs->invert != 1) { UNWRAP(cs, s, setClipPlanes); (*s->setClipPlanes) (s, output); WRAP(cs, s, setClipPlanes, cubeSetClipPlanes); return; } 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); return; } float left = s->outputDev[output].region.extents.x1 / s->outputDev[output].width; float top = s->outputDev[output].region.extents.y1 / s->outputDev[output].height; float right = (s->width - s->outputDev[output].region.extents.x2) / s->outputDev[output].width; float bottom = (s->height - s->outputDev[output].region.extents.y2) / s->outputDev[output].height; if (cs->invert != 1) { GLdouble clipPlane0[] = { 0.0, -1.0, 0.0, 0.5 + top}; GLdouble clipPlane1[] = { 0.0, 1.0, 0.0, 0.5 + bottom }; GLdouble clipPlane2[] = { 1.0, 0.0, 0.0, 0.5 + left}; GLdouble clipPlane3[] = { -1.0, 0.0, 0.0, 0.5 + right}; glClipPlane (GL_CLIP_PLANE0, clipPlane0); glClipPlane (GL_CLIP_PLANE1, clipPlane1); glClipPlane (GL_CLIP_PLANE2, clipPlane2); glClipPlane (GL_CLIP_PLANE3, clipPlane3); return; } float w = (float)(s->width - s->outputDev[output].width) / s->outputDev[output].width; float h = (float)(s->height - s->outputDev[output].height) / s->outputDev[output].height; GLdouble clipPlane0[] = { 1.0, 0.0, (0.5 + w) / cs->distance, 0.0 }; GLdouble clipPlane1[] = { -1.0, 0.0, (0.5 + w) / cs->distance, 0.0 }; GLdouble clipPlane2[] = { 0.0, -1.0, (0.5 + h) / cs->distance, 0.0 }; GLdouble clipPlane3[] = { 0.0, 1.0, (0.5 + h) / 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 cubeLoadImg(CompScreen * s, CubeCapInfo * cubeCap, int n) { unsigned int width, height; int pw, ph; CUBE_SCREEN(s); if (!cubeCap) return; if (!cs->fullscreenOutput) { pw = s->width; ph = s->height; } else { pw = s->outputDev[0].width; ph = s->outputDev[0].height; } finiTexture(s, &cubeCap->texture); initTexture(s, &cubeCap->texture); if (!cubeCap->imgNFile) return; cubeCap->imgCurFile = n % cubeCap->imgNFile; if (!readImageToTexture (s, &cubeCap->texture, cubeCap->imgFiles[cubeCap->imgCurFile].s, &width, &height)) { fprintf(stderr, "%s: Failed to load slide: %s\n", getProgramName(), cubeCap->imgFiles[cubeCap->imgCurFile].s); finiTexture(s, &cubeCap->texture); initTexture(s, &cubeCap->texture); return; } cubeInitTextureCoords(s, cubeCap, width, height); } static void cubeInitCubeCap(CompScreen * s, CubeCapInfo * cubeCap) { memset(cubeCap->tc, 0, sizeof(cubeCap->tc)); initTexture(s, &cubeCap->texture); cubeCap->scale = FALSE; cubeCap->imgCurFile = 0; if (cubeCap->imgNFile) { cubeLoadImg(s, cubeCap, cubeCap->imgCurFile); damageScreen(s); } } static Bool cubeUpdateGeometry(CompScreen * s, int sides, Bool invert) { GLfloat radius, distance; GLfloat *v; int i, n; CUBE_SCREEN(s); if (cs->mmMode != Multiple) sides *= cs->nOutput; distance = 0.5f / tanf(M_PI / sides); radius = 0.5f / sinf(M_PI / sides); n = (sides + 2) * 2; if (cs->nvertices != n) { v = realloc(cs->vertices, sizeof(GLfloat) * n * 3); if (!v) return FALSE; cs->nvertices = n; cs->vertices = v; } else v = cs->vertices; *v++ = 0.0f; *v++ = 0.5 * invert; *v++ = 0.0f; for (i = 0; i <= sides; i++) { *v++ = radius * sinf(i * 2 * M_PI / sides + M_PI / sides); *v++ = 0.5 * invert; *v++ = radius * cosf(i * 2 * M_PI / sides + M_PI / sides); } *v++ = 0.0f; *v++ = -0.5 * invert; *v++ = 0.0f; for (i = sides; i >= 0; i--) { *v++ = radius * sinf(i * 2 * M_PI / sides + M_PI / sides); *v++ = -0.5 * invert; *v++ = radius * cosf(i * 2 * M_PI / sides + M_PI / sides); } cs->invert = invert; cs->distance = distance; return TRUE; } static void cubeUpdateOutputs(CompScreen * s) { BoxPtr pBox0, pBox1; int i, j, k, x; CUBE_SCREEN(s); k = 0; cs->fullscreenOutput = TRUE; for (i = 0; i < s->nOutputDev; i++) { cs->outputMask[i] = -1; /* dimensions must match first output */ if (s->outputDev[i].width != s->outputDev[0].width || s->outputDev[i].height != s->outputDev[0].height) continue; pBox0 = &s->outputDev[0].region.extents; pBox1 = &s->outputDev[i].region.extents; /* top and bottom line must match first output */ if (pBox0->y1 != pBox1->y1 || pBox0->y2 != pBox1->y2) continue; k++; for (j = 0; j < s->nOutputDev; j++) { pBox0 = &s->outputDev[j].region.extents; /* must not intersect other output region */ if (i != j && pBox0->x2 > pBox1->x1 && pBox0->x1 < pBox1->x2) { k--; break; } } } if (cs->mmMode == OneBig) k = 1; if (cs->mmMode == Multiple) k = s->nOutputDev; if (k != s->nOutputDev) { cs->fullscreenOutput = FALSE; cs->nOutput = 1; return; } /* add output indices from left to right */ j = 0; for (;;) { x = MAXSHORT; k = -1; for (i = 0; i < s->nOutputDev; i++) { if (cs->outputMask[i] != -1) continue; if (s->outputDev[i].region.extents.x1 < x) { x = s->outputDev[i].region.extents.x1; k = i; } } if (k < 0) break; cs->outputMask[k] = j; cs->output[j] = k; j++; } cs->nOutput = j; if (cs->nOutput == 1) { if (s->outputDev[0].width != s->width || s->outputDev[0].height != s->height) cs->fullscreenOutput = FALSE; } } static void cubeUpdateSkyDomeTexture(CompScreen * screen) { CUBE_SCREEN(screen); finiTexture(screen, &cs->sky); initTexture(screen, &cs->sky); if (!cs->opt[CUBE_SCREEN_OPTION_SKYDOME].value.b) return; if (strlen(cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG].value.s) == 0 || !readImageToTexture(screen, &cs->sky, cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG]. value.s, NULL, NULL)) { GLfloat aaafTextureData[128][128][3]; GLfloat fRStart = (GLfloat) cs-> opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START].value.c[0] / 0xffff; GLfloat fGStart = (GLfloat) cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START]. value.c[1] / 0xffff; GLfloat fBStart = (GLfloat) cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START]. value.c[2] / 0xffff; GLfloat fREnd = (GLfloat) cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value. c[0] / 0xffff; GLfloat fGEnd = (GLfloat) cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value. c[1] / 0xffff; GLfloat fBEnd = (GLfloat) cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value. c[2] / 0xffff; GLfloat fRStep = (fREnd - fRStart) / 128.0f; GLfloat fGStep = (fGEnd - fGStart) / 128.0f; GLfloat fBStep = (fBStart - fBEnd) / 128.0f; GLfloat fR = fRStart; GLfloat fG = fGStart; GLfloat fB = fBStart; int iX, iY; for (iX = 127; iX >= 0; iX--) { fR += fRStep; fG += fGStep; fB -= fBStep; for (iY = 0; iY < 128; iY++) { aaafTextureData[iX][iY][0] = fR; aaafTextureData[iX][iY][1] = fG; aaafTextureData[iX][iY][2] = fB; } } cs->sky.target = GL_TEXTURE_2D; cs->sky.filter = GL_LINEAR; cs->sky.wrap = GL_CLAMP_TO_EDGE; glGenTextures(1, &cs->sky.name); glBindTexture(cs->sky.target, cs->sky.name); glTexParameteri(cs->sky.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(cs->sky.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(cs->sky.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(cs->sky.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(cs->sky.target, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_FLOAT, aaafTextureData); glBindTexture(cs->sky.target, 0); } } static Bool fillCircleTable(GLfloat ** ppSint, GLfloat ** ppCost, const int n) { const GLfloat angle = 2 * M_PI / (GLfloat) ((n == 0) ? 1 : n); const int size = abs(n); int i; *ppSint = (GLfloat *) calloc(sizeof(GLfloat), size + 1); *ppCost = (GLfloat *) calloc(sizeof(GLfloat), size + 1); if (!(*ppSint) || !(*ppCost)) { free(*ppSint); free(*ppCost); return FALSE; } (*ppSint)[0] = 0.0; (*ppCost)[0] = 1.0; for (i = 1; i < size; i++) { (*ppSint)[i] = sin(angle * i); (*ppCost)[i] = cos(angle * i); } (*ppSint)[size] = (*ppSint)[0]; (*ppCost)[size] = (*ppCost)[0]; return TRUE; } static void cubeUpdateSkyDomeList(CompScreen * s, GLfloat fRadius) { GLint iSlices = 128; GLint iStacks = 64; GLfloat afTexCoordX[4]; GLfloat afTexCoordY[4]; GLfloat *sint1; GLfloat *cost1; GLfloat *sint2; GLfloat *cost2; GLfloat r; GLfloat x; GLfloat y; GLfloat z; int i; int j; int iStacksStart; int iStacksEnd; int iSlicesStart; int iSlicesEnd; GLfloat fStepX; GLfloat fStepY; CUBE_SCREEN(s); if (cs->animateSkyDome) { iStacksStart = 11; /* min. 0 */ iStacksEnd = 53; /* max. 64 */ iSlicesStart = 0; /* min. 0 */ iSlicesEnd = 128; /* max. 128 */ } else { iStacksStart = 21; /* min. 0 */ iStacksEnd = 43; /* max. 64 */ iSlicesStart = 21; /* min. 0 */ iSlicesEnd = 44; /* max. 128 */ } fStepX = 1.0 / (GLfloat) (iSlicesEnd - iSlicesStart); fStepY = 1.0 / (GLfloat) (iStacksEnd - iStacksStart); if (!fillCircleTable(&sint1, &cost1, -iSlices)) return; if (!fillCircleTable(&sint2, &cost2, iStacks * 2)) { free(sint1); free(cost1); return; } afTexCoordX[0] = 1.0f; afTexCoordY[0] = fStepY; afTexCoordX[1] = 1.0f - fStepX; afTexCoordY[1] = fStepY; afTexCoordX[2] = 1.0f - fStepX; afTexCoordY[2] = 0.0f; afTexCoordX[3] = 1.0f; afTexCoordY[3] = 0.0f; if (!cs->skyListId) cs->skyListId = glGenLists(1); glNewList(cs->skyListId, GL_COMPILE); enableTexture(s, &cs->sky, COMP_TEXTURE_FILTER_GOOD); glBegin(GL_QUADS); for (i = iStacksStart; i < iStacksEnd; i++) { afTexCoordX[0] = 1.0f; afTexCoordX[1] = 1.0f - fStepX; afTexCoordX[2] = 1.0f - fStepX; afTexCoordX[3] = 1.0f; for (j = iSlicesStart; j < iSlicesEnd; j++) { /* bottom-right */ z = cost2[i]; r = sint2[i]; x = cost1[j]; y = sint1[j]; glTexCoord2f(afTexCoordX[3], afTexCoordY[3]); glVertex3f(x * r * fRadius, y * r * fRadius, z * fRadius); /* top-right */ z = cost2[i + 1]; r = sint2[i + 1]; x = cost1[j]; y = sint1[j]; glTexCoord2f(afTexCoordX[0], afTexCoordY[0]); glVertex3f(x * r * fRadius, y * r * fRadius, z * fRadius); /* top-left */ z = cost2[i + 1]; r = sint2[i + 1]; x = cost1[j + 1]; y = sint1[j + 1]; glTexCoord2f(afTexCoordX[1], afTexCoordY[1]); glVertex3f(x * r * fRadius, y * r * fRadius, z * fRadius); /* bottom-left */ z = cost2[i]; r = sint2[i]; x = cost1[j + 1]; y = sint1[j + 1]; glTexCoord2f(afTexCoordX[2], afTexCoordY[2]); glVertex3f(x * r * fRadius, y * r * fRadius, z * fRadius); afTexCoordX[0] -= fStepX; afTexCoordX[1] -= fStepX; afTexCoordX[2] -= fStepX; afTexCoordX[3] -= fStepX; } afTexCoordY[0] += fStepY; afTexCoordY[1] += fStepY; afTexCoordY[2] += fStepY; afTexCoordY[3] += fStepY; } glEnd(); disableTexture(s, &cs->sky); glEndList(); free(sint1); free(cost1); free(sint2); free(cost2); } static Bool cubeSetScreenOption(CompScreen * screen, char *name, CompOptionValue * value) { CompOption *o; int index; CUBE_SCREEN(screen); o = compFindOption(cs->opt, NUM_OPTIONS(cs), name, &index); if (!o) return FALSE; switch (index) { case CUBE_SCREEN_OPTION_COLOR: if (compSetColorOption(o, value)) { memcpy(cs->color, o->value.c, sizeof(cs->color)); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_IN: if (compSetBoolOption(o, value)) { if (cubeUpdateGeometry (screen, screen->hsize, o->value.b ? -1 : 1)) { IPCS_SetBool(IPCS_OBJECT(screen), cs->insideAtom, o->value.b); return TRUE; } } break; case CUBE_SCREEN_OPTION_SCALE_IMAGE_TOP: if (compSetBoolOption(o, value)) { cs->cubeCapTop.scale = o->value.b; cubeLoadImg(screen, &cs->cubeCapTop, cs->cubeCapTop.imgCurFile); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_SCALE_IMAGE_BOTTOM: if (compSetBoolOption(o, value)) { cs->cubeCapBottom.scale = o->value.b; cubeLoadImg(screen, &cs->cubeCapBottom, cs->cubeCapBottom.imgCurFile); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_IMAGES_ROTATE_MODE: if (compSetStringOption(o, value)) { int i; ImagesRotateMode mode = IMAGES_ROTATE_MODE_DEFAULT; for (i = 0; i < o->rest.s.nString; i++) if (strcmp(imagesRotateModes[i], o->value.s) == 0) mode = (ImagesRotateMode) i; switch (mode) { case ImagesRotateModeAfterMoving: cs->neverRotateImages = FALSE; cs->rotateImages = FALSE; break; case ImagesRotateModeWhileMoving: cs->neverRotateImages = FALSE; cs->rotateImages = TRUE; break; case ImagesRotateModeNever: default: cs->neverRotateImages = TRUE; cs->rotateImages = FALSE; break; } return TRUE; } break; case CUBE_SCREEN_OPTION_MULTIMONITOR: if (compSetStringOption(o, value)) { int i; MultiMonitorMode mode = MULTIMONITOR_MODE_DEFAULT; for (i = 0; i < o->rest.s.nString; i++) if (strcmp(multiMonitorModes[i], o->value.s) == 0) mode = (MultiMonitorMode) i; cs->mmMode = mode; if (cs->mmMode == OneBig) screen->projectionStyle = COMP_PERSPECTIVE_GLOBAL; else screen->projectionStyle = COMP_PERSPECTIVE_LOCAL; cubeUpdateOutputs(screen); cubeUpdateGeometry(screen, screen->hsize, cs->invert); IPCS_SetInt(IPCS_OBJECT(screen), cs->mmModeAtom, cs->mmMode); if (cs->opt[CUBE_SCREEN_OPTION_DRAW_CAPS].value.b) { cubeLoadImg(screen, &cs->cubeCapBottom, cs->cubeCapBottom.imgCurFile); cubeLoadImg(screen, &cs->cubeCapTop, cs->cubeCapTop.imgCurFile); } damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_IMAGES_TOP: if (compSetOptionList(o, value)) { cs->cubeCapTop.imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES_TOP].value.list.value; cs->cubeCapTop.imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES_TOP].value.list.nValue; cubeLoadImg(screen, &cs->cubeCapTop, cs->cubeCapTop.imgCurFile); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_IMAGES_BOTTOM: if (compSetOptionList(o, value)) { cs->cubeCapBottom.imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES_BOTTOM].value.list. value; cs->cubeCapBottom.imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES_BOTTOM].value.list. nValue; cubeLoadImg(screen, &cs->cubeCapBottom, cs->cubeCapBottom.imgCurFile); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_SKYDOME: if (compSetBoolOption(o, value)) { cubeUpdateSkyDomeTexture(screen); cubeUpdateSkyDomeList(screen, 1.0f); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_SKYDOME_IMG: if (compSetStringOption(o, value)) { cubeUpdateSkyDomeTexture(screen); cubeUpdateSkyDomeList(screen, 1.0f); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_SKYDOME_ANIM: if (compSetBoolOption(o, value)) { cs->animateSkyDome = o->value.b; cubeUpdateSkyDomeTexture(screen); cubeUpdateSkyDomeList(screen, 1.0f); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_SKYDOME_GRAD_START: if (compSetColorOption(o, value)) { memcpy(cs->skyGradStartColor, o->value.c, sizeof(cs->skyGradStartColor)); cubeUpdateSkyDomeTexture(screen); cubeUpdateSkyDomeList(screen, 1.0f); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_SKYDOME_GRAD_END: if (compSetColorOption(o, value)) { memcpy(cs->skyGradEndColor, o->value.c, sizeof(cs->skyGradEndColor)); cubeUpdateSkyDomeTexture(screen); cubeUpdateSkyDomeList(screen, 1.0f); damageScreen(screen); return TRUE; } break; case CUBE_SCREEN_OPTION_ACCELERATION: if (compSetFloatOption(o, value)) { cs->acceleration = o->value.f; return TRUE; } break; case CUBE_SCREEN_OPTION_SPEED: if (compSetFloatOption(o, value)) { cs->speed = o->value.f; return TRUE; } break; case CUBE_SCREEN_OPTION_TIMESTEP: if (compSetFloatOption(o, value)) { cs->timestep = o->value.f; return TRUE; } break; case CUBE_SCREEN_OPTION_MIPMAP: if (compSetBoolOption(o, value)) return TRUE; break; case CUBE_SCREEN_OPTION_UNFOLD_ZOOM_DISTANCE: if (compSetFloatOption(o, value)) { cs->unfoldDistance = o->value.f; return TRUE; } break; case CUBE_SCREEN_OPTION_FADE_TIME: if (compSetFloatOption(o, value)) { return TRUE; } break; case CUBE_SCREEN_OPTION_ACTIVE_OPACITY: case CUBE_SCREEN_OPTION_INACTIVE_OPACITY: if (compSetIntOption(o, value)) { return TRUE; } break; case CUBE_SCREEN_OPTION_TRANSPARENT: case CUBE_SCREEN_OPTION_STUCK_TO_SCREEN: case CUBE_SCREEN_OPTION_CAP_TRANSPARENT: case CUBE_SCREEN_OPTION_VIEWPORT_SLIDE: case CUBE_TRANSPARENT_MANUALONLY: case CUBE_SCREEN_OPTION_VIEWPORT_SLIDE_NO3D: case CUBE_SCREEN_OPTION_DRAW_CAPS: if (compSetBoolOption(o, value)) return TRUE; break; default: break; } return FALSE; } static void cubeScreenInitOptions(CubeScreen * cs) { CompOption *o; int i; o = &cs->opt[CUBE_SCREEN_OPTION_COLOR]; o->advanced = False; o->name = "color"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Cube Color"); o->longDesc = N_("Color of top and bottom sides of the Cube."); o->type = CompOptionTypeColor; o->value.c[0] = CUBE_COLOR_RED_DEFAULT; o->value.c[1] = CUBE_COLOR_GREEN_DEFAULT; o->value.c[2] = CUBE_COLOR_BLUE_DEFAULT; o->value.c[3] = 0xffff; o = &cs->opt[CUBE_SCREEN_OPTION_IN]; o->advanced = False; o->name = "in"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Inside Cube"); o->longDesc = N_("Change perspective to inside the Cube, looking out."); o->type = CompOptionTypeBool; o->value.b = CUBE_IN_DEFAULT; o = &cs->opt[CUBE_TRANSPARENT_MANUALONLY]; o->advanced = False; o->name = "manualonly"; o->group = N_("Transparency"); o->subGroup = N_(""); o->displayHints = ""; 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 = FALSE; o = &cs->opt[CUBE_SCREEN_OPTION_SCALE_IMAGE_TOP]; o->advanced = False; o->name = "scale_image_top"; o->group = N_("Caps"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Scale Image on Top"); o->longDesc = N_("Scale images to cover top face of Cube."); o->type = CompOptionTypeBool; o->value.b = CUBE_SCALE_IMAGE_TOP_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_IMAGES_TOP]; o->advanced = False; o->name = "images_top"; o->group = N_("Caps"); o->subGroup = N_(""); o->displayHints = "file;image;"; o->shortDesc = N_("Image Files on Top"); o->longDesc = N_("List of JPEG, PNG and SVG files that should be " "rendered on the top face of Cube."); o->type = CompOptionTypeList; o->value.list.type = CompOptionTypeString; o->value.list.nValue = N_CUBE_IMAGES; o->value.list.value = malloc(sizeof(CompOptionValue) * N_CUBE_IMAGES); for (i = 0; i < N_CUBE_IMAGES; i++) o->value.list.value[i].s = strdup(cubeImages[i]); o->rest.s.string = 0; o->rest.s.nString = 0; o = &cs->opt[CUBE_SCREEN_OPTION_SCALE_IMAGE_BOTTOM]; o->advanced = False; o->name = "scale_image_bottom"; o->group = N_("Caps"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Scale Image on Bottom"); o->longDesc = N_("Scale images to cover bottom face of Cube."); o->type = CompOptionTypeBool; o->value.b = CUBE_SCALE_IMAGE_BOTTOM_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_IMAGES_ROTATE_MODE]; o->advanced = False; o->name = "images_rotate_mode"; o->group = N_("Caps"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Images Rotate Mode"); o->longDesc = N_("Select between never, after moving and while moving mode."); o->type = CompOptionTypeString; o->value.s = strdup(imagesRotateModes[IMAGES_ROTATE_MODE_DEFAULT]); o->rest.s.string = imagesRotateModes; o->rest.s.nString = NUM_IMAGES_ROTATE_MODES; o = &cs->opt[CUBE_SCREEN_OPTION_IMAGES_BOTTOM]; o->advanced = False; o->name = "images_bottom"; o->group = N_("Caps"); o->subGroup = N_(""); o->displayHints = "file;image;"; o->shortDesc = N_("Image Files on Bottom"); o->longDesc = N_("List of JPEG, PNG and SVG files that should be " "rendered on the bottom face of Cube."); o->type = CompOptionTypeList; o->value.list.type = CompOptionTypeString; o->value.list.nValue = N_CUBE_IMAGES; o->value.list.value = malloc(sizeof(CompOptionValue) * N_CUBE_IMAGES); for (i = 0; i < N_CUBE_IMAGES; i++) o->value.list.value[i].s = strdup(cubeImages[i]); o->rest.s.string = 0; o->rest.s.nString = 0; o = &cs->opt[CUBE_SCREEN_OPTION_SKYDOME]; o->advanced = False; o->name = "skydome"; o->group = N_("Skydome"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Skydome"); o->longDesc = N_("Background image, shown behind the Cube."); o->type = CompOptionTypeBool; o->value.b = CUBE_SKYDOME_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG]; o->advanced = False; o->name = "skydome_image"; o->group = N_("Skydome"); o->subGroup = N_(""); o->displayHints = "file;image"; o->shortDesc = N_("Skydome Image"); o->longDesc = N_ ("Image to use for the Skydome. Dimensions must be a " "power of two (i.e. 1024, 2048, 4096...."); o->type = CompOptionTypeString; o->value.s = strdup(""); o->rest.s.string = 0; o->rest.s.nString = 0; o = &cs->opt[CUBE_SCREEN_OPTION_SKYDOME_ANIM]; o->advanced = False; o->name = "skydome_animated"; o->group = N_("Skydome"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Animate Skydome"); o->longDesc = N_ ("Animate Skydome when rotating Cube giving the appearance that you (not the cube) are moving."); o->type = CompOptionTypeBool; o->value.b = CUBE_SKYDOME_ANIMATE_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START]; o->advanced = False; o->name = "skydome_gradient_start_color"; o->group = N_("Skydome"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Skydome Gradient Start Color"); o->longDesc = N_ ("Color to use for the top color-stop of the Skydome-fallback gradient."); o->type = CompOptionTypeColor; o->value.c[0] = CUBE_SKYDOME_GRAD_START_RED_DEFAULT; o->value.c[1] = CUBE_SKYDOME_GRAD_START_GREEN_DEFAULT; o->value.c[2] = CUBE_SKYDOME_GRAD_START_BLUE_DEFAULT; o->value.c[3] = 0xffff; o = &cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END]; o->advanced = False; o->name = "skydome_gradient_end_color"; o->group = N_("Skydome"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Skydome Gradient End Color"); o->longDesc = N_ ("Color to use for the bottom color-stop of the Skydome-fallback gradient."); o->type = CompOptionTypeColor; o->value.c[0] = CUBE_SKYDOME_GRAD_END_RED_DEFAULT; o->value.c[1] = CUBE_SKYDOME_GRAD_END_GREEN_DEFAULT; o->value.c[2] = CUBE_SKYDOME_GRAD_END_BLUE_DEFAULT; o->value.c[3] = 0xffff; o = &cs->opt[CUBE_SCREEN_OPTION_ACCELERATION]; o->advanced = False; o->name = "acceleration"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Fold Acceleration"); o->longDesc = N_("Fold acceleration."); o->type = CompOptionTypeFloat; o->value.f = CUBE_ACCELERATION_DEFAULT; o->rest.f.min = CUBE_ACCELERATION_MIN; o->rest.f.max = CUBE_ACCELERATION_MAX; o->rest.f.precision = CUBE_ACCELERATION_PRECISION; o = &cs->opt[CUBE_SCREEN_OPTION_SPEED]; o->advanced = False; o->name = "speed"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Fold Speed"); o->longDesc = N_("Fold speed."); o->type = CompOptionTypeFloat; o->value.f = CUBE_SPEED_DEFAULT; o->rest.f.min = CUBE_SPEED_MIN; o->rest.f.max = CUBE_SPEED_MAX; o->rest.f.precision = CUBE_SPEED_PRECISION; o = &cs->opt[CUBE_SCREEN_OPTION_TIMESTEP]; o->advanced = False; o->name = "timestep"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Fold Timestep"); o->longDesc = N_("Fold timestep."); o->type = CompOptionTypeFloat; o->value.f = CUBE_TIMESTEP_DEFAULT; o->rest.f.min = CUBE_TIMESTEP_MIN; o->rest.f.max = CUBE_TIMESTEP_MAX; o->rest.f.precision = CUBE_TIMESTEP_PRECISION; o = &cs->opt[CUBE_SCREEN_OPTION_MIPMAP]; o->advanced = False; o->name = "mipmap"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Mipmap"); 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_VIEWPORT_SLIDE]; o->advanced = False; o->name = "change_viewport_slide"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Slide When Changing Viewports\nInstead of Rotating."); o->longDesc = N_("Slide when changing viewports instead of rotating."); o->type = CompOptionTypeBool; o->value.b = CUBE_VIEWPORT_SLIDE_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_VIEWPORT_SLIDE_NO3D]; o->advanced = False; o->name = "change_viewport_slide_no3d"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Keep the Cube Planar Even\nWhen Mouse Grabbing."); o->longDesc = N_("Keep the Cube planar even when mouse grabbing."); o->type = CompOptionTypeBool; o->value.b = CUBE_VIEWPORT_SLIDE_NO3D_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_DRAW_CAPS]; o->advanced = False; o->name = "draw_caps"; o->group = N_("Caps"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Draw Caps"); o->longDesc = N_("Draw the Cube 'caps'; uncheck to keep them transparent."); o->type = CompOptionTypeBool; o->value.b = CUBE_DRAW_CAPS_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_MULTIMONITOR]; o->advanced = False; o->name = "multimonitor_mode"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("MultiMonitor Mode"); o->longDesc = N_("Multi monitor mode behavior."); o->type = CompOptionTypeString; o->value.s = strdup(multiMonitorModes[MULTIMONITOR_MODE_DEFAULT]); o->rest.s.string = multiMonitorModes; o->rest.s.nString = NUM_MULTIMONITOR_MODES; o = &cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT]; o->advanced = False; o->name = "transparent"; o->group = N_("Transparency"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Transparent Cube"); o->longDesc = N_("Change desktop window opacity and draw complete Cube."); o->type = CompOptionTypeBool; o->value.b = CUBE_TRANSPARENT_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_STUCK_TO_SCREEN]; o->advanced = False; o->name = "stuck_to_screen"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Stick Sticky Windows to Screen"); o->longDesc = N_("Cause dock and sticky windows to be drawn stuck to the screen instead of the Cube."); o->type = CompOptionTypeBool; o->value.b = FALSE; o = &cs->opt[CUBE_SCREEN_OPTION_CAP_TRANSPARENT]; o->advanced = False; o->name = "cap_transparent_snap"; o->group = N_("Transparency"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Activate Transparancy on\nTop/Bottom Snap"); o->longDesc = N_("Treat the Cube opacity as if the Cube was active when the " "Cube is snapped to the top/bottom caps. "); o->type = CompOptionTypeBool; o->value.b = CAP_TRANSPARENT_DEFAULT; o = &cs->opt[CUBE_SCREEN_OPTION_FADE_TIME]; o->advanced = False; o->name = "fade_time"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; 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->advanced = False; o->name = "active_opacity"; o->group = N_("Transparency"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Opacity During Move"); o->longDesc = N_("Opacity of desktop window during move."); o->type = CompOptionTypeInt; o->value.i = CUBE_ACTIVE_OPACITY_DEFAULT; o->rest.i.min = 0; o->rest.i.max = 100; o = &cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY]; o->advanced = False; o->name = "inactive_opacity"; o->group = N_("Transparency"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Opacity When Not Moving"); o->longDesc = N_("Opacity of desktop window when not moving."); o->type = CompOptionTypeInt; o->value.i = CUBE_INACTIVE_OPACITY_DEFAULT; o->rest.i.min = 0; o->rest.i.max = 100; o = &cs->opt[CUBE_SCREEN_OPTION_UNFOLD_ZOOM_DISTANCE]; o->advanced = False; o->name = "unfold_distancee"; o->group = N_("Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Unfold Zoomback Distance"); o->longDesc = N_("Distance to zoom back when Unfolded."); o->type = CompOptionTypeFloat; o->value.f = CUBE_UNFOLD_ZOOM_DEFAULT; o->rest.f.min = CUBE_UNFOLD_ZOOM_MIN; o->rest.f.max = CUBE_UNFOLD_ZOOM_MAX; o->rest.f.precision = CUBE_UNFOLD_ZOOM_PRECISION; } static CompOption *cubeGetScreenOptions(CompScreen * screen, int *count) { if (screen) { CUBE_SCREEN(screen); *count = NUM_OPTIONS(cs); return cs->opt; } else { CubeScreen *cs = malloc(sizeof(CubeScreen)); cubeScreenInitOptions(cs); *count = NUM_OPTIONS(cs); return cs->opt; } } static int adjustVelocity(CubeScreen * cs) { float unfold, adjust, amount; if (cs->unfolded) unfold = 1.0f - cs->unfold; else unfold = 0.0f - cs->unfold; adjust = unfold * 0.02f * cs->acceleration; amount = fabs(unfold); if (amount < 1.0f) amount = 1.0f; else if (amount > 3.0f) amount = 3.0f; cs->unfoldVelocity = (amount * cs->unfoldVelocity + adjust) / (amount + 2.0f); return (fabs(unfold) < 0.002f && fabs(cs->unfoldVelocity) < 0.01f); } static void cubePreparePaintScreen(CompScreen * s, int msSinceLastPaint) { CUBE_SCREEN(s); if (cs->grabIndex) { int steps; float amount, chunk; amount = msSinceLastPaint * 0.2f * cs->speed; steps = amount / (0.5f * cs->timestep); if (!steps) steps = 1; chunk = amount / (float)steps; while (steps--) { cs->unfold += cs->unfoldVelocity * chunk; if (cs->unfold > 1.0f) cs->unfold = 1.0f; if (adjustVelocity(cs)) { if (cs->unfold < 0.5f) { if (cs->grabIndex) { removeScreenGrab(s, cs->grabIndex, NULL); cs->grabIndex = 0; } cs->unfold = 0.0f; } break; } } } /* Transparency */ if (cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT].value.b) { if (screenGrabExist(s, "rotate", 0) && (IPCS_GetBool(IPCS_OBJECT(s), cs->manualAtom) || !(cs->opt[CUBE_TRANSPARENT_MANUALONLY].value.b))) /* TODO: Add key to set boolean to toggle drawing at active opacity */ { if (!cs->opt[CUBE_SCREEN_OPTION_CAP_TRANSPARENT].value.b && IPCS_GetBool(IPCS_OBJECT(s), cs->snapTopBottomAtom)) cs->toOpacity = cs-> opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.i; else cs->toOpacity = cs-> opt[CUBE_SCREEN_OPTION_ACTIVE_OPACITY].value.i; } else cs->toOpacity = cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.i; cs->toOpacity = cs->toOpacity / 100.0 * 0xffff; } else { cs->toOpacity = OPAQUE; } if (cs->opt[CUBE_SCREEN_OPTION_FADE_TIME].value.f == 0.0f) { cs->desktopOpacity = cs->toOpacity; } else { 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); } } UNWRAP(cs, s, preparePaintScreen); (*s->preparePaintScreen) (s, msSinceLastPaint); WRAP(cs, s, preparePaintScreen, cubePreparePaintScreen); } static Bool cubePaintScreen(CompScreen * s, const ScreenPaintAttrib * sAttrib, Region region, int output, unsigned int mask) { Bool status; CUBE_SCREEN(s); if (cs->grabIndex || (cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT].value.b && ((cs->desktopOpacity != OPAQUE || s->berylDesktopManaged) || s->berylDesktopManaged))) mask &= ~PAINT_SCREEN_REGION_MASK; cs->finalPaint=TRUE; if (cs->grabIndex) { cs->finalPaint=!(cs->opt[CUBE_SCREEN_OPTION_STUCK_TO_SCREEN].value.b); mask |= PAINT_SCREEN_TRANSFORMED_MASK; } if ((!mask & PAINT_SCREEN_TRANSFORMED_MASK) && (cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT].value.b && ((cs->desktopOpacity != OPAQUE || s->berylDesktopManaged) || s->berylDesktopManaged))) { cs->finalPaint=!(cs->opt[CUBE_SCREEN_OPTION_STUCK_TO_SCREEN].value.b); if (cs->sky.name) { screenLighting(s, FALSE); glPushMatrix(); if (cs->mmMode == OneBig) { glScalef(cs->outputXScale, cs->outputYScale, 1); glTranslatef(cs->outputXOffset / cs->outputXScale, -cs->outputYOffset / cs->outputYScale, 0); } if (cs->animateSkyDome) // && cs->grabIndex == 0) { glRotatef(sAttrib->xRotate - ((s->x * 360.0f) / s->hsize), 0.0f, 1.0f, 0.0f); glRotatef(sAttrib->vRotate / 5.0f + 90.0f, 1.0f, 0.0f, 0.0f); } else { glRotatef(90.0f, 1.0f, 0.0f, 0.0f); } glCallList(cs->skyListId); glPopMatrix(); } else { glClear(GL_COLOR_BUFFER_BIT); } mask &= ~PAINT_SCREEN_CLEAR_MASK; } UNWRAP(cs, s, paintScreen); status = (*s->paintScreen) (s, sAttrib, region, output, mask); WRAP(cs, s, paintScreen, cubePaintScreen); if (!cs->finalPaint) { glPushMatrix(); prepareXCoords(s, output, -DEFAULT_Z_CAMERA); cs->finalPaint=TRUE; CompWindow * w; for (w=s->reverseWindows;w;w=w->prev) { if (((w->type & CompWindowTypeDockMask) || (w->state & CompWindowStateStickyMask && !(w->state & CompWindowStateBelowMask)) || w->attrib.override_redirect) && (w->mapNum && w->attrib.map_state == IsViewable && !(w->minimized) && !(w->state & CompWindowStateHiddenMask))) { s->paintWindow(w,&w->paint,getInfiniteRegion(),0); } } glPopMatrix(); } return status; } static void cubeDonePaintScreen(CompScreen * s) { CUBE_SCREEN(s); if (cs->grabIndex || cs->toOpacity != cs->desktopOpacity) damageScreen(s); UNWRAP(cs, s, donePaintScreen); (*s->donePaintScreen) (s); WRAP(cs, s, donePaintScreen, cubeDonePaintScreen); } typedef struct _CubeFacePaint { int xMove; ScreenPaintAttrib sa; float z; Bool rev; Bool painted; } CubeFacePaint; static void paintReversed(CompScreen * s, const ScreenPaintAttrib * sA, int output, int xMove, CubeFacePaint * face) { CUBE_SCREEN(s); float pm[16]; float mvm[16]; float mvp[16]; glPushMatrix(); //Get the matrices. // inputzoom should not scale here cs->paintingCaps = TRUE; (s->applyScreenTransform) (s, sA, output); prepareXCoords(s, output, -sA->zTranslate); cs->paintingCaps = FALSE; glGetFloatv(GL_MODELVIEW_MATRIX, mvm); glGetFloatv(GL_PROJECTION_MATRIX, pm); MULTM(pm, mvm, mvp); glPopMatrix(); float pntA[4] = { s->outputDev[output].region.extents.x1, s->outputDev[output].region.extents.y1, 0, 1 }; float pntB[4] = { s->outputDev[output].region.extents.x2, s->outputDev[output].region.extents.y1, 0, 1 }; float pntC[4] = { s->outputDev[output].region.extents.x1 + s->outputDev[output].width / 2.0f, s->outputDev[output].region.extents.y1 + s->outputDev[output].height / 2.0f, 0, 1 }; MULTMV(mvp, pntA); DIVV(pntA); MULTMV(mvp, pntB); DIVV(pntB); MULTMV(mvp, pntC); DIVV(pntC); float vecA[3] = { pntC[0] - pntA[0], pntC[1] - pntA[1], pntC[2] - pntA[2] }; float vecB[3] = { pntC[0] - pntB[0], pntC[1] - pntB[1], pntC[2] - pntB[2] }; float normal[3] = { vecA[1] * vecB[2] - vecA[2] * vecB[1], vecA[2] * vecB[0] - vecA[0] * vecB[2], vecA[0] * vecB[1] - vecA[1] * vecB[0] }; float length = sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); normal[0] /= length; normal[1] /= length; normal[2] /= length; face->sa = *sA; face->xMove = xMove; face->z = pntC[2]; face->rev = FALSE; if (normal[2] > 0.0) { face->rev = TRUE; } } static Bool capsReversed(void) { float pm[16]; float mvm[16]; float mvp[16]; glGetFloatv(GL_MODELVIEW_MATRIX, mvm); glGetFloatv(GL_PROJECTION_MATRIX, pm); MULTM(pm, mvm, mvp); float pntA[4] = { 0.0, 0.5, 0.0, 1 }; float pntB[4] = { 0.0, -0.5, 0.0, 1 }; MULTMV(mvp, pntA); DIVV(pntA); MULTMV(mvp, pntB); DIVV(pntB); float vec[3] = { pntB[0] - pntA[0], pntB[1] - pntA[1], pntB[2] - pntA[2] }; if (vec[2] > 0.0) { return TRUE; } return FALSE; } static void cubeMoveViewportAndPaint(CompScreen * s, const ScreenPaintAttrib * sAttrib, int output, unsigned int mask, int dx) { CUBE_SCREEN(s); Bool save; save=cs->finalPaint; if (cs->nOutput > 1) { int cubeOutput, dView; /* translate to cube output */ cubeOutput = cs->outputMask[output]; /* convert from window movement to viewport movement */ dView = -dx; cubeOutput += dView; if (cs->mmMode != Multiple) { dView = cubeOutput / cs->nOutput; cubeOutput = cubeOutput % cs->nOutput; if (cubeOutput < 0) { cubeOutput += cs->nOutput; dView--; } /* translate back to beryl output */ output = cs->output[cubeOutput]; } if (dView != 0) cs->finalPaint=!(cs->opt[CUBE_SCREEN_OPTION_STUCK_TO_SCREEN].value.b); if (dView != 0 && !screenGrabExist(s, "rotate", 0) && (((cs->desktopOpacity != OPAQUE || s->berylDesktopManaged)))) cs->noManaged = TRUE; moveScreenViewport(s, -dView, 0, FALSE); (*s->paintTransformedScreen) (s, sAttrib, &s->outputDev[output].region, output, mask); moveScreenViewport(s, dView, 0, FALSE); } else { if (dx != 0) cs->finalPaint=!(cs->opt[CUBE_SCREEN_OPTION_STUCK_TO_SCREEN].value.b); if (dx != 0 && !screenGrabExist(s, "rotate", 0) && (cs->desktopOpacity != OPAQUE || s->berylDesktopManaged)) cs->noManaged = TRUE; moveScreenViewport(s, dx, 0, FALSE); (*s->paintTransformedScreen) (s, sAttrib, &s->region, output, mask); moveScreenViewport(s, -dx, 0, FALSE); } cs->finalPaint=save; cs->noManaged = FALSE; } static void cubeDrawCubeCap(CompScreen * s, int hsize, int arrayOffset, CubeCapInfo * capOutside, CubeCapInfo * capInside, unsigned short opacity) { CubeCapInfo *cubeCap; CUBE_SCREEN(s); if (cs->invert == 1) cubeCap = capOutside; else if (cs->invert != 1) cubeCap = capInside; else cubeCap = NULL; glColor4us(cs->color[0], cs->color[1], cs->color[2], opacity); glDrawArrays(GL_TRIANGLE_FAN, arrayOffset, cs->nvertices >> 1); /*if (cubeCap && cubeCap->texture.name && s->hsize == 4) { if (opacity != OPAQUE) { glColor4us(0xffff, 0xffff, 0xffff, opacity); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } enableTexture(s, &cubeCap->texture, COMP_TEXTURE_FILTER_GOOD); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // as GL expects the texture coords with offset, but our // texture coord array is 0-based, we have to subtract the offset here glTexCoordPointer(2, GL_FLOAT, 0, cubeCap->tc - (arrayOffset << 1)); glDrawArrays(GL_TRIANGLE_FAN, arrayOffset, cs->nvertices >> 1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); disableTexture(s, &cubeCap->texture); screenTexEnvMode(s, GL_REPLACE); }*/ if (cubeCap && cubeCap->texture.name) { //screenTexEnvMode(s, GL_REPLACE); enableTexture(s, &cubeCap->texture, COMP_TEXTURE_FILTER_GOOD); int centerx = *cs->vertices; int centery = *(cs->vertices+1); int centerz = *(cs->vertices+2); glColor4f(1.0,1.0,1.0,1.0); if (opacity != OPAQUE) { glColor4us(0xffff, 0xffff, 0xffff, opacity); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } GLfloat x1,y1,x2,y2; x1 = cubeCap->tc[4]; x2 = cubeCap->tc[2]; y1 = cubeCap->tc[3]; y2 = cubeCap->tc[9]; glBegin(GL_QUADS); if (arrayOffset) centery-=1; if (arrayOffset) { glTexCoord2f(x1,y1); glVertex3f(centerx-0.5,centery+0.5,centerz+0.5); glTexCoord2f(x1,y2); glVertex3f(centerx-0.5,centery+0.5,centerz-0.5); glTexCoord2f(x2,y2); glVertex3f(centerx+0.5, centery+0.5, centerz-0.5); glTexCoord2f(x2,y1); glVertex3f(centerx+0.5,centery+0.5,centerz+0.5); } else { glTexCoord2f(x2,y2); glVertex3f(centerx+0.5,centery+0.5,centerz+0.5); glTexCoord2f(x2,y1); glVertex3f(centerx+0.5, centery+0.5, centerz-0.5); glTexCoord2f(x1,y1); glVertex3f(centerx-0.5,centery+0.5,centerz-0.5); glTexCoord2f(x1,y2); glVertex3f(centerx-0.5,centery+0.5,centerz+0.5); } glEnd(); disableTexture(s, &cubeCap->texture); } } static void cubePaintTransformedScreen(CompScreen * s, const ScreenPaintAttrib * sAttrib, Region region, int output, unsigned int mask) { ScreenPaintAttrib sa = *sAttrib; int hsize, xMove = 0; float size; CUBE_SCREEN(s); hsize = s->hsize; if (cs->mmMode != Multiple) hsize *= cs->nOutput; size = hsize; if (!cs->fullscreenOutput) { cs->outputXScale = (float)s->width / s->outputDev[output].width; cs->outputYScale = (float)s->height / s->outputDev[output].height; cs->outputXOffset = (s->width / 2.0f - (s->outputDev[output].region.extents.x1 + s->outputDev[output].region.extents.x2) / 2.0f) / (float)s->outputDev[output].width; cs->outputYOffset = (s->height / 2.0f - (s->outputDev[output].region.extents.y1 + s->outputDev[output].region.extents.y2) / 2.0f) / (float)s->outputDev[output].height; } else { cs->outputXScale = 1.0f; cs->outputYScale = 1.0f; cs->outputXOffset = 0.0f; cs->outputYOffset = 0.0f; } if (cs->sky.name) { screenLighting(s, FALSE); glPushMatrix(); if (cs->mmMode == OneBig) { glScalef(cs->outputXScale, cs->outputYScale, 1); glTranslatef(cs->outputXOffset / cs->outputXScale, -cs->outputYOffset / cs->outputYScale, 0); } if (cs->animateSkyDome) // && cs->grabIndex == 0) { glRotatef(sAttrib->vRotate / 5.0f + 90.0f, 1.0f, 0.0f, 0.0f); if (cs->invert != 1) glRotatef(- (sAttrib->xRotate - ((s->x * 360.0f) / s->hsize)), 0.0f, 0.0f, -1.0f); else glRotatef(sAttrib->xRotate - ((s->x * 360.0f) / s->hsize), 0.0f, 0.0f, -1.0f); } else { glRotatef(90.0f, 1.0f, 0.0f, 0.0f); } glCallList(cs->skyListId); glPopMatrix(); } else { clearTargetOutput(s->display, GL_COLOR_BUFFER_BIT); } mask &= ~PAINT_SCREEN_CLEAR_MASK; UNWRAP(cs, s, paintTransformedScreen); sa.xTranslate = sAttrib->xTranslate; sa.yTranslate = sAttrib->yTranslate; if (screenGrabExist(s, "rotate", "cube", 0) || sAttrib->zCamera!=-DEFAULT_Z_CAMERA) cs->finalPaint=!(cs->opt[CUBE_SCREEN_OPTION_STUCK_TO_SCREEN].value.b); else cs->finalPaint=TRUE; if (cs->grabIndex) { sa.vRotate = 0.0f; size += cs->unfold * 8.0f; size += powf(cs->unfold, 6) * 64.0; size += powf(cs->unfold, 16) * 8192.0; sa.zTranslate = -cs->invert * (0.5f / tanf(M_PI / size)); sa.zCamera -= cs->unfold * cs->unfoldDistance; sa.zCamera /= IPCS_IsSet(IPCS_OBJECT(s), cs-> zoomLevelAtom) ? IPCS_GetFloat(IPCS_OBJECT(s), cs->zoomLevelAtom) : 1; sa.xRotate = sAttrib->xRotate * cs->invert; if (sa.xRotate > 0.0f) { cs->xrotations = (int)(hsize * sa.xRotate) / 360; sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / hsize; } else { cs->xrotations = (int)(hsize * sa.xRotate) / 360; sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / s->hsize + 360.0f / hsize; cs->xrotations--; } sa.xRotate = sa.xRotate / size * hsize; } else if (cs->opt[CUBE_SCREEN_OPTION_VIEWPORT_SLIDE].value.b && (sa.vRotate == 0.0f || cs->opt[CUBE_SCREEN_OPTION_VIEWPORT_SLIDE_NO3D].value.b)) { if (cs->opt[CUBE_SCREEN_OPTION_VIEWPORT_SLIDE_NO3D].value.b) sa.vRotate = 0.0f; size += 8.0f + 64.0f + 8192.0f; sa.zTranslate = -cs->invert * (0.5f / tanf(M_PI / (size))); sa.xRotate = sAttrib->xRotate * cs->invert; if (sa.xRotate > 0.0f) { cs->xrotations = (int)(hsize * sa.xRotate) / 360; sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / hsize; } else { cs->xrotations = (int)(hsize * sa.xRotate) / 360; sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / hsize + 360.0f / hsize; cs->xrotations--; } sa.xRotate = sa.xRotate / size * hsize; } else { if (sAttrib->vRotate > 100.0f) sa.vRotate = 100.0f; else if (sAttrib->vRotate < -100.0f) sa.vRotate = -100.0f; else sa.vRotate = sAttrib->vRotate; 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; } else { cs->xrotations = (int)(size * sa.xRotate) / 360; sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / size + 360.0f / size; cs->xrotations--; } } ScreenPaintAttrib soa = sa; int rotations = cs->xrotations; CubeFacePaint *faces = malloc(sizeof(CubeFacePaint) * MAX(hsize, 3)); int fc = 0; int i; for (i = 0; i < MAX(hsize, 3); i++) faces[i].painted = FALSE; /* outside cube */ if (cs->invert == 1) { float yRotSav = sa.yRotate; if (cs->grabIndex || hsize > 4 || (cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT].value.b && (cs->desktopOpacity != OPAQUE || s->berylDesktopManaged)) || compDisplayGetRequestFlagForAny(s->display, "DRAW_ALL_FACES")) { int i; xMove = cs->xrotations - ((hsize >> 1) - 1); sa.yRotate += (360.0f / size) * ((hsize >> 1) - 1); for (i = 0; i < hsize; i++) { paintReversed(s, &sa, output, xMove, &faces[fc]); fc++; sa.yRotate -= 360.0f / size; xMove++; } } else { if (sAttrib->xRotate != 0.0f) { xMove = cs->xrotations; paintReversed(s, &sa, output, xMove, &faces[fc]); fc++; xMove++; } sa.yRotate -= 360.0f / size; paintReversed(s, &sa, output, xMove, &faces[fc]); fc++; } sa.yRotate = yRotSav; } else { if (sa.xRotate > 180.0f / size) { sa.yRotate -= 360.0f / size; cs->xrotations++; } sa.yRotate -= 360.0f / size; xMove = -1 - cs->xrotations; if (cs->grabIndex || sAttrib->vRotate > 60.0) { int i; if (sa.xRotate > 180.0f / size) { xMove -= ((hsize >> 1) - 2); sa.yRotate -= (360.0f / size) * ((hsize >> 1) - 2); } else { xMove -= ((hsize >> 1) - 1); sa.yRotate -= (360.0f / size) * ((hsize >> 1) - 1); } for (i = 0; i < hsize; i++) { paintReversed(s, &sa, output, xMove, &faces[fc]); fc++; sa.yRotate += 360.0f / size; xMove++; } } else { paintReversed(s, &sa, output, xMove, &faces[fc]); fc++; sa.yRotate += 360.0f / size; xMove = -cs->xrotations; paintReversed(s, &sa, output, xMove, &faces[fc]); fc++; sa.yRotate += 360.0f / size; xMove = 1 - cs->xrotations; paintReversed(s, &sa, output, xMove, &faces[fc]); fc++; } } Bool disabledCull = FALSE; GLenum filter; unsigned int newMask; int num = 0, j; if (cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT].value.b && (cs->desktopOpacity != OPAQUE || s->berylDesktopManaged)) mask |= PAINT_SCREEN_TRANSFORMED_MASK; if ((cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT].value.b || compDisplayGetRequestFlagForAny(s->display, "DRAW_ALL_FACES")) && cs->invert == 1) { if (glIsEnabled(GL_CULL_FACE) && (cs->desktopOpacity != OPAQUE || s->berylDesktopManaged)) { disabledCull = TRUE; glDisable(GL_CULL_FACE); } glNormal3f(0.0, 0.0, 1.0); newMask = mask | PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK; filter = s->display->textureFilter; if (cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b) s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR; for (i = 0; i < fc; i++) if (faces[i].rev) num++; for (i = 0; i < num; i++) { int found = 0; float minZ = -2.0; for (j = 0; j < fc; j++) { if (faces[j].z > minZ && !faces[j].painted && faces[j].rev) { found = j; minZ = faces[j].z; } } faces[found].painted = TRUE; cubeMoveViewportAndPaint(s, &faces[found].sa, output, newMask, faces[found].xMove); } s->display->textureFilter = filter; if (disabledCull) { glEnable(GL_CULL_FACE); disabledCull = FALSE; } } cs->paintingCaps = TRUE; if (cs->grabIndex == 0 && (hsize > 2) && (cs->invert != 1 || sa.vRotate != 0.0f || sa.yTranslate != 0.0f || (cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT].value.b && (cs->desktopOpacity != OPAQUE || s->berylDesktopManaged))) && cs->opt[CUBE_SCREEN_OPTION_DRAW_CAPS].value.b && !compDisplayGetRequestFlagForAny(s->display, "NO_CUBE_CAPS")) { screenLighting(s, TRUE); glColor4us(cs->color[0], cs->color[1], cs->color[2], cs->desktopOpacity); glPushMatrix(); if (sAttrib->xRotate > 0.0f) { sa.yRotate += 360.0f / size; (s->applyScreenTransform) (s, &soa, output); glTranslatef(cs->outputXOffset, -cs->outputYOffset, 0.0f); glScalef(cs->outputXScale, cs->outputYScale, 1.0f); sa.yRotate -= 360.0f / size; } else { (s->applyScreenTransform) (s, &soa, output); glTranslatef(cs->outputXOffset, -cs->outputYOffset, 0.0f); glScalef(cs->outputXScale, cs->outputYScale, 1.0f); } glVertexPointer(3, GL_FLOAT, 0, cs->vertices); //if (hsize != 4 && cs->invert != 1) // glRotatef(180.0f, 0.0f, 1.0f, 0.0f); glRotatef(360.0f/(float)hsize, 0.0f, 1.0f, 0.0f); if (cs->rotateImages) { if (soa.xRotate > (360.0f/(float)hsize)/2.0f) glRotatef(-360.0f/(float)hsize, 0.0f, 1.0f, 0.0f); } else if (cs->neverRotateImages) { glRotatef(rotations * (360.0f/(float)hsize), 0.0f, 1.0f, 0.0f); float previousRotation = IPCS_GetFloat(IPCS_OBJECT(s), cs-> previousRotationAtom); if (cs->invert != 1) previousRotation = -previousRotation; glRotatef(previousRotation * (360.0f/(float)hsize), 0.0f, 1.0f, 0.0f); } else { glRotatef(rotations *(360.0f/(float)hsize), 0.0f, 1.0f, 0.0f); } if (glIsEnabled(GL_CULL_FACE) && (cs->desktopOpacity != OPAQUE || s->berylDesktopManaged) && cs->invert == 1) { disabledCull = TRUE; glDisable(GL_CULL_FACE); } if ((cs->desktopOpacity != OPAQUE || s->berylDesktopManaged)) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } if (cs->invert == 1) { if (capsReversed()) { glNormal3f(0.0, -1.0, 0.0); glRotatef(360.0f-(360.0f/(float)hsize), 0.0f, 1.0f, 0.0f); cubeDrawCubeCap(s, hsize, cs->nvertices >> 1, &cs->cubeCapBottom, &cs->cubeCapTop, cs->desktopOpacity); glNormal3f(0.0, -1.0, 0.0); //glRotatef(-360.0f+(360.0f/(float)hsize), 0.0f, 1.0f, 0.0f); cubeDrawCubeCap(s, hsize, 0, &cs->cubeCapTop, &cs->cubeCapBottom, cs->desktopOpacity); } else { glNormal3f(0.0, 1.0, 0.0); glRotatef(360.0f-(360.0f/(float)hsize), 0.0f, 1.0f, 0.0f); cubeDrawCubeCap(s, hsize, 0, &cs->cubeCapTop, &cs->cubeCapBottom, cs->desktopOpacity); glNormal3f(0.0, 1.0, 0.0); cubeDrawCubeCap(s, hsize, cs->nvertices >> 1, &cs->cubeCapBottom, &cs->cubeCapTop, cs->desktopOpacity); } } else { glNormal3f(0.0, -1.0, 0.0); cubeDrawCubeCap(s, hsize, 0, &cs->cubeCapTop, &cs->cubeCapBottom, cs->desktopOpacity); glRotatef(360.0f-(360.0f/(float)hsize), 0.0f, 1.0f, 0.0f); glNormal3f(0.0, 1.0, 0.0); cubeDrawCubeCap(s, hsize, cs->nvertices >> 1, &cs->cubeCapBottom, &cs->cubeCapTop, cs->desktopOpacity); } glDisable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); if (disabledCull) glEnable(GL_CULL_FACE); glPopMatrix(); glColor4usv(defaultColor); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } glNormal3f(0.0, 0.0, -1.0); cs->paintingCaps = FALSE; newMask = mask | PAINT_SCREEN_ORDER_BACK_TO_FRONT_MASK; filter = s->display->textureFilter; if (cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b) s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR; if (cs->invert == 1) { num = 0; for (i = 0; i < fc; i++) if (!faces[i].rev) num++; } else num = fc; for (i = 0; i < num; i++) { int found = 0; float minZ = -2.0; for (j = 0; j < fc; j++) { if (faces[j].z > minZ && !faces[j].painted && (!faces[j].rev || cs->invert != 1)) { found = j; minZ = faces[j].z; } } faces[found].painted = TRUE; cubeMoveViewportAndPaint(s, &faces[found].sa, output, newMask, faces[found].xMove); } s->display->textureFilter = filter; WRAP(cs, s, paintTransformedScreen, cubePaintTransformedScreen); free(faces); } static void cubeApplyScreenTransform(CompScreen * s, const ScreenPaintAttrib * sAttrib, int output) { CUBE_SCREEN(s); glTranslatef(cs->outputXOffset, -cs->outputYOffset, 0.0f); glScalef(cs->outputXScale, cs->outputYScale, 1.0f); UNWRAP(cs, s, applyScreenTransform); (*s->applyScreenTransform) (s, sAttrib, output); WRAP(cs, s, applyScreenTransform, cubeApplyScreenTransform); glScalef(1.0f / cs->outputXScale, 1.0f / cs->outputYScale, 1.0f); glTranslatef(-cs->outputXOffset, cs->outputYOffset, 0.0f); } static void cubePaintBackground(CompScreen * s, Region region, unsigned int mask) { CUBE_SCREEN(s); if ((cs->desktopOpacity != OPAQUE || s->berylDesktopManaged)) { 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 || s->berylDesktopManaged)) { 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, Region region, unsigned int mask) { int status; CUBE_SCREEN(w->screen); WindowPaintAttrib wa = *attrib; if (w->type & CompWindowTypeDesktopMask) { if (cs->desktopOpacity == 0) return TRUE; wa.opacity = cs->desktopOpacity; } if (!w->managed && cs->noManaged) return TRUE; if ((w->type & CompWindowTypeDockMask) || (w->state & CompWindowStateStickyMask && !(w->state & CompWindowStateBelowMask))) { if (!cs->finalPaint) { return TRUE; } } UNWRAP(cs, w->screen, paintWindow); status = (*w->screen->paintWindow) (w, &wa, region, mask); WRAP(cs, w->screen, paintWindow, cubePaintWindow); return status; } static Bool cubeUnfold(CompDisplay * d, CompAction * action, CompActionState state, CompOption * option, int nOption) { CompScreen *s; Window xid; xid = getIntOptionNamed(option, nOption, "root", 0); s = findScreenAtDisplay(d, xid); if (s) { CUBE_SCREEN(s); IPCS_SetBool(IPCS_OBJECT(s),cs->unfoldedAtom, TRUE); int hsize = s->hsize; if (cs->mmMode != Multiple) hsize *= cs->nOutput; if (hsize < 4) return FALSE; if (otherScreenGrabExist(s, "rotate", "switcher", "cube", 0)) return FALSE; if (!cs->grabIndex) cs->grabIndex = pushScreenGrab(s, s->invisibleCursor, "cube"); if (cs->grabIndex) { cs->unfolded = TRUE; damageScreen(s); } if (state & CompActionStateInitButton) action->state |= CompActionStateTermButton; if (state & CompActionStateInitKey) action->state |= CompActionStateTermKey; } return FALSE; } static Bool cubeFold(CompDisplay * d, CompAction * action, CompActionState state, CompOption * option, int nOption) { CompScreen *s; Window xid; xid = getIntOptionNamed(option, nOption, "root", 0); for (s = d->screens; s; s = s->next) { CUBE_SCREEN(s); IPCS_SetBool(IPCS_OBJECT(s),cs->unfoldedAtom, FALSE); if (xid && s->root != xid) continue; if (cs->grabIndex) { cs->unfolded = FALSE; damageScreen(s); } } action->state &= ~(CompActionStateTermButton | CompActionStateTermKey); return FALSE; } static Bool cubeNextImage(CompDisplay * d, CompAction * action, CompActionState state, CompOption * option, int nOption) { CompScreen *s; Window xid; xid = getIntOptionNamed(option, nOption, "root", 0); s = findScreenAtDisplay(d, xid); if (s) { CUBE_SCREEN(s); if (cs->cubeCapTop.imgNFile) { cubeLoadImg(s, &cs->cubeCapTop, (cs->cubeCapTop.imgCurFile + 1) % cs->cubeCapTop.imgNFile); damageScreen(s); } if (cs->cubeCapBottom.imgNFile) { cubeLoadImg(s, &cs->cubeCapBottom, (cs->cubeCapBottom.imgCurFile + 1) % cs->cubeCapBottom.imgNFile); damageScreen(s); } } return FALSE; } static Bool cubePrevImage(CompDisplay * d, CompAction * action, CompActionState state, CompOption * option, int nOption) { CompScreen *s; Window xid; xid = getIntOptionNamed(option, nOption, "root", 0); s = findScreenAtDisplay(d, xid); if (s) { CUBE_SCREEN(s); if (cs->cubeCapTop.imgNFile) { cubeLoadImg(s, &cs->cubeCapBottom, (cs->cubeCapTop.imgCurFile - 1 + cs->cubeCapTop.imgNFile) % cs->cubeCapTop.imgNFile); damageScreen(s); } if (cs->cubeCapBottom.imgNFile) { cubeLoadImg(s, &cs->cubeCapBottom, (cs->cubeCapBottom.imgCurFile - 1 + cs->cubeCapBottom.imgNFile) % cs->cubeCapBottom.imgNFile); damageScreen(s); } } return FALSE; } static void cubeOutputChangeNotify(CompScreen * s) { CUBE_SCREEN(s); cubeUpdateOutputs(s); cubeUpdateGeometry(s, s->hsize, cs->invert); UNWRAP(cs, s, outputChangeNotify); (*s->outputChangeNotify) (s); WRAP(cs, s, outputChangeNotify, cubeOutputChangeNotify); } static Bool cubeSetGlobalScreenOption(CompScreen * s, char *name, CompOptionValue * value) { Bool status; CUBE_SCREEN(s); UNWRAP(cs, s, setScreenOption); status = (*s->setScreenOption) (s, name, value); WRAP(cs, s, setScreenOption, cubeSetGlobalScreenOption); if (status && strcmp(name, "hsize") == 0) cubeUpdateGeometry(s, s->hsize, cs->invert); return status; } static Bool cubeSetDisplayOption(CompDisplay * display, char *name, CompOptionValue * value) { CompOption *o; int index; CUBE_DISPLAY(display); o = compFindOption(cd->opt, NUM_OPTIONS(cd), name, &index); if (!o) return FALSE; switch (index) { case CUBE_DISPLAY_OPTION_UNFOLD: if (setDisplayAction(display, o, value)) return TRUE; break; case CUBE_DISPLAY_OPTION_NEXT: case CUBE_DISPLAY_OPTION_PREV: if (compSetActionOption(o, value)) return TRUE; default: break; } return FALSE; } static void cubeDisplayInitOptions(CubeDisplay * cd) { CompOption *o; o = &cd->opt[CUBE_DISPLAY_OPTION_UNFOLD]; o->advanced = False; o->name = "unfold"; o->group = N_("Bindings"); o->subGroup = N_("Unfold"); o->displayHints = ""; o->shortDesc = N_("Unfold Cube"); o->longDesc = N_("Unfold Cube."); o->type = CompOptionTypeAction; o->value.action.initiate = cubeUnfold; o->value.action.terminate = cubeFold; o->value.action.bell = FALSE; o->value.action.edgeMask = 0; o->value.action.state = CompActionStateInitEdge; o->value.action.state |= CompActionStateInitKey; o->value.action.state |= CompActionStateInitButton; o->value.action.type = CompBindingTypeKey; o->value.action.key.modifiers = CUBE_UNFOLD_MODIFIERS_DEFAULT; o->value.action.key.keysym = XStringToKeysym(CUBE_UNFOLD_KEY_DEFAULT); o = &cd->opt[CUBE_DISPLAY_OPTION_NEXT]; o->advanced = False; o->name = "next_slide"; o->group = N_("Bindings"); o->subGroup = N_("Next Slide"); o->displayHints = ""; o->shortDesc = N_("Next Slide"); o->longDesc = N_("Advance to Next Slide."); o->type = CompOptionTypeAction; o->value.action.initiate = cubeNextImage; o->value.action.terminate = 0; o->value.action.bell = FALSE; o->value.action.edgeMask = 0; o->value.action.state = CompActionStateInitEdge; o->value.action.state |= CompActionStateInitKey; o->value.action.state |= CompActionStateInitButton; o->value.action.type = 0; //o->value.action.type |= CompBindingTypeKey; o->value.action.key.modifiers = CUBE_NEXT_MODIFIERS_DEFAULT; o->value.action.key.keysym = XStringToKeysym(CUBE_NEXT_KEY_DEFAULT); o = &cd->opt[CUBE_DISPLAY_OPTION_PREV]; o->advanced = False; o->name = "prev_slide"; o->group = N_("Bindings"); o->subGroup = N_("Previous Slide"); o->displayHints = ""; o->shortDesc = N_("Previous Slide"); o->longDesc = N_("Go back to Previous Slide."); o->type = CompOptionTypeAction; o->value.action.initiate = cubePrevImage; o->value.action.terminate = 0; o->value.action.bell = FALSE; o->value.action.edgeMask = 0; o->value.action.state = CompActionStateInitEdge; o->value.action.state |= CompActionStateInitKey; o->value.action.state |= CompActionStateInitButton; o->value.action.type = 0; //o->value.action.type |= CompBindingTypeKey; o->value.action.key.modifiers = CUBE_PREV_MODIFIERS_DEFAULT; o->value.action.key.keysym = XStringToKeysym(CUBE_PREV_KEY_DEFAULT); } static CompOption *cubeGetDisplayOptions(CompDisplay * display, int *count) { if (display) { CUBE_DISPLAY(display); *count = NUM_OPTIONS(cd); return cd->opt; } else { CubeDisplay *cd = malloc(sizeof(CubeDisplay)); cubeDisplayInitOptions(cd); *count = NUM_OPTIONS(cd); return cd->opt; } } static Bool cubeInitDisplay(CompPlugin * p, CompDisplay * d) { CubeDisplay *cd; cd = malloc(sizeof(CubeDisplay)); if (!cd) return FALSE; cd->screenPrivateIndex = allocateScreenPrivateIndex(d); if (cd->screenPrivateIndex < 0) { free(cd); return FALSE; } cubeDisplayInitOptions(cd); d->privates[displayPrivateIndex].ptr = cd; return TRUE; } static void cubeFiniDisplay(CompPlugin * p, CompDisplay * d) { CUBE_DISPLAY(d); freeScreenPrivateIndex(d, cd->screenPrivateIndex); free(cd); } static Bool cubeInitScreen(CompPlugin * p, CompScreen * s) { CubeScreen *cs; CUBE_DISPLAY(s->display); cs = malloc(sizeof(CubeScreen)); if (!cs) return FALSE; cs->invert = 1; cs->color[0] = CUBE_COLOR_RED_DEFAULT; cs->color[1] = CUBE_COLOR_GREEN_DEFAULT; cs->color[2] = CUBE_COLOR_BLUE_DEFAULT; cs->nvertices = 0; cs->vertices = NULL; cs->grabIndex = 0; cs->skyListId = 0; cs->animateSkyDome = CUBE_SKYDOME_ANIMATE_DEFAULT; cs->skyGradStartColor[0] = CUBE_SKYDOME_GRAD_START_RED_DEFAULT; cs->skyGradStartColor[1] = CUBE_SKYDOME_GRAD_START_GREEN_DEFAULT; cs->skyGradStartColor[2] = CUBE_SKYDOME_GRAD_START_BLUE_DEFAULT; cs->skyGradEndColor[0] = CUBE_SKYDOME_GRAD_END_RED_DEFAULT; cs->skyGradEndColor[1] = CUBE_SKYDOME_GRAD_END_GREEN_DEFAULT; cs->skyGradEndColor[2] = CUBE_SKYDOME_GRAD_END_BLUE_DEFAULT; cs->rotateImages = FALSE; cs->neverRotateImages = TRUE; cs->snapTopBottomAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "CUBE_SNAP_TOP_BOTTOM", TRUE); cs->previousRotationAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_FLOAT, "PREVIOUS_ROTATION", TRUE); cs->paintingCapsAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_VPTR, "CUBE_PAINTING_CAPS_BOOL_PTR", TRUE); cs->manualAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "MOUSE_INITIATED_ROTATE", TRUE); cs->zoomLevelAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_FLOAT, "ZOOM_LEVEL", TRUE); cs->unfoldedAtom = IPCS_GetAtom(IPCS_OBJECT(s),IPCS_BOOL,"CUBE_UNFOLDED", TRUE); cs->paintingCaps = FALSE; IPCS_SetVPtr(IPCS_OBJECT(s), cs->paintingCapsAtom, (void *)&cs->paintingCaps); s->privates[cd->screenPrivateIndex].ptr = cs; initTexture(s, &cs->sky); cs->acceleration = CUBE_ACCELERATION_DEFAULT; cs->speed = CUBE_SPEED_DEFAULT; cs->timestep = CUBE_TIMESTEP_DEFAULT; cs->unfolded = FALSE; cs->unfold = 0.0f; cs->unfoldDistance = CUBE_UNFOLD_ZOOM_DEFAULT; cs->unfoldVelocity = 0.0f; cubeScreenInitOptions(cs); cs->cubeCapTop.imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES_TOP].value.list.value; cs->cubeCapTop.imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES_TOP].value.list.nValue; cs->cubeCapBottom.imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES_BOTTOM].value.list.value; cs->cubeCapBottom.imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES_BOTTOM].value.list.nValue; cs->mmMode = MULTIMONITOR_MODE_DEFAULT; cs->mmModeAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_INT, "MM_MODE", TRUE); IPCS_SetInt(IPCS_OBJECT(s), cs->mmModeAtom, cs->mmMode); cs->insideAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "INSIDE", TRUE); IPCS_SetBool(IPCS_OBJECT(s), cs->insideAtom, CUBE_IN_DEFAULT); addScreenAction(s, &cd->opt[CUBE_DISPLAY_OPTION_UNFOLD].value.action); cs->desktopOpacity = OPAQUE; cs->noManaged = FALSE; if (cs->mmMode == OneBig) s->projectionStyle = COMP_PERSPECTIVE_GLOBAL; else s->projectionStyle = COMP_PERSPECTIVE_LOCAL; WRAP(cs, s, preparePaintScreen, cubePreparePaintScreen); WRAP(cs, s, donePaintScreen, cubeDonePaintScreen); WRAP(cs, s, paintScreen, cubePaintScreen); WRAP(cs, s, paintTransformedScreen, cubePaintTransformedScreen); WRAP(cs, s, applyScreenTransform, cubeApplyScreenTransform); WRAP(cs, s, paintBackground, cubePaintBackground); WRAP(cs, s, paintWindow, cubePaintWindow); WRAP(cs, s, setScreenOption, cubeSetGlobalScreenOption); WRAP(cs, s, outputChangeNotify, cubeOutputChangeNotify); WRAP(cs, s, setClipPlanes, cubeSetClipPlanes); cubeUpdateOutputs(s); cubeInitCubeCap(s, &cs->cubeCapTop); cubeInitCubeCap(s, &cs->cubeCapBottom); if (!cubeUpdateGeometry(s, s->hsize, cs->invert)) return FALSE; return TRUE; } static void cubeFiniScreen(CompPlugin * p, CompScreen * s) { CUBE_SCREEN(s); CUBE_DISPLAY(s->display); if (cs->skyListId) glDeleteLists(cs->skyListId, 1); IPCS_Unset(IPCS_OBJECT(s), cs->paintingCapsAtom); UNWRAP(cs, s, preparePaintScreen); UNWRAP(cs, s, donePaintScreen); UNWRAP(cs, s, paintScreen); UNWRAP(cs, s, paintTransformedScreen); UNWRAP(cs, s, applyScreenTransform); UNWRAP(cs, s, paintBackground); UNWRAP(cs, s, paintWindow); UNWRAP(cs, s, setScreenOption); UNWRAP(cs, s, outputChangeNotify); UNWRAP(cs, s, setClipPlanes); removeScreenAction(s, &cd->opt[CUBE_DISPLAY_OPTION_UNFOLD].value.action); finiTexture(s, &cs->cubeCapTop.texture); finiTexture(s, &cs->cubeCapBottom.texture); finiTexture(s, &cs->sky); if (cs->vertices) free(cs->vertices); free(cs); } static Bool cubeInit(CompPlugin * p) { displayPrivateIndex = allocateDisplayPrivateIndex(); if (displayPrivateIndex < 0) return FALSE; return TRUE; } static void cubeFini(CompPlugin * p) { if (displayPrivateIndex >= 0) freeDisplayPrivateIndex(displayPrivateIndex); } CompPluginDep cubeDeps[] = { {CompPluginRuleAfter, "animation"} , {CompPluginRuleAfter, "decoration"} , {CompPluginRuleAfter, "fade"} , {CompPluginRuleAfter, "wobbly"} , {CompPluginRuleAfter, "inputzoom"} , {CompPluginRuleAfter, "3d"} , {CompPluginRuleAfterCategory, "imageformat"} , }; CompPluginFeature cubeFeatures[] = { {"largedesktop"} , {"cube"} }; CompPluginVTable cubeVTable = { "cube", N_("Desktop Cube"), N_("Place windows on cube"), cubeInit, cubeFini, cubeInitDisplay, cubeFiniDisplay, cubeInitScreen, cubeFiniScreen, 0, /* InitWindow */ 0, /* FiniWindow */ cubeGetDisplayOptions, cubeSetDisplayOption, cubeGetScreenOptions, cubeSetScreenOption, cubeDeps, sizeof(cubeDeps) / sizeof(cubeDeps[0]), cubeFeatures, sizeof(cubeFeatures) / sizeof(cubeFeatures[0]), BERYL_ABI_INFO, "beryl-plugins", "desktop", 0, 0, True, }; CompPluginVTable *getCompPluginInfo(void) { return &cubeVTable; }