summaryrefslogtreecommitdiff
path: root/beryl-plugins/src/inputzoom.c
diff options
context:
space:
mode:
authoronestone <onestone@d7aaf104-2d23-0410-ae22-9d23157bf5a3>2006-11-08 22:53:15 +0000
committeronestone <onestone@d7aaf104-2d23-0410-ae22-9d23157bf5a3>2006-11-08 22:53:15 +0000
commitbff1e218876995a8569a1748b9abe7247b5288b1 (patch)
treeac1f099ec77096f0fa0b1e5822ee2c6b145fd23c /beryl-plugins/src/inputzoom.c
parentbfe93671609355cae5d1d52f277fc8758d705b05 (diff)
downloadmarex-dev-bff1e218876995a8569a1748b9abe7247b5288b1.tar.gz
marex-dev-bff1e218876995a8569a1748b9abe7247b5288b1.tar.bz2
beryl-plugins: added input enabled zoom plugin
git-svn-id: file:///beryl/trunk@1093 d7aaf104-2d23-0410-ae22-9d23157bf5a3
Diffstat (limited to 'beryl-plugins/src/inputzoom.c')
-rwxr-xr-xberyl-plugins/src/inputzoom.c943
1 files changed, 943 insertions, 0 deletions
diff --git a/beryl-plugins/src/inputzoom.c b/beryl-plugins/src/inputzoom.c
new file mode 100755
index 0000000..223d4ff
--- /dev/null
+++ b/beryl-plugins/src/inputzoom.c
@@ -0,0 +1,943 @@
+/*
+ *
+ * Beryl Input-Enabled-Zoom-Plugin
+ *
+ * Copyright : (C) 2006 by Dennis Kasprzyk
+ * E-mail : onestone@beryl-project.org
+ *
+ * Copyright : (C) 2006 Quinn Storm
+ * E-mail : quinnstorm@beryl-project.org
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
+
+#include <beryl.h>
+
+#define ZOOM_IN_BUTTON_DEFAULT Button4
+#define ZOOM_IN_MODIFIERS_DEFAULT CompSuperMask
+
+#define ZOOM_OUT_BUTTON_DEFAULT Button5
+#define ZOOM_OUT_MODIFIERS_DEFAULT CompSuperMask
+
+#define ZOOM_SPEED_DEFAULT 1.00f
+#define ZOOM_SPEED_MIN 0.1f
+#define ZOOM_SPEED_MAX 4.0f
+#define ZOOM_SPEED_PRECISION 0.1f
+
+#define ZOOM_STEP_DEFAULT 1.25f
+#define ZOOM_STEP_MIN 1.05f
+#define ZOOM_STEP_MAX 5.0f
+#define ZOOM_STEP_PRECISION 0.05f
+
+#define ZOOM_MAX_FACTOR_DEFAULT 16.0f
+#define ZOOM_MAX_FACTOR_MIN 1.1f
+#define ZOOM_MAX_FACTOR_MAX 64.0f
+#define ZOOM_MAX_FACTOR_PRECISION 0.1f
+
+#define ZOOM_TIMESTEP_DEFAULT 1.2f
+#define ZOOM_TIMESTEP_MIN 0.1f
+#define ZOOM_TIMESTEP_MAX 20.0f
+#define ZOOM_TIMESTEP_PRECISION 0.1f
+
+#define ZOOM_FILTER_LINEAR_DEFAULT TRUE
+
+#define ZOOM_HIDE_NORMAL_CURSOR_DEFAULT FALSE
+#define ZOOM_SHOW_SCALED_CURSOR_DEFAULT TRUE
+
+static int displayPrivateIndex;
+
+#define ZOOM_DISPLAY_OPTION_IN 0
+#define ZOOM_DISPLAY_OPTION_OUT 1
+#define ZOOM_DISPLAY_OPTION_NUM 2
+
+typedef struct _ZoomDisplay
+{
+ int screenPrivateIndex;
+ HandleEventProc handleEvent;
+
+ Bool fixesSupported;
+ int fixesEventBase;
+ int fixesErrorBase;
+ Bool canHideCursor;
+
+ CompOption opt[ZOOM_DISPLAY_OPTION_NUM];
+} ZoomDisplay;
+
+#define ZOOM_SCREEN_OPTION_SPEED 0
+#define ZOOM_SCREEN_OPTION_STEP 1
+#define ZOOM_SCREEN_OPTION_MAX_FACTOR 2
+#define ZOOM_SCREEN_OPTION_TIMESTEP 3
+#define ZOOM_SCREEN_OPTION_FILTER_LINEAR 4
+#define ZOOM_SCREEN_OPTION_HIDE_NORMAL_CURSOR 5
+#define ZOOM_SCREEN_OPTION_SHOW_SCALED_CURSOR 6
+#define ZOOM_SCREEN_OPTION_NUM 7
+
+typedef struct _CursorTexture
+{
+ Bool isSet;
+ GLuint texture;
+ int width;
+ int height;
+ int hotX;
+ int hotY;
+} CursorTexture;
+
+typedef struct _ZoomScreen
+{
+ PreparePaintScreenProc preparePaintScreen;
+ DonePaintScreenProc donePaintScreen;
+ PaintScreenProc paintScreen;
+ SetScreenOptionForPluginProc setScreenOptionForPlugin;
+
+ CompOption opt[ZOOM_SCREEN_OPTION_NUM];
+
+ float speed;
+ float step;
+ float timestep;
+ float maxScale;
+
+ GLfloat currentScale;
+ GLfloat newScale;
+
+ GLfloat zVelocity;
+
+ GLfloat xtrans;
+ GLfloat ytrans;
+ GLfloat ztrans;
+
+ GLfloat xscale;
+ GLfloat yscale;
+
+ Bool active;
+
+ CursorTexture cursor;
+ int mouseX;
+ int mouseY;
+ Bool cursorHidden;
+ Bool cursorInfoSelected;
+ Bool showScaled;
+ Bool hideNormal;
+
+ float maxTranslate;
+} ZoomScreen;
+
+#define GET_ZOOM_DISPLAY(d) \
+ ((ZoomDisplay *) (d)->privates[displayPrivateIndex].ptr)
+
+#define ZOOM_DISPLAY(d) \
+ ZoomDisplay *zd = GET_ZOOM_DISPLAY (d)
+
+#define GET_ZOOM_SCREEN(s, zd) \
+ ((ZoomScreen *) (s)->privates[(zd)->screenPrivateIndex].ptr)
+
+#define ZOOM_SCREEN(s) \
+ ZoomScreen *zs = GET_ZOOM_SCREEN (s, GET_ZOOM_DISPLAY (s->display))
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+
+static void
+updateCursor (Display *dpy,CursorTexture * cursor)
+{
+ glEnable (GL_TEXTURE_RECTANGLE_ARB);
+ if (!cursor->isSet)
+ {
+ cursor->isSet = TRUE;
+ glGenTextures (1, &cursor->texture);
+ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, cursor->texture);
+ glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ }
+
+ XFixesCursorImage * ci = XFixesGetCursorImage(dpy);
+ cursor->width = ci->width;
+ cursor->height = ci->height;
+ cursor->hotX = ci->xhot;
+ cursor->hotY = ci->yhot;
+
+ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, cursor->texture);
+ glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0 , GL_RGBA, cursor->width, cursor->height,
+ 0, GL_BGRA, GL_UNSIGNED_BYTE, ci->pixels);
+ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
+ glDisable (GL_TEXTURE_RECTANGLE_ARB);
+ XFree (ci);
+}
+
+static void
+freeCursor (CursorTexture * cursor)
+{
+ if (!cursor->isSet)
+ return;
+ cursor->isSet = FALSE;glEnable (GL_TEXTURE_RECTANGLE_ARB);
+ glDeleteTextures (1, &cursor->texture);
+ cursor->texture = 0;
+}
+
+static void
+zoomHandleEvent (CompDisplay * d, XEvent * event)
+{
+ CompScreen *s;
+
+ ZOOM_DISPLAY (d);
+
+ if (event->type == zd->fixesEventBase + XFixesCursorNotify)
+ {
+ XFixesCursorNotifyEvent *cev = (XFixesCursorNotifyEvent *) event;
+ s = findScreenAtDisplay (d, cev->window);
+ if (s)
+ {
+ ZOOM_SCREEN(s);
+ if (zs->cursor.isSet)
+ updateCursor (d->display, &zs->cursor);
+ }
+ }
+
+ UNWRAP (zd, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (zd, d, handleEvent, zoomHandleEvent);
+}
+
+static Bool
+zoomSetScreenOption (CompScreen * screen, char *name, CompOptionValue * value)
+{
+ CompOption *o;
+ int index;
+
+ ZOOM_SCREEN (screen);
+
+ o = compFindOption (zs->opt, NUM_OPTIONS (zs), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index)
+ {
+ case ZOOM_SCREEN_OPTION_STEP:
+ if (compSetFloatOption (o, value))
+ {
+ zs->step = o->value.f;
+ return TRUE;
+ }
+ break;
+ case ZOOM_SCREEN_OPTION_MAX_FACTOR:
+ if (compSetFloatOption (o, value))
+ {
+ zs->maxScale = o->value.f;
+ return TRUE;
+ }
+ break;
+ case ZOOM_SCREEN_OPTION_SPEED:
+ if (compSetFloatOption (o, value))
+ {
+ zs->speed = o->value.f;
+ return TRUE;
+ }
+ break;
+ case ZOOM_SCREEN_OPTION_TIMESTEP:
+ if (compSetFloatOption (o, value))
+ {
+ zs->timestep = o->value.f;
+ return TRUE;
+ }
+ break;
+ case ZOOM_SCREEN_OPTION_FILTER_LINEAR:
+ if (compSetBoolOption (o, value))
+ return TRUE;
+ case ZOOM_SCREEN_OPTION_HIDE_NORMAL_CURSOR:
+ if (compSetBoolOption (o, value))
+ {
+ zs->hideNormal = o->value.b;
+ return TRUE;
+ }
+ break;
+ case ZOOM_SCREEN_OPTION_SHOW_SCALED_CURSOR:
+ if (compSetBoolOption (o, value))
+ {
+ zs->showScaled = o->value.b;
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+zoomScreenInitOptions (ZoomScreen * zs)
+{
+ CompOption *o;
+
+ o = &zs->opt[ZOOM_SCREEN_OPTION_SPEED];
+ o->name = "speed";
+ o->shortDesc = N_("Speed");
+ o->longDesc = N_("Zoom Speed");
+ o->type = CompOptionTypeFloat;
+ o->value.f = ZOOM_SPEED_DEFAULT;
+ o->rest.f.min = ZOOM_SPEED_MIN;
+ o->rest.f.max = ZOOM_SPEED_MAX;
+ o->rest.f.precision = ZOOM_SPEED_PRECISION;
+
+ o = &zs->opt[ZOOM_SCREEN_OPTION_STEP];
+ o->name = "step";
+ o->shortDesc = N_("Step");
+ o->longDesc =
+ N_
+ ("Zoomfactor multiplicator for amount of zooming in each zoomIn / zoomOut");
+ o->type = CompOptionTypeFloat;
+ o->value.f = ZOOM_STEP_DEFAULT;
+ o->rest.f.min = ZOOM_STEP_MIN;
+ o->rest.f.max = ZOOM_STEP_MAX;
+ o->rest.f.precision = ZOOM_STEP_PRECISION;
+
+ o = &zs->opt[ZOOM_SCREEN_OPTION_MAX_FACTOR];
+ o->name = "max";
+ o->shortDesc = N_("Maximum Zoom");
+ o->longDesc = N_("Maximum Zoom Factor");
+ o->type = CompOptionTypeFloat;
+ o->value.f = ZOOM_MAX_FACTOR_DEFAULT;
+ o->rest.f.min = ZOOM_MAX_FACTOR_MIN;
+ o->rest.f.max = ZOOM_MAX_FACTOR_MAX;
+ o->rest.f.precision = ZOOM_MAX_FACTOR_PRECISION;
+
+ o = &zs->opt[ZOOM_SCREEN_OPTION_TIMESTEP];
+ o->name = "timestep";
+ o->shortDesc = N_("Timestep");
+ o->longDesc = N_("Zoom Timestep");
+ o->type = CompOptionTypeFloat;
+ o->value.f = ZOOM_TIMESTEP_DEFAULT;
+ o->rest.f.min = ZOOM_TIMESTEP_MIN;
+ o->rest.f.max = ZOOM_TIMESTEP_MAX;
+ o->rest.f.precision = ZOOM_TIMESTEP_PRECISION;
+
+ o = &zs->opt[ZOOM_SCREEN_OPTION_FILTER_LINEAR];
+ o->name = "filter_linear";
+ o->shortDesc = N_("Filter Linear");
+ o->longDesc = N_("Use linear filter when zoomed in");
+ o->type = CompOptionTypeBool;
+ o->value.b = ZOOM_FILTER_LINEAR_DEFAULT;
+
+ o = &zs->opt[ZOOM_SCREEN_OPTION_HIDE_NORMAL_CURSOR];
+ o->name = "hide_normal";
+ o->shortDesc = N_("Hide normal cursor");
+ o->longDesc = N_("Hide normal cursor during zoom");
+ o->type = CompOptionTypeBool;
+ o->value.b = ZOOM_HIDE_NORMAL_CURSOR_DEFAULT;
+
+ o = &zs->opt[ZOOM_SCREEN_OPTION_SHOW_SCALED_CURSOR];
+ o->name = "show_scaled";
+ o->shortDesc = N_("Show scaled cursor");
+ o->longDesc = N_("Show scaled cursor during zoom");
+ o->type = CompOptionTypeBool;
+ o->value.b = ZOOM_SHOW_SCALED_CURSOR_DEFAULT;
+}
+static CompOption *
+zoomGetScreenOptions (CompScreen * screen, int *count)
+{
+ if (screen)
+ {
+ ZOOM_SCREEN (screen);
+
+ *count = NUM_OPTIONS (zs);
+ return zs->opt;
+ }
+ else
+ {
+ ZoomScreen * zs = malloc(sizeof(ZoomScreen));
+ zoomScreenInitOptions(zs);
+ *count = NUM_OPTIONS (zs);
+ return zs->opt;
+ }
+}
+
+
+static int
+adjustZoomVelocity (ZoomScreen * zs)
+{
+ float d, adjust, amount;
+
+ d = (zs->newScale - zs->currentScale) * 75.0f;
+
+ adjust = d * 0.002f;
+ amount = fabs (d);
+ if (amount < 1.0f)
+ amount = 1.0f;
+ else if (amount > 5.0f)
+ amount = 5.0f;
+
+ zs->zVelocity = (amount * zs->zVelocity + adjust) / (amount + 1.0f);
+
+ return (fabs (d) < 0.1f && fabs (zs->zVelocity) < 0.005f);
+}
+
+static void
+zoomPreparePaintScreen (CompScreen * s, int msSinceLastPaint)
+{
+ ZOOM_SCREEN (s);
+ ZOOM_DISPLAY (s->display);
+
+ if (zs->active)
+ {
+ int steps;
+ float amount, chunk;
+
+ amount = msSinceLastPaint * 0.05f * zs->speed;
+ steps = amount / (0.5f * zs->timestep);
+ if (!steps)
+ steps = 1;
+ chunk = amount / (float)steps;
+
+ while (steps--)
+ {
+
+ if (adjustZoomVelocity (zs))
+ {
+ zs->currentScale = zs->newScale;
+ zs->zVelocity = 0.0f;
+ }
+ else
+ {
+ zs->currentScale += (zs->zVelocity * msSinceLastPaint) /
+ s->redrawTime;
+ }
+
+ zs->xscale = zs->currentScale;
+ zs->yscale = zs->currentScale;
+
+ if (zs->currentScale == 1.0f && zs->zVelocity == 0.0f)
+ {
+ zs->active = FALSE;
+ break;
+ }
+
+ }
+ int winX,winY;
+ unsigned int mask_return;
+ Window root_return;
+ Window child_return;
+
+
+ XQueryPointer(s->display->display, s->root, &root_return, &child_return,
+ &zs->mouseX, &zs->mouseY, &winX, &winY, &mask_return);
+
+ zs->xtrans = -((((zs->mouseX - (s->width / 2.0))) / (s->width)) * zs->xscale - ((zs->mouseX - (s->width / 2.0)) / (s->width)));
+ zs->ytrans = ((((zs->mouseY - (s->height / 2.0))) / (s->height)) * zs->yscale - (((zs->mouseY - (s->height / 2.0))) / (s->height)));
+
+
+ if (zs->currentScale == 1.0f && zs->zVelocity == 0.0f)
+ {
+ zs->active = FALSE;
+ }
+ }
+
+ if (!zs->active && zd->fixesSupported && zs->cursorInfoSelected)
+ {
+ zs->cursorInfoSelected = FALSE;
+ XFixesSelectCursorInput (s->display->display,s->root,0);
+ }
+ if (!zs->active && zs->cursor.isSet)
+ {
+ freeCursor (&zs->cursor);
+ }
+ if (zd->canHideCursor && !zs->active && zs->cursorHidden)
+ {
+ zs->cursorHidden = FALSE;
+ XFixesShowCursor (s->display->display, s->root);
+ }
+
+ UNWRAP (zs, s, preparePaintScreen);
+ (*s->preparePaintScreen) (s, msSinceLastPaint);
+ WRAP (zs, s, preparePaintScreen, zoomPreparePaintScreen);
+}
+
+static void
+zoomDonePaintScreen (CompScreen * s)
+{
+ ZOOM_SCREEN (s);
+
+ if (zs->active)
+ {
+ damageScreen (s);
+ }
+
+ UNWRAP (zs, s, donePaintScreen);
+ (*s->donePaintScreen) (s);
+ WRAP (zs, s, donePaintScreen, zoomDonePaintScreen);
+}
+
+static Bool
+zoomPaintScreen (CompScreen * s,
+ const ScreenPaintAttrib * sAttrib,
+ Region region, int output, unsigned int mask)
+{
+ Bool status;
+
+ ZOOM_SCREEN (s);
+
+ if (zs->active)
+ {
+ ScreenPaintAttrib sa = *sAttrib;
+ int saveFilter;
+
+ sa.xTranslate += zs->xtrans;
+ sa.yTranslate += zs->ytrans;
+
+ sa.xScale = zs->xscale;
+ sa.yScale = zs->yscale;
+
+ /* hack to get sides rendered correctly */
+ if (zs->xtrans > 0.0f)
+ sa.xRotate += 0.000001f;
+ else
+ sa.xRotate -= 0.000001f;
+
+ mask &= ~PAINT_SCREEN_REGION_MASK;
+ mask |= PAINT_SCREEN_TRANSFORMED_MASK | PAINT_SCREEN_CLEAR_MASK;
+
+ saveFilter = s->filter[SCREEN_TRANS_FILTER];
+
+ if (zs->opt[ZOOM_SCREEN_OPTION_FILTER_LINEAR].value.b ||
+ zs->zVelocity != 0.0f)
+ s->filter[SCREEN_TRANS_FILTER] = COMP_TEXTURE_FILTER_GOOD;
+ else
+ s->filter[SCREEN_TRANS_FILTER] = COMP_TEXTURE_FILTER_FAST;
+
+
+ UNWRAP (zs, s, paintScreen);
+ status = (*s->paintScreen) (s, &sa, region, output, mask);
+ WRAP (zs, s, paintScreen, zoomPaintScreen);
+
+ if (zs->cursor.isSet)
+ {
+ glPushMatrix ();
+ glLoadIdentity ();
+ glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
+ glScalef (1.0f / s->width, -1.0f / s->height, 1.0f);
+ glTranslatef (0.0f, -s->height, 0.0f);
+
+ glTranslatef (zs->mouseX, zs->mouseY, 0.0);
+ glScalef (zs->xscale, zs->yscale, 1.0f);
+ int x = - zs->cursor.hotX;
+ int y = - zs->cursor.hotY;
+ glEnable (GL_BLEND);
+ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, zs->cursor.texture);
+ glEnable (GL_TEXTURE_RECTANGLE_ARB);
+
+ glBegin (GL_QUADS);
+ glTexCoord2d(0,0);
+ glVertex2f(x,y);
+ glTexCoord2d(0, zs->cursor.height);
+ glVertex2f(x,y + zs->cursor.height);
+ glTexCoord2d(zs->cursor.width, zs->cursor.height);
+ glVertex2f(x + zs->cursor.width, y + zs->cursor.height);
+ glTexCoord2d(zs->cursor.width, 0);
+ glVertex2f(x + zs->cursor.width,y);
+ glEnd ();
+
+ glDisable (GL_BLEND);
+
+ glDisable (GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
+
+ glPopMatrix ();
+ }
+
+ s->filter[SCREEN_TRANS_FILTER] = saveFilter;
+ }
+ else
+ {
+ UNWRAP (zs, s, paintScreen);
+ status = (*s->paintScreen) (s, sAttrib, region, output, mask);
+ WRAP (zs, s, paintScreen, zoomPaintScreen);
+ }
+
+ return status;
+}
+
+static Bool
+zoomIn (CompDisplay * d,
+ CompAction * action,
+ CompActionState state, CompOption * option, int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ ZOOM_DISPLAY (d);
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ ZOOM_SCREEN (s);
+
+ zs->active = TRUE;
+
+ if (zd->fixesSupported && !zs->cursorInfoSelected && zs->showScaled)
+ {
+ zs->cursorInfoSelected = TRUE;
+ XFixesSelectCursorInput (s->display->display,s->root,XFixesDisplayCursorNotifyMask);
+ updateCursor (d->display, &zs->cursor);
+ }
+ if (zd->canHideCursor && !zs->cursorHidden && zs->hideNormal)
+ {
+ zs->cursorHidden = TRUE;
+ XFixesHideCursor (d->display, s->root);
+ }
+
+ zs->newScale *= zs->step;
+ if (zs->newScale > zs->maxScale)
+ zs->newScale = zs->maxScale;
+
+ damageScreen (s);
+ }
+
+ return FALSE;
+}
+
+static Bool
+zoomOut (CompDisplay * d,
+ CompAction * action,
+ CompActionState state, CompOption * option, int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ ZOOM_DISPLAY (d);
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ ZOOM_SCREEN (s);
+
+ zs->active = TRUE;
+
+ if (zd->fixesSupported && !zs->cursorInfoSelected && zs->showScaled)
+ {
+ zs->cursorInfoSelected = TRUE;
+ XFixesSelectCursorInput (s->display->display,s->root,XFixesDisplayCursorNotifyMask);
+ updateCursor (d->display, &zs->cursor);
+ }
+ if (zd->canHideCursor && !zs->cursorHidden && zs->hideNormal)
+ {
+ zs->cursorHidden = TRUE;
+ XFixesHideCursor (d->display, s->root);
+ }
+
+ zs->newScale /= zs->step;
+ if (zs->newScale < 1.0)
+ zs->newScale = 1.0;
+
+ damageScreen (s);
+ }
+
+ return TRUE;
+}
+
+static void
+zoomUpdateCubeOptions (CompScreen * s)
+{
+ CompPlugin *p;
+
+ ZOOM_SCREEN (s);
+
+ p = findActivePlugin ("cube");
+ if (p && p->vTable->getScreenOptions)
+ {
+ CompOption *options, *option;
+ int nOptions;
+
+ options = (*p->vTable->getScreenOptions) (s, &nOptions);
+ option = compFindOption (options, nOptions, "in", 0);
+ if (option)
+ zs->maxTranslate = option->value.b ? 0.85f : 1.5f;
+ }
+ else
+ {
+ zs->maxTranslate = 1.5f;
+ }
+}
+
+static Bool
+zoomSetScreenOptionForPlugin (CompScreen * s,
+ char *plugin,
+ char *name, CompOptionValue * value)
+{
+ Bool status;
+
+ ZOOM_SCREEN (s);
+
+ UNWRAP (zs, s, setScreenOptionForPlugin);
+ status = (*s->setScreenOptionForPlugin) (s, plugin, name, value);
+ WRAP (zs, s, setScreenOptionForPlugin, zoomSetScreenOptionForPlugin);
+
+ if (status && strcmp (plugin, "cube") == 0)
+ zoomUpdateCubeOptions (s);
+
+ return status;
+}
+
+static Bool
+zoomSetDisplayOption (CompDisplay * display,
+ char *name, CompOptionValue * value)
+{
+ CompOption *o;
+ int index;
+
+ ZOOM_DISPLAY (display);
+
+ o = compFindOption (zd->opt, NUM_OPTIONS (zd), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index)
+ {
+ case ZOOM_DISPLAY_OPTION_IN:
+ if (setDisplayAction (display, o, value))
+ return TRUE;
+ break;
+ case ZOOM_DISPLAY_OPTION_OUT:
+ if (setDisplayAction (display, o, value))
+ return TRUE;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+zoomDisplayInitOptions (ZoomDisplay * zd)
+{
+ CompOption *o;
+
+ o = &zd->opt[ZOOM_DISPLAY_OPTION_IN];
+ o->name = "zoom_in";
+ o->shortDesc = N_("Zoom In");
+ o->longDesc = N_("Zoom In");
+ o->type = CompOptionTypeAction;
+ o->value.action.initiate = zoomIn;
+ o->value.action.terminate = 0;
+ o->value.action.bell = FALSE;
+ o->value.action.edgeMask = 0;
+ o->value.action.state = CompActionStateInitKey;
+ o->value.action.state |= CompActionStateInitButton;
+ o->value.action.type = CompBindingTypeButton;
+ o->value.action.button.modifiers = ZOOM_IN_MODIFIERS_DEFAULT;
+ o->value.action.button.button = ZOOM_IN_BUTTON_DEFAULT;
+
+ o = &zd->opt[ZOOM_DISPLAY_OPTION_OUT];
+ o->name = "zoom_out";
+ o->shortDesc = N_("Zoom Out");
+ o->longDesc = N_("Zoom Out");
+ o->type = CompOptionTypeAction;
+ o->value.action.initiate = zoomOut;
+ o->value.action.terminate = 0;
+ o->value.action.bell = FALSE;
+ o->value.action.edgeMask = 0;
+ o->value.action.state = CompActionStateInitKey;
+ o->value.action.state |= CompActionStateInitButton;
+ o->value.action.type = CompBindingTypeButton;
+ o->value.action.button.modifiers = ZOOM_OUT_MODIFIERS_DEFAULT;
+ o->value.action.button.button = ZOOM_OUT_BUTTON_DEFAULT;
+}
+
+static CompOption *
+zoomGetDisplayOptions (CompDisplay * display, int *count)
+{
+ if (display)
+ {
+ ZOOM_DISPLAY (display);
+
+ *count = NUM_OPTIONS (zd);
+ return zd->opt;
+ }
+ else
+ {
+ ZoomDisplay * zd = malloc(sizeof(ZoomDisplay));
+ zoomDisplayInitOptions(zd);
+ *count = NUM_OPTIONS (zd);
+ return zd->opt;
+ }
+}
+
+static Bool
+zoomInitDisplay (CompPlugin * p, CompDisplay * d)
+{
+ ZoomDisplay *zd;
+
+ zd = malloc (sizeof (ZoomDisplay));
+ if (!zd)
+ return FALSE;
+
+ zd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (zd->screenPrivateIndex < 0)
+ {
+ free (zd);
+ return FALSE;
+ }
+
+ zoomDisplayInitOptions (zd);
+
+ WRAP (zd, d, handleEvent, zoomHandleEvent);
+
+ d->privates[displayPrivateIndex].ptr = zd;
+
+
+ zd->fixesSupported = XFixesQueryExtension (d->display, &zd->fixesEventBase, &zd->fixesErrorBase);
+
+ int minor,major;
+
+ XFixesQueryVersion (d->display, &major, &minor);
+
+ if (major >= 4)
+ zd->canHideCursor = TRUE;
+ else
+ zd->canHideCursor = FALSE;
+
+ return TRUE;
+}
+
+static void
+zoomFiniDisplay (CompPlugin * p, CompDisplay * d)
+{
+ ZOOM_DISPLAY (d);
+
+ UNWRAP (zd, d, handleEvent);
+ freeScreenPrivateIndex (d, zd->screenPrivateIndex);
+
+ free (zd);
+}
+
+static Bool
+zoomInitScreen (CompPlugin * p, CompScreen * s)
+{
+ ZoomScreen *zs;
+
+ ZOOM_DISPLAY (s->display);
+
+ zs = malloc (sizeof (ZoomScreen));
+ if (!zs)
+ return FALSE;
+
+ zs->active = FALSE;
+
+ zs->currentScale = 1.0f;
+ zs->newScale = 1.0f;
+
+ zs->zVelocity = 0.0f;
+
+ zs->maxTranslate = 0.85f;
+
+ zs->speed = ZOOM_SPEED_DEFAULT;
+ zs->step = ZOOM_STEP_DEFAULT;
+ zs->maxScale = ZOOM_MAX_FACTOR_DEFAULT;
+ zs->timestep = ZOOM_TIMESTEP_DEFAULT;
+
+ zoomScreenInitOptions (zs);
+
+ addScreenAction (s, &zd->opt[ZOOM_DISPLAY_OPTION_IN].value.action);
+ addScreenAction (s, &zd->opt[ZOOM_DISPLAY_OPTION_OUT].value.action);
+
+ WRAP (zs, s, preparePaintScreen, zoomPreparePaintScreen);
+ WRAP (zs, s, donePaintScreen, zoomDonePaintScreen);
+ WRAP (zs, s, paintScreen, zoomPaintScreen);
+ WRAP (zs, s, setScreenOptionForPlugin, zoomSetScreenOptionForPlugin);
+
+ s->privates[zd->screenPrivateIndex].ptr = zs;
+
+ zoomUpdateCubeOptions (s);
+
+ zs->cursor.isSet = FALSE;
+ zs->cursorHidden = FALSE;
+ zs->cursorInfoSelected = FALSE;
+
+ zs->showScaled = ZOOM_SHOW_SCALED_CURSOR_DEFAULT;
+ zs->hideNormal = ZOOM_HIDE_NORMAL_CURSOR_DEFAULT;
+
+ return TRUE;
+}
+
+static void
+zoomFiniScreen (CompPlugin * p, CompScreen * s)
+{
+ ZOOM_SCREEN (s);
+
+ UNWRAP (zs, s, preparePaintScreen);
+ UNWRAP (zs, s, donePaintScreen);
+ UNWRAP (zs, s, paintScreen);
+ UNWRAP (zs, s, setScreenOptionForPlugin);
+
+ free (zs);
+}
+
+
+static Bool
+zoomInit (CompPlugin * p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+zoomFini (CompPlugin * p)
+{
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+CompPluginVTable zoomVTable = {
+ "inputzoom",
+ N_("Input enabled Zoom"),
+ N_("Input Enabled Zoom"),
+ zoomInit,
+ zoomFini,
+ zoomInitDisplay,
+ zoomFiniDisplay,
+ zoomInitScreen,
+ zoomFiniScreen,
+ 0,
+ 0,
+ zoomGetDisplayOptions,
+ zoomSetDisplayOption,
+ zoomGetScreenOptions,
+ zoomSetScreenOption,
+ 0,
+ 0,
+ 0,
+ 0,
+ BERYL_ABI_INFO,
+ "beryl-plugins"
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ return &zoomVTable;
+}