~mc-return/compiz/compiz.merge-src-screen.cpp-improvements

« back to all changes in this revision

Viewing changes to plugins/zoom.cpp

  • Committer: Dennis kasprzyk
  • Author(s): Dennis Kasprzyk
  • Date: 2009-03-15 05:09:18 UTC
  • Revision ID: git-v1:163f6b6f3c3b7764987cbdf8e03cc355edeaa499
New generalized build system.

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 "zoom.h"
27
 
 
28
 
COMPIZ_PLUGIN_20081216 (zoom, ZoomPluginVTable)
29
 
 
30
 
static int
31
 
adjustZoomVelocity (ZoomScreen *zs)
32
 
{
33
 
    float d, adjust, amount;
34
 
 
35
 
    d = (1.0f - zs->scale) * 10.0f;
36
 
 
37
 
    adjust = d * 0.002f;
38
 
    amount = fabs (d);
39
 
    if (amount < 1.0f)
40
 
        amount = 1.0f;
41
 
    else if (amount > 5.0f)
42
 
        amount = 5.0f;
43
 
 
44
 
    zs->velocity = (amount * zs->velocity + adjust) / (amount + 1.0f);
45
 
 
46
 
    return (fabs (d) < 0.02f && fabs (zs->velocity) < 0.005f);
47
 
}
48
 
 
49
 
void
50
 
ZoomScreen::zoomInEvent ()
51
 
{
52
 
    CompOption::Vector o (0);
53
 
 
54
 
    o.push_back (CompOption ("root", CompOption::TypeInt));
55
 
    o.push_back (CompOption ("output", CompOption::TypeInt));
56
 
    o.push_back (CompOption ("x1", CompOption::TypeInt));
57
 
    o.push_back (CompOption ("y1", CompOption::TypeInt));
58
 
    o.push_back (CompOption ("x2", CompOption::TypeInt));
59
 
    o.push_back (CompOption ("y2", CompOption::TypeInt));
60
 
 
61
 
    o[0].value ().set ((int) screen->root ());
62
 
    o[1].value ().set ((int) zoomOutput);
63
 
    o[2].value ().set ((int) current[zoomOutput].x1);
64
 
    o[3].value ().set ((int) current[zoomOutput].y1);
65
 
    o[4].value ().set ((int) current[zoomOutput].x2);
66
 
    o[5].value ().set ((int) current[zoomOutput].y2);
67
 
 
68
 
    screen->handleCompizEvent ("zoom", "in", o);
69
 
}
70
 
 
71
 
void
72
 
ZoomScreen::zoomOutEvent ()
73
 
{
74
 
    CompOption::Vector o (0);
75
 
 
76
 
    o.push_back (CompOption ("root", CompOption::TypeInt));
77
 
    o.push_back (CompOption ("output", CompOption::TypeInt));
78
 
 
79
 
    o[0].value ().set ((int) screen->root ());
80
 
    o[1].value ().set ((int) zoomOutput);
81
 
 
82
 
    screen->handleCompizEvent ("zoom", "out", o);
83
 
}
84
 
 
85
 
void
86
 
ZoomScreen::preparePaint (int ms)
87
 
{
88
 
    if (adjust)
89
 
    {
90
 
        int   steps;
91
 
        float amount;
92
 
 
93
 
        amount = ms * 0.35f * opt[ZOOM_OPTION_SPEED].value ().f ();
94
 
        steps  = amount / (0.5f * opt[ZOOM_OPTION_TIMESTEP].value ().f ());
95
 
        if (!steps) steps = 1;
96
 
 
97
 
        while (steps--)
98
 
        {
99
 
            if (adjustZoomVelocity (this))
100
 
            {
101
 
                BoxPtr pBox =
102
 
                    &screen->outputDevs ()[zoomOutput].region ()->extents;
103
 
 
104
 
                scale = 1.0f;
105
 
                velocity = 0.0f;
106
 
                adjust = false;
107
 
 
108
 
                if (current[zoomOutput].x1 == pBox->x1 &&
109
 
                    current[zoomOutput].y1 == pBox->y1 &&
110
 
                    current[zoomOutput].x2 == pBox->x2 &&
111
 
                    current[zoomOutput].y2 == pBox->y2)
112
 
                {
113
 
                    zoomed &= ~(1 << zoomOutput);
114
 
                    zoomOutEvent ();
115
 
                }
116
 
                else
117
 
                {
118
 
                    zoomInEvent ();
119
 
                }
120
 
 
121
 
                break;
122
 
            }
123
 
            else
124
 
            {
125
 
                scale += (velocity * ms) / (float) cScreen->redrawTime ();
126
 
            }
127
 
        }
128
 
    }
129
 
 
130
 
    cScreen->preparePaint (ms);
131
 
}
132
 
 
133
 
