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

« back to all changes in this revision

Viewing changes to plugins/zoom.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
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <math.h>
 
30
#include <sys/time.h>
 
31
 
 
32
#include <compiz.h>
 
33
 
 
34
#define ZOOM_POINTER_INVERT_Y_DEFAULT FALSE
 
35
 
 
36
#define ZOOM_POINTER_SENSITIVITY_DEFAULT   1.0f
 
37
#define ZOOM_POINTER_SENSITIVITY_MIN       0.01f
 
38
#define ZOOM_POINTER_SENSITIVITY_MAX       100.0f
 
39
#define ZOOM_POINTER_SENSITIVITY_PRECISION 0.01f
 
40
 
 
41
#define ZOOM_POINTER_SENSITIVITY_FACTOR 0.0015f
 
42
 
 
43
#define ZOOM_INITIATE_BUTTON_DEFAULT    Button3
 
44
#define ZOOM_INITIATE_MODIFIERS_DEFAULT (CompPressMask | CompSuperMask)
 
45
 
 
46
#define ZOOM_TERMINATE_BUTTON_DEFAULT    Button3
 
47
#define ZOOM_TERMINATE_MODIFIERS_DEFAULT CompReleaseMask
 
48
 
 
49
#define ZOOM_IN_BUTTON_DEFAULT    Button4
 
50
#define ZOOM_IN_MODIFIERS_DEFAULT (CompPressMask | CompSuperMask)
 
51
 
 
52
#define ZOOM_OUT_BUTTON_DEFAULT    Button5
 
53
#define ZOOM_OUT_MODIFIERS_DEFAULT (CompPressMask | CompSuperMask)
 
54
 
 
55
#define ZOOM_SPEED_DEFAULT   1.5f
 
56
#define ZOOM_SPEED_MIN       0.1f
 
57
#define ZOOM_SPEED_MAX       50.0f
 
58
#define ZOOM_SPEED_PRECISION 0.1f
 
59
 
 
60
#define ZOOM_TIMESTEP_DEFAULT   1.2f
 
61
#define ZOOM_TIMESTEP_MIN       0.1f
 
62
#define ZOOM_TIMESTEP_MAX       50.0f
 
63
#define ZOOM_TIMESTEP_PRECISION 0.1f
 
64
 
 
65
static int displayPrivateIndex;
 
66
 
 
67
typedef struct _ZoomDisplay {
 
68
    int             screenPrivateIndex;
 
69
    HandleEventProc handleEvent;
 
70
} ZoomDisplay;
 
71
 
 
72
#define ZOOM_SCREEN_OPTION_POINTER_INVERT_Y    0
 
73
#define ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY 1
 
74
#define ZOOM_SCREEN_OPTION_INITIATE            2
 
75
#define ZOOM_SCREEN_OPTION_TERMINATE           3
 
76
#define ZOOM_SCREEN_OPTION_IN                  4
 
77
#define ZOOM_SCREEN_OPTION_OUT                 5
 
78
#define ZOOM_SCREEN_OPTION_SPEED               6
 
79
#define ZOOM_SCREEN_OPTION_TIMESTEP            7
 
80
#define ZOOM_SCREEN_OPTION_NUM                 8
 
81
 
 
82
typedef struct _ZoomScreen {
 
83
    PreparePaintScreenProc       preparePaintScreen;
 
84
    DonePaintScreenProc          donePaintScreen;
 
85
    PaintScreenProc              paintScreen;
 
86
    SetScreenOptionForPluginProc setScreenOptionForPlugin;
 
87
 
 
88
    CompOption opt[ZOOM_SCREEN_OPTION_NUM];
 
89
 
 
90
    Bool  pointerInvertY;
 
91
    float pointerSensitivity;
 
92
 
 
93
    float speed;
 
94
    float timestep;
 
95
 
 
96
    int grabIndex;
 
97
 
 
98
    GLfloat currentZoom;
 
99
    GLfloat newZoom;
 
100
 
 
101
    GLfloat xVelocity;
 
102
    GLfloat yVelocity;
 
103
    GLfloat zVelocity;
 
104
 
 
105
    GLfloat xTranslate;
 
106
    GLfloat yTranslate;
 
107
 
 
108
    GLfloat xtrans;
 
109
    GLfloat ytrans;
 
110
    GLfloat ztrans;
 
111
 
 
112
    int    prevPointerX;
 
113
    int    prevPointerY;
 
114
    XPoint savedPointer;
 
115
    Bool   grabbed;
 
116
 
 
117
    float maxTranslate;
 
118
} ZoomScreen;
 
