rendered paste body/*
* Copyright © 2005 Novell, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Novell, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
* Novell, Inc. makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: David Reveman <davidr@novell.com>
* Mirco Müller <macslow@bangang.de> (Skydome support)
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#ifdef USE_LIBRSVG
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#include <librsvg/rsvg.h>
#include <librsvg/rsvg-cairo.h>
#endif
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <compiz.h>
#define CUBE_COLOR_RED_DEFAULT 0xefef
#define CUBE_COLOR_GREEN_DEFAULT 0xebeb
#define CUBE_COLOR_BLUE_DEFAULT 0xe7e7
#define CUBE_IN_DEFAULT FALSE
typedef enum _RotationMode
{
NoRotation = 0,
RotationChange,
RotationManual
} RotationMode;
static char *cubeImages[] = {
"freedesktop"
};
#define N_CUBE_IMAGES (sizeof (cubeImages) / sizeof (cubeImages[0]))
#define CUBE_SCALE_IMAGE_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 "Down"
#define CUBE_UNFOLD_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#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_FADE_TIME_DEFAULT 1.0
#define CUBE_FADE_TIME_MAX 10.0
#define CUBE_FADE_TIME_MIN 0.0
#define CUBE_FADE_TIME_PRECISION 0.1
#define CUBE_OPACITY_MIN 0.0
#define CUBE_OPACITY_MAX 100.0
#define CUBE_OPACITY_PRECISION 1.0
#define CUBE_TRANSPARENT_MANUAL_ONLY_DEFAULT FALSE
#define CUBE_ACTIVE_OPACITY_DEFAULT 30
#define CUBE_INACTIVE_OPACITY_DEFAULT 100
#define CUBE_SPEED_DEFAULT 1.5f
#define CUBE_SPEED_MIN 0.1f
#define CUBE_SPEED_MAX 50.0f
#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 TRUE
#define CUBE_DISPLAY_OPTION_UNFOLD 0
#define CUBE_DISPLAY_OPTION_NEXT 1
#define CUBE_DISPLAY_OPTION_PREV 2
#define CUBE_DISPLAY_OPTION_NUM 3
static int displayPrivateIndex;
typedef struct _CubeDisplay {
int screenPrivateIndex;
CompOption opt[CUBE_DISPLAY_OPTION_NUM];
HandleCompizEventProc handleCompizEvent;
} CubeDisplay;
#define CUBE_SCREEN_OPTION_COLOR 0
#define CUBE_SCREEN_OPTION_IN 1
#define CUBE_SCREEN_OPTION_SCALE_IMAGE 2
#define CUBE_SCREEN_OPTION_IMAGES 3
#define CUBE_SCREEN_OPTION_SKYDOME 4
#define CUBE_SCREEN_OPTION_SKYDOME_IMG 5
#define CUBE_SCREEN_OPTION_SKYDOME_ANIM 6
#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_START 7
#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_END 8
#define CUBE_SCREEN_OPTION_ACCELERATION 9
#define CUBE_SCREEN_OPTION_SPEED 10
#define CUBE_SCREEN_OPTION_TIMESTEP 11
#define CUBE_SCREEN_OPTION_MIPMAP 12
#define CUBE_SCREEN_OPTION_ACTIVE_OPACITY 13
#define CUBE_SCREEN_OPTION_INACTIVE_OPACITY 14
#define CUBE_SCREEN_OPTION_FADE_TIME 15
#define CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY 16
#define CUBE_SCREEN_OPTION_NUM 17
#define MULTM(x,y,z) \
z[0] = x[0] * y[0] + x[4] * y[1] + x[8] * y[2] + x[12] * y[3]; \
z[1] = x[1] * y[0] + x[5] * y[1] + x[9] * y[2] + x[13] * y[3]; \
z[2] = x[2] * y[0] + x[6] * y[1] + x[10] * y[2] + x[14] * y[3]; \
z[3] = x[3] * y[0] + x[7] * y[1] + x[11] * y[2] + x[15] * y[3]; \
z[4] = x[0] * y[4] + x[4] * y[5] + x[8] * y[6] + x[12] * y[7]; \
z[5] = x[1] * y[4] + x[5] * y[5] + x[9] * y[6] + x[13] * y[7]; \
z[6] = x[2] * y[4] + x[6] * y[5] + x[10] * y[6] + x[14] * y[7]; \
z[7] = x[3] * y[4] + x[7] * y[5] + x[11] * y[6] + x[15] * y[7]; \
z[8] = x[0] * y[8] + x[4] * y[9] + x[8] * y[10] + x[12] * y[11]; \
z[9] = x[1] * y[8] + x[5] * y[9] + x[9] * y[10] + x[13] * y[11]; \
z[10] = x[2] * y[8] + x[6] * y[9] + x[10] * y[10] + x[14] * y[11]; \
z[11] = x[3] * y[8] + x[7] * y[9] + x[11] * y[10] + x[15] * y[11]; \
z[12] = x[0] * y[12] + x[4] * y[13] + x[8] * y[14] + x[12] * y[15]; \
z[13] = x[1] * y[12] + x[5] * y[13] + x[9] * y[14] + x[13] * y[15]; \
z[14] = x[2] * y[12] + x[6] * y[13] + x[10] * y[14] + x[14] * y[15]; \
z[15] = x[3] * y[12] + x[7] * y[13] + x[11] * y[14] + x[15] * y[15];
#define MULTMV(m, v) { \
float v0 = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3]; \
float v1 = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3]; \
float v2 = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3]; \
float v3 = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3]; \
v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; }
#define DIVV(v) \
v[0] /= v[3]; \
v[1] /= v[3]; \
v[2] /= v[3]; \
v[3] /= v[3];
typedef struct _CubeScreen {
PreparePaintScreenProc preparePaintScreen;
DonePaintScreenProc donePaintScreen;
PaintScreenProc paintScreen;
PaintTransformedScreenProc paintTransformedScreen;
ApplyScreenTransformProc applyScreenTransform;
SetScreenOptionProc setScreenOption;
OutputChangeNotifyProc outputChangeNotify;
SetClipPlanesProc setClipPlanes;
PaintBackgroundProc paintBackground;
PaintWindowProc paintWindow;
CompOption opt[CUBE_SCREEN_OPTION_NUM];
int invert;
int xrotations;
GLfloat distance;
Bool paintTopBottom;
GLushort color[3];
GLfloat tc[12];
int grabIndex;
float acceleration;
float speed;
float timestep;
Bool unfolded;
GLfloat unfold, unfoldVelocity;
GLfloat *vertices;
int nvertices;
GLuint skyListId;
Bool animateSkyDome;
Pixmap pixmap;
int pw, ph;
CompTexture texture, sky;
int imgNFile;
int imgCurFile;
CompOptionValue *imgFiles;
int nOutput;
int output[64];
int outputMask[64];
Bool cleared[64];
Bool fullscreenOutput;
RotationMode rotationMode;
float outputXScale;
float outputYScale;
float outputXOffset;
float outputYOffset;
Bool disableCaps;
Bool paintAllViewports;
float desktopOpacity;
float toOpacity;
#ifdef USE_LIBRSVG
cairo_t *cr;
#endif
} 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
cubeInitSvg (CompScreen *s)
{
CUBE_SCREEN (s);
cs->pixmap = None;
cs->pw = cs->ph = 0;
#ifdef USE_LIBRSVG
cs->cr = NULL;
#endif
}
static void
cubeFiniSvg (CompScreen *s)
{
CUBE_SCREEN (s);
#ifdef USE_LIBRSVG
if (cs->cr)
cairo_destroy (cs->cr);
#endif
if (cs->pixmap)
XFreePixmap (s->display->display, cs->pixmap);
}
static Bool
readSvgToTexture (CompScreen *s,
CompTexture *texture,
const char *svgFileName,
unsigned int *returnWidth,
unsigned int *returnHeight)
{
#ifdef USE_LIBRSVG
unsigned int width, height, pw, ph;
char *name;
GError *error = NULL;
RsvgHandle *svgHandle;
RsvgDimensionData svgDimension;
CUBE_SCREEN (s);
name = strdup (svgFileName);
svgHandle = rsvg_handle_new_from_file (name, &error);
free (name);
if (!svgHandle)
return FALSE;
rsvg_handle_get_dimensions (svgHandle, &svgDimension);
width = svgDimension.width;
height = svgDimension.height;
if (cs->opt[CUBE_SCREEN_OPTION_SCALE_IMAGE].value.b)
{
pw = (cs->nOutput > 1) ? s->outputDev[0].width : s->width;
ph = (cs->nOutput > 1) ? s->outputDev[0].height : s->height;
}
else
{
pw = width;
ph = height;
}
if (!cs->pixmap || cs->pw != pw || cs->ph != ph)
{
cairo_surface_t *surface;
Visual *visual;
int depth;
if (cs->cr)
{
cairo_destroy (cs->cr);
cs->cr = NULL;
}
if (cs->pixmap)
XFreePixmap (s->display->display, cs->pixmap);
cs->pw = pw;
cs->ph = ph;
depth = DefaultDepth (s->display->display, s->screenNum);
cs->pixmap = XCreatePixmap (s->display->display, s->root,
cs->pw, cs->ph,
depth);
if (!bindPixmapToTexture (s, texture, cs->pixmap,
cs->pw, cs->ph, depth))
{
fprintf (stderr, "%s: Couldn't bind slide pixmap 0x%x to "
"texture\n", programName, (int) cs->pixmap);
return FALSE;
}
visual = DefaultVisual (s->display->display, s->screenNum);
surface = cairo_xlib_surface_create (s->display->display,
cs->pixmap, visual,
cs->pw, cs->ph);
cs->cr = cairo_create (surface);
cairo_surface_destroy (surface);
}
cairo_save (cs->cr);
cairo_set_source_rgb (cs->cr,
(double) cs->color[0] / 0xffff,
(double) cs->color[1] / 0xffff,
(double) cs->color[2] / 0xffff);
cairo_rectangle (cs->cr, 0, 0, cs->pw, cs->ph);
cairo_fill (cs->cr);
cairo_scale (cs->cr, (double) cs->pw / width, (double) cs->ph / height);
rsvg_handle_render_cairo (svgHandle, cs->cr);
rsvg_handle_free (svgHandle);
cairo_restore (cs->cr);
*returnWidth = cs->pw;
*returnHeight = cs->ph;
return TRUE;
#else
return FALSE;
#endif
}
static void
cubeLoadImg (CompScreen *s,
int n)
{
unsigned int width, height;
int pw, ph;
CUBE_SCREEN (s);
if (!cs->fullscreenOutput)
{
pw = s->width;
ph = s->height;
}
else
{
pw = s->outputDev[0].width;
ph = s->outputDev[0].height;
}
if (!cs->imgNFile || cs->pw != pw || cs->ph != ph)
{
finiTexture (s, &cs->texture);
initTexture (s, &cs->texture);
cubeFiniSvg (s);
cubeInitSvg (s);
if (!cs->imgNFile)
return;
}
cs->imgCurFile = n % cs->imgNFile;
if (readImageToTexture (s, &cs->texture,
cs->imgFiles[cs->imgCurFile].s,
&width, &height))
{
cubeFiniSvg (s);
cubeInitSvg (s);
}
else if (!readSvgToTexture (s, &cs->texture,
cs->imgFiles[cs->imgCurFile].s,
&width, &height))
{
fprintf (stderr, "%s: Failed to load slide: %s\n",
programName, cs->imgFiles[cs->imgCurFile].s);
finiTexture (s, &cs->texture);
initTexture (s, &cs->texture);
cubeFiniSvg (s);
cubeInitSvg (s);
return;
}
cs->tc[0] = COMP_TEX_COORD_X (&cs->texture.matrix, width / 2.0f);
cs->tc[1] = COMP_TEX_COORD_Y (&cs->texture.matrix, height / 2.0f);
if (cs->opt[CUBE_SCREEN_OPTION_SCALE_IMAGE].value.b)
{
cs->tc[2] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
cs->tc[3] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
cs->tc[4] = COMP_TEX_COORD_X (&cs->texture.matrix, 0.0f);
cs->tc[5] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
cs->tc[6] = COMP_TEX_COORD_X (&cs->texture.matrix, 0.0f);
cs->tc[7] = COMP_TEX_COORD_Y (&cs->texture.matrix, height);
cs->tc[8] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
cs->tc[9] = COMP_TEX_COORD_Y (&cs->texture.matrix, height);
cs->tc[10] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
cs->tc[11] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
}
else
{
float x1 = width / 2.0f - pw / 2.0f;
float y1 = height / 2.0f - ph / 2.0f;
float x2 = width / 2.0f + pw / 2.0f;
float y2 = height / 2.0f + ph / 2.0f;
cs->tc[2] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
cs->tc[3] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
cs->tc[4] = COMP_TEX_COORD_X (&cs->texture.matrix, x1);
cs->tc[5] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
cs->tc[6] = COMP_TEX_COORD_X (&cs->texture.matrix, x1);
cs->tc[7] = COMP_TEX_COORD_Y (&cs->texture.matrix, y2);
cs->tc[8] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
cs->tc[9] = COMP_TEX_COORD_Y (&cs->texture.matrix, y2);
cs->tc[10] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
cs->tc[11] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
}
}
static Bool
cubeUpdateGeometry (CompScreen *s,
int sides,
Bool invert)
{
GLfloat radius, distance;
GLfloat *v;
int i, n;
CUBE_SCREEN (s);
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 (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 CompOption *
cubeGetScreenOptions (CompPlugin *plugin,
CompScreen *screen,
int *count)
{
CUBE_SCREEN (screen);
*count = NUM_OPTIONS (cs);
return cs->opt;
}
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 (CompPlugin *plugin,
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))
return TRUE;
}
break;
case CUBE_SCREEN_OPTION_SCALE_IMAGE:
if (compSetBoolOption (o, value))
{
cubeLoadImg (screen, cs->imgCurFile);
damageScreen (screen);
return TRUE;
}
break;
case CUBE_SCREEN_OPTION_IMAGES:
if (compSetOptionList (o, value))
{
cs->imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.value;
cs->imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
cubeLoadImg (screen, cs->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))
{
cubeUpdateSkyDomeTexture (screen);
cubeUpdateSkyDomeList (screen, 1.0f);
damageScreen (screen);
return TRUE;
}
break;
case CUBE_SCREEN_OPTION_SKYDOME_GRAD_END:
if (compSetColorOption (o, value))
{
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_FADE_TIME:
case CUBE_SCREEN_OPTION_ACTIVE_OPACITY:
case CUBE_SCREEN_OPTION_INACTIVE_OPACITY:
if (compSetFloatOption (o,value))
return TRUE;
default:
break;
}
return FALSE;
}
static void
cubeScreenInitOptions (CubeScreen *cs,
Display *display)
{
CompOption *o;
int i;
o = &cs->opt[CUBE_SCREEN_OPTION_COLOR];
o->name = "color";
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->name = "in";
o->shortDesc = N_("Inside Cube");
o->longDesc = N_("Inside cube");
o->type = CompOptionTypeBool;
o->value.b = CUBE_IN_DEFAULT;
o = &cs->opt[CUBE_SCREEN_OPTION_SCALE_IMAGE];
o->name = "scale_image";
o->shortDesc = N_("Scale image");
o->longDesc = N_("Scale images to cover top face of cube");
o->type = CompOptionTypeBool;
o->value.b = CUBE_SCALE_IMAGE_DEFAULT;
o = &cs->opt[CUBE_SCREEN_OPTION_IMAGES];
o->name = "images";
o->shortDesc = N_("Image files");
o->longDesc = N_("List of PNG and SVG files that should be rendered "
"on 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_SKYDOME];
o->name = "skydome";
o->shortDesc = N_("Skydome");
o->longDesc = N_("Render skydome");
o->type = CompOptionTypeBool;
o->value.b = CUBE_SKYDOME_DEFAULT;
o = &cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG];
o->name = "skydome_image";
o->shortDesc = N_("Skydome Image");
o->longDesc = N_("Image to use as texture for the skydome");
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->name = "skydome_animated";
o->shortDesc = N_("Animate Skydome");
o->longDesc = N_("Animate skydome when rotating cube");
o->type = CompOptionTypeBool;
o->value.b = CUBE_SKYDOME_ANIMATE_DEFAULT;
o = &cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START];
o->name = "skydome_gradient_start_color";
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->name = "skydome_gradient_end_color";
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->name = "acceleration";
o->shortDesc = N_("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->name = "speed";
o->shortDesc = N_("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->name = "timestep";
o->shortDesc = N_("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->name = "mipmap";
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_FADE_TIME];
o->name = "fade_time";
o->shortDesc = N_("Fade Time");
o->longDesc = N_("Desktop Window Opacity Fade Time.");
o->type = CompOptionTypeFloat;
o->value.f = CUBE_FADE_TIME_DEFAULT;
o->rest.f.min = CUBE_FADE_TIME_MIN;
o->rest.f.max = CUBE_FADE_TIME_MAX;
o->rest.f.precision = CUBE_FADE_TIME_PRECISION;
o = &cs->opt[CUBE_SCREEN_OPTION_ACTIVE_OPACITY];
o->name = "active_opacity";
o->shortDesc = N_("Opacity During Rotation");
o->longDesc = N_("Opacity of desktop window during rotation.");
o->type = CompOptionTypeFloat;
o->value.f = CUBE_ACTIVE_OPACITY_DEFAULT;
o->rest.f.min = CUBE_OPACITY_MIN;
o->rest.f.max = CUBE_OPACITY_MAX;
o->rest.f.precision = CUBE_OPACITY_PRECISION;
o = &cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY];
o->name = "inactive_opacity";
o->shortDesc = N_("Opacity When Not Rotating");
o->longDesc = N_("Opacity of desktop window when not rotating.");
o->type = CompOptionTypeFloat;
o->value.f = CUBE_INACTIVE_OPACITY_DEFAULT;
o->rest.f.min = CUBE_OPACITY_MIN;
o->rest.f.max = CUBE_OPACITY_MAX;
o->rest.f.precision = CUBE_OPACITY_PRECISION;
o = &cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY];
o->name = "transparent_manual_only";
o->shortDesc = N_("Transparency Only\non Mouse Rotate");
o->longDesc =
N_
("Initiates Cube transparency only if rotation is mouse driven.");
o->type = CompOptionTypeBool;
o->value.b = CUBE_TRANSPARENT_MANUAL_ONLY_DEFAULT;
}
static int
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;
}
}
}
memset (cs->cleared, 0, sizeof (Bool) * s->nOutputDev);
//transparency, mostly copied/ported from beryl's cube.c, orig. by onestone
if (cs->rotationMode != NoRotation && ((cs->rotationMode == RotationManual) ||
!(cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY].value.b)))
{
cs->toOpacity =
(cs->opt[CUBE_SCREEN_OPTION_ACTIVE_OPACITY].value.f / 100.0f) * OPAQUE;
}
else
cs->toOpacity =
(cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.f / 100.0f) * OPAQUE;
if (cs->opt[CUBE_SCREEN_OPTION_FADE_TIME].value.f == 0.0f)
cs->desktopOpacity = cs->toOpacity;
else if (cs->desktopOpacity != cs->toOpacity)
{
float steps = (msSinceLastPaint * OPAQUE / 1000.0) /
cs->opt[CUBE_SCREEN_OPTION_FADE_TIME].value.f;
if (steps < 12)
steps = 12;
if (cs->toOpacity > cs->desktopOpacity)
{
cs->desktopOpacity += steps;
cs->desktopOpacity = MIN(cs->toOpacity, cs->desktopOpacity);
}
if (cs->toOpacity < cs->desktopOpacity)
{
cs->desktopOpacity -= steps;
cs->desktopOpacity = MAX(cs->toOpacity, cs->desktopOpacity);
}
}
UNWRAP (cs, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP (cs, s, preparePaintScreen, cubePreparePaintScreen);
}
static Bool
cubePaintScreen (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
const CompTransform *transform,
Region region,
int output,
unsigned int mask)
{
Bool status;
CUBE_SCREEN (s);
if (cs->grabIndex || cs->desktopOpacity != OPAQUE)
{
mask &= ~PAINT_SCREEN_REGION_MASK;
mask |= PAINT_SCREEN_TRANSFORMED_MASK;
}
UNWRAP (cs, s, paintScreen);
status = (*s->paintScreen) (s, sAttrib, transform, region, output, mask);
WRAP (cs, s, paintScreen, cubePaintScreen);
return status;
}
static void
cubeDonePaintScreen (CompScreen *s)
{
CUBE_SCREEN (s);
if (cs->grabIndex || cs->desktopOpacity != cs->toOpacity)
damageScreen (s);
UNWRAP (cs, s, donePaintScreen);
(*s->donePaintScreen) (s);
WRAP (cs, s, donePaintScreen, cubeDonePaintScreen);
}
static void
cubePaintBackground(CompScreen * s, Region region, unsigned int mask)
{
CUBE_SCREEN(s);
if (cs->desktopOpacity != OPAQUE)
{
if (s->desktopWindowCount)
{
glColor4us(0, 0, 0, 0);
glEnable(GL_BLEND);
}
else
{
glColor4us(0xffff, 0xffff, 0xffff, cs->desktopOpacity);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
}
UNWRAP (cs, s, paintBackground);
(*s->paintBackground) (s, region, mask);
WRAP (cs, s, paintBackground, cubePaintBackground);
if (cs->desktopOpacity != OPAQUE)
{
if (s->desktopWindowCount)
{
glColor3usv(defaultColor);
glDisable(GL_BLEND);
}
else
{
glColor3usv(defaultColor);
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
screenTexEnvMode(s, GL_REPLACE);
}
}
}
static Bool
cubePaintWindow (CompWindow *w,
const WindowPaintAttrib *attrib,
const CompTransform *transform,
Region region,
unsigned int mask)
{
Bool status;
CompScreen* s = w->screen;
CUBE_SCREEN(s);
WindowPaintAttrib wa = *attrib;
if (w->type & CompWindowTypeDesktopMask)
wa.opacity = cs->desktopOpacity;
UNWRAP (cs, s, paintWindow);
status = (*s->paintWindow) (w, &wa, transform, region, mask);
WRAP (cs, s, paintWindow, cubePaintWindow);
return status;
}
static Bool
cubeCheckFTB (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
const CompTransform *transform,
int output)
{
float mvp[16];
CompTransform sTransform = *transform;
(*s->applyScreenTransform) (s, sAttrib, output, &sTransform);
transformToScreenSpace (s, output, -sAttrib->zTranslate, &sTransform);
MULTM(s->projection, sTransform.m, mvp);
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 ortho[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]};
if (ortho[2] > 0.0f) //The viewport is reversed, should be painted front to back.
return TRUE;
return FALSE;
}
static void
cubeMoveViewportAndPaint (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
const CompTransform *transform,
int output,
unsigned int mask,
int dx)
{
CUBE_SCREEN (s);
Bool ftb = cubeCheckFTB(s, sAttrib, transform, output);
if (ftb && !(mask & PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK))
return;
if (!ftb && (mask & PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK))
return;
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;
dView = cubeOutput / cs->nOutput;
cubeOutput = cubeOutput % cs->nOutput;
if (cubeOutput < 0)
{
cubeOutput += cs->nOutput;
dView--;
}
/* translate back to compiz output */
output = cs->output[cubeOutput];
moveScreenViewport (s, -dView, 0, FALSE);
(*s->paintTransformedScreen) (s, sAttrib, transform,
&s->outputDev[output].region,
output, mask);
moveScreenViewport (s, dView, 0, FALSE);
}
else
{
moveScreenViewport (s, dx, 0, FALSE);
(*s->paintTransformedScreen) (s, sAttrib, transform, &s->region,
output, mask);
moveScreenViewport (s, -dx, 0, FALSE);
}
}
void
cubePaintAllViewports (CompScreen *s,
ScreenPaintAttrib *sAttrib,
const CompTransform *transform,
Region region,
int output,
unsigned int mask,
int xMove,
int size,
int hsize)
{
CUBE_SCREEN(s);
ScreenPaintAttrib sa = *sAttrib;
int i;
int iFirstSign; // 1 if we do xMove += i first and -1 if we do xMove -= i first.
if (cs->invert == 1)
{
// xMove ==> dx for the viewport which is the nearest to the viewer in z axis.
// xMove +/- hsize / 2 ==> dx for the viewport which is the farest to the viewer in z axis.
if ((sa.xRotate < 0.0f && hsize % 2 == 1) ||
(sa.xRotate > 0.0f && hsize % 2 == 0))
{
xMove += hsize / 2;
sa.yRotate -= (hsize / 2) * 360.0f / size;
iFirstSign = 1;
}
else
{
xMove -= hsize / 2;
sa.yRotate += (hsize / 2) * 360.0f / size;
iFirstSign = -1;
}
}
else
{
// xMove is already the dx for farest viewport.
if (sa.xRotate > 0.0f)
iFirstSign = -1;
else
iFirstSign = 1;
}
for (i = 0; i <= hsize / 2; i++)
{
xMove += iFirstSign * i;
sa.yRotate -= cs->invert * iFirstSign * i * 360.0f / size;
cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
xMove);
sa.yRotate += cs->invert * iFirstSign * i * 360.0f / size;
xMove -= iFirstSign * i;
if (i == 0 || i * 2 == hsize) // same viewport.
continue;
xMove -= iFirstSign * i;
sa.yRotate += cs->invert * iFirstSign * i * 360.0f / size;
cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
xMove);
sa.yRotate -= cs->invert * iFirstSign * i * 360.0f / size;
xMove += iFirstSign * i;
}
}
static void
cubePaintTransformedScreen (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
const CompTransform *transform,
Region region,
int output,
unsigned int mask)
{
ScreenPaintAttrib sa = *sAttrib;
int hsize, xMove = 0;
float size;
Bool clear;
Bool wasCulled = FALSE;
GLenum filter = s->display->textureFilter;
CUBE_SCREEN (s);
hsize = s->hsize * cs->nOutput;
size = hsize;
if (cs->desktopOpacity != OPAQUE)
{
wasCulled = glIsEnabled(GL_CULL_FACE);
if (wasCulled)
glDisable(GL_CULL_FACE);
}
if (!cs->fullscreenOutput)
{
cs->outputXScale = (float) s->width / s->outputDev[output].width;
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;
}
clear = cs->cleared[output];
if (!clear)
{
if (cs->sky.name)
{
screenLighting (s, FALSE);
glPushMatrix ();
if (cs->animateSkyDome && cs->grabIndex == 0)
{
glRotatef (sAttrib->xRotate, 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
{
clearTargetOutput (s->display, GL_COLOR_BUFFER_BIT);
}
cs->cleared[output] = TRUE;
}
mask &= ~PAINT_SCREEN_CLEAR_MASK;
UNWRAP (cs, s, paintTransformedScreen);
sa.xTranslate = sAttrib->xTranslate;
sa.yTranslate = sAttrib->yTranslate;
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));
/* distance we move the camera back when unfolding the cube.
currently hardcoded to 1.5 but it should probably be optional. */
sa.zCamera -= cs->unfold * 1.5f;
}
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;
if (sa.xRotate > 0.0f)
cs->xrotations = (int) (hsize * sa.xRotate + 180) / 360;
else
cs->xrotations = (int) (hsize * sa.xRotate - 180) / 360;
sa.xRotate -= (360.0f * cs->xrotations) / size;
sa.xRotate *= cs->invert;
xMove = cs->xrotations;
if (cs->grabIndex && cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b)
s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
if (cs->invert == 1)
mask |= PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK; // Outside cube - start with FTB faces.
// Inside cube - start with BTF faces.
if (cs->paintAllViewports || cs->desktopOpacity != OPAQUE || cs->invert == -1)
cubePaintAllViewports(s, &sa, transform, region, output, mask, xMove, size, hsize);
if (cs->invert == 1)
mask &= ~PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK; // Outside cube - continue with caps and then BTF faces.
else
mask |= PAINT_SCREEN_ORDER_FRONT_TO_BACK_MASK; // Inside cube - continue with caps and then FTB faces.
if (!clear && cs->grabIndex == 0 && hsize > 2 &&
(cs->invert != 1 || sa.vRotate != 0.0f || sa.yTranslate != 0.0f))
{
CompTransform sTransform = *transform;
screenLighting (s, TRUE);
glColor4us (cs->color[0], cs->color[1], cs->color[2], cs->desktopOpacity);
glPushMatrix ();
sa.yRotate += 360.0f / size;
(*s->applyScreenTransform) (s, &sa, output, &sTransform);
glLoadMatrixf (sTransform.m);
glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
sa.yRotate -= 360.0f / size;
if (cs->desktopOpacity != OPAQUE)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
int i;
for (i = 0; i < 2; i++)
{
if ((i == 0 && sAttrib->vRotate < 0.0f) ||
(i == 1 && sAttrib->vRotate > 0.0f))
{
glNormal3f (0.0f, -1.0f, 0.0f);
if (cs->invert == 1 && hsize == 4 && cs->texture.name)
{
enableTexture (s, &cs->texture, COMP_TEXTURE_FILTER_GOOD);
glTexCoordPointer (2, GL_FLOAT, 0, cs->tc);
glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
disableTexture (s, &cs->texture);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
}
else
{
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
}
}
else
{
glNormal3f (0.0f, 1.0f, 0.0f);
glDrawArrays (GL_TRIANGLE_FAN, cs->nvertices >> 1,
cs->nvertices >> 1);
}
}
glNormal3f (0.0f, 1.0f, 0.0f);
glDrawArrays (GL_TRIANGLE_FAN, cs->nvertices >> 1,
cs->nvertices >> 1);
glNormal3f (0.0f, 0.0f, -1.0f);
glPopMatrix ();
glColor4usv (defaultColor);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
if (cs->paintAllViewports || cs->desktopOpacity != OPAQUE || cs->invert == 1)
cubePaintAllViewports(s, &sa, transform, region, output, mask, xMove, size, hsize);
WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
if (cs->desktopOpacity != OPAQUE && wasCulled)
glEnable(GL_CULL_FACE);
s->display->textureFilter = filter;
}
static void cubeSetClipPlanes (CompScreen *s, Region region, int output)
{
CUBE_SCREEN(s);
glTranslatef(cs->outputXOffset, -cs->outputYOffset, 0.0f);
glScalef( cs->outputXScale, cs->outputYScale, 1.0f);
UNWRAP(cs, s, setClipPlanes);
(*s->setClipPlanes) (s, region, output);
WRAP(cs, s, setClipPlanes, cubeSetClipPlanes);
if (cs->invert == 1)
{
GLdouble clipPlane0[] = { 1.0, 0.0, 0.5 / cs->distance, 0.0 };
GLdouble clipPlane1[] = { -1.0, 0.0, 0.5 / cs->distance, 0.0 };
GLdouble clipPlane2[] = { 0.0, -1.0, 0.5 / cs->distance, 0.0 };
GLdouble clipPlane3[] = { 0.0, 1.0, 0.5 / cs->distance, 0.0 };
glClipPlane (GL_CLIP_PLANE0, clipPlane0);
glClipPlane (GL_CLIP_PLANE1, clipPlane1);
glClipPlane (GL_CLIP_PLANE2, clipPlane2);
glClipPlane (GL_CLIP_PLANE3, clipPlane3);
}
else
{
GLdouble clipPlane0[] = { -1.0, 0.0, -0.5 / cs->distance, 0.0 };
GLdouble clipPlane1[] = { 1.0, 0.0, -0.5 / cs->distance, 0.0 };
GLdouble clipPlane2[] = { 0.0, 1.0, -0.5 / cs->distance, 0.0 };
GLdouble clipPlane3[] = { 0.0, -1.0, -0.5 / cs->distance, 0.0 };
glClipPlane (GL_CLIP_PLANE0, clipPlane0);
glClipPlane (GL_CLIP_PLANE1, clipPlane1);
glClipPlane (GL_CLIP_PLANE2, clipPlane2);
glClipPlane (GL_CLIP_PLANE3, clipPlane3);
}
}
static void
cubeApplyScreenTransform (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
int output,
CompTransform *transform)
{
CUBE_SCREEN (s);
matrixTranslate (transform, cs->outputXOffset, -cs->outputYOffset, 0.0f);
matrixScale (transform, cs->outputXScale, cs->outputYScale, 1.0f);
UNWRAP (cs, s, applyScreenTransform);
(*s->applyScreenTransform) (s, sAttrib, output, transform);
WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
matrixScale (transform, 1.0f / cs->outputXScale,
1.0f / cs->outputYScale, 1.0f);
matrixTranslate (transform, -cs->outputXOffset, cs->outputYOffset, 0.0f);
}
static void cubeHandleCompizEvent(CompDisplay * d, char *pluginName,
char *eventName, CompOption * option, int nOption)
{
CUBE_DISPLAY(d);
UNWRAP (cd, d, handleCompizEvent);
(*d->handleCompizEvent) (d, pluginName, eventName, option, nOption);
WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent);
if (strcmp(pluginName, "3d") == 0)
{
if (strcmp(eventName, "disableCapsEvent") == 0)
{
Window xid = getIntOptionNamed(option, nOption, "root", 0);
CompScreen *s = findScreenAtDisplay(d, xid);
if (s)
{
CUBE_SCREEN(s);
cs->disableCaps = getBoolOptionNamed(option, nOption, "disableCaps", FALSE);
}
}
else if (strcmp(eventName, "paintAllViewportsEvent") == 0)
{
Window xid = getIntOptionNamed(option, nOption, "root", 0);
CompScreen *s = findScreenAtDisplay(d, xid);
if (s)
{
CUBE_SCREEN(s);
cs->paintAllViewports = getBoolOptionNamed(option, nOption, "paintAllViewports", FALSE);
}
}
}
if (strcmp(pluginName, "rotate") == 0)
{
if (strcmp(eventName, "rotateEvent") == 0)
{
Window xid = getIntOptionNamed(option, nOption, "root", 0);
CompScreen *s = findScreenAtDisplay(d, xid);
if (s)
{
CUBE_SCREEN(s);
Bool rotate = getBoolOptionNamed(option, nOption, "rotating", FALSE);
Bool manual = getBoolOptionNamed(option, nOption, "manual", FALSE);
if (rotate && manual)
cs->rotationMode = RotationManual;
else if (rotate)
cs->rotationMode = RotationChange;
else
cs->rotationMode = NoRotation;
damageScreen(s);
}
}
}
}
static void
cubeFoldEvent(CompScreen *s, Bool unfolded)
{
CompOption o[2];
o[0].type = CompOptionTypeInt;
o[0].name = "root";
o[0].value.i = s->root;
o[1].type = CompOptionTypeBool;
o[1].name = "unfolded";
o[1].value.b = unfolded;
(*s->display->handleCompizEvent) (s->display,
"cube",
"unfoldEvent",
o, 2);
}
static Bool
cubeUnfold (CompDisplay *d,
CompAction *action,
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 (s->hsize * cs->nOutput < 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)
{
cubeFoldEvent (s, TRUE);
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);
if (xid && s->root != xid)
continue;
if (cs->grabIndex)
{
cubeFoldEvent (s, FALSE);
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->imgNFile)
{
cubeLoadImg (s, (cs->imgCurFile + 1) % cs->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->imgNFile)
{
cubeLoadImg (s, (cs->imgCurFile - 1 + cs->imgNFile) % cs->imgNFile);
damageScreen (s);
}
}
return FALSE;
}
static void
cubeOutputChangeNotify (CompScreen *s)
{
CUBE_SCREEN (s);
cubeUpdateOutputs (s);
cubeUpdateGeometry (s, s->hsize, cs->invert);
if (cs->imgNFile)
cubeLoadImg (s, cs->imgCurFile);
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 CompOption *
cubeGetDisplayOptions (CompPlugin *plugin,
CompDisplay *display,
int *count)
{
CUBE_DISPLAY (display);
*count = NUM_OPTIONS (cd);
return cd->opt;
}
static Bool
cubeSetDisplayOption (CompPlugin *plugin,
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,
Display *display)
{
CompOption *o;
o = &cd->opt[CUBE_DISPLAY_OPTION_UNFOLD];
o->name = "unfold";
o->shortDesc = N_("Unfold");
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.keycode =
XKeysymToKeycode (display,
XStringToKeysym (CUBE_UNFOLD_KEY_DEFAULT));
o = &cd->opt[CUBE_DISPLAY_OPTION_NEXT];
o->name = "next_slide";
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 = CompBindingTypeKey;
o->value.action.key.modifiers = CUBE_NEXT_MODIFIERS_DEFAULT;
o->value.action.key.keycode =
XKeysymToKeycode (display,
XStringToKeysym (CUBE_NEXT_KEY_DEFAULT));
o = &cd->opt[CUBE_DISPLAY_OPTION_PREV];
o->name = "prev_slide";
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 = CompBindingTypeKey;
o->value.action.key.modifiers = CUBE_PREV_MODIFIERS_DEFAULT;
o->value.action.key.keycode =
XKeysymToKeycode (display,
XStringToKeysym (CUBE_PREV_KEY_DEFAULT));
}
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->display);
d->privates[displayPrivateIndex].ptr = cd;
WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent);
return TRUE;
}
static void
cubeFiniDisplay (CompPlugin *p,
CompDisplay *d)
{
#ifdef USE_LIBRSVG
rsvg_term ();
#endif
CUBE_DISPLAY (d);
UNWRAP (cd, d, handleCompizEvent);
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->tc[0] = cs->tc[1] = cs->tc[2] = cs->tc[3] = 0.0f;
cs->tc[4] = cs->tc[5] = cs->tc[6] = cs->tc[7] = 0.0f;
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;
s->privates[cd->screenPrivateIndex].ptr = cs;
cs->paintTopBottom = FALSE;
initTexture (s, &cs->texture);
initTexture (s, &cs->sky);
cubeInitSvg (s);
cs->imgFiles = 0;
cs->imgNFile = 0;
cs->imgCurFile = 0;
cs->acceleration = CUBE_ACCELERATION_DEFAULT;
cs->speed = CUBE_SPEED_DEFAULT;
cs->timestep = CUBE_TIMESTEP_DEFAULT;
cs->unfolded = FALSE;
cs->unfold = 0.0f;
cs->unfoldVelocity = 0.0f;
cs->fullscreenOutput = TRUE;
cs->disableCaps = FALSE;
cs->paintAllViewports = FALSE;
cs->rotationMode = NoRotation;
cs->desktopOpacity = (CUBE_INACTIVE_OPACITY_DEFAULT / 100.0f) * OPAQUE;
memset (cs->cleared, 0, sizeof (cs->cleared));
cubeScreenInitOptions (cs, s->display->display);
cs->imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.value;
cs->imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
addScreenAction (s, &cd->opt[CUBE_DISPLAY_OPTION_UNFOLD].value.action);
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, setScreenOption, cubeSetGlobalScreenOption);
WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
WRAP (cs, s, setClipPlanes, cubeSetClipPlanes);
WRAP (cs, s, paintBackground, cubePaintBackground);
WRAP (cs, s, paintWindow, cubePaintWindow);
cubeUpdateOutputs (s);
if (!cubeUpdateGeometry (s, s->hsize, cs->invert))
return FALSE;
if (cs->imgNFile)
{
cubeLoadImg (s, cs->imgCurFile);
damageScreen (s);
}
return TRUE;
}
static void
cubeFiniScreen (CompPlugin *p,
CompScreen *s)
{
CUBE_SCREEN (s);
CUBE_DISPLAY (s->display);
if (cs->skyListId)
glDeleteLists (cs->skyListId, 1);
removeScreenAction (s, &cd->opt[CUBE_DISPLAY_OPTION_UNFOLD].value.action);
UNWRAP (cs, s, preparePaintScreen);
UNWRAP (cs, s, donePaintScreen);
UNWRAP (cs, s, paintScreen);
UNWRAP (cs, s, paintTransformedScreen);
UNWRAP (cs, s, applyScreenTransform);
UNWRAP (cs, s, setScreenOption);
UNWRAP (cs, s, outputChangeNotify);
UNWRAP (cs, s, setClipPlanes);
UNWRAP (cs, s, paintBackground);
UNWRAP (cs, s, paintWindow);
finiTexture (s, &cs->texture);
finiTexture (s, &cs->sky);
cubeFiniSvg (s);
free (cs);
}
static Bool
cubeInit (CompPlugin *p)
{
#ifdef USE_LIBRSVG
rsvg_init ();
#endif
displayPrivateIndex = allocateDisplayPrivateIndex ();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void
cubeFini (CompPlugin *p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex (displayPrivateIndex);
}
static int
cubeGetVersion (CompPlugin *plugin,
int version)
{
return ABIVERSION;
}
CompPluginDep cubeDeps[] = {
{ CompPluginRuleBefore, "scale" },
{ CompPluginRuleBefore, "switcher" }
};
CompPluginFeature cubeFeatures[] = {
{ "largedesktop" }
};
CompPluginVTable cubeVTable = {
"cube",
N_("Desktop Cube"),
N_("Place windows on cube"),
cubeGetVersion,
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])
};
CompPluginVTable *
getCompPluginInfo (void)
{
return &cubeVTable;
}