void
134
 
ZoomScreen::donePaint ()
135
 
{
136
 
    if (adjust)
137
 
        cScreen->damageScreen ();
138
 
 
139
 
    if (!adjust && zoomed == 0)
140
 
    {
141
 
        cScreen->preparePaintSetEnabled (this, false);
142
 
        cScreen->donePaintSetEnabled (this, false);
143
 
        gScreen->glPaintOutputSetEnabled (this, false);
144
 
    }
145
 
 
146
 
    cScreen->donePaint ();
147
 
}
148
 
 
149
 
bool
150
 
ZoomScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
151
 
                           const GLMatrix &transform,
152
 
                           const CompRegion &region,
153
 
                           CompOutput *output,
154
 
                           unsigned int mask)
155
 
{
156
 
    GLMatrix zTransform (transform);
157
 
    bool     status;
158
 
 
159
 
    if (output->id () != ~0 && (zoomed & (1 << output->id ())))
160
 
    {
161
 
        GLTexture::Filter saveFilter;
162
 
        ZoomBox           box;
163
 
        float             scale, x, y, x1, y1;
164
 
        float             oWidth = output->width ();
165
 
        float             oHeight = output->height ();
166
 
 
167
 
        mask &= ~PAINT_SCREEN_REGION_MASK;
168
 
 
169
 
        getCurrentZoom (output->id (), &box);
170
 
 
171
 
        x1 = box.x1 - output->x1 ();
172
 
        y1 = box.y1 - output->y1 ();
173
 
 
174
 
        scale = oWidth / (box.x2 - box.x1);
175
 
 
176
 
        x = ((oWidth  / 2.0f) - x1) / oWidth;
177
 
        y = ((oHeight / 2.0f) - y1) / oHeight;
178
 
 
179
 
        x = 0.5f - x * scale;
180
 
        y = 0.5f - y * scale;
181
 
 
182
 
        zTransform.translate (-x, y, 0.0f);
183
 
        zTransform.scale (scale, scale, 1.0f);
184
 
 
185
 
        mask |= PAINT_SCREEN_TRANSFORMED_MASK;
186
 
 
187
 
        saveFilter = gScreen->filter (SCREEN_TRANS_FILTER);
188
 
 
189
 
        if ((zoomOutput != output->id () || !adjust) && scale > 3.9f &&
190
 
            !opt[ZOOM_OPTION_FILTER_LINEAR].value ().b ())
191
 
            gScreen->setFilter (SCREEN_TRANS_FILTER, GLTexture::Fast);
192
 
 
193
 
        status = gScreen->glPaintOutput (sAttrib, zTransform, region, output,
194
 
                                         mask);
195
 
 
196
 
        gScreen->setFilter (SCREEN_TRANS_FILTER, saveFilter);
197
 
    }
198
 
    else
199
 
    {
200
 
        status = gScreen->glPaintOutput (sAttrib, transform, region, output,
201
 
                                         mask);
202
 
    }
203
 
 
204
 
    if (status && grab)
205
 
    {
206
 
        int x1, x2, y1, y2;
207
 
 
208
 
        x1 = MIN (this->x1, this->x2);
209
 
        y1 = MIN (this->y1, this->y2);
210
 
        x2 = MAX (this->x1, this->x2);
211
 
        y2 = MAX (this->y1, this->y2);
212
 
 
213
 
        if (grabIndex)
214
 
        {
215
 
            zTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
216
 
 
217
 
            glPushMatrix ();
218
 
            glLoadMatrixf (zTransform.getMatrix ());
219
 
            glDisableClientState (GL_TEXTURE_COORD_ARRAY);
220
 
            glEnable (GL_BLEND);
221
 
            glColor4us (0x2fff, 0x2fff, 0x4fff, 0x4fff);
222
 
            glRecti (x1, y2, x2, y1);
223
 
            glColor4us (0x2fff, 0x2fff, 0x4fff, 0x9fff);
224
 
            glBegin (GL_LINE_LOOP);
225
 
            glVertex2i (x1, y1);
226
 
            glVertex2i (x2, y1);
227
 
            glVertex2i (x2, y2);
228
 
            glVertex2i (x1, y2);
229
 
            glEnd ();
230
 
            glColor4usv (defaultColor);
231
 
            glDisable (GL_BLEND);
232
 
            glEnableClientState (GL_TEXTURE_COORD_ARRAY);
233
 
            glPopMatrix ();
234
 
        }
235
 
    }
236
 
 
237
 
    return status;
238
 
}
239
 
 
240
 
 
241
 