119
 
 
120
#define GET_ZOOM_DISPLAY(d)                                   \
 
121
    ((ZoomDisplay *) (d)->privates[displayPrivateIndex].ptr)
 
122
 
 
123
#define ZOOM_DISPLAY(d)                    \
 
124
    ZoomDisplay *zd = GET_ZOOM_DISPLAY (d)
 
125
 
 
126
#define GET_ZOOM_SCREEN(s, zd)                                   \
 
127
    ((ZoomScreen *) (s)->privates[(zd)->screenPrivateIndex].ptr)
 
128
 
 
129
#define ZOOM_SCREEN(s)                                                  \
 
130
    ZoomScreen *zs = GET_ZOOM_SCREEN (s, GET_ZOOM_DISPLAY (s->display))
 
131
 
 
132
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
 
133
 
 
134
static CompOption *
 
135
zoomGetScreenOptions (CompScreen *screen,
 
136
                      int        *count)
 
137
{
 
138
    ZOOM_SCREEN (screen);
 
139
 
 
140
    *count = NUM_OPTIONS (zs);
 
141
    return zs->opt;
 
142
}
 
143
 
 
144
static Bool
 
145
zoomSetScreenOption (CompScreen      *screen,
 
146
                     char            *name,
 
147
                     CompOptionValue *value)
 
148
{
 
149
    CompOption *o;
 
150
    int        index;
 
151
 
 
152
    ZOOM_SCREEN (screen);
 
153
 
 
154
    o = compFindOption (zs->opt, NUM_OPTIONS (zs), name, &index);
 
155
    if (!o)
 
156
        return FALSE;
 
157
 
 
158
    switch (index) {
 
159
    case ZOOM_SCREEN_OPTION_POINTER_INVERT_Y:
 
160
        if (compSetBoolOption (o, value))
 
161
        {
 
162
            zs->pointerInvertY = o->value.b;
 
163
            return TRUE;
 
164
        }
 
165
        break;
 
166
    case ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY:
 
167
        if (compSetFloatOption (o, value))
 
168
        {
 
169
            zs->pointerSensitivity = o->value.f *
 
170
                ZOOM_POINTER_SENSITIVITY_FACTOR;
 
171
            return TRUE;
 
172
        }
 
173
        break;
 
174
    case ZOOM_SCREEN_OPTION_INITIATE:
 
175
    case ZOOM_SCREEN_OPTION_IN:
 
176
        if (addScreenBinding (screen, &value->bind))
 
177
        {
 
178
            removeScreenBinding (screen, &o->value.bind);
 
179
 
 
180
            if (compSetBindingOption (o, value))
 
181
                return TRUE;
 
182
        }
 
183
        break;
 
184
    case ZOOM_SCREEN_OPTION_TERMINATE:
 
185
    case ZOOM_SCREEN_OPTION_OUT:
 
186
        if (compSetBindingOption (o, value))
 
187
            return TRUE;
 
188
        break;
 
189
    case ZOOM_SCREEN_OPTION_SPEED:
 
190
        if (compSetFloatOption (o, value))
 
191
        {
 
192
            zs->speed = o->value.f;
 
193
            return TRUE;
 
194
        }
 
195
        break;
 
196
    case ZOOM_SCREEN_OPTION_TIMESTEP:
 
197
        if (compSetFloatOption (o, value))
 
198
        {
 
199
            zs->timestep = o->value.f;
 
200
            return TRUE;
 
201
        }
 
202
        break;
 
203
    default:
 
204
        break;
 
205
    }
 
206
 
 
207
    return FALSE;
 
208
}
 
209
 
 
210
static void
 
211
zoomScreenInitOptions (ZoomScreen *zs,
 
212
                       Display    *display)
 
