~alan-griffiths/compiz-core/Bug-931283

« back to all changes in this revision

Viewing changes to plugins/cube.c

  • Committer: David Reveman
  • Date: 2006-02-09 06:03:09 UTC
  • Revision ID: git-v1:9959c2b13ded64a5e66359a8097250dc9d87fc1c
Initial revision

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2005 Novell, Inc.
 
3
 *
 
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
 
13
 * implied warranty.
 
14
 *
 
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.
 
22
 *
 
23
 * Author: David Reveman <davidr@novell.com>
 
24
 */
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
#include <config.h>
 
28
#endif
 
29
 
 
30
#define _GNU_SOURCE
 
31
#include <string.h>
 
32
#include <stdlib.h>
 
33
#include <math.h>
 
34
#include <sys/time.h>
 
35
 
 
36
#ifdef USE_LIBSVG_CAIRO
 
37
#include <cairo-xlib.h>
 
38
#include <svg-cairo.h>
 
39
#endif
 
40
 
 
41
#include <X11/Xatom.h>
 
42
#include <X11/Xproto.h>
 
43
 
 
44
#include <compiz.h>
 
45
 
 
46
#define CUBE_COLOR_RED_DEFAULT   0xefef
 
47
#define CUBE_COLOR_GREEN_DEFAULT 0xebeb
 
48
#define CUBE_COLOR_BLUE_DEFAULT  0xe7e7
 
49
 
 
50
#define CUBE_IN_DEFAULT FALSE
 
51
 
 
52
#define CUBE_NEXT_KEY_DEFAULT       "space"
 
53
#define CUBE_NEXT_MODIFIERS_DEFAULT CompPressMask
 
54
 
 
55
#define CUBE_PREV_KEY_DEFAULT       "BackSpace"
 
56
#define CUBE_PREV_MODIFIERS_DEFAULT CompPressMask
 
57
 
 
58
static int displayPrivateIndex;
 
59
 
 
60
typedef struct _CubeDisplay {
 
61
    int             screenPrivateIndex;
 
62
    HandleEventProc handleEvent;
 
63
} CubeDisplay;
 
64
 
 
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
 
71
 
 
72
typedef struct _CubeScreen {
 
73
    PaintTransformedScreenProc paintTransformedScreen;
 
74
    PaintBackgroundProc        paintBackground;
 
75
    SetScreenOptionProc        setScreenOption;
 
76
 
 
77
    CompOption opt[CUBE_SCREEN_OPTION_NUM];
 
78
 
 
79
    int      invert;
 
80
    int      xrotations;
 
81
    GLfloat  distance;
 
82
    Bool     paintTopBottom;
 
83
    GLushort color[3];
 
84
    GLfloat  tc[12];
 
85
 
 
86
    GLfloat  *vertices;
 
87
    int      nvertices;
 
88
 
 
89
    Pixmap          pixmap;
 
90
    int             pw, ph;
 
91
    CompTexture     texture;
 
92
 
 
93
#ifdef USE_LIBSVG_CAIRO
 
94
    cairo_t         *cr;
 
95
    svg_cairo_t     *svgc;
 
96
    int             svgNFile;
 
97
    int             svgCurFile;
 
98
    CompOptionValue *svgFiles;
 
99
#endif
 
100
 
 
101
} CubeScreen;
 
102
 
 
103
#define GET_CUBE_DISPLAY(d)                                  \
 
104
    ((CubeDisplay *) (d)->privates[displayPrivateIndex].ptr)
 
105
 
 
106
#define CUBE_DISPLAY(d)                    \
 
107
    CubeDisplay *cd = GET_CUBE_DISPLAY (d)
 
108
 
 
109
#define GET_CUBE_SCREEN(s, cd)                                   \
 
110
    ((CubeScreen *) (s)->privates[(cd)->screenPrivateIndex].ptr)
 
111
 
 
112
#define CUBE_SCREEN(s)                                                  \
 
113
    CubeScreen *cs = GET_CUBE_SCREEN (s, GET_CUBE_DISPLAY (s->display))
 
114
 
 
115
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
 
116
 
 
117
#ifdef USE_LIBSVG_CAIRO
 