void
242
 
ZoomScreen::initiateForSelection (int output)
243
 
{
244
 
    int tmp;
245
 
 
246
 
    if (x1 > x2)
247
 
    {
248
 
        tmp = x1;
249
 
        x1 = x2;
250
 
        x2 = tmp;
251
 
    }
252
 
 
253
 
    if (y1 > y2)
254
 
    {
255
 
        tmp = y1;
256
 
        y1 = y2;
257
 
        y2 = tmp;
258
 
    }
259
 
 
260
 
    if (x1 < x2 && y1 < y2)
261
 
    {
262
 
        float  oWidth, oHeight;
263
 
        float  xScale, yScale, scale;
264
 
        BoxRec box;
265
 
        int    cx, cy;
266
 
        int    width, height;
267
 
 
268
 
        oWidth  = screen->outputDevs ()[output].width ();
269
 
        oHeight = screen->outputDevs ()[output].height ();
270
 
 
271
 
        cx = (int) ((x1 + x2) / 2.0f + 0.5f);
272
 
        cy = (int) ((y1 + y2) / 2.0f + 0.5f);
273
 
 
274
 
        width  = x2 - x1;
275
 
        height = y2 - y1;
276
 
 
277
 
        xScale = oWidth  / width;
278
 
        yScale = oHeight / height;
279
 
 
280
 
        scale = MAX (MIN (xScale, yScale), 1.0f);
281
 
 
282
 
        box.x1 = cx - (oWidth  / scale) / 2.0f;
283
 
        box.y1 = cy - (oHeight / scale) / 2.0f;
284
 
        box.x2 = cx + (oWidth  / scale) / 2.0f;
285
 
        box.y2 = cy + (oHeight / scale) / 2.0f;
286
 
 
287
 
        if (box.x1 < screen->outputDevs ()[output].x1 ())
288
 
        {
289
 
            box.x2 += screen->outputDevs ()[output].x1 () - box.x1;
290
 
            box.x1 = screen->outputDevs ()[output].x1 ();
291
 
        }
292
 
        else if (box.x2 > screen->outputDevs ()[output].x2 ())
293
 
        {
294
 
            box.x1 -= box.x2 - screen->outputDevs ()[output].x2 ();
295
 
            box.x2 = screen->outputDevs ()[output].x2 ();
296
 
        }
297
 
 
298
 
        if (box.y1 < screen->outputDevs ()[output].y1 ())
299
 
        {
300
 
            box.y2 += screen->outputDevs ()[output].y1 () - box.y1;
301
 
            box.y1 = screen->outputDevs ()[output].y1 ();
302
 
        }
303
 
        else if (box.y2 > screen->outputDevs ()[output].y2 ())
304
 
        {
305
 
            box.y1 -= box.y2 - screen->outputDevs ()[output].y2 ();
306
 
            box.y2 = screen->outputDevs ()[output].y2 ();
307
 
        }
308
 
 
309
 
        if (zoomed & (1 << output))
310
 
        {
311
 
            getCurrentZoom (output, &last[output]);
312
 
        }
313
 
        else
314
 
        {
315
 
            last[output].x1 = screen->outputDevs ()[output].x1 ();
316
 
            last[output].y1 = screen->outputDevs ()[output].y1 ();
317
 
            last[output].x2 = screen->outputDevs ()[output].x2 ();
318
 
            last[output].y2 = screen->outputDevs ()[output].y2 ();
319
 
        }
320
 
 
321
 
        current[output].x1 = box.x1;
322
 
        current[output].y1 = box.y1;
323
 
        current[output].x2 = box.x2;
324
 
        current[output].y2 = box.y2;
325
 
 
326
 
        this->scale = 0.0f;
327
 
        adjust = true;
328
 
        cScreen->preparePaintSetEnabled (this, true);
329
 
        cScreen->donePaintSetEnabled (this, true);
330
 
        gScreen->glPaintOutputSetEnabled (this, true);
331
 
        zoomOutput = output;
332
 
        zoomed |= (1 << output);
333
 
 
334
 
        cScreen->damageScreen ();
335
 
    }
336
 
}
337
 
 
338
 