213
{
 
214
    CompOption *o;
 
215
 
 
216
    o = &zs->opt[ZOOM_SCREEN_OPTION_POINTER_INVERT_Y];
 
217
    o->name      = "invert_y";
 
218
    o->shortDesc = "Pointer Invert Y";
 
219
    o->longDesc  = "Invert Y axis for pointer movement";
 
220
    o->type      = CompOptionTypeBool;
 
221
    o->value.b   = ZOOM_POINTER_INVERT_Y_DEFAULT;
 
222
 
 
223
    o = &zs->opt[ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY];
 
224
    o->name             = "sensitivity";
 
225
    o->shortDesc        = "Pointer Sensitivity";
 
226
    o->longDesc         = "Sensitivity of pointer movement";
 
227
    o->type             = CompOptionTypeFloat;
 
228
    o->value.f          = ZOOM_POINTER_SENSITIVITY_DEFAULT;
 
229
    o->rest.f.min       = ZOOM_POINTER_SENSITIVITY_MIN;
 
230
    o->rest.f.max       = ZOOM_POINTER_SENSITIVITY_MAX;
 
231
    o->rest.f.precision = ZOOM_POINTER_SENSITIVITY_PRECISION;
 
232
 
 
233
    o = &zs->opt[ZOOM_SCREEN_OPTION_INITIATE];
 
234
    o->name                          = "initiate";
 
235
    o->shortDesc                     = "Initiate";
 
236
    o->longDesc                      = "Zoom In";
 
237
    o->type                          = CompOptionTypeBinding;
 
238
    o->value.bind.type               = CompBindingTypeButton;
 
239
    o->value.bind.u.button.modifiers = ZOOM_INITIATE_MODIFIERS_DEFAULT;
 
240
    o->value.bind.u.button.button    = ZOOM_INITIATE_BUTTON_DEFAULT;
 
241
 
 
242
    o = &zs->opt[ZOOM_SCREEN_OPTION_TERMINATE];
 
243
    o->name                          = "terminate";
 
244
    o->shortDesc                     = "Terminate";
 
245
    o->longDesc                      = "Zoom to Normal View";
 
246
    o->type                          = CompOptionTypeBinding;
 
247
    o->value.bind.type               = CompBindingTypeButton;
 
248
    o->value.bind.u.button.modifiers = ZOOM_TERMINATE_MODIFIERS_DEFAULT;
 
249
    o->value.bind.u.button.button    = ZOOM_TERMINATE_BUTTON_DEFAULT;
 
250
 
 
251
    o = &zs->opt[ZOOM_SCREEN_OPTION_IN];
 
252
    o->name                          = "zoom_in";
 
253
    o->shortDesc                     = "Zoom In";
 
254
    o->longDesc                      = "Zoom In";
 
255
    o->type                          = CompOptionTypeBinding;
 
256
    o->value.bind.type               = CompBindingTypeButton;
 
257
    o->value.bind.u.button.modifiers = ZOOM_IN_MODIFIERS_DEFAULT;
 
258
    o->value.bind.u.button.button    = ZOOM_IN_BUTTON_DEFAULT;
 
259
 
 
260
    o = &zs->opt[ZOOM_SCREEN_OPTION_OUT];
 
261
    o->name                          = "zoom_out";
 
262
    o->shortDesc                     = "Zoom Out";
 
263
    o->longDesc                      = "Zoom Out";
 
264
    o->type                          = CompOptionTypeBinding;
 
265
    o->value.bind.type               = CompBindingTypeButton;
 
266
    o->value.bind.u.button.modifiers = ZOOM_OUT_MODIFIERS_DEFAULT;
 
267
    o->value.bind.u.button.button    = ZOOM_OUT_BUTTON_DEFAULT;
 
268
 
 
269
    o = &zs->opt[ZOOM_SCREEN_OPTION_SPEED];
 
270
    o->name             = "speed";
 
271
    o->shortDesc        = "Speed";
 
272
    o->longDesc         = "Zoom Speed";
 
273
    o->type             = CompOptionTypeFloat;
 
274
    o->value.f          = ZOOM_SPEED_DEFAULT;
 
275
    o->rest.f.min       = ZOOM_SPEED_MIN;
 
276
    o->rest.f.max       = ZOOM_SPEED_MAX;
 
277
    o->rest.f.precision = ZOOM_SPEED_PRECISION;
 
278
 
 
279
    o = &zs->opt[ZOOM_SCREEN_OPTION_TIMESTEP];
 
280
    o->name             = "timestep";
 
281
    o->shortDesc        = "Timestep";
 
282
    o->longDesc         = "Zoom Timestep";
 
283
    o->type             = CompOptionTypeFloat;
 
284
    o->value.f          = ZOOM_TIMESTEP_DEFAULT;
 
285
    o->rest.f.min       = ZOOM_TIMESTEP_MIN;
 
286
    o->rest.f.max       = ZOOM_TIMESTEP_MAX;
 
287
    o->rest.f.precision = ZOOM_TIMESTEP_PRECISION;
 
288
}
 