118
static void
 
119
cubeInitSvg (CompScreen *s)
 
120
 
 
121
{
 
122
    CUBE_SCREEN (s);
 
123
 
 
124
    cs->pixmap = None;
 
125
    cs->pw = cs->ph = 0;
 
126
    cs->cr = 0;
 
127
    cs->svgc = 0;
 
128
}
 
129
 
 
130
static void
 
131
cubeFiniSvg (CompScreen *s)
 
132
 
 
133
{
 
134
    CUBE_SCREEN (s);
 
135
 
 
136
    if (cs->svgc)
 
137
        svg_cairo_destroy (cs->svgc);
 
138
 
 
139
    if (cs->cr)
 
140
        cairo_destroy (cs->cr);
 
141
 
 
142
    if (cs->pixmap)
 
143
        XFreePixmap (s->display->display, cs->pixmap);
 
144
}
 
145
 
 
146
static void
 
147
cubeLoadSvg (CompScreen *s,
 
148
             int        n)
 
149
{
 
150
    unsigned int width, height;
 
151
 
 
152
    CUBE_SCREEN (s);
 
153
 
 
154
    if (!cs->svgNFile || cs->pw != s->width || cs->ph != s->height)
 
155
    {
 
156
        finiTexture (s, &cs->texture);
 
157
        initTexture (s, &cs->texture);
 
158
        cubeFiniSvg (s);
 
159
        cubeInitSvg (s);
 
160
 
 
161
        if (!cs->svgNFile)
 
162
            return;
 
163
    }
 
164
 
 
165
    if (!cs->pixmap)
 
166
    {
 
167
        cairo_surface_t *surface;
 
168
        Visual          *visual;
 
169
        int             depth;
 
170
 
 
171
        cs->pw = s->width;
 
172
        cs->ph = s->height;
 
173
 
 
174
        depth = DefaultDepth (s->display->display, s->screenNum);
 
175
        cs->pixmap = XCreatePixmap (s->display->display, s->root,
 
176
                                    s->width, s->height,
 
177
                                    depth);
 
178
 
 
179
        if (!bindPixmapToTexture (s, &cs->texture, cs->pixmap,
 
180
                                  s->width, s->height, depth))
 
181
        {
 
182
            fprintf (stderr, "%s: Couldn't bind slide pixmap 0x%x to "
 
183
                     "texture\n", programName, (int) cs->pixmap);
 
184
        }
 
185
 
 
186
        if (cs->texture.target == GL_TEXTURE_RECTANGLE_ARB)
 
187
        {
 
188
            cs->tc[0] = s->width / 2.0f;
 
189
            cs->tc[1] = s->height / 2.0f;
 
190
 
 
191
            cs->tc[2] = s->width;
 
192
            cs->tc[3] = s->height;
 
193
 
 
194
            cs->tc[4] = 0.0f;
 
195
            cs->tc[5] = s->height;
 
196
 
 
197
            cs->tc[6] = 0.0f;
 
198
            cs->tc[7] = 0.0f;
 
199
 
 
200
            cs->tc[8] = s->width;
 
201
            cs->tc[9] = 0.0f;
 
202
 
 
203
            cs->tc[10] = s->width;
 
204
            cs->tc[11] = s->height;
 
205
        }
 
206
        else
 
207
        {
 
208
            cs->tc[0] = 0.5f;
 
209
            cs->tc[1] = 0.5f;
 
210
 
 
211
            cs->tc[2] = 1.0f;
 
212
            cs->tc[3] = 1.0f;
 
213
 
 
214
            cs->tc[4] = 0.0f;
 
215
            cs->tc[5] = 1.0f;
 
216
 
 
217
            cs->tc[6] = 0.0f;
 
218
            cs->tc[7] = 0.0f;
 
219
 
 
220
            cs->tc[8] = 1.0f;
 
221
            cs->tc[9] = 0.0f;
 
222
 
 
223
            cs->tc[10] = 1.0;
 
224
            cs->tc[11] = 1.0f;
 
225
        }
 
226
 
 
227
        visual = DefaultVisual (s->display->display, s->screenNum);
 
228
        surface = cairo_xlib_surface_create (s->display->display,
 
229
                                             cs->pixmap, visual,
 
230
                                             s->width, s->height);
 
231
        cs->cr = cairo_create (surface);
 
232
        cairo_surface_destroy (surface);
 
233
    }
 
234
 
 
235
    cs->svgCurFile = n % cs->svgNFile;
 
236
 
 
237
    if (cs->svgc)
 
238
        svg_cairo_destroy (cs->svgc);
 
239
 
 
240
    if (svg_cairo_create (&cs->svgc))
 
241
    {
 
242
        fprintf (stderr, "%s: Failed to create svg_cairo_t.\n",
 
243
                 programName);
 
244
        return;
 
245
    }
 
246
 
 
247
    svg_cairo_set_viewport_dimension (cs->svgc, s->width, s->height);
 
248
 
 
249
    if (svg_cairo_parse (cs->svgc, cs->svgFiles[cs->svgCurFile].s))
 
250
    {
 
251
        fprintf (stderr, "%s: Failed to load svg: %s.\n",
 
252
                 programName, cs->svgFiles[cs->svgCurFile].s);
 
253
        return;
 
254
    }
 
255
 
 
256
    svg_cairo_get_size (cs->svgc, &width, &height);
 
257
 
 
258
    cairo_save (cs->cr);
 
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);
 