static bool
339
 
zoomIn (CompAction         *action,
340
 
        CompAction::State  state,
341
 
        CompOption::Vector &options)
342
 
{
343
 
    float   w, h, x0, y0;
344
 
    int     output;
345
 
    ZoomBox box;
346
 
 
347
 
    ZOOM_SCREEN (screen);
348
 
 
349
 
    output = screen->outputDeviceForPoint (pointerX, pointerY);
350
 
 
351
 
    if (!zs->grabIndex)
352
 
    {
353
 
        zs->grabIndex = screen->pushGrab (None, "zoom");
354
 
        screen->handleEventSetEnabled (zs, true);
355
 
    }
356
 
 
357
 
    if (zs->zoomed & (1 << output))
358
 
    {
359
 
        zs->getCurrentZoom (output, &box);
360
 
    }
361
 
    else
362
 
    {
363
 
        box.x1 = screen->outputDevs ()[output].x1 ();
364
 
        box.y1 = screen->outputDevs ()[output].y1 ();
365
 
        box.x2 = screen->outputDevs ()[output].x2 ();
366
 
        box.y2 = screen->outputDevs ()[output].y2 ();
367
 
    }
368
 
 
369
 
    w = (box.x2 - box.x1) /
370
 
        zs->opt[ZOOM_OPTION_ZOOM_FACTOR].value ().f ();
371
 
    h = (box.y2 - box.y1) /
372
 
        zs->opt[ZOOM_OPTION_ZOOM_FACTOR].value ().f ();
373
 
 
374
 
    x0 = (pointerX - screen->outputDevs ()[output].x1 ()) / (float)
375
 
        screen->outputDevs ()[output].width ();
376
 
    y0 = (pointerY - screen->outputDevs ()[output].y1 ()) / (float)
377
 
        screen->outputDevs ()[output].height ();
378
 
 
379
 
    zs->x1 = box.x1 + (x0 * (box.x2 - box.x1) - x0 * w + 0.5f);
380
 
    zs->y1 = box.y1 + (y0 * (box.y2 - box.y1) - y0 * h + 0.5f);
381
 
    zs->x2 = zs->x1 + w;
382
 
    zs->y2 = zs->y1 + h;
383
 
 
384
 
    zs->initiateForSelection (output);
385
 
 
386
 
    return TRUE;
387
 
}
388
 
 
389
 
static bool
390
 
zoomInitiate (CompAction         *action,
391
 
              CompAction::State  state,
392
 
              CompOption::Vector &options)
393
 
{
394
 
    int   output, x1, y1;
395
 
    float scale;
396
 
 
397
 
    ZOOM_SCREEN (screen);
398
 
 
399
 
    if (screen->otherGrabExist ("zoom", 0))
400
 
        return false;
401
 
 
402
 
    if (!zs->grabIndex)
403
 
    {
404
 
        zs->grabIndex = screen->pushGrab (None, "zoom");
405
 
        screen->handleEventSetEnabled (zs, true);
406
 
    }
407
 
 
408
 
    if (state & CompAction::StateInitButton)
409
 
        action->setState (action->state () | CompAction::StateTermButton);
410
 
 
411
 
    /* start selection zoom rectangle */
412
 
 
413
 
    output = screen->outputDeviceForPoint (pointerX, pointerY);
414
 
 
415
 
    if (zs->zoomed & (1 << output))
416
 
    {
417
 
        ZoomBox box;
418
 
        float   oWidth;
419
 
 
420
 
        zs->getCurrentZoom (output, &box);
421
 
 
422
 
        oWidth = screen->outputDevs ()[output].width ();
423
 
        scale = oWidth / (box.x2 - box.x1);
424
 
 
425
 
        x1 = box.x1;
426
 
        y1 = box.y1;
427
 
    }
428
 
    else
429
 
    {
430
 
        scale = 1.0f;
431
 
        x1 = screen->outputDevs ()[output].x1 ();
432
 
        y1 = screen->outputDevs ()[output].y1 ();
433
 
    }
434
 
 
435
 
    zs->x1 = zs->x2 = x1 +
436
 
        ((pointerX - screen->outputDevs ()[output].x1 ()) /
437
 
            scale + 0.5f);
438
 
    zs->y1 = zs->y2 = y1 +
439
 
        ((pointerY - screen->outputDevs ()[output].y1 ()) /
440
 
            scale + 0.5f);
441
 
 
442
 
    zs->zoomOutput = output;
443
 
 
444
 
    zs->grab = true;
445
 
    zs->gScreen->glPaintOutputSetEnabled (zs, true);
446
 
 
447
 
    zs->cScreen->damageScreen ();
448
 
 
449
 
    return true;
450
 
}
451
 
 
452
 
