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>
28
COMPIZ_PLUGIN_20081216 (zoom, ZoomPluginVTable)
31
adjustZoomVelocity (ZoomScreen *zs)
33
float d, adjust, amount;
35
d = (1.0f - zs->scale) * 10.0f;
41
else if (amount > 5.0f)
44
zs->velocity = (amount * zs->velocity + adjust) / (amount + 1.0f);
46
return (fabs (d) < 0.02f && fabs (zs->velocity) < 0.005f);
50
ZoomScreen::zoomInEvent ()
52
CompOption::Vector o (0);
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));
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);
68
screen->handleCompizEvent ("zoom", "in", o);
72
ZoomScreen::zoomOutEvent ()
74
CompOption::Vector o (0);
76
o.push_back (CompOption ("root", CompOption::TypeInt));
77
o.push_back (CompOption ("output", CompOption::TypeInt));
79
o[0].value ().set ((int) screen->root ());
80
o[1].value ().set ((int) zoomOutput);
82
screen->handleCompizEvent ("zoom", "out", o);
86
ZoomScreen::preparePaint (int ms)
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;
99
if (adjustZoomVelocity (this))
102
&screen->outputDevs ()[zoomOutput].region ()->extents;
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)
113
zoomed &= ~(1 << zoomOutput);
125
scale += (velocity * ms) / (float) cScreen->redrawTime ();
130
cScreen->preparePaint (ms);
134
ZoomScreen::donePaint ()
137
cScreen->damageScreen ();
139
if (!adjust && zoomed == 0)
141
cScreen->preparePaintSetEnabled (this, false);
142
cScreen->donePaintSetEnabled (this, false);
143
gScreen->glPaintOutputSetEnabled (this, false);
146
cScreen->donePaint ();
150
ZoomScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
151
const GLMatrix &transform,
152
const CompRegion ®ion,
156
GLMatrix zTransform (transform);
159
if (output->id () != ~0 && (zoomed & (1 << output->id ())))
161
GLTexture::Filter saveFilter;
163
float scale, x, y, x1, y1;
164
float oWidth = output->width ();
165
float oHeight = output->height ();
167
mask &= ~PAINT_SCREEN_REGION_MASK;
169
getCurrentZoom (output->id (), &box);
171
x1 = box.x1 - output->x1 ();
172
y1 = box.y1 - output->y1 ();
174
scale = oWidth / (box.x2 - box.x1);
176
x = ((oWidth / 2.0f) - x1) / oWidth;
177
y = ((oHeight / 2.0f) - y1) / oHeight;
179
x = 0.5f - x * scale;
180
y = 0.5f - y * scale;
182
zTransform.translate (-x, y, 0.0f);
183
zTransform.scale (scale, scale, 1.0f);
185
mask |= PAINT_SCREEN_TRANSFORMED_MASK;
187
saveFilter = gScreen->filter (SCREEN_TRANS_FILTER);
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);
193
status = gScreen->glPaintOutput (sAttrib, zTransform, region, output,
196
gScreen->setFilter (SCREEN_TRANS_FILTER, saveFilter);
200
status = gScreen->glPaintOutput (sAttrib, transform, region, output,
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);
215
zTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
218
glLoadMatrixf (zTransform.getMatrix ());
219
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
221
glColor4us (0x2fff, 0x2fff, 0x4fff, 0x4fff);
222
glRecti (x1, y2, x2, y1);
223
glColor4us (0x2fff, 0x2fff, 0x4fff, 0x9fff);
224
glBegin (GL_LINE_LOOP);
230
glColor4usv (defaultColor);
231
glDisable (GL_BLEND);
232
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
242
ZoomScreen::initiateForSelection (int output)
260
if (x1 < x2 && y1 < y2)
262
float oWidth, oHeight;
263
float xScale, yScale, scale;
268
oWidth = screen->outputDevs ()[output].width ();
269
oHeight = screen->outputDevs ()[output].height ();
271
cx = (int) ((x1 + x2) / 2.0f + 0.5f);
272
cy = (int) ((y1 + y2) / 2.0f + 0.5f);
277
xScale = oWidth / width;
278
yScale = oHeight / height;
280
scale = MAX (MIN (xScale, yScale), 1.0f);
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;
287
if (box.x1 < screen->outputDevs ()[output].x1 ())
289
box.x2 += screen->outputDevs ()[output].x1 () - box.x1;
290
box.x1 = screen->outputDevs ()[output].x1 ();
292
else if (box.x2 > screen->outputDevs ()[output].x2 ())
294
box.x1 -= box.x2 - screen->outputDevs ()[output].x2 ();
295
box.x2 = screen->outputDevs ()[output].x2 ();
298
if (box.y1 < screen->outputDevs ()[output].y1 ())
300
box.y2 += screen->outputDevs ()[output].y1 () - box.y1;
301
box.y1 = screen->outputDevs ()[output].y1 ();
303
else if (box.y2 > screen->outputDevs ()[output].y2 ())
305
box.y1 -= box.y2 - screen->outputDevs ()[output].y2 ();
306
box.y2 = screen->outputDevs ()[output].y2 ();
309
if (zoomed & (1 << output))
311
getCurrentZoom (output, &last[output]);
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 ();
321
current[output].x1 = box.x1;
322
current[output].y1 = box.y1;
323
current[output].x2 = box.x2;
324
current[output].y2 = box.y2;
328
cScreen->preparePaintSetEnabled (this, true);
329
cScreen->donePaintSetEnabled (this, true);
330
gScreen->glPaintOutputSetEnabled (this, true);
332
zoomed |= (1 << output);
334
cScreen->damageScreen ();
339
zoomIn (CompAction *action,
340
CompAction::State state,
341
CompOption::Vector &options)
347
ZOOM_SCREEN (screen);
349
output = screen->outputDeviceForPoint (pointerX, pointerY);
353
zs->grabIndex = screen->pushGrab (None, "zoom");
354
screen->handleEventSetEnabled (zs, true);
357
if (zs->zoomed & (1 << output))
359
zs->getCurrentZoom (output, &box);
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 ();
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 ();
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 ();
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);
384
zs->initiateForSelection (output);
390
zoomInitiate (CompAction *action,
391
CompAction::State state,
392
CompOption::Vector &options)
397
ZOOM_SCREEN (screen);
399
if (screen->otherGrabExist ("zoom", 0))
404
zs->grabIndex = screen->pushGrab (None, "zoom");
405
screen->handleEventSetEnabled (zs, true);
408
if (state & CompAction::StateInitButton)
409
action->setState (action->state () | CompAction::StateTermButton);
411
/* start selection zoom rectangle */
413
output = screen->outputDeviceForPoint (pointerX, pointerY);
415
if (zs->zoomed & (1 << output))
420
zs->getCurrentZoom (output, &box);
422
oWidth = screen->outputDevs ()[output].width ();
423
scale = oWidth / (box.x2 - box.x1);
431
x1 = screen->outputDevs ()[output].x1 ();
432
y1 = screen->outputDevs ()[output].y1 ();
435
zs->x1 = zs->x2 = x1 +
436
((pointerX - screen->outputDevs ()[output].x1 ()) /
438
zs->y1 = zs->y2 = y1 +
439
((pointerY - screen->outputDevs ()[output].y1 ()) /
442
zs->zoomOutput = output;
445
zs->gScreen->glPaintOutputSetEnabled (zs, true);
447
zs->cScreen->damageScreen ();
453
zoomOut (CompAction *action,
454
CompAction::State state,
455
CompOption::Vector &options)
459
ZOOM_SCREEN (screen);
461
output = screen->outputDeviceForPoint (pointerX, pointerY);
463
zs->getCurrentZoom (output, &zs->last[output]);
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 ();
470
zs->zoomOutput = output;
477
screen->removeGrab (zs->grabIndex, NULL);
479
screen->handleEventSetEnabled (zs, false);
482
zs->cScreen->damageScreen ();
488
zoomTerminate (CompAction *action,
489
CompAction::State state,
490
CompOption::Vector &options)
492
ZOOM_SCREEN (screen);
498
output = screen->outputDeviceForPoint (zs->x1, zs->y1);
500
if (zs->x2 > screen->outputDevs ()[output].x2 ())
501
zs->x2 = screen->outputDevs ()[output].x2 ();
503
if (zs->y2 > screen->outputDevs ()[output].y2 ())
504
zs->y2 = screen->outputDevs ()[output].y2 ();
506
zs->initiateForSelection (output);
512
zoomOut (action, state, noOptions);
514
action->setState (action->state () & ~(CompAction::StateTermKey |
515
CompAction::StateTermButton));
519
zoomInitiatePan (CompAction *action,
520
CompAction::State state,
521
CompOption::Vector &options)
525
ZOOM_SCREEN (screen);
527
output = screen->outputDeviceForPoint (pointerX, pointerY);
529
if (!(zs->zoomed & (1 << output)))
532
if (screen->otherGrabExist ("zoom", 0))
535
if (state & CompAction::StateInitButton)
536
action->setState (action->state () | CompAction::StateTermButton);
538
if (!zs->panGrabIndex)
539
zs->panGrabIndex = screen->pushGrab (zs->panCursor, "zoom-pan");
541
zs->zoomOutput = output;
547
zoomTerminatePan (CompAction *action,
548
CompAction::State state,
549
CompOption::Vector &options)
551
ZOOM_SCREEN (screen);
553
if (zs->panGrabIndex)
555
screen->removeGrab (zs->panGrabIndex, NULL);
556
zs->panGrabIndex = 0;
565
ZoomScreen::getCurrentZoom (int output, ZoomBox *pBox)
567
if (output == zoomOutput)
571
inverse = 1.0f - scale;
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;
584
pBox->x1 = current[output].x1;
585
pBox->y1 = current[output].y1;
586
pBox->x2 = current[output].x2;
587
pBox->y2 = current[output].y2;
592
ZoomScreen::handleMotionEvent (int xRoot, int yRoot)
596
int output = zoomOutput;
598
float scale, oWidth = screen->outputDevs ()[output].width ();
600
getCurrentZoom (output, &box);
602
if (zoomed & (1 << output))
603
scale = oWidth / (box.x2 - box.x1);
611
dx = (xRoot - lastPointerX) / scale;
612
dy = (yRoot - lastPointerY) / scale;
619
if (box.x1 < screen->outputDevs ()[output].x1 ())
621
box.x2 += screen->outputDevs ()[output].x1 () - box.x1;
622
box.x1 = screen->outputDevs ()[output].x1 ();
624
else if (box.x2 > screen->outputDevs ()[output].x2 ())
626
box.x1 -= box.x2 - screen->outputDevs ()[output].x2 ();
627
box.x2 = screen->outputDevs ()[output].x2 ();
630
if (box.y1 < screen->outputDevs ()[output].y1 ())
632
box.y2 += screen->outputDevs ()[output].y1 () - box.y1;
633
box.y1 = screen->outputDevs ()[output].y1 ();
635
else if (box.y2 > screen->outputDevs ()[output].y2 ())
637
box.y1 -= box.y2 - screen->outputDevs ()[output].y2 ();
638
box.y2 = screen->outputDevs ()[output].y2 ();
641
current[output] = box;
643
cScreen->damageScreen ();
649
if (zoomed & (1 << output))
656
x1 = screen->outputDevs ()[output].x1 ();
657
y1 = screen->outputDevs ()[output].y1 ();
661
((xRoot - screen->outputDevs ()[output].x1 ()) /
664
((yRoot - screen->outputDevs ()[output].y1 ()) /
667
cScreen->damageScreen ();
673
ZoomScreen::handleEvent (XEvent *event)
675
switch (event->type) {
677
if (event->xmotion.root == screen->root ())
678
handleMotionEvent (pointerX, pointerY);
682
if (event->xcrossing.root == screen->root ())
683
handleMotionEvent (pointerX, pointerY);
688
screen->handleEvent (event);
693
ZoomScreen::getOptions ()
699
ZoomScreen::setOption (const char *name,
700
CompOption::Value &value)
705
o = CompOption::findOption (opt, name, &index);
709
return CompOption::setOption (*o, value);
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 }
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),
737
if (!zoomVTable->getMetadata ()->initOptions (zoomOptionInfo,
738
ZOOM_OPTION_NUM, opt))
744
panCursor = XCreateFontCursor (screen->dpy (), XC_fleur);
746
memset (¤t, 0, sizeof (current));
747
memset (&last, 0, sizeof (last));
749
ScreenInterface::setHandler (screen, false);
750
CompositeScreenInterface::setHandler (cScreen, false);
751
GLScreenInterface::setHandler (gScreen, false);
755
ZoomScreen::~ZoomScreen ()
758
XFreeCursor (screen->dpy (), panCursor);
762
ZoomPluginVTable::init ()
764
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
765
!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
766
!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
769
getMetadata ()->addFromOptionInfo (zoomOptionInfo, ZOOM_OPTION_NUM);
770
getMetadata ()->addFromFile (name ());