264
    cairo_fill (cs->cr);
 
265
 
 
266
    cairo_scale (cs->cr,
 
267
                 (double) s->width / width,
 
268
                 (double) s->height / height);
 
269
 
 
270
    svg_cairo_render (cs->svgc, cs->cr);
 
271
    cairo_restore (cs->cr);
 
272
}
 
273
#endif
 
274
 
 
275
static Bool
 
276
cubeUpdateGeometry (CompScreen *s,
 
277
                    int        sides,
 
278
                    Bool       invert)
 
279
{
 
280
    GLfloat radius, distance;
 
281
    GLfloat *v;
 
282
    int     i, n;
 
283
 
 
284
    CUBE_SCREEN (s);
 
285
 
 
286
    distance = 0.5f / tanf (M_PI / sides);
 
287
    radius   = 0.5f / sinf (M_PI / sides);
 
288
 
 
289
    n = (sides + 2) * 2;
 
290
 
 
291
    if (cs->nvertices != n)
 
292
    {
 
293
        v = realloc (cs->vertices, sizeof (GLfloat) * n * 3);
 
294
        if (!v)
 
295
            return FALSE;
 
296
 
 
297
        cs->nvertices = n;
 
298
        cs->vertices  = v;
 
299
    }
 
300
    else
 
301
        v = cs->vertices;
 
302
 
 
303
    *v++ = 0.0f;
 
304
    *v++ = 0.5 * invert;
 
305
    *v++ = 0.0f;
 
306
 
 
307
    for (i = 0; i <= sides; i++)
 
308
    {
 
309
        *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
 
310
        *v++ = 0.5 * invert;
 
311
        *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
 
312
    }
 
313
 
 
314
    *v++ = 0.0f;
 
315
    *v++ = -0.5 * invert;
 
316
    *v++ = 0.0f;
 
317
 
 
318
    for (i = sides; i >= 0; i--)
 
319
    {
 
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);
 
323
    }
 
324
 
 
325
    cs->invert   = invert;
 
326
    cs->distance = distance;
 
327
 
 
328
    return TRUE;
 
329
}
 
330
 
 
331
static CompOption *
 
332
cubeGetScreenOptions (CompScreen *screen,
 
333
                      int        *count)
 
334
{
 
335
    CUBE_SCREEN (screen);
 
336
 
 
337
    *count = NUM_OPTIONS (cs);
 
338
    return cs->opt;
 
339
}
 
340
 
 
341
static Bool
 
342
cubeSetScreenOption (CompScreen      *screen,
 
343
                     char            *name,
 
344
                     CompOptionValue *value)
 