289
 
 
290
#define MIN_Z 0.001f
 
291
 
 
292
static int
 
293
adjustZoomVelocity (ZoomScreen *zs)
 
294
{
 
295
    float d, adjust, amount;
 
296
 
 
297
    d = (zs->newZoom - zs->currentZoom) * 200.0f;
 
298
 
 
299
    adjust = d * 0.002f;
 
300
    amount = fabs (d);
 
301
    if (amount < 1.0f)
 
302
        amount = 1.0f;
 
303
    else if (amount > 10.0f)
 
304
        amount = 10.0f;
 
305
 
 
306
    zs->zVelocity = (amount * zs->zVelocity + adjust) / (amount + 1.0f);
 
307
 
 
308
    return (fabs (d) < 0.1f && fabs (zs->zVelocity) < 0.005f);
 
309
}
 
310
 
 
311
static void
 
312
zoomPreparePaintScreen (CompScreen *s,
 
313
                        int        msSinceLastPaint)
 
314
{
 
315
    ZOOM_SCREEN (s);
 
316
 
 
317
    if (zs->grabIndex)
 
318
    {
 
319
        int   steps;
 
320
        float amount, chunk;
 
321
 
 
322
        amount = msSinceLastPaint * 0.05f * zs->speed;
 
323
        steps  = amount / (0.5f * zs->timestep);
 
324
        if (!steps) steps = 1;
 
325
        chunk  = amount / (float) steps;
 
326
 
 
327
        while (steps--)
 
328
        {
 
329
            zs->xVelocity /= 1.25f;
 
330
            zs->yVelocity /= 1.25f;
 
331
 
 
332
            if (fabs (zs->xVelocity) < 0.001f)
 
333
                zs->xVelocity = 0.0f;
 
334
            if (fabs (zs->yVelocity) < 0.001f)
 
335
                zs->yVelocity = 0.0f;
 
336
 
 
337
            zs->xTranslate += zs->xVelocity * chunk;
 
338
            if (zs->xTranslate < -zs->maxTranslate)
 
339
            {
 
340
                zs->xTranslate = -zs->maxTranslate;
 
341
                zs->xVelocity  = 0.0f;
 
342
            }
 
343
            else if (zs->xTranslate > zs->maxTranslate)
 
344
            {
 
345
                zs->xTranslate = zs->maxTranslate;
 
346
                zs->xVelocity  = 0.0f;
 
347
            }
 
348
 
 
349
            zs->yTranslate += zs->yVelocity * chunk;
 
350
            if (zs->yTranslate < -zs->maxTranslate)
 
351
            {
 
352
                zs->yTranslate = -zs->maxTranslate;
 
353
                zs->yVelocity  = 0.0f;
 
354
            }
 
355
            else if (zs->yTranslate > zs->maxTranslate)
 
356
            {
 
357
                zs->yTranslate = zs->maxTranslate;
 
358
                zs->yVelocity  = 0.0f;
 
359
            }
 
360
 
 
361
            if (adjustZoomVelocity (zs))
 
362
            {
 
363
                zs->currentZoom = zs->newZoom;
 
364
                zs->zVelocity = 0.0f;
 
365
            }
 
366
            else
 
367
            {
 
368
                zs->currentZoom += (zs->zVelocity * msSinceLastPaint) /
 
369
                    s->redrawTime;
 
370
            }
 
371
 
 
372
            zs->ztrans = DEFAULT_Z_CAMERA * zs->currentZoom;
 
373
            if (zs->ztrans <= 0.0f)
 
374
            {
 
375
                zs->zVelocity = 0.0f;
 
376
                zs->ztrans = 0.0f;
 
377
            }
 
378
 
 
379
            zs->xtrans = -zs->xTranslate * (1.0f - zs->currentZoom);
 
380
            zs->ytrans = zs->yTranslate * (1.0f - zs->currentZoom);
 
381
 
 
382
            if (!zs->grabbed)
 
383
            {
 
384
                if (zs->currentZoom == 1.0f && zs->zVelocity == 0.0f)
 
385
                {
 
386
                    zs->xVelocity = zs->yVelocity = 0.0f;
 
387
 
 
388
                    removeScreenGrab (s, zs->grabIndex, &zs->savedPointer);
 
389
                    zs->grabIndex = FALSE;
 
390
                    break;
 
391
                }
 
392
            }
 
393
        }
 
394
    }
 
395
 
 
396
    UNWRAP (zs, s, preparePaintScreen);
 
397
    (*s->preparePaintScreen) (s, msSinceLastPaint);
 
398
    WRAP (zs, s, preparePaintScreen, zoomPreparePaintScreen);
 
399
}
 