static bool
453
 
zoomOut (CompAction         *action,
454
 
         CompAction::State  state,
455
 
         CompOption::Vector &options)
456
 
{
457
 
    int output;
458
 
 
459
 
    ZOOM_SCREEN (screen);
460
 
 
461
 
    output = screen->outputDeviceForPoint (pointerX, pointerY);
462
 
 
463
 
    zs->getCurrentZoom (output, &zs->last[output]);
464
 
 
465
 
    zs->current[output].x1 = screen->outputDevs ()[output].x1 ();
466
 
    zs->current[output].y1 = screen->outputDevs ()[output].y1 ();
467
 
    zs->current[output].x2 = screen->outputDevs ()[output].x2 ();
468
 
    zs->current[output].y2 = screen->outputDevs ()[output].y2 ();
469
 
 
470
 
    zs->zoomOutput = output;
471
 
    zs->scale = 0.0f;
472
 
    zs->adjust = true;
473
 
    zs->grab = false;
474
 
 
475
 
    if (zs->grabIndex)
476
 
    {
477
 
        screen->removeGrab (zs->grabIndex, NULL);
478
 
        zs->grabIndex = 0;
479
 
        screen->handleEventSetEnabled (zs, false);
480
 
    }
481
 
 
482
 
    zs->cScreen->damageScreen ();
483
 
 
484
 
    return true;
485
 
}
486
 
 
487
 
static bool
488
 
zoomTerminate (CompAction         *action,
489
 
               CompAction::State  state,
490
 
               CompOption::Vector &options)
491
 
{
492
 
    ZOOM_SCREEN (screen);
493
 
 
494
 
    if (zs->grab)
495
 
    {
496
 
        int output;
497
 
 
498
 
        output = screen->outputDeviceForPoint (zs->x1, zs->y1);
499
 
 
500
 
        if (zs->x2 > screen->outputDevs ()[output].x2 ())
501
 
            zs->x2 = screen->outputDevs ()[output].x2 ();
502
 
 
503
 
        if (zs->y2 > screen->outputDevs ()[output].y2 ())
504
 
            zs->y2 = screen->outputDevs ()[output].y2 ();
505
 
 
506
 
        zs->initiateForSelection (output);
507
 
 
508
 
        zs->grab = false;
509
 
    }
510
 
    else
511
 
    {
512
 
        zoomOut (action, state, noOptions);
513
 
    }
514
 
    action->setState (action->state () & ~(CompAction::StateTermKey |
515
 
                                           CompAction::StateTermButton));
516
 
}
517
 
 
518
 
static bool
519
 
zoomInitiatePan (CompAction         *action,
520
 
                 CompAction::State  state,
521
 
                 CompOption::Vector &options)
522
 
{
523
 
    int output;
524
 
 
525
 
    ZOOM_SCREEN (screen);
526
 
 
527
 
    output = screen->outputDeviceForPoint (pointerX, pointerY);
528
 
 
529
 
    if (!(zs->zoomed & (1 << output)))
530
 
        return false;
531
 
 
532
 
    if (screen->otherGrabExist ("zoom", 0))
533
 
        return false;
534
 
 
535
 
    if (state & CompAction::StateInitButton)
536
 
        action->setState (action->state () | CompAction::StateTermButton);
537
 
 
538
 
    if (!zs->panGrabIndex)
539
 
        zs->panGrabIndex = screen->pushGrab (zs->panCursor, "zoom-pan");
540
 
 
541
 
    zs->zoomOutput = output;
542
 
 
543
 
    return true;
544
 
}
545
 
 
546
 
static bool
547
 
zoomTerminatePan (CompAction         *action,
548
 
                  CompAction::State  state,
549
 
                  CompOption::Vector &options)
