/*
* 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 <davidr@novell.com>
* Mirco Müller <macslow@bangang.de> (Skydome support)
* Guillaume Seguin <ixce@beryl-project.org> (Bottom caps, rotation stuff)
* Dennis Kasprzyk <onestone@beryl-project.org> (Transparent cube)
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <beryl.h>
#include <beryl_helpers.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1