345
{
 
346
    CompOption *o;
 
347
    int        index;
 
348
 
 
349
    CUBE_SCREEN (screen);
 
350
 
 
351
    o = compFindOption (cs->opt, NUM_OPTIONS (cs), name, &index);
 
352
    if (!o)
 
353
        return FALSE;
 
354
 
 
355
    switch (index) {
 
356
    case CUBE_SCREEN_OPTION_COLOR:
 
357
        if (compSetColorOption (o, value))
 
358
        {
 
359
            memcpy (cs->color, o->value.c, sizeof (cs->color));
 
360
            damageScreen (screen);
 
361
            return TRUE;
 
362
        }
 
363
        break;
 
364
    case CUBE_SCREEN_OPTION_IN:
 
365
        if (compSetBoolOption (o, value))
 
366
        {
 
367
            if (cubeUpdateGeometry (screen, screen->size, o->value.b ? -1 : 1))
 
368
                return TRUE;
 
369
        }
 
370
        break;
 
371
    case CUBE_SCREEN_OPTION_SVGS:
 
372
        if (compSetOptionList (o, value))
 
373
        {
 
374
 
 
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;
 
378
 
 
379
            cubeLoadSvg (screen, cs->svgCurFile);
 
380
            damageScreen (screen);
 
381
#endif
 
382
 
 
383
            return TRUE;
 
384
        }
 
385
        break;
 
386
    case CUBE_SCREEN_OPTION_NEXT:
 
387
    case CUBE_SCREEN_OPTION_PREV:
 
388
        if (compSetBindingOption (o, value))
 
389
            return TRUE;
 
390
    default:
 
391
        break;
 
392
    }
 
393
 
 
394
    return FALSE;
 
395
}
 
396
 
 
397
static void
 
398
cubeScreenInitOptions (CubeScreen *cs,
 
399
                       Display    *display)
 
400
{
 
401
    CompOption *o;
 
402
 
 
403
    o = &cs->opt[CUBE_SCREEN_OPTION_COLOR];
 
404
    o->name       = "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;
 
412
 
 
413
    o = &cs->opt[CUBE_SCREEN_OPTION_IN];
 
414
    o->name       = "in";
 
415
    o->shortDesc  = "Inside Cube";
 
416
    o->longDesc   = "Inside cube";
 
417
    o->type       = CompOptionTypeBool;
 
418
    o->value.b    = CUBE_IN_DEFAULT;
 
419
 
 
420
    o = &cs->opt[CUBE_SCREEN_OPTION_SVGS];
 
421
    o->name              = "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;
 
430
 
 
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));
 
440
 
 
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));
 
450
}
 
451
 
 
452
static void
 
453
cubePaintTransformedScreen (CompScreen              *s,
 
454
                            const ScreenPaintAttrib *sAttrib,
 
455
                            unsigned int            mask)
 
456
{
 
457
    ScreenPaintAttrib sa = *sAttrib;
 
458
    int               xMove = 0;
 
459
 
 
460
    CUBE_SCREEN (s);
 
461
 
 
462
    if (mask & PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)
 
463
        glClear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
464
    else
 
465
        glClear (GL_COLOR_BUFFER_BIT);
 
466
 
 
467
    if (sa.vRotate > 100.0f)
 
468
        sa.vRotate = 100.0f;
 
469
    else if (sAttrib->vRotate < -100.0f)
 
470
        sa.vRotate = -100.0f;
 
471
    else
 
472
        sa.vRotate = sAttrib->vRotate;
 
473
 
 
474
    UNWRAP (cs, s, paintTransformedScreen);
 
475
 
 
476
    sa.xTranslate = sAttrib->xTranslate;
 
477
    sa.yTranslate = sAttrib->yTranslate;
 
478
    sa.zTranslate = -cs->invert * cs->distance;
 
479
 
 
480
    sa.xRotate = sAttrib->xRotate * cs->invert;
 
481
    if (sa.xRotate > 0.0f)
 
482
    {
 
483
        cs->xrotations = (int) (s->size * sa.xRotate) / 360;
 
484
        sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / s->size;
 
485
    }
 
486
    else
 
487
    {
 
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;
 
491
        cs->xrotations--;
 
492
    }
 
493
 
 
494
    if (cs->invert != 1 || sa.vRotate != 0.0f || sa.yTranslate != 0.0f)
 
495
    {
 
496
        glColor3usv (cs->color);
 
497
 
 
498
        glPushMatrix ();
 
499
 
 
500
        if (sAttrib->xRotate > 0.0f)
 
501
        {
 
502
            sa.yRotate += 360.0f / s->size;
 
503
            translateRotateScreen (&sa);
 
504
            sa.yRotate -= 360.0f / s->size;
 
505
        }
 
506
        else
 
507
            translateRotateScreen (&sa);
 
508
 
 
509
        glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
 
510
 
 
511
        if (cs->invert == 1 && s->size == 4 && cs->texture.name)
 
512
        {
 
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);
 
517
        }
 
518
        else
 
519
            glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
 
520
 
 
521
        glDrawArrays (GL_TRIANGLE_FAN, cs->nvertices >> 1,
 
522
                      cs->nvertices >> 1);
 
523
 
 
524
        glPopMatrix ();
 
525
    }
 