400
 
 
401
static void
 
402
zoomDonePaintScreen (CompScreen *s)
 
403
{
 
404
    ZOOM_SCREEN (s);
 
405
 
 
406
    if (zs->grabIndex)
 
407
    {
 
408
        if (zs->currentZoom != zs->newZoom ||
 
409
            zs->xVelocity || zs->yVelocity || zs->zVelocity)
 
410
            damageScreen (s);
 
411
    }
 
412
 
 
413
    UNWRAP (zs, s, donePaintScreen);
 
414
    (*s->donePaintScreen) (s);
 
415
    WRAP (zs, s, donePaintScreen, zoomDonePaintScreen);
 
416
}
 
417
 
 
418
static Bool
 
419
zoomPaintScreen (CompScreen              *s,
 
420
                 const ScreenPaintAttrib *sAttrib,
 
421
                 Region                  region,
 
422
                 unsigned int            mask)
 
423
{
 
424
    Bool status;
 
425
 
 
426
    ZOOM_SCREEN (s);
 
427
 
 
428
    if (zs->grabIndex)
 
429
    {
 
430
        ScreenPaintAttrib sa = *sAttrib;
 
431
 
 
432
        sa.xTranslate += zs->xtrans;
 
433
        sa.yTranslate += zs->ytrans;
 
434
 
 
435
        sa.zCamera = -zs->ztrans;
 
436
 
 
437
        /* hack to get sides rendered correctly */
 
438
        if (zs->xtrans > 0.0f)
 
439
            sa.xRotate += 0.000001f;
 
440
        else
 
441
            sa.xRotate -= 0.000001f;
 
442
 
 
443
        mask &= ~PAINT_SCREEN_REGION_MASK;
 
444
        mask |= PAINT_SCREEN_TRANSFORMED_MASK;
 
445
 
 
446
        UNWRAP (zs, s, paintScreen);
 
447
        status = (*s->paintScreen) (s, &sa, region, mask);
 
448
        WRAP (zs, s, paintScreen, zoomPaintScreen);
 
449
    }
 
450
    else
 
451
    {
 
452
        UNWRAP (zs, s, paintScreen);
 
453
        status = (*s->paintScreen) (s, sAttrib, region, mask);
 
454
        WRAP (zs, s, paintScreen, zoomPaintScreen);
 
455
    }
 
456
 
 
457
    return status;
 
458
}
 
459
 
 
460
static void
 
461
zoomIn (CompScreen *s,
 
462
        int        x,
 
463
        int        y)
 
464
{
 
465
    ZOOM_SCREEN (s);
 
466
 
 
467
    /* some other plugin has already grabbed the screen */
 
468
    if (s->maxGrab - zs->grabIndex)
 
469
        return;
 
470
 
 
471
    zs->prevPointerX = x;
 
472
    zs->prevPointerY = y;
 
473
 
 
474
    if (!zs->grabIndex)
 
475
    {
 
476
        zs->grabIndex = pushScreenGrab (s, s->invisibleCursor);
 
477
 
 
478
        zs->savedPointer.x = zs->prevPointerX;
 
479
        zs->savedPointer.y = zs->prevPointerY;
 
480
    }
 
481
 
 
482
    if (zs->grabIndex)
 
483
    {
 
484
        zs->grabbed = TRUE;
 
485
 
 
486
        zs->newZoom /= 2.0f;
 
487
 
 
488
        damageScreen (s);
 
489
 
 
490
        if (zs->currentZoom == 1.0f)
 
491
        {
 
492
            zs->xTranslate = (x - s->width / 2) / (float) s->width;
 
493
            zs->yTranslate = (y - s->height / 2) / (float) s->height;
 
494
 
 
495
            zs->xTranslate /= zs->newZoom;
 
496
            zs->yTranslate /= zs->newZoom;
 
497
        }
 
498
    }
 
499
}
 
500
 
 
501
static void
 
