summaryrefslogtreecommitdiff
path: root/plugins/zoom
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/zoom')
-rw-r--r--plugins/zoom/CMakeLists.txt5
-rw-r--r--plugins/zoom/src/zoom.cpp774
-rw-r--r--plugins/zoom/src/zoom.h127
-rw-r--r--plugins/zoom/zoom.xml.in62
4 files changed, 968 insertions, 0 deletions
diff --git a/plugins/zoom/CMakeLists.txt b/plugins/zoom/CMakeLists.txt
new file mode 100644
index 0000000..5ab0315
--- /dev/null
+++ b/plugins/zoom/CMakeLists.txt
@@ -0,0 +1,5 @@
+find_package (Compiz REQUIRED)
+
+include (CompizPlugin)
+
+compiz_plugin(zoom PLUGINDEPS composite opengl) \ No newline at end of file
diff --git a/plugins/zoom/src/zoom.cpp b/plugins/zoom/src/zoom.cpp
new file mode 100644
index 0000000..4f7a05b
--- /dev/null
+++ b/plugins/zoom/src/zoom.cpp
@@ -0,0 +1,774 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include "zoom.h"
+
+COMPIZ_PLUGIN_20081216 (zoom, ZoomPluginVTable)
+
+static int
+adjustZoomVelocity (ZoomScreen *zs)
+{
+ float d, adjust, amount;
+
+ d = (1.0f - zs->scale) * 10.0f;
+
+ adjust = d * 0.002f;
+ amount = fabs (d);
+ if (amount < 1.0f)
+ amount = 1.0f;
+ else if (amount > 5.0f)
+ amount = 5.0f;
+
+ zs->velocity = (amount * zs->velocity + adjust) / (amount + 1.0f);
+
+ return (fabs (d) < 0.02f && fabs (zs->velocity) < 0.005f);
+}
+
+void
+ZoomScreen::zoomInEvent ()
+{
+ CompOption::Vector o (0);
+
+ o.push_back (CompOption ("root", CompOption::TypeInt));
+ o.push_back (CompOption ("output", CompOption::TypeInt));
+ o.push_back (CompOption ("x1", CompOption::TypeInt));
+ o.push_back (CompOption ("y1", CompOption::TypeInt));
+ o.push_back (CompOption ("x2", CompOption::TypeInt));
+ o.push_back (CompOption ("y2", CompOption::TypeInt));
+
+ o[0].value ().set ((int) screen->root ());
+ o[1].value ().set ((int) zoomOutput);
+ o[2].value ().set ((int) current[zoomOutput].x1);
+ o[3].value ().set ((int) current[zoomOutput].y1);
+ o[4].value ().set ((int) current[zoomOutput].x2);
+ o[5].value ().set ((int) current[zoomOutput].y2);
+
+ screen->handleCompizEvent ("zoom", "in", o);
+}
+
+void
+ZoomScreen::zoomOutEvent ()
+{
+ CompOption::Vector o (0);
+
+ o.push_back (CompOption ("root", CompOption::TypeInt));
+ o.push_back (CompOption ("output", CompOption::TypeInt));
+
+ o[0].value ().set ((int) screen->root ());
+ o[1].value ().set ((int) zoomOutput);
+
+ screen->handleCompizEvent ("zoom", "out", o);
+}
+
+void
+ZoomScreen::preparePaint (int ms)
+{
+ if (adjust)
+ {
+ int steps;
+ float amount;
+
+ amount = ms * 0.35f * opt[ZOOM_OPTION_SPEED].value ().f ();
+ steps = amount / (0.5f * opt[ZOOM_OPTION_TIMESTEP].value ().f ());
+ if (!steps) steps = 1;
+
+ while (steps--)
+ {
+ if (adjustZoomVelocity (this))
+ {
+ BoxPtr pBox =
+ &screen->outputDevs ()[zoomOutput].region ()->extents;
+
+ scale = 1.0f;
+ velocity = 0.0f;
+ adjust = false;
+
+ if (current[zoomOutput].x1 == pBox->x1 &&
+ current[zoomOutput].y1 == pBox->y1 &&
+ current[zoomOutput].x2 == pBox->x2 &&
+ current[zoomOutput].y2 == pBox->y2)
+ {
+ zoomed &= ~(1 << zoomOutput);
+ zoomOutEvent ();
+ }
+ else
+ {
+ zoomInEvent ();
+ }
+
+ break;
+ }
+ else
+ {
+ scale += (velocity * ms) / (float) cScreen->redrawTime ();
+ }
+ }
+ }
+
+ cScreen->preparePaint (ms);
+}
+
+void
+ZoomScreen::donePaint ()
+{
+ if (adjust)
+ cScreen->damageScreen ();
+
+ if (!adjust && zoomed == 0)
+ {
+ cScreen->preparePaintSetEnabled (this, false);
+ cScreen->donePaintSetEnabled (this, false);
+ gScreen->glPaintOutputSetEnabled (this, false);
+ }
+
+ cScreen->donePaint ();
+}
+
+bool
+ZoomScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
+ const GLMatrix &transform,
+ const CompRegion &region,
+ CompOutput *output,
+ unsigned int mask)
+{
+ GLMatrix zTransform (transform);
+ bool status;
+
+ if (output->id () != ~0 && (zoomed & (1 << output->id ())))
+ {
+ GLTexture::Filter saveFilter;
+ ZoomBox box;
+ float scale, x, y, x1, y1;
+ float oWidth = output->width ();
+ float oHeight = output->height ();
+
+ mask &= ~PAINT_SCREEN_REGION_MASK;
+
+ getCurrentZoom (output->id (), &box);
+
+ x1 = box.x1 - output->x1 ();
+ y1 = box.y1 - output->y1 ();
+
+ scale = oWidth / (box.x2 - box.x1);
+
+ x = ((oWidth / 2.0f) - x1) / oWidth;
+ y = ((oHeight / 2.0f) - y1) / oHeight;
+
+ x = 0.5f - x * scale;
+ y = 0.5f - y * scale;
+
+ zTransform.translate (-x, y, 0.0f);
+ zTransform.scale (scale, scale, 1.0f);
+
+ mask |= PAINT_SCREEN_TRANSFORMED_MASK;
+
+ saveFilter = gScreen->filter (SCREEN_TRANS_FILTER);
+
+ if ((zoomOutput != output->id () || !adjust) && scale > 3.9f &&
+ !opt[ZOOM_OPTION_FILTER_LINEAR].value ().b ())
+ gScreen->setFilter (SCREEN_TRANS_FILTER, GLTexture::Fast);
+
+ status = gScreen->glPaintOutput (sAttrib, zTransform, region, output,
+ mask);
+
+ gScreen->setFilter (SCREEN_TRANS_FILTER, saveFilter);
+ }
+ else
+ {
+ status = gScreen->glPaintOutput (sAttrib, transform, region, output,
+ mask);
+ }
+
+ if (status && grab)
+ {
+ int x1, x2, y1, y2;
+
+ x1 = MIN (this->x1, this->x2);
+ y1 = MIN (this->y1, this->y2);
+ x2 = MAX (this->x1, this->x2);
+ y2 = MAX (this->y1, this->y2);
+
+ if (grabIndex)
+ {
+ zTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
+
+ glPushMatrix ();
+ glLoadMatrixf (zTransform.getMatrix ());
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glEnable (GL_BLEND);
+ glColor4us (0x2fff, 0x2fff, 0x4fff, 0x4fff);
+ glRecti (x1, y2, x2, y1);
+ glColor4us (0x2fff, 0x2fff, 0x4fff, 0x9fff);
+ glBegin (GL_LINE_LOOP);
+ glVertex2i (x1, y1);
+ glVertex2i (x2, y1);
+ glVertex2i (x2, y2);
+ glVertex2i (x1, y2);
+ glEnd ();
+ glColor4usv (defaultColor);
+ glDisable (GL_BLEND);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ glPopMatrix ();
+ }
+ }
+
+ return status;
+}
+
+
+void
+ZoomScreen::initiateForSelection (int output)
+{
+ int tmp;
+
+ if (x1 > x2)
+ {
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+
+ if (y1 > y2)
+ {
+ tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ }
+
+ if (x1 < x2 && y1 < y2)
+ {
+ float oWidth, oHeight;
+ float xScale, yScale, scale;
+ BoxRec box;
+ int cx, cy;
+ int width, height;
+
+ oWidth = screen->outputDevs ()[output].width ();
+ oHeight = screen->outputDevs ()[output].height ();
+
+ cx = (int) ((x1 + x2) / 2.0f + 0.5f);
+ cy = (int) ((y1 + y2) / 2.0f + 0.5f);
+
+ width = x2 - x1;
+ height = y2 - y1;
+
+ xScale = oWidth / width;
+ yScale = oHeight / height;
+
+ scale = MAX (MIN (xScale, yScale), 1.0f);
+
+ box.x1 = cx - (oWidth / scale) / 2.0f;
+ box.y1 = cy - (oHeight / scale) / 2.0f;
+ box.x2 = cx + (oWidth / scale) / 2.0f;
+ box.y2 = cy + (oHeight / scale) / 2.0f;
+
+ if (box.x1 < screen->outputDevs ()[output].x1 ())
+ {
+ box.x2 += screen->outputDevs ()[output].x1 () - box.x1;
+ box.x1 = screen->outputDevs ()[output].x1 ();
+ }
+ else if (box.x2 > screen->outputDevs ()[output].x2 ())
+ {
+ box.x1 -= box.x2 - screen->outputDevs ()[output].x2 ();
+ box.x2 = screen->outputDevs ()[output].x2 ();
+ }
+
+ if (box.y1 < screen->outputDevs ()[output].y1 ())
+ {
+ box.y2 += screen->outputDevs ()[output].y1 () - box.y1;
+ box.y1 = screen->outputDevs ()[output].y1 ();
+ }
+ else if (box.y2 > screen->outputDevs ()[output].y2 ())
+ {
+ box.y1 -= box.y2 - screen->outputDevs ()[output].y2 ();
+ box.y2 = screen->outputDevs ()[output].y2 ();
+ }
+
+ if (zoomed & (1 << output))
+ {
+ getCurrentZoom (output, &last[output]);
+ }
+ else
+ {
+ last[output].x1 = screen->outputDevs ()[output].x1 ();
+ last[output].y1 = screen->outputDevs ()[output].y1 ();
+ last[output].x2 = screen->outputDevs ()[output].x2 ();
+ last[output].y2 = screen->outputDevs ()[output].y2 ();
+ }
+
+ current[output].x1 = box.x1;
+ current[output].y1 = box.y1;
+ current[output].x2 = box.x2;
+ current[output].y2 = box.y2;
+
+ this->scale = 0.0f;
+ adjust = true;
+ cScreen->preparePaintSetEnabled (this, true);
+ cScreen->donePaintSetEnabled (this, true);
+ gScreen->glPaintOutputSetEnabled (this, true);
+ zoomOutput = output;
+ zoomed |= (1 << output);
+
+ cScreen->damageScreen ();
+ }
+}
+
+static bool
+zoomIn (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+ float w, h, x0, y0;
+ int output;
+ ZoomBox box;
+
+ ZOOM_SCREEN (screen);
+
+ output = screen->outputDeviceForPoint (pointerX, pointerY);
+
+ if (!zs->grabIndex)
+ {
+ zs->grabIndex = screen->pushGrab (None, "zoom");
+ screen->handleEventSetEnabled (zs, true);
+ }
+
+ if (zs->zoomed & (1 << output))
+ {
+ zs->getCurrentZoom (output, &box);
+ }
+ else
+ {
+ box.x1 = screen->outputDevs ()[output].x1 ();
+ box.y1 = screen->outputDevs ()[output].y1 ();
+ box.x2 = screen->outputDevs ()[output].x2 ();
+ box.y2 = screen->outputDevs ()[output].y2 ();
+ }
+
+ w = (box.x2 - box.x1) /
+ zs->opt[ZOOM_OPTION_ZOOM_FACTOR].value ().f ();
+ h = (box.y2 - box.y1) /
+ zs->opt[ZOOM_OPTION_ZOOM_FACTOR].value ().f ();
+
+ x0 = (pointerX - screen->outputDevs ()[output].x1 ()) / (float)
+ screen->outputDevs ()[output].width ();
+ y0 = (pointerY - screen->outputDevs ()[output].y1 ()) / (float)
+ screen->outputDevs ()[output].height ();
+
+ zs->x1 = box.x1 + (x0 * (box.x2 - box.x1) - x0 * w + 0.5f);
+ zs->y1 = box.y1 + (y0 * (box.y2 - box.y1) - y0 * h + 0.5f);
+ zs->x2 = zs->x1 + w;
+ zs->y2 = zs->y1 + h;
+
+ zs->initiateForSelection (output);
+
+ return TRUE;
+}
+
+static bool
+zoomInitiate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+ int output, x1, y1;
+ float scale;
+
+ ZOOM_SCREEN (screen);
+
+ if (screen->otherGrabExist ("zoom", 0))
+ return false;
+
+ if (!zs->grabIndex)
+ {
+ zs->grabIndex = screen->pushGrab (None, "zoom");
+ screen->handleEventSetEnabled (zs, true);
+ }
+
+ if (state & CompAction::StateInitButton)
+ action->setState (action->state () | CompAction::StateTermButton);
+
+ /* start selection zoom rectangle */
+
+ output = screen->outputDeviceForPoint (pointerX, pointerY);
+
+ if (zs->zoomed & (1 << output))
+ {
+ ZoomBox box;
+ float oWidth;
+
+ zs->getCurrentZoom (output, &box);
+
+ oWidth = screen->outputDevs ()[output].width ();
+ scale = oWidth / (box.x2 - box.x1);
+
+ x1 = box.x1;
+ y1 = box.y1;
+ }
+ else
+ {
+ scale = 1.0f;
+ x1 = screen->outputDevs ()[output].x1 ();
+ y1 = screen->outputDevs ()[output].y1 ();
+ }
+
+ zs->x1 = zs->x2 = x1 +
+ ((pointerX - screen->outputDevs ()[output].x1 ()) /
+ scale + 0.5f);
+ zs->y1 = zs->y2 = y1 +
+ ((pointerY - screen->outputDevs ()[output].y1 ()) /
+ scale + 0.5f);
+
+ zs->zoomOutput = output;
+
+ zs->grab = true;
+ zs->gScreen->glPaintOutputSetEnabled (zs, true);
+
+ zs->cScreen->damageScreen ();
+
+ return true;
+}
+
+static bool
+zoomOut (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+ int output;
+
+ ZOOM_SCREEN (screen);
+
+ output = screen->outputDeviceForPoint (pointerX, pointerY);
+
+ zs->getCurrentZoom (output, &zs->last[output]);
+
+ zs->current[output].x1 = screen->outputDevs ()[output].x1 ();
+ zs->current[output].y1 = screen->outputDevs ()[output].y1 ();
+ zs->current[output].x2 = screen->outputDevs ()[output].x2 ();
+ zs->current[output].y2 = screen->outputDevs ()[output].y2 ();
+
+ zs->zoomOutput = output;
+ zs->scale = 0.0f;
+ zs->adjust = true;
+ zs->grab = false;
+
+ if (zs->grabIndex)
+ {
+ screen->removeGrab (zs->grabIndex, NULL);
+ zs->grabIndex = 0;
+ screen->handleEventSetEnabled (zs, false);
+ }
+
+ zs->cScreen->damageScreen ();
+
+ return true;
+}
+
+static bool
+zoomTerminate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+ ZOOM_SCREEN (screen);
+
+ if (zs->grab)
+ {
+ int output;
+
+ output = screen->outputDeviceForPoint (zs->x1, zs->y1);
+
+ if (zs->x2 > screen->outputDevs ()[output].x2 ())
+ zs->x2 = screen->outputDevs ()[output].x2 ();
+
+ if (zs->y2 > screen->outputDevs ()[output].y2 ())
+ zs->y2 = screen->outputDevs ()[output].y2 ();
+
+ zs->initiateForSelection (output);
+
+ zs->grab = false;
+ }
+ else
+ {
+ zoomOut (action, state, noOptions);
+ }
+ action->setState (action->state () & ~(CompAction::StateTermKey |
+ CompAction::StateTermButton));
+}
+
+static bool
+zoomInitiatePan (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+ int output;
+
+ ZOOM_SCREEN (screen);
+
+ output = screen->outputDeviceForPoint (pointerX, pointerY);
+
+ if (!(zs->zoomed & (1 << output)))
+ return false;
+
+ if (screen->otherGrabExist ("zoom", 0))
+ return false;
+
+ if (state & CompAction::StateInitButton)
+ action->setState (action->state () | CompAction::StateTermButton);
+
+ if (!zs->panGrabIndex)
+ zs->panGrabIndex = screen->pushGrab (zs->panCursor, "zoom-pan");
+
+ zs->zoomOutput = output;
+
+ return true;
+}
+
+static bool
+zoomTerminatePan (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+ ZOOM_SCREEN (screen);
+
+ if (zs->panGrabIndex)
+ {
+ screen->removeGrab (zs->panGrabIndex, NULL);
+ zs->panGrabIndex = 0;
+
+ zs->zoomInEvent ();
+ }
+
+ return true;
+}
+
+void
+ZoomScreen::getCurrentZoom (int output, ZoomBox *pBox)
+{
+ if (output == zoomOutput)
+ {
+ float inverse;
+
+ inverse = 1.0f - scale;
+
+ pBox->x1 = scale * current[output].x1 +
+ inverse * last[output].x1;
+ pBox->y1 = scale * current[output].y1 +
+ inverse * last[output].y1;
+ pBox->x2 = scale * current[output].x2 +
+ inverse * last[output].x2;
+ pBox->y2 = scale * current[output].y2 +
+ inverse * last[output].y2;
+ }
+ else
+ {
+ pBox->x1 = current[output].x1;
+ pBox->y1 = current[output].y1;
+ pBox->x2 = current[output].x2;
+ pBox->y2 = current[output].y2;
+ }
+}
+
+void
+ZoomScreen::handleMotionEvent (int xRoot, int yRoot)
+{
+ if (grabIndex)
+ {
+ int output = zoomOutput;
+ ZoomBox box;
+ float scale, oWidth = screen->outputDevs ()[output].width ();
+
+ getCurrentZoom (output, &box);
+
+ if (zoomed & (1 << output))
+ scale = oWidth / (box.x2 - box.x1);
+ else
+ scale = 1.0f;
+
+ if (panGrabIndex)
+ {
+ float dx, dy;
+
+ dx = (xRoot - lastPointerX) / scale;
+ dy = (yRoot - lastPointerY) / scale;
+
+ box.x1 -= dx;
+ box.y1 -= dy;
+ box.x2 -= dx;
+ box.y2 -= dy;
+
+ if (box.x1 < screen->outputDevs ()[output].x1 ())
+ {
+ box.x2 += screen->outputDevs ()[output].x1 () - box.x1;
+ box.x1 = screen->outputDevs ()[output].x1 ();
+ }
+ else if (box.x2 > screen->outputDevs ()[output].x2 ())
+ {
+ box.x1 -= box.x2 - screen->outputDevs ()[output].x2 ();
+ box.x2 = screen->outputDevs ()[output].x2 ();
+ }
+
+ if (box.y1 < screen->outputDevs ()[output].y1 ())
+ {
+ box.y2 += screen->outputDevs ()[output].y1 () - box.y1;
+ box.y1 = screen->outputDevs ()[output].y1 ();
+ }
+ else if (box.y2 > screen->outputDevs ()[output].y2 ())
+ {
+ box.y1 -= box.y2 - screen->outputDevs ()[output].y2 ();
+ box.y2 = screen->outputDevs ()[output].y2 ();
+ }
+
+ current[output] = box;
+
+ cScreen->damageScreen ();
+ }
+ else
+ {
+ int x1, y1;
+
+ if (zoomed & (1 << output))
+ {
+ x1 = box.x1;
+ y1 = box.y1;
+ }
+ else
+ {
+ x1 = screen->outputDevs ()[output].x1 ();
+ y1 = screen->outputDevs ()[output].y1 ();
+ }
+
+ this->x2 = x1 +
+ ((xRoot - screen->outputDevs ()[output].x1 ()) /
+ scale + 0.5f);
+ this->y2 = y1 +
+ ((yRoot - screen->outputDevs ()[output].y1 ()) /
+ scale + 0.5f);
+
+ cScreen->damageScreen ();
+ }
+ }
+}
+
+void
+ZoomScreen::handleEvent (XEvent *event)
+{
+ switch (event->type) {
+ case MotionNotify:
+ if (event->xmotion.root == screen->root ())
+ handleMotionEvent (pointerX, pointerY);
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ if (event->xcrossing.root == screen->root ())
+ handleMotionEvent (pointerX, pointerY);
+ default:
+ break;
+ }
+
+ screen->handleEvent (event);
+}
+
+
+CompOption::Vector &
+ZoomScreen::getOptions ()
+{
+ return opt;
+}
+
+bool
+ZoomScreen::setOption (const char *name,
+ CompOption::Value &value)
+{
+ CompOption *o;
+ unsigned int index;
+
+ o = CompOption::findOption (opt, name, &index);
+ if (!o)
+ return false;
+
+ return CompOption::setOption (*o, value);
+}
+
+static const CompMetadata::OptionInfo zoomOptionInfo[] = {
+ { "initiate_button", "button", 0, zoomInitiate, zoomTerminate },
+ { "zoom_in_button", "button", 0, zoomIn, 0 },
+ { "zoom_out_button", "button", 0, zoomOut, 0 },
+ { "zoom_pan_button", "button", 0, zoomInitiatePan, zoomTerminatePan },
+ { "speed", "float", "<min>0.1</min>", 0, 0 },
+ { "timestep", "float", "<min>0.1</min>", 0, 0 },
+ { "zoom_factor", "float", "<min>1.01</min>", 0, 0 },
+ { "filter_linear", "bool", 0, 0, 0 }
+};
+
+ZoomScreen::ZoomScreen (CompScreen *screen) :
+ PrivateHandler<ZoomScreen,CompScreen> (screen),
+ cScreen (CompositeScreen::get (screen)),
+ gScreen (GLScreen::get (screen)),
+ opt(ZOOM_OPTION_NUM),
+ grabIndex (0),
+ grab (false),
+ zoomed (0),
+ adjust (false),
+ panGrabIndex (0),
+ velocity (0.0),
+ scale (0.0),
+ zoomOutput (0)
+{
+ if (!zoomVTable->getMetadata ()->initOptions (zoomOptionInfo,
+ ZOOM_OPTION_NUM, opt))
+ {
+ setFailed ();
+ return;
+ }
+
+ panCursor = XCreateFontCursor (screen->dpy (), XC_fleur);
+
+ memset (&current, 0, sizeof (current));
+ memset (&last, 0, sizeof (last));
+
+ ScreenInterface::setHandler (screen, false);
+ CompositeScreenInterface::setHandler (cScreen, false);
+ GLScreenInterface::setHandler (gScreen, false);
+}
+
+
+ZoomScreen::~ZoomScreen ()
+{
+ if (panCursor)
+ XFreeCursor (screen->dpy (), panCursor);
+}
+
+bool
+ZoomPluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
+ !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
+ return false;
+
+ getMetadata ()->addFromOptionInfo (zoomOptionInfo, ZOOM_OPTION_NUM);
+ getMetadata ()->addFromFile (name ());
+
+ return true;
+}
+
diff --git a/plugins/zoom/src/zoom.h b/plugins/zoom/src/zoom.h
new file mode 100644
index 0000000..41e64a1
--- /dev/null
+++ b/plugins/zoom/src/zoom.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <sys/time.h>
+
+#include <X11/cursorfont.h>
+
+#include <core/core.h>
+#include <core/privatehandler.h>
+
+#include <composite/composite.h>
+#include <opengl/opengl.h>
+
+#define ZOOM_OPTION_INITIATE_BUTTON 0
+#define ZOOM_OPTION_IN_BUTTON 1
+#define ZOOM_OPTION_OUT_BUTTON 2
+#define ZOOM_OPTION_PAN_BUTTON 3
+#define ZOOM_OPTION_SPEED 4
+#define ZOOM_OPTION_TIMESTEP 5
+#define ZOOM_OPTION_ZOOM_FACTOR 6
+#define ZOOM_OPTION_FILTER_LINEAR 7
+#define ZOOM_OPTION_NUM 8
+
+#define ZOOM_SCREEN(s) \
+ ZoomScreen *zs = ZoomScreen::get (s)
+
+struct ZoomBox {
+ float x1;
+ float y1;
+ float x2;
+ float y2;
+};
+
+class ZoomScreen :
+ public ScreenInterface,
+ public CompositeScreenInterface,
+ public GLScreenInterface,
+ public PrivateHandler<ZoomScreen,CompScreen>
+{
+ public:
+
+ ZoomScreen (CompScreen *screen);
+ ~ZoomScreen ();
+
+ CompOption::Vector & getOptions ();
+ bool setOption (const char *name, CompOption::Value &value);
+
+ void handleEvent (XEvent *);
+
+ void preparePaint (int);
+ void donePaint ();
+
+ bool glPaintOutput (const GLScreenPaintAttrib &,
+ const GLMatrix &, const CompRegion &,
+ CompOutput *, unsigned int);
+
+ void getCurrentZoom (int output, ZoomBox *pBox);
+ void handleMotionEvent (int xRoot, int yRoot);
+ void initiateForSelection (int output);
+
+ void zoomInEvent ();
+ void zoomOutEvent ();
+
+ CompositeScreen *cScreen;
+ GLScreen *gScreen;
+
+ CompOption::Vector opt;
+
+ float pointerSensitivity;
+
+ CompScreen::GrabHandle grabIndex;
+ bool grab;
+
+ int zoomed;
+
+ bool adjust;
+
+ CompScreen::GrabHandle panGrabIndex;
+ Cursor panCursor;
+
+ GLfloat velocity;
+ GLfloat scale;
+
+ ZoomBox current[16];
+ ZoomBox last[16];
+
+ int x1, y1, x2, y2;
+
+ int zoomOutput;
+};
+
+class ZoomPluginVTable :
+ public CompPlugin::VTableForScreen<ZoomScreen>
+{
+ public:
+
+ bool init ();
+
+ PLUGIN_OPTION_HELPER (ZoomScreen);
+
+};
diff --git a/plugins/zoom/zoom.xml.in b/plugins/zoom/zoom.xml.in
new file mode 100644
index 0000000..ff8bb5a
--- /dev/null
+++ b/plugins/zoom/zoom.xml.in
@@ -0,0 +1,62 @@
+<compiz>
+ <plugin name="zoom">
+ <_short>Zoom Desktop</_short>
+ <_long>Zoom and pan desktop cube</_long>
+ <deps>
+ <requirement>
+ <plugin>opengl</plugin>
+ </requirement>
+ </deps>
+ <options>
+ <option name="initiate_button" type="button">
+ <_short>Initiate</_short>
+ <_long>Zoom In</_long>
+ <default>&lt;Super&gt;Button3</default>
+ </option>
+ <option name="zoom_in_button" type="button">
+ <_short>Zoom In</_short>
+ <_long>Zoom In</_long>
+ <default>&lt;Super&gt;Button4</default>
+ </option>
+ <option name="zoom_out_button" type="button">
+ <_short>Zoom Out</_short>
+ <_long>Zoom Out</_long>
+ <default>&lt;Super&gt;Button5</default>
+ </option>
+ <option name="zoom_pan_button" type="button">
+ <_short>Zoom Pan</_short>
+ <_long>Zoom pan</_long>
+ <default>&lt;Super&gt;Button2</default>
+ </option>
+ <option name="speed" type="float">
+ <_short>Speed</_short>
+ <_long>Zoom Speed</_long>
+ <default>1.5</default>
+ <min>0.1</min>
+ <max>50</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="timestep" type="float">
+ <_short>Timestep</_short>
+ <_long>Zoom Timestep</_long>
+ <default>1.2</default>
+ <min>0.1</min>
+ <max>50</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="zoom_factor" type="float">
+ <_short>Zoom factor</_short>
+ <_long>Zoom factor</_long>
+ <default>2</default>
+ <min>1.01</min>
+ <max>3</max>
+ <precision>0.01</precision>
+ </option>
+ <option name="filter_linear" type="bool">
+ <_short>Filter Linear</_short>
+ <_long>Use linear filter when zoomed in</_long>
+ <default>false</default>
+ </option>
+ </options>
+ </plugin>
+</compiz>