526
 
 
527
    /* outside 4 side cube */
 
528
    if (s->size == 4 && cs->invert == 1)
 
529
    {
 
530
        if (sAttrib->xRotate != 0.0f)
 
531
        {
 
532
            xMove = cs->xrotations;
 
533
 
 
534
            moveScreenViewport (s, xMove, FALSE);
 
535
            (*s->paintTransformedScreen) (s, &sa, mask);
 
536
            moveScreenViewport (s, -xMove, FALSE);
 
537
 
 
538
            xMove++;
 
539
 
 
540
            moveScreenViewport (s, xMove, FALSE);
 
541
        }
 
542
 
 
543
        sa.yRotate -= 360.0f / s->size;
 
544
 
 
545
        (*s->paintTransformedScreen) (s, &sa, mask);
 
546
 
 
547
        moveScreenViewport (s, -xMove, FALSE);
 
548
    }
 
549
    else
 
550
    {
 
551
        if (sa.xRotate > 180.0f / s->size)
 
552
        {
 
553
            sa.yRotate -= 360.0f / s->size;
 
554
            cs->xrotations++;
 
555
        }
 
556
 
 
557
        sa.yRotate -= 360.0f / s->size;
 
558
        xMove = -1 - cs->xrotations;
 
559
 
 
560
        moveScreenViewport (s, xMove, FALSE);
 
561
        (*s->paintTransformedScreen) (s, &sa, mask);
 
562
        moveScreenViewport (s, -xMove, FALSE);
 
563
 
 
564
        sa.yRotate += 360.0f / s->size;
 
565
        xMove = -cs->xrotations;
 
566
 
 
567
        moveScreenViewport (s, xMove, FALSE);
 
568
        (*s->paintTransformedScreen) (s, &sa, mask);
 
569
        moveScreenViewport (s, -xMove, FALSE);
 
570
 
 
571
        sa.yRotate += 360.0f / s->size;
 
572
        xMove = 1 - cs->xrotations;
 
573
 
 
574
        moveScreenViewport (s, xMove, FALSE);
 
575
        (*s->paintTransformedScreen) (s, &sa, mask);
 
576
        moveScreenViewport (s, -xMove, FALSE);
 
577
    }
 
578
 
 
579
    WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
 
580
}
 
581
 
 
582
static void
 
583
cubePaintBackground (CompScreen   *s,
 
584
                     Region       region,
 
585
                     unsigned int mask)
 
586
{
 
587
    CUBE_SCREEN (s);
 
588
 
 
589
    s->stencilRef++;
 
590
 
 
591
    UNWRAP (cs, s, paintBackground);
 
592
    (*s->paintBackground) (s, region, mask);
 
593
    WRAP (cs, s, paintBackground, cubePaintBackground);
 
594
}
 
595
 
 
596
#ifdef USE_LIBSVG_CAIRO
 
597
static void
 
598
cubeHandleEvent (CompDisplay *d,
 
599
                 XEvent      *event)
 