502
zoomOut (CompScreen *s)
 
503
{
 
504
    ZOOM_SCREEN (s);
 
505
 
 
506
    if (zs->grabIndex)
 
507
    {
 
508
        zs->newZoom *= 2.0f;
 
509
        if (zs->newZoom > DEFAULT_Z_CAMERA - (DEFAULT_Z_CAMERA / 10.0f))
 
510
        {
 
511
            zs->grabbed = FALSE;
 
512
            zs->newZoom = 1.0f;
 
513
        }
 
514
 
 
515
        damageScreen (s);
 
516
    }
 
517
}
 
518
 
 
519
static void
 
520
zoomTerminate (CompScreen *s)
 
521
{
 
522
    ZOOM_SCREEN (s);
 
523
 
 
524
    if (zs->grabIndex)
 
525
    {
 
526
        zs->newZoom = 1.0f;
 
527
        zs->grabbed = FALSE;
 
528
 
 
529
        damageScreen (s);
 
530
    }
 
531
}
 
532
 
 
533
static void
 
534
zoomHandleEvent (CompDisplay *d,
 
535
                 XEvent      *event)
 
536
{
 
537
    CompScreen *s;
 
538
 
 
539
    ZOOM_DISPLAY (d);
 
540
 
 
541
    switch (event->type) {
 
542
    case KeyPress:
 
543
    case KeyRelease:
 
544
        s = findScreenAtDisplay (d, event->xkey.root);
 
545
        if (s)
 
546
        {
 
547
            ZOOM_SCREEN (s);
 
548
 
 
549
            if (EV_KEY (&zs->opt[ZOOM_SCREEN_OPTION_INITIATE], event) ||
 
550
                EV_KEY (&zs->opt[ZOOM_SCREEN_OPTION_IN], event))
 
551
                zoomIn (s,
 
552
                        event->xkey.x_root,
 
553
                        event->xkey.y_root);
 
554
 
 
555
            if (EV_KEY (&zs->opt[ZOOM_SCREEN_OPTION_OUT], event))
 
556
                zoomOut (s);
 
557
 
 
558
            if (EV_KEY (&zs->opt[ZOOM_SCREEN_OPTION_TERMINATE], event) ||
 
559
                (event->type         == KeyPress &&
 
560
                 event->xkey.keycode == s->escapeKeyCode))
 
561
                zoomTerminate (s);
 
562
        }
 
563
        break;
 
564
    case ButtonPress:
 
565
    case ButtonRelease:
 
566
        s = findScreenAtDisplay (d, event->xbutton.root);
 
567
        if (s)
 
568
        {
 
569
            ZOOM_SCREEN (s);
 
570
 
 
571
            if (EV_BUTTON (&zs->opt[ZOOM_SCREEN_OPTION_INITIATE], event) ||
 
572
                EV_BUTTON (&zs->opt[ZOOM_SCREEN_OPTION_IN], event))
 
573
                zoomIn (s,
 
574
                        event->xbutton.x_root,
 
575
                        event->xbutton.y_root);
 
576
 
 
577
            if (EV_BUTTON (&zs->opt[ZOOM_SCREEN_OPTION_OUT], event))
 
578
                zoomOut (s);
 
579
 
 
580
            if (EV_BUTTON (&zs->opt[ZOOM_SCREEN_OPTION_TERMINATE], event))
 
581
                zoomTerminate (s);
 
582
        }
 
583
        break;
 
584
    case MotionNotify:
 
585
        s = findScreenAtDisplay (d, event->xmotion.root);
 
586
        if (s)
 
587
        {
 
588
            ZOOM_SCREEN (s);
 
589
 
 
590
            if (zs->grabIndex && zs->grabbed)
 
591
            {
 
592
                GLfloat pointerDx;
 
593
                GLfloat pointerDy;
 
594
 
 
595
                pointerDx = event->xmotion.x_root - zs->prevPointerX;
 
596
                pointerDy = event->xmotion.y_root - zs->prevPointerY;
 
597
                zs->prevPointerX = event->xmotion.x_root;
 
598
                zs->prevPointerY = event->xmotion.y_root;
 
599
 
 
600
                if (event->xmotion.x_root < 50             ||
 
601
                    event->xmotion.y_root < 50             ||
 
602
                    event->xmotion.x_root > s->width  - 50 ||
 
603
                    event->xmotion.y_root > s->height - 50)
 
604
                {
 
605
                    zs->prevPointerX = s->width / 2;
 
606
                    zs->prevPointerY = s->height / 2;
 
607
 
 
608
                    XWarpPointer (d->display, None, s->root, 0, 0, 0, 0,
 
609
                                  zs->prevPointerX, zs->prevPointerY);
 
610
                }
 
611
 
 
612
                if (zs->pointerInvertY)
 
613
                    pointerDy = -pointerDy;
 
614
 
 
615
                zs->xVelocity += pointerDx * zs->pointerSensitivity;
 
616
                zs->yVelocity += pointerDy * zs->pointerSensitivity;
 
617
 
 
618
                damageScreen (s);
 
619
            }
 
620
        }
 
621
    default:
 
622
        break;
 
623
    }
 
624
 
 
625
    UNWRAP (zd, d, handleEvent);
 
626
    (*d->handleEvent) (d, event);
 
627
    WRAP (zd, d, handleEvent, zoomHandleEvent);
 
628
}
 