550
 
{
551
 
    ZOOM_SCREEN (screen);
552
 
 
553
 
    if (zs->panGrabIndex)
554
 
    {
555
 
        screen->removeGrab (zs->panGrabIndex, NULL);
556
 
        zs->panGrabIndex = 0;
557
 
 
558
 
        zs->zoomInEvent ();
559
 
    }
560
 
 
561
 
    return true;
562
 
}
563
 
 
564
 
void
565
 
ZoomScreen::getCurrentZoom (int output, ZoomBox *pBox)
566
 
{
567
 
    if (output == zoomOutput)
568
 
    {
569
 
        float inverse;
570
 
 
571
 
        inverse = 1.0f - scale;
572
 
 
573
 
        pBox->x1 = scale * current[output].x1 +
574
 
            inverse * last[output].x1;
575
 
        pBox->y1 = scale * current[output].y1 +
576
 
            inverse * last[output].y1;
577
 
        pBox->x2 = scale * current[output].x2 +
578
 
            inverse * last[output].x2;
579
 
        pBox->y2 = scale * current[output].y2 +
580
 
            inverse * last[output].y2;
581
 
    }
582
 
    else
583
 
    {
584
 
        pBox->x1 = current[output].x1;
585
 
        pBox->y1 = current[output].y1;
586
 
        pBox->x2 = current[output].x2;
587
 
        pBox->y2 = current[output].y2;
588
 
    }
589
 
}
590
 
 
591
 
void
592
 
ZoomScreen::handleMotionEvent (int xRoot, int yRoot)
593
 
{
594
 
    if (grabIndex)
595
 
    {
596
 
        int     output = zoomOutput;
597
 
        ZoomBox box;
598
 
        float   scale, oWidth = screen->outputDevs ()[output].width ();
599
 
 
600
 
        getCurrentZoom (output, &box);
601
 
 
602
 
        if (zoomed & (1 << output))
603
 
            scale = oWidth / (box.x2 - box.x1);
604
 
        else
605
 
            scale = 1.0f;
606
 
 
607
 
        if (panGrabIndex)
608
 
        {
609
 
            float dx, dy;
610
 
 
611
 
            dx = (xRoot - lastPointerX) / scale;
612
 
            dy = (yRoot - lastPointerY) / scale;
613
 
 
614
 
            box.x1 -= dx;
615
 
            box.y1 -= dy;
616
 
            box.x2 -= dx;
617
 
            box.y2 -= dy;
618
 
 
619
 
            if (box.x1 < screen->outputDevs ()[output].x1 ())
620
 
            {
621
 
                box.x2 += screen->outputDevs ()[output].x1 () - box.x1;
622
 
                box.x1 = screen->outputDevs ()[output].x1 ();
623
 
            }
624
 
            else if (box.x2 > screen->outputDevs ()[output].x2 ())
625
 
            {
626
 
                box.x1 -= box.x2 - screen->outputDevs ()[output].x2 ();
627
 
                box.x2 = screen->outputDevs ()[output].x2 ();
628
 
            }
629
 
 
630
 
            if (box.y1 < screen->outputDevs ()[output].y1 ())
631
 
            {
632
 
                box.y2 += screen->outputDevs ()[output].y1 () - box.y1;
633
 
                box.y1 = screen->outputDevs ()[output].y1 ();
634
 
            }
635
 
            else if (box.y2 > screen->outputDevs ()[output].y2 ())
636
 
            {
637
 
                box.y1 -= box.y2 - screen->outputDevs ()[output].y2 ();
638
 
                box.y2 = screen->outputDevs ()[output].y2 ();
639
 
            }
640
 
 
641
 
            current[output] = box;
642
 
 
643
 
            cScreen->damageScreen ();
644
 
        }
645
 
        else
646
 
        {
647
 
            int x1, y1;
648
 
 
649
 
            if (zoomed & (1 << output))
650
 
            {
651
 
                x1 = box.x1;
652
 
                y1 = box.y1;
653
 
            }
654
 
            else
655
 
            {
656
 
                x1 = screen->outputDevs ()[output].x1 ();
657
 
                y1 = screen->outputDevs ()[output].y1 ();
658
 
            }
659
 
 
660
 
            this->x2 = x1 +
661
 
                ((xRoot - screen->outputDevs ()[output].x1 ()) /
662
 
                 scale + 0.5f);
663
 
            this->y2 = y1 +
664
 
                ((yRoot - screen->outputDevs ()[output].y1 ()) /
665
 
                 scale + 0.5f);
666
 
 
667
 
            cScreen->damageScreen ();
668
 
        }
669
 
    }
670
 
}
671
 
 
672
 