600
{
 
601
    CompScreen *s;
 
602
 
 
603
    CUBE_DISPLAY (d);
 
604
 
 
605
    switch (event->type) {
 
606
    case KeyPress:
 
607
    case KeyRelease:
 
608
        s = findScreenAtDisplay (d, event->xkey.root);
 
609
        if (s)
 
610
        {
 
611
            CUBE_SCREEN (s);
 
612
 
 
613
            if (EV_KEY (&cs->opt[CUBE_SCREEN_OPTION_NEXT], event))
 
614
            {
 
615
                cubeLoadSvg (s, (cs->svgCurFile + 1) % cs->svgNFile);
 
616
                damageScreen (s);
 
617
            }
 
618
 
 
619
            if (EV_KEY (&cs->opt[CUBE_SCREEN_OPTION_PREV], event))
 
620
            {
 
621
                cubeLoadSvg (s, (cs->svgCurFile - 1 + cs->svgNFile) %
 
622
                             cs->svgNFile);
 
623
                damageScreen (s);
 
624
            }
 
625
        }
 
626
        break;
 
627
    case ButtonPress:
 
628
    case ButtonRelease:
 
629
        s = findScreenAtDisplay (d, event->xbutton.root);
 
630
        if (s)
 
631
        {
 
632
            CUBE_SCREEN (s);
 
633
 
 
634
            if (EV_BUTTON (&cs->opt[CUBE_SCREEN_OPTION_NEXT], event))
 
635
            {
 
636
                cubeLoadSvg (s, (cs->svgCurFile + 1) % cs->svgNFile);
 
637
                damageScreen (s);
 
638
            }
 
639
 
 
640
            if (EV_BUTTON (&cs->opt[CUBE_SCREEN_OPTION_PREV], event))
 
641
            {
 
642
                cubeLoadSvg (s, (cs->svgCurFile - 1 + cs->svgNFile) %
 
643
                             cs->svgNFile);
 
644
                damageScreen (s);
 
645
            }
 
646
        }
 
647
    default:
 
648
        break;
 
649
    }
 
650
 
 
651
    UNWRAP (cd, d, handleEvent);
 
652
    (*d->handleEvent) (d, event);
 
653
    WRAP (cd, d, handleEvent, cubeHandleEvent);
 
654
}
 
655
#endif
 
656
 
 
657
static Bool
 
658
cubeSetGlobalScreenOption (CompScreen      *s,
 
659
                           char            *name,
 
660
                           CompOptionValue *value)
 
661
{
 
662
    Bool status;
 
663
 
 
664
    CUBE_SCREEN (s);
 
665
 
 
666
    UNWRAP (cs, s, setScreenOption);
 
667
    status = (*s->setScreenOption) (s, name, value);
 
668
    WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
 
669
 
 
670
    if (status && strcmp (name, "size") == 0)
 
671
        cubeUpdateGeometry (s, s->size, cs->invert);
 
672
 
 
673
    return status;
 
674
}
 
675
 
 
676
static Bool
 
677
cubeInitDisplay (CompPlugin  *p,
 
678
                 CompDisplay *d)
 
679
{
 
680
    CubeDisplay *cd;
 
681
 
 
682
    cd = malloc (sizeof (CubeDisplay));
 
683
    if (!cd)
 
684
        return FALSE;
 
685
 
 
686
    cd->screenPrivateIndex = allocateScreenPrivateIndex (d);
 
687
    if (cd->screenPrivateIndex < 0)
 
688
    {
 
689
        free (cd);
 
690
        return FALSE;
 
691
    }
 
692
 
 
693
#ifdef USE_LIBSVG_CAIRO
 
694
    WRAP (cd, d, handleEvent, cubeHandleEvent);
 
695
#endif
 
696
 
 
697
    d->privates[displayPrivateIndex].ptr = cd;
 
698
 
 
699
    return TRUE;
 
700
}
 
701
 
 
702
static void
 
703
cubeFiniDisplay (CompPlugin  *p,
 
704
                 CompDisplay *d)
 
705
{
 
706
    CUBE_DISPLAY (d);
 
707
 
 
708
    freeScreenPrivateIndex (d, cd->screenPrivateIndex);
 
709
 
 
710
#ifdef USE_LIBSVG_CAIRO
 
711
    UNWRAP (cd, d, handleEvent);
 
712
#endif
 
713
 
 
714
    free (cd);
 
715
}
 