629
 
 
630
static void
 
631
zoomUpdateCubeOptions (CompScreen *s)
 
632
{
 
633
    CompPlugin *p;
 
634
 
 
635
    ZOOM_SCREEN (s);
 
636
 
 
637
    p = findActivePlugin ("cube");
 
638
    if (p && p->vTable->getScreenOptions)
 
639
    {
 
640
        CompOption *options, *option;
 
641
        int        nOptions;
 
642
 
 
643
        options = (*p->vTable->getScreenOptions) (s, &nOptions);
 
644
        option = compFindOption (options, nOptions, "in", 0);
 
645
        if (option)
 
646
            zs->maxTranslate = option->value.b ? 0.85f : 1.5f;
 
647
    }
 
648
}
 
649
 
 
650
static Bool
 
651
zoomSetScreenOptionForPlugin (CompScreen      *s,
 
652
                              char            *plugin,
 
653
                              char            *name,
 
654
                              CompOptionValue *value)
 
655
{
 
656
    Bool status;
 
657
 
 
658
    ZOOM_SCREEN (s);
 
659
 
 
660
    UNWRAP (zs, s, setScreenOptionForPlugin);
 
661
    status = (*s->setScreenOptionForPlugin) (s, plugin, name, value);
 
662
    WRAP (zs, s, setScreenOptionForPlugin, zoomSetScreenOptionForPlugin);
 
663
 
 
664
    if (status && strcmp (plugin, "cube") == 0)
 
665
        zoomUpdateCubeOptions (s);
 
666
 
 
667
    return status;
 
668
}
 
669
 
 
670
static Bool
 
671
zoomInitDisplay (CompPlugin  *p,
 
672
                 CompDisplay *d)
 
673
{
 
674
    ZoomDisplay *zd;
 
675
 
 
676
    zd = malloc (sizeof (ZoomDisplay));
 
677
    if (!zd)
 
678
        return FALSE;
 
679
 
 
680
    zd->screenPrivateIndex = allocateScreenPrivateIndex (d);
 
681
    if (zd->screenPrivateIndex < 0)
 
682
    {
 
683
        free (zd);
 
684
        return FALSE;
 
685
    }
 
686
 
 
687
    WRAP (zd, d, handleEvent, zoomHandleEvent);
 
688
 
 
689
    d->privates[displayPrivateIndex].ptr = zd;
 
690
 
 
691
    return TRUE;
 
692
}
 
693
 
 
694
static void
 
695
zoomFiniDisplay (CompPlugin  *p,
 
696
                 CompDisplay *d)
 
697
{
 
698
    ZOOM_DISPLAY (d);
 
699
 
 
700
    freeScreenPrivateIndex (d, zd->screenPrivateIndex);
 
701
 
 
702
    UNWRAP (zd, d, handleEvent);
 
703
 
 
704
    free (zd);
 
705
}
 
706
 
 
707
static Bool
 
708
zoomInitScreen (CompPlugin *p,
 
709
                CompScreen *s)
 