void
673
 
ZoomScreen::handleEvent (XEvent *event)
674
 
{
675
 
    switch (event->type) {
676
 
        case MotionNotify:
677
 
            if (event->xmotion.root == screen->root ())
678
 
                handleMotionEvent (pointerX, pointerY);
679
 
            break;
680
 
        case EnterNotify:
681
 
        case LeaveNotify:
682
 
            if (event->xcrossing.root == screen->root ())
683
 
                handleMotionEvent (pointerX, pointerY);
684
 
        default:
685
 
            break;
686
 
    }
687
 
 
688
 
    screen->handleEvent (event);
689
 
}
690
 
 
691
 
 
692
 
CompOption::Vector &
693
 
ZoomScreen::getOptions ()
694
 
{
695
 
    return opt;
696
 
}
697
 
 
698
 
bool
699
 
ZoomScreen::setOption (const char        *name,
700
 
                       CompOption::Value &value)
701
 
{
702
 
    CompOption *o;
703
 
    unsigned int index;
704
 
 
705
 
    o = CompOption::findOption (opt, name, &index);
706
 
    if (!o)
707
 
        return false;
708
 
 
709
 
    return CompOption::setOption (*o, value);
710
 
}
711
 
 
712
 
static const CompMetadata::OptionInfo zoomOptionInfo[] = {
713
 
    { "initiate_button", "button", 0, zoomInitiate, zoomTerminate },
714
 
    { "zoom_in_button", "button", 0, zoomIn, 0 },
715
 
    { "zoom_out_button", "button", 0, zoomOut, 0 },
716
 
    { "zoom_pan_button", "button", 0, zoomInitiatePan, zoomTerminatePan },
717
 
    { "speed", "float", "<min>0.1</min>", 0, 0 },
718
 
    { "timestep", "float", "<min>0.1</min>", 0, 0 },
719
 
    { "zoom_factor", "float", "<min>1.01</min>", 0, 0 },
720
 
    { "filter_linear", "bool", 0, 0, 0 }
721
 
};
722
 
 
723
 
ZoomScreen::ZoomScreen (CompScreen *screen) :
724
 
    PrivateHandler<ZoomScreen,CompScreen> (screen),
725
 
    cScreen (CompositeScreen::get (screen)),
726
 
    gScreen (GLScreen::get (screen)),
727
 
    opt(ZOOM_OPTION_NUM),
728
 
    grabIndex (0),
729
 
    grab (false),
730
 
    zoomed (0),
731
 
    adjust (false),
732
 
    panGrabIndex (0),
733
 
    velocity (0.0),
734
 
    scale (0.0),
735
 
    zoomOutput (0)
736
 
{
737
 
    if (!zoomVTable->getMetadata ()->initOptions (zoomOptionInfo,
738
 
                                                  ZOOM_OPTION_NUM, opt))
739
 
    {
740
 
        setFailed ();
741
 
        return;
742
 
    }
743
 
 
744
 
    panCursor = XCreateFontCursor (screen->dpy (), XC_fleur);
745
 
 
746
 
    memset (&current, 0, sizeof (current));
747
 
    memset (&last, 0, sizeof (last));
748
 
 
749
 
    ScreenInterface::setHandler (screen, false);
750
 
    CompositeScreenInterface::setHandler (cScreen, false);
751
 
    GLScreenInterface::setHandler (gScreen, false);
752
 
}
753
 
 
754
 
 
755
 
ZoomScreen::~ZoomScreen ()
756
 
{
757
 
    if (panCursor)
758
 
        XFreeCursor (screen->dpy (), panCursor);
759
 
}
760
 
 
761
 
bool
762
 
ZoomPluginVTable::init ()
763
 
{
764
 
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
765
 
        !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
766
 
        !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
767
 
         return false;
768
 
 
769
 
    getMetadata ()->addFromOptionInfo (zoomOptionInfo, ZOOM_OPTION_NUM);
770
 
    getMetadata ()->addFromFile (name ());
771
 
 
772
 
    return true;
773
 
}
774