2
* Copyright © 2005 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
36
#ifdef USE_LIBSVG_CAIRO
37
#include <cairo-xlib.h>
38
#include <svg-cairo.h>
41
#include <X11/Xatom.h>
42
#include <X11/Xproto.h>
46
#define CUBE_COLOR_RED_DEFAULT 0xefef
47
#define CUBE_COLOR_GREEN_DEFAULT 0xebeb
48
#define CUBE_COLOR_BLUE_DEFAULT 0xe7e7
50
#define CUBE_IN_DEFAULT FALSE
52
#define CUBE_NEXT_KEY_DEFAULT "space"
53
#define CUBE_NEXT_MODIFIERS_DEFAULT CompPressMask
55
#define CUBE_PREV_KEY_DEFAULT "BackSpace"
56
#define CUBE_PREV_MODIFIERS_DEFAULT CompPressMask
58
static int displayPrivateIndex;
60
typedef struct _CubeDisplay {
61
int screenPrivateIndex;
62
HandleEventProc handleEvent;
65
#define CUBE_SCREEN_OPTION_COLOR 0
66
#define CUBE_SCREEN_OPTION_IN 1
67
#define CUBE_SCREEN_OPTION_SVGS 2
68
#define CUBE_SCREEN_OPTION_NEXT 3
69
#define CUBE_SCREEN_OPTION_PREV 4
70
#define CUBE_SCREEN_OPTION_NUM 5
72
typedef struct _CubeScreen {
73
PaintTransformedScreenProc paintTransformedScreen;
74
PaintBackgroundProc paintBackground;
75
SetScreenOptionProc setScreenOption;
77
CompOption opt[CUBE_SCREEN_OPTION_NUM];
93
#ifdef USE_LIBSVG_CAIRO
98
CompOptionValue *svgFiles;
103
#define GET_CUBE_DISPLAY(d) \
104
((CubeDisplay *) (d)->privates[displayPrivateIndex].ptr)
106
#define CUBE_DISPLAY(d) \
107
CubeDisplay *cd = GET_CUBE_DISPLAY (d)
109
#define GET_CUBE_SCREEN(s, cd) \
110
((CubeScreen *) (s)->privates[(cd)->screenPrivateIndex].ptr)
112
#define CUBE_SCREEN(s) \
113
CubeScreen *cs = GET_CUBE_SCREEN (s, GET_CUBE_DISPLAY (s->display))
115
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
117
#ifdef USE_LIBSVG_CAIRO
119
cubeInitSvg (CompScreen *s)
131
cubeFiniSvg (CompScreen *s)
137
svg_cairo_destroy (cs->svgc);
140
cairo_destroy (cs->cr);
143
XFreePixmap (s->display->display, cs->pixmap);
147
cubeLoadSvg (CompScreen *s,
150
unsigned int width, height;
154
if (!cs->svgNFile || cs->pw != s->width || cs->ph != s->height)
156
finiTexture (s, &cs->texture);
157
initTexture (s, &cs->texture);
167
cairo_surface_t *surface;
174
depth = DefaultDepth (s->display->display, s->screenNum);
175
cs->pixmap = XCreatePixmap (s->display->display, s->root,
179
if (!bindPixmapToTexture (s, &cs->texture, cs->pixmap,
180
s->width, s->height, depth))
182
fprintf (stderr, "%s: Couldn't bind slide pixmap 0x%x to "
183
"texture\n", programName, (int) cs->pixmap);
186
if (cs->texture.target == GL_TEXTURE_RECTANGLE_ARB)
188
cs->tc[0] = s->width / 2.0f;
189
cs->tc[1] = s->height / 2.0f;
191
cs->tc[2] = s->width;
192
cs->tc[3] = s->height;
195
cs->tc[5] = s->height;
200
cs->tc[8] = s->width;
203
cs->tc[10] = s->width;
204
cs->tc[11] = s->height;
227
visual = DefaultVisual (s->display->display, s->screenNum);
228
surface = cairo_xlib_surface_create (s->display->display,
230
s->width, s->height);
231
cs->cr = cairo_create (surface);
232
cairo_surface_destroy (surface);
235
cs->svgCurFile = n % cs->svgNFile;
238
svg_cairo_destroy (cs->svgc);
240
if (svg_cairo_create (&cs->svgc))
242
fprintf (stderr, "%s: Failed to create svg_cairo_t.\n",
247
svg_cairo_set_viewport_dimension (cs->svgc, s->width, s->height);
249
if (svg_cairo_parse (cs->svgc, cs->svgFiles[cs->svgCurFile].s))
251
fprintf (stderr, "%s: Failed to load svg: %s.\n",
252
programName, cs->svgFiles[cs->svgCurFile].s);
256
svg_cairo_get_size (cs->svgc, &width, &height);
259
cairo_set_source_rgb (cs->cr,
260
(double) cs->color[0] / 0xffff,
261
(double) cs->color[1] / 0xffff,
262
(double) cs->color[2] / 0xffff);
263
cairo_rectangle (cs->cr, 0, 0, s->width, s->height);
267
(double) s->width / width,
268
(double) s->height / height);
270
svg_cairo_render (cs->svgc, cs->cr);
271
cairo_restore (cs->cr);
276
cubeUpdateGeometry (CompScreen *s,
280
GLfloat radius, distance;
286
distance = 0.5f / tanf (M_PI / sides);
287
radius = 0.5f / sinf (M_PI / sides);
291
if (cs->nvertices != n)
293
v = realloc (cs->vertices, sizeof (GLfloat) * n * 3);
307
for (i = 0; i <= sides; i++)
309
*v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
311
*v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
315
*v++ = -0.5 * invert;
318
for (i = sides; i >= 0; i--)
320
*v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
321
*v++ = -0.5 * invert;
322
*v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
326
cs->distance = distance;
332
cubeGetScreenOptions (CompScreen *screen,
335
CUBE_SCREEN (screen);
337
*count = NUM_OPTIONS (cs);
342
cubeSetScreenOption (CompScreen *screen,
344
CompOptionValue *value)
349
CUBE_SCREEN (screen);
351
o = compFindOption (cs->opt, NUM_OPTIONS (cs), name, &index);
356
case CUBE_SCREEN_OPTION_COLOR:
357
if (compSetColorOption (o, value))
359
memcpy (cs->color, o->value.c, sizeof (cs->color));
360
damageScreen (screen);
364
case CUBE_SCREEN_OPTION_IN:
365
if (compSetBoolOption (o, value))
367
if (cubeUpdateGeometry (screen, screen->size, o->value.b ? -1 : 1))
371
case CUBE_SCREEN_OPTION_SVGS:
372
if (compSetOptionList (o, value))
375
#ifdef USE_LIBSVG_CAIRO
376
cs->svgFiles = cs->opt[CUBE_SCREEN_OPTION_SVGS].value.list.value;
377
cs->svgNFile = cs->opt[CUBE_SCREEN_OPTION_SVGS].value.list.nValue;
379
cubeLoadSvg (screen, cs->svgCurFile);
380
damageScreen (screen);
386
case CUBE_SCREEN_OPTION_NEXT:
387
case CUBE_SCREEN_OPTION_PREV:
388
if (compSetBindingOption (o, value))
398
cubeScreenInitOptions (CubeScreen *cs,
403
o = &cs->opt[CUBE_SCREEN_OPTION_COLOR];
405
o->shortDesc = "Cube Color";
406
o->longDesc = "Color of top and bottom sides of the cube";
407
o->type = CompOptionTypeColor;
408
o->value.c[0] = CUBE_COLOR_RED_DEFAULT;
409
o->value.c[1] = CUBE_COLOR_GREEN_DEFAULT;
410
o->value.c[2] = CUBE_COLOR_BLUE_DEFAULT;
411
o->value.c[3] = 0xffff;
413
o = &cs->opt[CUBE_SCREEN_OPTION_IN];
415
o->shortDesc = "Inside Cube";
416
o->longDesc = "Inside cube";
417
o->type = CompOptionTypeBool;
418
o->value.b = CUBE_IN_DEFAULT;
420
o = &cs->opt[CUBE_SCREEN_OPTION_SVGS];
422
o->shortDesc = "SVG files";
423
o->longDesc = "List of SVG files rendered on top face of cube";
424
o->type = CompOptionTypeList;
425
o->value.list.type = CompOptionTypeString;
426
o->value.list.nValue = 0;
427
o->value.list.value = 0;
428
o->rest.s.string = 0;
429
o->rest.s.nString = 0;
431
o = &cs->opt[CUBE_SCREEN_OPTION_NEXT];
432
o->name = "next_slide";
433
o->shortDesc = "Next Slide";
434
o->longDesc = "Adavence to next slide";
435
o->type = CompOptionTypeBinding;
436
o->value.bind.type = CompBindingTypeKey;
437
o->value.bind.u.key.modifiers = CUBE_NEXT_MODIFIERS_DEFAULT;
438
o->value.bind.u.key.keycode =
439
XKeysymToKeycode (display, XStringToKeysym (CUBE_NEXT_KEY_DEFAULT));
441
o = &cs->opt[CUBE_SCREEN_OPTION_PREV];
442
o->name = "prev_slide";
443
o->shortDesc = "Previous Slide";
444
o->longDesc = "Go back to previous slide";
445
o->type = CompOptionTypeBinding;
446
o->value.bind.type = CompBindingTypeKey;
447
o->value.bind.u.key.modifiers = CUBE_PREV_MODIFIERS_DEFAULT;
448
o->value.bind.u.key.keycode =
449
XKeysymToKeycode (display, XStringToKeysym (CUBE_PREV_KEY_DEFAULT));
453
cubePaintTransformedScreen (CompScreen *s,
454
const ScreenPaintAttrib *sAttrib,
457
ScreenPaintAttrib sa = *sAttrib;
462
if (mask & PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)
463
glClear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
465
glClear (GL_COLOR_BUFFER_BIT);
467
if (sa.vRotate > 100.0f)
469
else if (sAttrib->vRotate < -100.0f)
470
sa.vRotate = -100.0f;
472
sa.vRotate = sAttrib->vRotate;
474
UNWRAP (cs, s, paintTransformedScreen);
476
sa.xTranslate = sAttrib->xTranslate;
477
sa.yTranslate = sAttrib->yTranslate;
478
sa.zTranslate = -cs->invert * cs->distance;
480
sa.xRotate = sAttrib->xRotate * cs->invert;
481
if (sa.xRotate > 0.0f)
483
cs->xrotations = (int) (s->size * sa.xRotate) / 360;
484
sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / s->size;
488
cs->xrotations = (int) (s->size * sa.xRotate) / 360;
489
sa.xRotate = sa.xRotate -
490
(360.0f * cs->xrotations) / s->size + 360.0f / s->size;
494
if (cs->invert != 1 || sa.vRotate != 0.0f || sa.yTranslate != 0.0f)
496
glColor3usv (cs->color);
500
if (sAttrib->xRotate > 0.0f)
502
sa.yRotate += 360.0f / s->size;
503
translateRotateScreen (&sa);
504
sa.yRotate -= 360.0f / s->size;
507
translateRotateScreen (&sa);
509
glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
511
if (cs->invert == 1 && s->size == 4 && cs->texture.name)
513
enableTexture (s, &cs->texture, COMP_TEXTURE_FILTER_GOOD);
514
glTexCoordPointer (2, GL_FLOAT, 0, cs->tc);
515
glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
516
disableTexture (&cs->texture);
519
glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
521
glDrawArrays (GL_TRIANGLE_FAN, cs->nvertices >> 1,
527
/* outside 4 side cube */
528
if (s->size == 4 && cs->invert == 1)
530
if (sAttrib->xRotate != 0.0f)
532
xMove = cs->xrotations;
534
moveScreenViewport (s, xMove, FALSE);
535
(*s->paintTransformedScreen) (s, &sa, mask);
536
moveScreenViewport (s, -xMove, FALSE);
540
moveScreenViewport (s, xMove, FALSE);
543
sa.yRotate -= 360.0f / s->size;
545
(*s->paintTransformedScreen) (s, &sa, mask);
547
moveScreenViewport (s, -xMove, FALSE);
551
if (sa.xRotate > 180.0f / s->size)
553
sa.yRotate -= 360.0f / s->size;
557
sa.yRotate -= 360.0f / s->size;
558
xMove = -1 - cs->xrotations;
560
moveScreenViewport (s, xMove, FALSE);
561
(*s->paintTransformedScreen) (s, &sa, mask);
562
moveScreenViewport (s, -xMove, FALSE);
564
sa.yRotate += 360.0f / s->size;
565
xMove = -cs->xrotations;
567
moveScreenViewport (s, xMove, FALSE);
568
(*s->paintTransformedScreen) (s, &sa, mask);
569
moveScreenViewport (s, -xMove, FALSE);
571
sa.yRotate += 360.0f / s->size;
572
xMove = 1 - cs->xrotations;
574
moveScreenViewport (s, xMove, FALSE);
575
(*s->paintTransformedScreen) (s, &sa, mask);
576
moveScreenViewport (s, -xMove, FALSE);
579
WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
583
cubePaintBackground (CompScreen *s,
591
UNWRAP (cs, s, paintBackground);
592
(*s->paintBackground) (s, region, mask);
593
WRAP (cs, s, paintBackground, cubePaintBackground);
596
#ifdef USE_LIBSVG_CAIRO
598
cubeHandleEvent (CompDisplay *d,
605
switch (event->type) {
608
s = findScreenAtDisplay (d, event->xkey.root);
613
if (EV_KEY (&cs->opt[CUBE_SCREEN_OPTION_NEXT], event))
615
cubeLoadSvg (s, (cs->svgCurFile + 1) % cs->svgNFile);
619
if (EV_KEY (&cs->opt[CUBE_SCREEN_OPTION_PREV], event))
621
cubeLoadSvg (s, (cs->svgCurFile - 1 + cs->svgNFile) %
629
s = findScreenAtDisplay (d, event->xbutton.root);
634
if (EV_BUTTON (&cs->opt[CUBE_SCREEN_OPTION_NEXT], event))
636
cubeLoadSvg (s, (cs->svgCurFile + 1) % cs->svgNFile);
640
if (EV_BUTTON (&cs->opt[CUBE_SCREEN_OPTION_PREV], event))
642
cubeLoadSvg (s, (cs->svgCurFile - 1 + cs->svgNFile) %
651
UNWRAP (cd, d, handleEvent);
652
(*d->handleEvent) (d, event);
653
WRAP (cd, d, handleEvent, cubeHandleEvent);
658
cubeSetGlobalScreenOption (CompScreen *s,
660
CompOptionValue *value)
666
UNWRAP (cs, s, setScreenOption);
667
status = (*s->setScreenOption) (s, name, value);
668
WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
670
if (status && strcmp (name, "size") == 0)
671
cubeUpdateGeometry (s, s->size, cs->invert);
677
cubeInitDisplay (CompPlugin *p,
682
cd = malloc (sizeof (CubeDisplay));
686
cd->screenPrivateIndex = allocateScreenPrivateIndex (d);
687
if (cd->screenPrivateIndex < 0)
693
#ifdef USE_LIBSVG_CAIRO
694
WRAP (cd, d, handleEvent, cubeHandleEvent);
697
d->privates[displayPrivateIndex].ptr = cd;
703
cubeFiniDisplay (CompPlugin *p,
708
freeScreenPrivateIndex (d, cd->screenPrivateIndex);
710
#ifdef USE_LIBSVG_CAIRO
711
UNWRAP (cd, d, handleEvent);
718
cubeInitScreen (CompPlugin *p,
723
CUBE_DISPLAY (s->display);
725
cs = malloc (sizeof (CubeScreen));
731
cs->tc[0] = cs->tc[1] = cs->tc[2] = cs->tc[3] = 0.0f;
732
cs->tc[4] = cs->tc[5] = cs->tc[6] = cs->tc[7] = 0.0f;
734
cs->color[0] = CUBE_COLOR_RED_DEFAULT;
735
cs->color[1] = CUBE_COLOR_GREEN_DEFAULT;
736
cs->color[2] = CUBE_COLOR_BLUE_DEFAULT;
741
s->privates[cd->screenPrivateIndex].ptr = cs;
743
cs->paintTopBottom = FALSE;
745
initTexture (s, &cs->texture);
747
#ifdef USE_LIBSVG_CAIRO
755
cubeScreenInitOptions (cs, s->display->display);
757
WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
758
WRAP (cs, s, paintBackground, cubePaintBackground);
759
WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
761
if (!cubeUpdateGeometry (s, s->size, cs->invert))
768
cubeFiniScreen (CompPlugin *p,
773
UNWRAP (cs, s, paintTransformedScreen);
774
UNWRAP (cs, s, paintBackground);
775
UNWRAP (cs, s, setScreenOption);
777
finiTexture (s, &cs->texture);
779
#ifdef USE_LIBSVG_CAIRO
787
cubeInit (CompPlugin *p)
789
displayPrivateIndex = allocateDisplayPrivateIndex ();
790
if (displayPrivateIndex < 0)
797
cubeFini (CompPlugin *p)
799
if (displayPrivateIndex >= 0)
800
freeDisplayPrivateIndex (displayPrivateIndex);
803
CompPluginDep cubeDeps[] = {
804
{ CompPluginRuleBefore, "expose" }
807
CompPluginVTable cubeVTable = {
810
"Place windows on cube",
819
0, /* GetDisplayOptions */
820
0, /* SetDisplayOption */
821
cubeGetScreenOptions,
824
sizeof (cubeDeps) / sizeof (cubeDeps[0])
828
getCompPluginInfo (void)