710
{
 
711
    ZoomScreen *zs;
 
712
 
 
713
    ZOOM_DISPLAY (s->display);
 
714
 
 
715
    zs = malloc (sizeof (ZoomScreen));
 
716
    if (!zs)
 
717
        return FALSE;
 
718
 
 
719
    zs->grabIndex = 0;
 
720
 
 
721
    zs->currentZoom = 1.0f;
 
722
    zs->newZoom = 1.0f;
 
723
 
 
724
    zs->xVelocity = 0.0f;
 
725
    zs->yVelocity = 0.0f;
 
726
    zs->zVelocity = 0.0f;
 
727
 
 
728
    zs->xTranslate = 0.0f;
 
729
    zs->yTranslate = 0.0f;
 
730
 
 
731
    zs->maxTranslate = 0.0f;
 
732
 
 
733
    zs->savedPointer.x = 0;
 
734
    zs->savedPointer.y = 0;
 
735
    zs->prevPointerX = 0;
 
736
    zs->prevPointerY = 0;
 
737
 
 
738
    zs->grabbed = FALSE;
 
739
 
 
740
    zs->pointerInvertY     = ZOOM_POINTER_INVERT_Y_DEFAULT;
 
741
    zs->pointerSensitivity = ZOOM_POINTER_SENSITIVITY_DEFAULT *
 
742
        ZOOM_POINTER_SENSITIVITY_FACTOR;
 
743
 
 
744
    zs->speed    = ZOOM_SPEED_DEFAULT;
 
745
    zs->timestep = ZOOM_TIMESTEP_DEFAULT;
 
746
 
 
747
    zoomScreenInitOptions (zs, s->display->display);
 
748
 
 
749
    addScreenBinding (s, &zs->opt[ZOOM_SCREEN_OPTION_INITIATE].value.bind);
 
750
    addScreenBinding (s, &zs->opt[ZOOM_SCREEN_OPTION_IN].value.bind);
 
751
 
 
752
    WRAP (zs, s, preparePaintScreen, zoomPreparePaintScreen);
 
753
    WRAP (zs, s, donePaintScreen, zoomDonePaintScreen);
 
754
    WRAP (zs, s, paintScreen, zoomPaintScreen);
 
755
    WRAP (zs, s, setScreenOptionForPlugin, zoomSetScreenOptionForPlugin);
 
756
 
 
757
    s->privates[zd->screenPrivateIndex].ptr = zs;
 
758
 
 
759
    zoomUpdateCubeOptions (s);
 
760
 
 
761
    return TRUE;
 
762
}
 
763
 
 
764
static void
 
765
zoomFiniScreen (CompPlugin *p,
 
766
                CompScreen *s)
 
767
{
 
768
    ZOOM_SCREEN (s);
 
769
 
 
770
    UNWRAP (zs, s, preparePaintScreen);
 
771
    UNWRAP (zs, s, donePaintScreen);
 
772
    UNWRAP (zs, s, paintScreen);
 
773
    UNWRAP (zs, s, setScreenOptionForPlugin);
 
774
 
 
775
    free (zs);
 
776
}
 
777
 
 
778
static Bool
 
779
zoomInit (CompPlugin *p)
 
780
{
 
781
    displayPrivateIndex = allocateDisplayPrivateIndex ();
 
782
    if (displayPrivateIndex < 0)
 
783
        return FALSE;
 
784
 
 
785
    return TRUE;
 
786
}
 
787
 
 
788
static void
 
789
zoomFini (CompPlugin *p)
 
790
{
 
791
    if (displayPrivateIndex >= 0)
 
792
        freeDisplayPrivateIndex (displayPrivateIndex);
 
793
}
 
794
 
 
795
CompPluginDep zoomDeps[] = {
 
796
    { CompPluginRuleAfter, "cube" }
 
797
};
 
798
 
 
799
CompPluginVTable zoomVTable = {
 
800
    "zoom",
 
801
    "Zoom Desktop",
 
802
    "Zoom and pan desktop cube",
 
803
    zoomInit,
 
804
    zoomFini,
 
805
    zoomInitDisplay,
 
806
    zoomFiniDisplay,
 
807
    zoomInitScreen,
 
808
    zoomFiniScreen,
 
809
    0, /* InitWindow */
 
810
    0, /* FiniWindow */
 
811
    0, /* GetDisplayOptions */
 
812
    0, /* SetDisplayOption */
 
813
    zoomGetScreenOptions,
 
814
    zoomSetScreenOption,
 
815
    zoomDeps,
 
816
    sizeof (zoomDeps) / sizeof (zoomDeps[0])
 
817
};
 
818
 
 
819
CompPluginVTable *
 
820
getCompPluginInfo (void)
 
821
{
 
822
    return &zoomVTable;
 
823
}