716
 
 
717
static Bool
 
718
cubeInitScreen (CompPlugin *p,
 
719
                CompScreen *s)
 
720
{
 
721
    CubeScreen *cs;
 
722
 
 
723
    CUBE_DISPLAY (s->display);
 
724
 
 
725
    cs = malloc (sizeof (CubeScreen));
 
726
    if (!cs)
 
727
        return FALSE;
 
728
 
 
729
    cs->invert = 1;
 
730
 
 
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;
 
733
 
 
734
    cs->color[0] = CUBE_COLOR_RED_DEFAULT;
 
735
    cs->color[1] = CUBE_COLOR_GREEN_DEFAULT;
 
736
    cs->color[2] = CUBE_COLOR_BLUE_DEFAULT;
 
737
 
 
738
    cs->nvertices = 0;
 
739
    cs->vertices  = NULL;
 
740
 
 
741
    s->privates[cd->screenPrivateIndex].ptr = cs;
 
742
 
 
743
    cs->paintTopBottom = FALSE;
 
744
 
 
745
    initTexture (s, &cs->texture);
 
746
 
 
747
#ifdef USE_LIBSVG_CAIRO
 
748
    cubeInitSvg (s);
 
749
 
 
750
    cs->svgFiles   = 0;
 
751
    cs->svgNFile   = 0;
 
752
    cs->svgCurFile = 0;
 
753
#endif
 
754
 
 
755
    cubeScreenInitOptions (cs, s->display->display);
 
756
 
 
757
    WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
 
758
    WRAP (cs, s, paintBackground, cubePaintBackground);
 
759
    WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
 
760
 
 
761
    if (!cubeUpdateGeometry (s, s->size, cs->invert))
 
762
        return FALSE;
 
763
 
 
764
    return TRUE;
 
765
}
 
766
 
 
767
static void
 
768
cubeFiniScreen (CompPlugin *p,
 
769
                CompScreen *s)
 
770
{
 
771
    CUBE_SCREEN (s);
 
772
 
 
773
    UNWRAP (cs, s, paintTransformedScreen);
 
774
    UNWRAP (cs, s, paintBackground);
 
775
    UNWRAP (cs, s, setScreenOption);
 
776
 
 
777
    finiTexture (s, &cs->texture);
 
778
 
 
779
#ifdef USE_LIBSVG_CAIRO
 
780
    cubeFiniSvg (s);
 
781
#endif
 
782
 
 
783
    free (cs);
 
784
}
 
785
 
 
786
static Bool
 
787
cubeInit (CompPlugin *p)
 
788
{
 
789
    displayPrivateIndex = allocateDisplayPrivateIndex ();
 
790
    if (displayPrivateIndex < 0)
 
791
        return FALSE;
 
792
 
 
793
    return TRUE;
 
794
}
 
795
 
 
796
static void
 
797
cubeFini (CompPlugin *p)
 
798
{
 
799
    if (displayPrivateIndex >= 0)
 
800
        freeDisplayPrivateIndex (displayPrivateIndex);
 
801
}
 
802
 
 
803
CompPluginDep cubeDeps[] = {
 
804
    { CompPluginRuleBefore, "expose" }
 
805
};
 
806
 
 
807
CompPluginVTable cubeVTable = {
 
808
    "cube",
 
809
    "Desktop Cube",
 
810
    "Place windows on cube",
 
811
    cubeInit,
 
812
    cubeFini,
 
813
    cubeInitDisplay,
 
814
    cubeFiniDisplay,
 
815
    cubeInitScreen,
 
816
    cubeFiniScreen,
 
817
    0, /* InitWindow */
 
818
    0, /* FiniWindow */
 
819
    0, /* GetDisplayOptions */
 
820
    0, /* SetDisplayOption */
 
821
    cubeGetScreenOptions,
 
822
    cubeSetScreenOption,
 
823
    cubeDeps,
 
824
    sizeof (cubeDeps) / sizeof (cubeDeps[0])
 
825
};
 
826
 
 
827
CompPluginVTable *
 
828
getCompPluginInfo (void)
 
829
{
 
830
    return &cubeVTable;
 
831
}