/*
* Copyright © 2005 Novell, Inc.
*
* 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.
*
* Author: David Reveman <davidr@novell.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/time.h>
#include <beryl.h>
#define ZOOM_POINTER_INVERT_Y_DEFAULT FALSE
#define ZOOM_POINTER_SENSITIVITY_DEFAULT 1.0f
#define ZOOM_POINTER_SENSITIVITY_MIN 0.01f
#define ZOOM_POINTER_SENSITIVITY_MAX 100.0f
#define ZOOM_POINTER_SENSITIVITY_PRECISION 0.01f
#define ZOOM_POINTER_SENSITIVITY_FACTOR 0.001f
#define ZOOM_INITIATE_BUTTON_DEFAULT Button3
#define ZOOM_INITIATE_MODIFIERS_DEFAULT CompSuperMask
#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.5f
#define ZOOM_SPEED_MIN 0.1f
#define ZOOM_SPEED_MAX 50.0f
#define ZOOM_SPEED_PRECISION 0.1f
#define ZOOM_STEP_DEFAULT 2.0f
#define ZOOM_STEP_MIN 1.0f
#define ZOOM_STEP_MAX 5.0f
#define ZOOM_STEP_PRECISION 0.01f
#define ZOOM_MIN_DEFAULT 0.1f
#define ZOOM_MIN_MIN 0.0f
#define ZOOM_MIN_MAX 1.0f
#define ZOOM_MIN_PRECISION 0.01f
#define ZOOM_MAX_DEFAULT 1.0f
#define ZOOM_MAX_MIN 1.0f
#define ZOOM_MAX_MAX 100.0f
#define ZOOM_MAX_PRECISION 0.01f
#define ZOOM_TIMESTEP_DEFAULT 1.2f
#define ZOOM_TIMESTEP_MIN 0.1f
#define ZOOM_TIMESTEP_MAX 50.0f
#define ZOOM_TIMESTEP_PRECISION 0.1f
#define ZOOM_FILTER_LINEAR_DEFAULT TRUE
#define ZOOM_ALLOW_KEYBOARD_INPUT_DEFAULT TRUE
static int displayPrivateIndex;
#define ZOOM_DISPLAY_OPTION_INITIATE 0
#define ZOOM_DISPLAY_OPTION_IN 1
#define ZOOM_DISPLAY_OPTION_OUT 2
#define ZOOM_DISPLAY_OPTION_NUM 3
typedef struct _ZoomDisplay
{
int screenPrivateIndex;
HandleEventProc handleEvent;
CompOption opt[ZOOM_DISPLAY_OPTION_NUM];
} ZoomDisplay;
#define ZOOM_SCREEN_OPTION_POINTER_INVERT_Y 0
#define ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY 1
#define ZOOM_SCREEN_OPTION_SPEED 2
#define ZOOM_SCREEN_OPTION_STEP 3
#define ZOOM_SCREEN_OPTION_MIN 4
#define ZOOM_SCREEN_OPTION_MAX 5
#define ZOOM_SCREEN_OPTION_TIMESTEP 6
#define ZOOM_SCREEN_OPTION_FILTER_LINEAR 7
#define ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT 8
#define ZOOM_SCREEN_OPTION_NUM 9
typedef struct _ZoomScreen
{
PreparePaintScreenProc preparePaintScreen;
DonePaintScreenProc donePaintScreen;
PaintScreenProc paintScreen;
SetScreenOptionForPluginProc setScreenOptionForPlugin;
CompOption opt[ZOOM_SCREEN_OPTION_NUM];
Bool pointerInvertY;
float pointerSensitivity;
float speed;
float step;
float timestep;
float minZoom;
float maxZoom;
int grabIndex;
GLfloat currentZoom;
GLfloat newZoom;
GLfloat xVelocity;
GLfloat yVelocity;
GLfloat zVelocity;
GLfloat xTranslate;
GLfloat yTranslate;
GLfloat xtrans;
GLfloat ytrans;
GLfloat ztrans;
XPoint savedPointer;
Bool grabbed;
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 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_POINTER_INVERT_Y:
if (compSetBoolOption(o, value))
{
zs->pointerInvertY = o->value.b;
return TRUE;
}
break;
case ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY:
if (compSetFloatOption(o, value))
{
zs->pointerSensitivity = o->value.f *
ZOOM_POINTER_SENSITIVITY_FACTOR;
return TRUE;
}
break;
case ZOOM_SCREEN_OPTION_STEP:
if (compSetFloatOption(o, value))
{
zs->step = o->value.f;
return TRUE;
}
break;
case ZOOM_SCREEN_OPTION_MIN:
if (compSetFloatOption(o, value))
{
zs->minZoom = o->value.f;
return TRUE;
}
break;
case ZOOM_SCREEN_OPTION_MAX:
if (compSetFloatOption(o, value))
{
zs->maxZoom = 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_ALLOW_KEYBOARD_INPUT:
if (compSetBoolOption(o, value))
return TRUE;
default:
break;
}
return FALSE;
}
static void zoomScreenInitOptions(ZoomScreen * zs)
{
CompOption *o;
o = &zs->opt[ZOOM_SCREEN_OPTION_POINTER_INVERT_Y];
o->advanced = False;
o->name = "invert_y";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Pointer Invert Y");
o->longDesc = N_("Invert Y axis for Pointer movement.");
o->type = CompOptionTypeBool;
o->value.b = ZOOM_POINTER_INVERT_Y_DEFAULT;
o = &zs->opt[ZOOM_SCREEN_OPTION_POINTER_SENSITIVITY];
o->advanced = False;
o->name = "sensitivity";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Pointer Sensitivity");
o->longDesc = N_("Sensitivity of Pointer movement.");
o->type = CompOptionTypeFloat;
o->value.f = ZOOM_POINTER_SENSITIVITY_DEFAULT;
o->rest.f.min = ZOOM_POINTER_SENSITIVITY_MIN;
o->rest.f.max = ZOOM_POINTER_SENSITIVITY_MAX;
o->rest.f.precision = ZOOM_POINTER_SENSITIVITY_PRECISION;
o = &zs->opt[ZOOM_SCREEN_OPTION_SPEED];
o->advanced = False;
o->name = "speed";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
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->advanced = False;
o->name = "step";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Zoom Step");
o->longDesc = N_("Zoom factor multiplier for amount of Zooming "
"in each ZoomIn/ZoomOut.");
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_MIN];
o->advanced = False;
o->name = "min";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Minimum Zoom");
o->longDesc = N_("Minimum Zoom Value (how close you can zoom).");
o->type = CompOptionTypeFloat;
o->value.f = ZOOM_MIN_DEFAULT;
o->rest.f.min = ZOOM_MIN_MIN;
o->rest.f.max = ZOOM_MIN_MAX;
o->rest.f.precision = ZOOM_MIN_PRECISION;
o = &zs->opt[ZOOM_SCREEN_OPTION_MAX];
o->advanced = False;
o->name = "max";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Maximum Zoom");
o->longDesc = N_("Maximum Zoom Value (how far you can zoom away).");
o->type = CompOptionTypeFloat;
o->value.f = ZOOM_MAX_DEFAULT;
o->rest.f.min = ZOOM_MAX_MIN;
o->rest.f.max = ZOOM_MAX_MAX;
o->rest.f.precision = ZOOM_MAX_PRECISION;
o = &zs->opt[ZOOM_SCREEN_OPTION_TIMESTEP];
o->advanced = False;
o->name = "timestep";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Zoom 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->advanced = False;
o->name = "filter_linear";
o->group = N_("Misc. options");
o->subGroup = N_("Visual quality");
o->displayHints = "";
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_ALLOW_KEYBOARD_INPUT];
o->advanced = False;
o->name = "allow_keyboard_input";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Allow Keyboard Input");
o->longDesc = N_("Allow Keyboard Input when Zoomed.");
o->type = CompOptionTypeBool;
o->value.b = ZOOM_ALLOW_KEYBOARD_INPUT_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->newZoom - zs->currentZoom) * 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);
if (zs->grabIndex)
{
compDisplaySetRequestFlagForPlugin(s->display, "zoom", "ENABLE_3D");
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--)
{
zs->xVelocity /= 1.25f;
zs->yVelocity /= 1.25f;
if (fabs(zs->xVelocity) < 0.001f)
zs->xVelocity = 0.0f;
if (fabs(zs->yVelocity) < 0.001f)
zs->yVelocity = 0.0f;
zs->xTranslate += zs->xVelocity * chunk;
if (zs->xTranslate < -zs->maxTranslate)
{
zs->xTranslate = -zs->maxTranslate;
zs->xVelocity = 0.0f;
}
else if (zs->xTranslate > zs->maxTranslate)
{
zs->xTranslate = zs->maxTranslate;
zs->xVelocity = 0.0f;
}
zs->yTranslate += zs->yVelocity * chunk;
if (zs->yTranslate < -zs->maxTranslate)
{
zs->yTranslate = -zs->maxTranslate;
zs->yVelocity = 0.0f;
}
else if (zs->yTranslate > zs->maxTranslate)
{
zs->yTranslate = zs->maxTranslate;
zs->yVelocity = 0.0f;
}
if (adjustZoomVelocity(zs))
{
zs->currentZoom = zs->newZoom;
zs->zVelocity = 0.0f;
}
else
{
zs->currentZoom +=
(zs->zVelocity * msSinceLastPaint) / s->redrawTime;
}
zs->ztrans = DEFAULT_Z_CAMERA * zs->currentZoom;
if (zs->ztrans <= 0.1f)
{
zs->zVelocity = 0.0f;
zs->ztrans = 0.1f;
}
zs->xtrans = -zs->xTranslate * (1.0f - zs->currentZoom);
zs->ytrans = zs->yTranslate * (1.0f - zs->currentZoom);
if (!zs->grabbed)
{
if (zs->currentZoom == 1.0f && zs->zVelocity == 0.0f)
{
zs->xVelocity = zs->yVelocity = 0.0f;
compDisplayClearRequestFlagForPlugin
(s->display, "zoom", "ENABLE_3D");
removeScreenGrabKeyboardOptional(s,
zs->
grabIndex,
&zs->
savedPointer,
!zs->
opt
[ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT].
value.b);
zs->grabIndex = FALSE;
break;
}
}
}
}
UNWRAP(zs, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP(zs, s, preparePaintScreen, zoomPreparePaintScreen);
}
static void zoomDonePaintScreen(CompScreen * s)
{
ZOOM_SCREEN(s);
if (zs->grabIndex)
{
if (zs->currentZoom != zs->newZoom ||
zs->xVelocity || zs->yVelocity || zs->zVelocity)
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->grabIndex)
{
ScreenPaintAttrib sa = *sAttrib;
int saveFilter;
sa.xTranslate += zs->xtrans;
sa.yTranslate += zs->ytrans;
sa.zCamera = -zs->ztrans;
/* 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);
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;
xid = getIntOptionNamed(option, nOption, "root", 0);
s = findScreenAtDisplay(d, xid);
if (s)
{
ZOOM_SCREEN(s);
if (otherScreenGrabExist(s, "zoom", "scale", 0))
return FALSE;
if (!zs->grabIndex)
{
zs->grabIndex = pushScreenGrabKeyboardOptional
(s, s->invisibleCursor, "zoom",
!zs->opt[ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT].value.
b);
zs->savedPointer.x = d->pointerX;
zs->savedPointer.y = d->pointerY;
}
if (zs->grabIndex)
{
int x, y;
x = getIntOptionNamed(option, nOption, "x", 0);
y = getIntOptionNamed(option, nOption, "y", 0);
zs->grabbed = TRUE;
zs->newZoom /= zs->step;
if (zs->newZoom < zs->minZoom)
zs->newZoom = zs->minZoom;
damageScreen(s);
if (zs->currentZoom == 1.0f)
{
zs->xTranslate = (x - s->width / 2) / (s->width * 2.0f);
zs->yTranslate = (y - s->height / 2) / (s->height * 2.0f);
zs->xTranslate /= zs->newZoom;
zs->yTranslate /= zs->newZoom;
}
else if ((zs->currentZoom > 1.0f
&& zs->newZoom <= 1.0f)
|| (zs->newZoom > 0.98f && zs->newZoom < 1.02f))
{
zs->newZoom = 1.0f;
zs->grabbed = FALSE;
damageScreen(s);
}
}
}
return FALSE;
}
static Bool
zoomInitiate(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
zoomIn(d, action, state, option, nOption);
if (state & CompActionStateInitKey)
action->state |= CompActionStateTermKey;
if (state & CompActionStateInitButton)
action->state |= CompActionStateTermButton;
return FALSE;
}
static Bool
zoomOut(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
CompScreen *s;
Window xid;
xid = getIntOptionNamed(option, nOption, "root", 0);
s = findScreenAtDisplay(d, xid);
if (s)
{
ZOOM_SCREEN(s);
if (otherScreenGrabExist(s, "zoom", "scale", 0))
return FALSE;
if (!zs->grabIndex)
{
zs->grabIndex = pushScreenGrabKeyboardOptional
(s, s->invisibleCursor, "zoom",
!zs->opt[ZOOM_SCREEN_OPTION_ALLOW_KEYBOARD_INPUT].value.
b);
zs->savedPointer.x = d->pointerX;
zs->savedPointer.y = d->pointerY;
}
if (zs->grabIndex && zs->currentZoom == 1.0 && zs->maxZoom == 1.0)
{
zs->grabbed = FALSE;
damageScreen(s);
return FALSE;
}
if (zs->grabIndex)
{
int x, y;
x = getIntOptionNamed(option, nOption, "x", 0);
y = getIntOptionNamed(option, nOption, "y", 0);
zs->grabbed = TRUE;
zs->newZoom *= zs->step;
if (zs->newZoom > zs->maxZoom)
zs->newZoom = zs->maxZoom;
if (zs->currentZoom == 1.0f)
{
zs->xTranslate = (x - s->width / 2) / (s->width * 2.0f);
zs->yTranslate = (y - s->height / 2) / (s->height * 2.0f);
zs->xTranslate *= zs->newZoom;
zs->yTranslate *= zs->newZoom;
}
if ((zs->currentZoom < 1.0f && zs->newZoom >= 1.0f)
|| (zs->newZoom > 0.98f && zs->newZoom < 1.02f))
{
zs->grabbed = FALSE;
zs->newZoom = 1.0f;
}
damageScreen(s);
}
}
return FALSE;
}
static Bool
zoomTerminate(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
CompScreen *s;
Window xid;
xid = getIntOptionNamed(option, nOption, "root", 0);
for (s = d->screens; s; s = s->next)
{
ZOOM_SCREEN(s);
if (xid && s->root != xid)
continue;
if (zs->grabIndex)
{
zs->newZoom = 1.0f;
zs->grabbed = FALSE;
damageScreen(s);
}
}
action->state &= ~(CompActionStateTermKey | CompActionStateTermButton);
return FALSE;
}
static void zoomHandleEvent(CompDisplay * d, XEvent * event)
{
CompScreen *s;
ZOOM_DISPLAY(d);
switch (event->type)
{
case MotionNotify:
s = findScreenAtDisplay(d, event->xmotion.root);
if (s)
{
ZOOM_SCREEN(s);
if (zs->grabIndex && zs->grabbed)
{
GLfloat pointerDx;
GLfloat pointerDy;
pointerDx = d->pointerX - d->lastPointerX;
pointerDy = d->pointerY - d->lastPointerY;
if (event->xmotion.x_root < 50 ||
event->xmotion.y_root < 50 ||
event->xmotion.x_root > s->width - 50
|| event->xmotion.y_root > s->height - 50)
{
warpPointer(d,
(s->width / 2) -
d->pointerX, (s->height / 2) - d->pointerY);
}
if (zs->pointerInvertY)
pointerDy = -pointerDy;
zs->xVelocity += pointerDx * zs->pointerSensitivity;
zs->yVelocity += pointerDy * zs->pointerSensitivity;
damageScreen(s);
}
}
default:
break;
}
UNWRAP(zd, d, handleEvent);
(*d->handleEvent) (d, event);
WRAP(zd, d, handleEvent, zoomHandleEvent);
}
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_INITIATE:
case ZOOM_DISPLAY_OPTION_IN:
case ZOOM_DISPLAY_OPTION_OUT:
if (setDisplayAction(display, o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static void zoomDisplayInitOptions(ZoomDisplay * zd)
{
CompOption *o;
o = &zd->opt[ZOOM_DISPLAY_OPTION_INITIATE];
o->advanced = False;
o->name = "initiate";
o->group = N_("Bindings");
o->subGroup = N_("Initiate");
o->displayHints = "";
o->shortDesc = N_("Initiate");
o->longDesc = N_("Initiate Zoom.");
o->type = CompOptionTypeAction;
o->value.action.initiate = zoomInitiate;
o->value.action.terminate = zoomTerminate;
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_INITIATE_MODIFIERS_DEFAULT;
o->value.action.button.button = ZOOM_INITIATE_BUTTON_DEFAULT;
o = &zd->opt[ZOOM_DISPLAY_OPTION_IN];
o->advanced = False;
o->name = "zoom_in";
o->group = N_("Bindings");
o->subGroup = N_("Zoom In");
o->displayHints = "";
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->advanced = False;
o->name = "zoom_out";
o->group = N_("Bindings");
o->subGroup = N_("Zoom Out");
o->displayHints = "";
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;
return TRUE;
}
static void zoomFiniDisplay(CompPlugin * p, CompDisplay * d)
{
ZOOM_DISPLAY(d);
freeScreenPrivateIndex(d, zd->screenPrivateIndex);
UNWRAP(zd, d, handleEvent);
free(zd);
}
static Bool zoomInitScreen(CompPlugin * p, CompScreen * s)
{
ZoomScreen *zs;
ZOOM_DISPLAY(s->display);
zs = malloc(sizeof(ZoomScreen));
if (!zs)
return FALSE;
zs->grabIndex = 0;
zs->currentZoom = 1.0f;
zs->newZoom = 1.0f;
zs->xVelocity = 0.0f;
zs->yVelocity = 0.0f;
zs->zVelocity = 0.0f;
zs->xTranslate = 0.0f;
zs->yTranslate = 0.0f;
zs->maxTranslate = 0.85f;
zs->savedPointer.x = 0;
zs->savedPointer.y = 0;
zs->grabbed = FALSE;
zs->pointerInvertY = ZOOM_POINTER_INVERT_Y_DEFAULT;
zs->pointerSensitivity = ZOOM_POINTER_SENSITIVITY_DEFAULT *
ZOOM_POINTER_SENSITIVITY_FACTOR;
zs->speed = ZOOM_SPEED_DEFAULT;
zs->step = ZOOM_STEP_DEFAULT;
zs->minZoom = ZOOM_MIN_DEFAULT;
zs->maxZoom = ZOOM_MAX_DEFAULT;
zs->timestep = ZOOM_TIMESTEP_DEFAULT;
zoomScreenInitOptions(zs);
addScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_INITIATE].value.action);
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);
return TRUE;
}
static void zoomFiniScreen(CompPlugin * p, CompScreen * s)
{
ZOOM_SCREEN(s);
ZOOM_DISPLAY(s->display);
UNWRAP(zs, s, preparePaintScreen);
UNWRAP(zs, s, donePaintScreen);
UNWRAP(zs, s, paintScreen);
UNWRAP(zs, s, setScreenOptionForPlugin);
removeScreenAction(s,
&zd->opt[ZOOM_DISPLAY_OPTION_INITIATE].value.action);
removeScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_IN].value.action);
removeScreenAction(s, &zd->opt[ZOOM_DISPLAY_OPTION_OUT].value.action);
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);
}
CompPluginFeature zoomFeatures[] = {
{"zoom"}
};
CompPluginVTable zoomVTable = {
"zoom",
N_("Zoom Desktop"),
N_("Zoom and pan desktop cube"),
zoomInit,
zoomFini,
zoomInitDisplay,
zoomFiniDisplay,
zoomInitScreen,
zoomFiniScreen,
0, /* InitWindow */
0, /* FiniWindow */
zoomGetDisplayOptions,
zoomSetDisplayOption,
zoomGetScreenOptions,
zoomSetScreenOption,
0,
0,
zoomFeatures,
sizeof(zoomFeatures) / sizeof(zoomFeatures[0]),
BERYL_ABI_INFO,
"beryl-plugins-unsupported",
"accessibility",
0,
0,
False,
};
CompPluginVTable *getCompPluginInfo(void)
{
return &zoomVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1