You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2024 lines
46 KiB

/*
* 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/Xatom.h>
#include <X11/Xproto.h>
#include <compiz-cube.h>
static int cubeDisplayPrivateIndex;
#define ROTATE_POINTER_SENSITIVITY_FACTOR 0.05f
static CompMetadata rotateMetadata;
static int displayPrivateIndex;
#define ROTATE_DISPLAY_OPTION_INITIATE_BUTTON 0
#define ROTATE_DISPLAY_OPTION_LEFT_KEY 1
#define ROTATE_DISPLAY_OPTION_LEFT_BUTTON 2
#define ROTATE_DISPLAY_OPTION_RIGHT_KEY 3
#define ROTATE_DISPLAY_OPTION_RIGHT_BUTTON 4
#define ROTATE_DISPLAY_OPTION_LEFT_WINDOW_KEY 5
#define ROTATE_DISPLAY_OPTION_LEFT_WINDOW_BUTTON 6
#define ROTATE_DISPLAY_OPTION_RIGHT_WINDOW_KEY 7
#define ROTATE_DISPLAY_OPTION_RIGHT_WINDOW_BUTTON 8
#define ROTATE_DISPLAY_OPTION_EDGEFLIP_POINTER 9
#define ROTATE_DISPLAY_OPTION_EDGEFLIP_WINDOW 10
#define ROTATE_DISPLAY_OPTION_EDGEFLIP_DND 11
#define ROTATE_DISPLAY_OPTION_FLIPTIME 12
#define ROTATE_DISPLAY_OPTION_TO_1_KEY 13
#define ROTATE_DISPLAY_OPTION_TO_2_KEY 14
#define ROTATE_DISPLAY_OPTION_TO_3_KEY 15
#define ROTATE_DISPLAY_OPTION_TO_4_KEY 16
#define ROTATE_DISPLAY_OPTION_TO_5_KEY 17
#define ROTATE_DISPLAY_OPTION_TO_6_KEY 18
#define ROTATE_DISPLAY_OPTION_TO_7_KEY 19
#define ROTATE_DISPLAY_OPTION_TO_8_KEY 20
#define ROTATE_DISPLAY_OPTION_TO_9_KEY 21
#define ROTATE_DISPLAY_OPTION_TO_10_KEY 22
#define ROTATE_DISPLAY_OPTION_TO_11_KEY 23
#define ROTATE_DISPLAY_OPTION_TO_12_KEY 24
#define ROTATE_DISPLAY_OPTION_TO_1_WINDOW_KEY 25
#define ROTATE_DISPLAY_OPTION_TO_2_WINDOW_KEY 26
#define ROTATE_DISPLAY_OPTION_TO_3_WINDOW_KEY 27
#define ROTATE_DISPLAY_OPTION_TO_4_WINDOW_KEY 28
#define ROTATE_DISPLAY_OPTION_TO_5_WINDOW_KEY 29
#define ROTATE_DISPLAY_OPTION_TO_6_WINDOW_KEY 30
#define ROTATE_DISPLAY_OPTION_TO_7_WINDOW_KEY 31
#define ROTATE_DISPLAY_OPTION_TO_8_WINDOW_KEY 32
#define ROTATE_DISPLAY_OPTION_TO_9_WINDOW_KEY 33
#define ROTATE_DISPLAY_OPTION_TO_10_WINDOW_KEY 34
#define ROTATE_DISPLAY_OPTION_TO_11_WINDOW_KEY 35
#define ROTATE_DISPLAY_OPTION_TO_12_WINDOW_KEY 36
#define ROTATE_DISPLAY_OPTION_TO_KEY 37
#define ROTATE_DISPLAY_OPTION_WINDOW_KEY 38
#define ROTATE_DISPLAY_OPTION_FLIP_LEFT_EDGE 39
#define ROTATE_DISPLAY_OPTION_FLIP_RIGHT_EDGE 40
#define ROTATE_DISPLAY_OPTION_RAISE_ON_ROTATE 41
#define ROTATE_DISPLAY_OPTION_NUM 42
typedef struct _RotateDisplay {
int screenPrivateIndex;
HandleEventProc handleEvent;
CompOption opt[ROTATE_DISPLAY_OPTION_NUM];
} RotateDisplay;
#define ROTATE_SCREEN_OPTION_POINTER_INVERT_Y 0
#define ROTATE_SCREEN_OPTION_POINTER_SENSITIVITY 1
#define ROTATE_SCREEN_OPTION_ACCELERATION 2
#define ROTATE_SCREEN_OPTION_SNAP_TOP 3
#define ROTATE_SCREEN_OPTION_SNAP_BOTTOM 4
#define ROTATE_SCREEN_OPTION_SPEED 5
#define ROTATE_SCREEN_OPTION_TIMESTEP 6
#define ROTATE_SCREEN_OPTION_ZOOM 7
#define ROTATE_SCREEN_OPTION_NUM 8
typedef struct _RotateScreen {
PreparePaintScreenProc preparePaintScreen;
DonePaintScreenProc donePaintScreen;
PaintOutputProc paintOutput;
WindowGrabNotifyProc windowGrabNotify;
WindowUngrabNotifyProc windowUngrabNotify;
ActivateWindowProc activateWindow;
CubeGetRotationProc getRotation;
CompOption opt[ROTATE_SCREEN_OPTION_NUM];
float pointerSensitivity;
Bool snapTop;
Bool snapBottom;
int grabIndex;
GLfloat xrot, xVelocity;
GLfloat yrot, yVelocity;
GLfloat baseXrot;
Bool moving;
GLfloat moveTo;
Window moveWindow;
int moveWindowX;
XPoint savedPointer;
Bool grabbed;
Bool focusDefault;
CompTimeoutHandle rotateHandle;
Bool slow;
unsigned int grabMask;
CompWindow *grabWindow;
float progress;
float progressVelocity;
GLfloat zoomTranslate;
} RotateScreen;
#define GET_ROTATE_DISPLAY(d) \
((RotateDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
#define ROTATE_DISPLAY(d) \
RotateDisplay *rd = GET_ROTATE_DISPLAY (d)
#define GET_ROTATE_SCREEN(s, rd) \
((RotateScreen *) (s)->base.privates[(rd)->screenPrivateIndex].ptr)
#define ROTATE_SCREEN(s) \
RotateScreen *rs = GET_ROTATE_SCREEN (s, GET_ROTATE_DISPLAY (s->display))
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static CompOption *
rotateGetScreenOptions (CompPlugin *plugin,
CompScreen *screen,
int *count)
{
ROTATE_SCREEN (screen);
*count = NUM_OPTIONS (rs);
return rs->opt;
}
static Bool
rotateSetScreenOption (CompPlugin *plugin,
CompScreen *screen,
const char *name,
CompOptionValue *value)
{
CompOption *o;
int index;
ROTATE_SCREEN (screen);
o = compFindOption (rs->opt, NUM_OPTIONS (rs), name, &index);
if (!o)
return FALSE;
switch (index) {
case ROTATE_SCREEN_OPTION_POINTER_SENSITIVITY:
if (compSetFloatOption (o, value))
{
rs->pointerSensitivity = o->value.f *
ROTATE_POINTER_SENSITIVITY_FACTOR;
return TRUE;
}
break;
default:
return compSetScreenOption (screen, o, value);
}
return FALSE;
}
static int
adjustVelocity (RotateScreen *rs,
int size,
int invert)
{
float xrot, yrot, adjust, amount;
if (rs->moving)
{
xrot = rs->moveTo + (rs->xrot + rs->baseXrot);
}
else
{
xrot = rs->xrot;
if (rs->xrot < -180.0f / size)
xrot = 360.0f / size + rs->xrot;
else if (rs->xrot > 180.0f / size)
xrot = rs->xrot - 360.0f / size;
}
adjust = -xrot * 0.05f * rs->opt[ROTATE_SCREEN_OPTION_ACCELERATION].value.f;
amount = fabs (xrot);
if (amount < 10.0f)
amount = 10.0f;
else if (amount > 30.0f)
amount = 30.0f;
if (rs->slow)
adjust *= 0.05f;
rs->xVelocity = (amount * rs->xVelocity + adjust) / (amount + 2.0f);
yrot = rs->yrot;
/* Only snap if more than 2 viewports */
if (size > 2)
{
if (rs->yrot > 50.0f && ((rs->snapTop && invert == 1) ||
(rs->snapBottom && invert != 1)))
yrot -= 90.f;
else if (rs->yrot < -50.0f && ((rs->snapTop && invert != 1) ||
(rs->snapBottom && invert == 1)))
yrot += 90.f;
}
adjust = -yrot * 0.05f * rs->opt[ROTATE_SCREEN_OPTION_ACCELERATION].value.f;
amount = fabs (rs->yrot);
if (amount < 10.0f)
amount = 10.0f;
else if (amount > 30.0f)
amount = 30.0f;
rs->yVelocity = (amount * rs->yVelocity + adjust) / (amount + 2.0f);
return (fabs (xrot) < 0.1f && fabs (rs->xVelocity) < 0.2f &&
fabs (yrot) < 0.1f && fabs (rs->yVelocity) < 0.2f);
}
static void
rotateReleaseMoveWindow (CompScreen *s)
{
CompWindow *w;
ROTATE_SCREEN (s);
w = findWindowAtScreen (s, rs->moveWindow);
if (w)
syncWindowPosition (w);
rs->moveWindow = None;
}
static void
rotatePreparePaintScreen (CompScreen *s,
int msSinceLastPaint)
{
ROTATE_SCREEN (s);
CUBE_SCREEN (s);
float oldXrot = rs->xrot + rs->baseXrot;
if (rs->grabIndex || rs->moving)
{
int steps;
float amount, chunk;
amount = msSinceLastPaint * 0.05f *
rs->opt[ROTATE_SCREEN_OPTION_SPEED].value.f;
steps = amount /
(0.5f * rs->opt[ROTATE_SCREEN_OPTION_TIMESTEP].value.f);
if (!steps) steps = 1;
chunk = amount / (float) steps;
while (steps--)
{
rs->xrot += rs->xVelocity * chunk;
rs->yrot += rs->yVelocity * chunk;
if (rs->xrot > 360.0f / s->hsize)
{
rs->baseXrot += 360.0f / s->hsize;
rs->xrot -= 360.0f / s->hsize;
}
else if (rs->xrot < 0.0f)
{
rs->baseXrot -= 360.0f / s->hsize;
rs->xrot += 360.0f / s->hsize;
}
if (cs->invert == -1)
{
if (rs->yrot > 45.0f)
{
rs->yVelocity = 0.0f;
rs->yrot = 45.0f;
}
else if (rs->yrot < -45.0f)
{
rs->yVelocity = 0.0f;
rs->yrot = -45.0f;
}
}
else
{
if (rs->yrot > 100.0f)
{
rs->yVelocity = 0.0f;
rs->yrot = 100.0f;
}
else if (rs->yrot < -100.0f)
{
rs->yVelocity = 0.0f;
rs->yrot = -100.0f;
}
}
if (rs->grabbed)
{
rs->xVelocity /= 1.25f;
rs->yVelocity /= 1.25f;
if (fabs (rs->xVelocity) < 0.01f)
rs->xVelocity = 0.0f;
if (fabs (rs->yVelocity) < 0.01f)
rs->yVelocity = 0.0f;
}
else if (adjustVelocity (rs, s->hsize, cs->invert))
{
rs->xVelocity = 0.0f;
rs->yVelocity = 0.0f;
if (fabs (rs->yrot) < 0.1f)
{
float xrot;
int tx;
xrot = rs->baseXrot + rs->xrot;
if (xrot < 0.0f)
tx = (s->hsize * xrot / 360.0f) - 0.5f;
else
tx = (s->hsize * xrot / 360.0f) + 0.5f;
/* flag end of rotation */
cs->rotationState = RotationNone;
moveScreenViewport (s, tx, 0, TRUE);
rs->xrot = 0.0f;
rs->yrot = 0.0f;
rs->baseXrot = rs->moveTo = 0.0f;
rs->moving = FALSE;
if (rs->grabIndex)
{
removeScreenGrab (s, rs->grabIndex, &rs->savedPointer);
rs->grabIndex = 0;
}
if (rs->moveWindow)
{
CompWindow *w;
w = findWindowAtScreen (s, rs->moveWindow);
if (w)
{
moveWindow (w, rs->moveWindowX - w->attrib.x, 0,
TRUE, TRUE);
syncWindowPosition (w);
}
}
else if (rs->focusDefault)
{
int i;
for (i = 0; i < s->maxGrab; i++)
if (s->grabs[i].active &&
strcmp ("switcher", s->grabs[i].name) == 0)
break;
/* only focus default window if switcher isn't active */
if (i == s->maxGrab)
focusDefaultWindow (s);
}
rs->moveWindow = 0;
}
break;
}
}
if (rs->moveWindow)
{
CompWindow *w;
w = findWindowAtScreen (s, rs->moveWindow);
if (w)
{
float xrot = (s->hsize * (rs->baseXrot + rs->xrot)) / 360.0f;
moveWindowToViewportPosition (w,
rs->moveWindowX - xrot * s->width,
w->attrib.y,
FALSE);
}
}
}
if (rs->moving)
{
if (fabs (rs->xrot + rs->baseXrot + rs->moveTo) <=
(360.0 / (s->hsize * 2.0)))
{
rs->progress = fabs (rs->xrot + rs->baseXrot + rs->moveTo) /
(360.0 / (s->hsize * 2.0));
}
else if (fabs (rs->xrot + rs->baseXrot) <= (360.0 / (s->hsize * 2.0)))
{
rs->progress = fabs (rs->xrot + rs->baseXrot) /
(360.0 / (s->hsize * 2.0));
}
else
{
rs->progress += fabs (rs->xrot + rs->baseXrot - oldXrot) /
(360.0 / (s->hsize * 2.0));
rs->progress = MIN (rs->progress, 1.0);
}
}
else if (rs->progress != 0.0f || rs->grabbed)
{
int steps;
float amount, chunk;
amount = msSinceLastPaint * 0.05f *
rs->opt[ROTATE_SCREEN_OPTION_SPEED].value.f;
steps = amount /
(0.5f * rs->opt[ROTATE_SCREEN_OPTION_TIMESTEP].value.f);
if (!steps)
steps = 1;
chunk = amount / (float) steps;
while (steps--)
{
float dt, adjust, tamount;
if (rs->grabbed)
dt = 1.0 - rs->progress;
else
dt = 0.0f - rs->progress;
adjust = dt * 0.15f;
tamount = fabs (dt) * 1.5f;
if (tamount < 0.2f)
tamount = 0.2f;
else if (tamount > 2.0f)
tamount = 2.0f;
rs->progressVelocity = (tamount * rs->progressVelocity + adjust) /
(tamount + 1.0f);
rs->progress += rs->progressVelocity * chunk;
if (fabs (dt) < 0.01f && fabs (rs->progressVelocity) < 0.0001f)
{
if (rs->grabbed)
rs->progress = 1.0f;
else
rs->progress = 0.0f;
break;
}
}
}
if (cs->invert == 1 && !cs->unfolded)
{
rs->zoomTranslate = rs->opt[ROTATE_SCREEN_OPTION_ZOOM].value.f *
rs->progress;
}
else
{
rs->zoomTranslate = 0.0;
}
UNWRAP (rs, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP (rs, s, preparePaintScreen, rotatePreparePaintScreen);
}
static void
rotateDonePaintScreen (CompScreen *s)
{
ROTATE_SCREEN (s);
if (rs->grabIndex || rs->moving ||
(rs->progress != 0.0 && rs->progress != 1.0))
{
if ((!rs->grabbed && !rs->snapTop && !rs->snapBottom) ||
rs->xVelocity || rs->yVelocity || rs->progressVelocity)
{
damageScreen (s);
}
}
UNWRAP (rs, s, donePaintScreen);
(*s->donePaintScreen) (s);
WRAP (rs, s, donePaintScreen, rotateDonePaintScreen);
}
static void
rotateGetRotation (CompScreen *s,
float *x,
float *v,
float *progress)
{
CUBE_SCREEN (s);
ROTATE_SCREEN (s);
UNWRAP (rs, cs, getRotation);
(*cs->getRotation) (s, x, v, progress);
WRAP (rs, cs, getRotation, rotateGetRotation);
*x += rs->baseXrot + rs->xrot;
*v += rs->yrot;
*progress = MAX (*progress, rs->progress);
}
static Bool
rotatePaintOutput (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
const CompTransform *transform,
Region region,
CompOutput *output,
unsigned int mask)
{
Bool status;
ROTATE_SCREEN (s);
if (rs->grabIndex || rs->moving || rs->progress != 0.0f)
{
CompTransform sTransform = *transform;
matrixTranslate (&sTransform, 0.0f, 0.0f, -rs->zoomTranslate);
mask &= ~PAINT_SCREEN_REGION_MASK;
mask |= PAINT_SCREEN_TRANSFORMED_MASK;
UNWRAP (rs, s, paintOutput);
status = (*s->paintOutput) (s, sAttrib, &sTransform, region,
output, mask);
WRAP (rs, s, paintOutput, rotatePaintOutput);
}
else
{
UNWRAP (rs, s, paintOutput);
status = (*s->paintOutput) (s, sAttrib, transform, region,
output, mask);
WRAP (rs, s, paintOutput, rotatePaintOutput);
}
return status;
}
static Bool
rotateInitiate (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)
{
ROTATE_SCREEN (s);
CUBE_SCREEN (s);
if (s->hsize < 2)
return FALSE;
if (rs->rotateHandle && rs->grabWindow)
{
if (otherScreenGrabExist (s, "rotate", "move", NULL))
return FALSE;
}
else
{
if (otherScreenGrabExist (s, "rotate", "switcher", "cube", NULL))
return FALSE;
}
rs->moving = FALSE;
rs->slow = FALSE;
/* Set the rotation state for cube - if action is non-NULL,
we set it to manual (as we were called from the 'Initiate
Rotation' binding. Otherwise, we set it to Change. */
if (action)
cs->rotationState = RotationManual;
else
cs->rotationState = RotationChange;
if (!rs->grabIndex)
{
rs->grabIndex = pushScreenGrab (s, s->invisibleCursor, "rotate");
if (rs->grabIndex)
{
int x, y;
x = getIntOptionNamed (option, nOption, "x", 0);
y = getIntOptionNamed (option, nOption, "y", 0);
rs->savedPointer.x = x;
rs->savedPointer.y = y;
}
}
if (rs->grabIndex)
{
rs->moveTo = 0.0f;
rs->grabbed = TRUE;
rs->snapTop = rs->opt[ROTATE_SCREEN_OPTION_SNAP_TOP].value.b;
rs->snapBottom = rs->opt[ROTATE_SCREEN_OPTION_SNAP_BOTTOM].value.b;
if (state & CompActionStateInitButton)
action->state |= CompActionStateTermButton;
if (state & CompActionStateInitKey)
action->state |= CompActionStateTermKey;
}
}
return TRUE;
}
static Bool
rotateTerminate (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)
{
ROTATE_SCREEN (s);
if (xid && s->root != xid)
continue;
if (rs->grabIndex)
{
if (!xid)
{
rs->snapTop = FALSE;
rs->snapBottom = FALSE;
}
rs->grabbed = FALSE;
damageScreen (s);
}
}
action->state &= ~(CompActionStateTermButton | CompActionStateTermKey);
return FALSE;
}
static Bool
rotate (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)
{
int direction;
ROTATE_SCREEN (s);
if (s->hsize < 2)
return FALSE;
if (otherScreenGrabExist (s, "rotate", "move", "switcher",
"group-drag", "cube", NULL))
return FALSE;
direction = getIntOptionNamed (option, nOption, "direction", 0);
if (!direction)
return FALSE;
if (rs->moveWindow)
rotateReleaseMoveWindow (s);
/* we allow the grab to fail here so that we can rotate on
drag-and-drop */
if (!rs->grabIndex)
{
CompOption o[3];
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", 0);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", 0);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
rotateInitiate (d, NULL, 0, o, 3);
}
rs->focusDefault = getBoolOptionNamed (option, nOption,
"focus_default", TRUE);
rs->moving = TRUE;
rs->moveTo += (360.0f / s->hsize) * direction;
rs->grabbed = FALSE;
damageScreen (s);
}
return FALSE;
}
static Bool
rotateWithWindow (CompDisplay *d,
CompAction *action,
CompActionState state,
CompOption *option,
int nOption)
{
CompScreen *s;
Window xid;
ROTATE_DISPLAY (d);
xid = getIntOptionNamed (option, nOption, "root", 0);
s = findScreenAtDisplay (d, xid);
if (s)
{
Bool raise = rd->opt[ROTATE_DISPLAY_OPTION_RAISE_ON_ROTATE].value.b;
int direction;
ROTATE_SCREEN (s);
if (s->hsize < 2)
return FALSE;
direction = getIntOptionNamed (option, nOption, "direction", 0);
if (!direction)
return FALSE;
xid = getIntOptionNamed (option, nOption, "window", 0);
if (rs->moveWindow != xid)
{
CompWindow *w;
rotateReleaseMoveWindow (s);
if (!rs->grabIndex && !rs->moving)
{
w = findWindowAtScreen (s, xid);
if (w)
{
if (!(w->type & (CompWindowTypeDesktopMask |
CompWindowTypeDockMask)))
{
if (!(w->state & CompWindowStateStickyMask))
{
rs->moveWindow = w->id;
rs->moveWindowX = w->attrib.x;
if (raise)
raiseWindow (w);
}
}
}
}
}
if (!rs->grabIndex)
{
CompOption o[3];
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", 0);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", 0);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
rotateInitiate (d, NULL, 0, o, 3);
}
if (rs->grabIndex)
{
rs->moving = TRUE;
rs->moveTo += (360.0f / s->hsize) * direction;
rs->grabbed = FALSE;
damageScreen (s);
}
}
return FALSE;
}
static Bool
rotateLeft (CompDisplay *d,
CompAction *action,
CompActionState state,
CompOption *option,
int nOption)
{
CompOption o[4];
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", 0);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", 0);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = getIntOptionNamed (option, nOption, "root", 0);
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = -1;
rotate (d, NULL, 0, o, 4);
return FALSE;
}
static Bool
rotateRight (CompDisplay *d,
CompAction *action,
CompActionState state,
CompOption *option,
int nOption)
{
CompOption o[4];
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", 0);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", 0);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = getIntOptionNamed (option, nOption, "root", 0);
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = 1;
rotate (d, NULL, 0, o, 4);
return FALSE;
}
static Bool
rotateLeftWithWindow (CompDisplay *d,
CompAction *action,
CompActionState state,
CompOption *option,
int nOption)
{
CompOption o[5];
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", 0);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", 0);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = getIntOptionNamed (option, nOption, "root", 0);
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = -1;
o[4].type = CompOptionTypeInt;
o[4].name = "window";
o[4].value.i = getIntOptionNamed (option, nOption, "window", 0);
rotateWithWindow (d, NULL, 0, o, 5);
return FALSE;
}
static Bool
rotateRightWithWindow (CompDisplay *d,
CompAction *action,
CompActionState state,
CompOption *option,
int nOption)
{
CompOption o[5];
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", 0);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", 0);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = getIntOptionNamed (option, nOption, "root", 0);
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = 1;
o[4].type = CompOptionTypeInt;
o[4].name = "window";
o[4].value.i = getIntOptionNamed (option, nOption, "window", 0);
rotateWithWindow (d, NULL, 0, o, 5);
return FALSE;
}
static Bool
rotateFlipLeft (void *closure)
{
CompScreen *s = closure;
int warpX;
CompOption o[4];
ROTATE_SCREEN (s);
rs->moveTo = 0.0f;
rs->slow = FALSE;
if (otherScreenGrabExist (s, "rotate", "move", "group-drag", NULL))
return FALSE;
warpX = pointerX + s->width;
warpPointer (s, s->width - 10, 0);
lastPointerX = warpX;
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = 0;
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = pointerY;
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = -1;
rotate (s->display, NULL, 0, o, 4);
XWarpPointer (s->display->display, None, None, 0, 0, 0, 0, -1, 0);
rs->savedPointer.x = lastPointerX - 9;
rs->rotateHandle = 0;
return FALSE;
}
static Bool
rotateFlipRight (void *closure)
{
CompScreen *s = closure;
int warpX;
CompOption o[4];
ROTATE_SCREEN (s);
rs->moveTo = 0.0f;
rs->slow = FALSE;
if (otherScreenGrabExist (s, "rotate", "move", "group-drag", NULL))
return FALSE;
warpX = pointerX - s->width;
warpPointer (s, 10 - s->width, 0);
lastPointerX = warpX;
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = 0;
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = pointerY;
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = 1;
rotate (s->display, NULL, 0, o, 4);
XWarpPointer (s->display->display, None, None, 0, 0, 0, 0, 1, 0);
rs->savedPointer.x = lastPointerX + 9;
rs->rotateHandle = 0;
return FALSE;
}
static void
rotateEdgeFlip (CompScreen *s,
int edge,
CompAction *action,
CompActionState state,
CompOption *option,
int nOption)
{
CompOption o[4];
ROTATE_DISPLAY (s->display);
if (s->hsize < 2)
return;
if (otherScreenGrabExist (s, "rotate", "move", "group-drag", NULL))
return;
if (state & CompActionStateInitEdgeDnd)
{
if (!rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_DND].value.b)
return;
if (otherScreenGrabExist (s, "rotate", NULL))
return;
}
else if (otherScreenGrabExist (s, "rotate", "group-drag", NULL))
{
ROTATE_SCREEN (s);
if (!rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_WINDOW].value.b)
return;
if (!rs->grabWindow)
return;
/* bail out if window is horizontally maximized, fullscreen,
or sticky */
if (rs->grabWindow->state & (CompWindowStateMaximizedHorzMask |
CompWindowStateFullscreenMask |
CompWindowStateStickyMask))
return;
}
else if (otherScreenGrabExist (s, "rotate", NULL))
{
/* in that case, 'group-drag' must be the active screen grab */
if (!rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_WINDOW].value.b)
return;
}
else
{
if (!rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_POINTER].value.b)
return;
}
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = 0;
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = pointerY;
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
if (edge == SCREEN_EDGE_LEFT)
{
int flipTime = rd->opt[ROTATE_DISPLAY_OPTION_FLIPTIME].value.i;
ROTATE_SCREEN (s);
if (flipTime == 0 || (rs->moving && !rs->slow))
{
int pointerDx = pointerX - lastPointerX;
int warpX;
warpX = pointerX + s->width;
warpPointer (s, s->width - 10, 0);
lastPointerX = warpX - pointerDx;
o[3].value.i = -1;
rotate (s->display, NULL, 0, o, 4);
XWarpPointer (s->display->display, None, None,
0, 0, 0, 0, -1, 0);
rs->savedPointer.x = lastPointerX - 9;
}
else
{
if (!rs->rotateHandle)
{
int flipTime = rd->opt[ROTATE_DISPLAY_OPTION_FLIPTIME].value.i;
rs->rotateHandle = compAddTimeout (flipTime,
(float) flipTime * 1.2,
rotateFlipLeft, s);
}
rs->moving = TRUE;
rs->moveTo -= 360.0f / s->hsize;
rs->slow = TRUE;
if (state & CompActionStateInitEdge)
action->state |= CompActionStateTermEdge;
if (state & CompActionStateInitEdgeDnd)
action->state |= CompActionStateTermEdgeDnd;
damageScreen (s);
}
}
else
{
int flipTime = rd->opt[ROTATE_DISPLAY_OPTION_FLIPTIME].value.i;
ROTATE_SCREEN (s);
if (flipTime == 0 || (rs->moving && !rs->slow))
{
int pointerDx = pointerX - lastPointerX;
int warpX;
warpX = pointerX - s->width;
warpPointer (s, 10 - s->width, 0);
lastPointerX = warpX - pointerDx;
o[3].value.i = 1;
rotate (s->display, NULL, 0, o, 4);
XWarpPointer (s->display->display, None, None,
0, 0, 0, 0, 1, 0);
rs->savedPointer.x = lastPointerX + 9;
}
else
{
if (!rs->rotateHandle)
{
int flipTime = rd->opt[ROTATE_DISPLAY_OPTION_FLIPTIME].value.i;
rs->rotateHandle =
compAddTimeout (flipTime, (float) flipTime * 1.2,
rotateFlipRight, s);
}
rs->moving = TRUE;
rs->moveTo += 360.0f / s->hsize;
rs->slow = TRUE;
if (state & CompActionStateInitEdge)
action->state |= CompActionStateTermEdge;
if (state & CompActionStateInitEdgeDnd)
action->state |= CompActionStateTermEdgeDnd;
damageScreen (s);
}
}
}
static Bool
rotateFlipTerminate (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)
{
ROTATE_SCREEN (s);
if (xid && s->root != xid)
continue;
if (rs->rotateHandle)
{
compRemoveTimeout (rs->rotateHandle);
rs->rotateHandle = 0;
if (rs->slow)
{
rs->moveTo = 0.0f;
rs->slow = FALSE;
}
damageScreen (s);
}
action->state &= ~(CompActionStateTermEdge |
CompActionStateTermEdgeDnd);
}
return FALSE;
}
static Bool
rotateEdgeFlipLeft (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)
rotateEdgeFlip (s, SCREEN_EDGE_LEFT, action, state, option, nOption);
return FALSE;
}
static Bool
rotateEdgeFlipRight (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)
rotateEdgeFlip (s, SCREEN_EDGE_RIGHT, action, state, option, nOption);
return FALSE;
}
static int
rotateRotationTo (CompScreen *s,
int face)
{
int delta;
ROTATE_SCREEN (s);
delta = face - s->x - (rs->moveTo / (360.0f / s->hsize));
if (delta > s->hsize / 2)
delta -= s->hsize;
else if (delta < -(s->hsize / 2))
delta += s->hsize;
return delta;
}
static Bool
rotateTo (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)
{
CompOption o[4];
int face = -1;
int i = ROTATE_DISPLAY_OPTION_TO_1_KEY;
ROTATE_DISPLAY (s->display);
while (i <= ROTATE_DISPLAY_OPTION_TO_12_KEY)
{
if (action == &rd->opt[i].value.action)
{
face = i - ROTATE_DISPLAY_OPTION_TO_1_KEY;
break;
}
i++;
}
if (face < 0)
face = getIntOptionNamed (option, nOption, "face", s->x);
if (face > s->hsize)
return FALSE;
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", pointerX);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", pointerY);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = rotateRotationTo (s, face);
rotate (d, NULL, 0, o, 4);
}
return FALSE;
}
static Bool
rotateToWithWindow (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)
{
CompOption o[5];
int face = -1;
int i = ROTATE_DISPLAY_OPTION_TO_1_WINDOW_KEY;
ROTATE_DISPLAY (s->display);
while (i <= ROTATE_DISPLAY_OPTION_TO_12_WINDOW_KEY)
{
if (action == &rd->opt[i].value.action)
{
face = i - ROTATE_DISPLAY_OPTION_TO_1_WINDOW_KEY;
break;
}
i++;
}
if (face < 0)
face = getIntOptionNamed (option, nOption, "face", s->x);
if (face > s->hsize)
return FALSE;
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = getIntOptionNamed (option, nOption, "x", pointerX);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = getIntOptionNamed (option, nOption, "y", pointerY);
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = rotateRotationTo (s, face);
o[4].type = CompOptionTypeInt;
o[4].name = "window";
o[4].value.i = getIntOptionNamed (option, nOption, "window", 0);
rotateWithWindow (d, NULL, 0, o, 5);
}
return FALSE;
}
static void
rotateHandleEvent (CompDisplay *d,
XEvent *event)
{
CompScreen *s;
ROTATE_DISPLAY (d);
switch (event->type) {
case MotionNotify:
s = findScreenAtDisplay (d, event->xmotion.root);
if (s)
{
ROTATE_SCREEN (s);
CUBE_SCREEN (s);
if (rs->grabIndex)
{
if (rs->grabbed)
{
GLfloat pointerDx, pointerDy;
pointerDx = pointerX - lastPointerX;
pointerDy = pointerY - 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 (s,
(s->width / 2) - pointerX,
(s->height / 2) - pointerY);
}
if (rs->opt[ROTATE_SCREEN_OPTION_POINTER_INVERT_Y].value.b)
pointerDy = -pointerDy;
rs->xVelocity += pointerDx * rs->pointerSensitivity *
cs->invert;
rs->yVelocity += pointerDy * rs->pointerSensitivity;
damageScreen (s);
}
else
{
rs->savedPointer.x += pointerX - lastPointerX;
rs->savedPointer.y += pointerY - lastPointerY;
}
}
}
break;
case ClientMessage:
if (event->xclient.message_type == d->desktopViewportAtom)
{
s = findScreenAtDisplay (d, event->xclient.window);
if (s)
{
int dx;
ROTATE_SCREEN (s);
if (otherScreenGrabExist (s, "rotate", "switcher", "cube", NULL))
break;
/* reset movement */
rs->moveTo = 0.0f;
dx = event->xclient.data.l[0] / s->width - s->x;
if (dx)
{
Window win;
int i, x, y;
unsigned int ui;
CompOption o[4];
XQueryPointer (d->display, s->root,
&win, &win, &x, &y, &i, &i, &ui);
if (dx * 2 > s->hsize)
dx -= s->hsize;
else if (dx * 2 < -s->hsize)
dx += s->hsize;
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = x;
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = y;
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = dx;
rotate (d, NULL, 0, o, 4);
}
}
}
default:
break;
}
UNWRAP (rd, d, handleEvent);
(*d->handleEvent) (d, event);
WRAP (rd, d, handleEvent, rotateHandleEvent);
}
static void
rotateActivateWindow (CompWindow *w)
{
CompScreen *s = w->screen;
ROTATE_SCREEN (s);
if (w->placed &&
!otherScreenGrabExist (s, "rotate", "switcher", "cube", NULL))
{
int dx;
/* reset movement */
rs->moveTo = 0.0f;
defaultViewportForWindow (w, &dx, NULL);
dx -= s->x;
if (dx)
{
Window win;
int i, x, y;
unsigned int ui;
CompOption o[5];
XQueryPointer (s->display->display, s->root,
&win, &win, &x, &y, &i, &i, &ui);
if (dx * 2 > s->hsize)
dx -= s->hsize;
else if (dx * 2 < -s->hsize)
dx += s->hsize;
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i = x;
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i = y;
o[2].type = CompOptionTypeInt;
o[2].name = "root";
o[2].value.i = s->root;
o[3].type = CompOptionTypeInt;
o[3].name = "direction";
o[3].value.i = dx;
o[4].type = CompOptionTypeBool;
o[4].name = "focus_default";
o[4].value.b = FALSE;
rotate (s->display, NULL, 0, o, 5);
}
}
UNWRAP (rs, s, activateWindow);
(*s->activateWindow) (w);
WRAP (rs, s, activateWindow, rotateActivateWindow);
}
static void
rotateWindowGrabNotify (CompWindow *w,
int x,
int y,
unsigned int state,
unsigned int mask)
{
ROTATE_SCREEN (w->screen);
if (!rs->grabWindow)
{
rs->grabMask = mask;
rs->grabWindow = w;
}
UNWRAP (rs, w->screen, windowGrabNotify);
(*w->screen->windowGrabNotify) (w, x, y, state, mask);
WRAP (rs, w->screen, windowGrabNotify, rotateWindowGrabNotify);
}
static void
rotateWindowUngrabNotify (CompWindow *w)
{
ROTATE_SCREEN (w->screen);
if (w == rs->grabWindow)
{
rs->grabMask = 0;
rs->grabWindow = NULL;
}
UNWRAP (rs, w->screen, windowUngrabNotify);
(*w->screen->windowUngrabNotify) (w);
WRAP (rs, w->screen, windowUngrabNotify, rotateWindowUngrabNotify);
}
static CompOption *
rotateGetDisplayOptions (CompPlugin *plugin,
CompDisplay *display,
int *count)
{
ROTATE_DISPLAY (display);
*count = NUM_OPTIONS (rd);
return rd->opt;
}
static Bool
rotateSetDisplayOption (CompPlugin *plugin,
CompDisplay *display,
const char *name,
CompOptionValue *value)
{
CompOption *o;
ROTATE_DISPLAY (display);
o = compFindOption (rd->opt, NUM_OPTIONS (rd), name, NULL);
if (!o)
return FALSE;
return compSetDisplayOption (display, o, value);
}
static const CompMetadataOptionInfo rotateDisplayOptionInfo[] = {
{ "initiate_button", "button", 0, rotateInitiate, rotateTerminate },
{ "rotate_left_key", "key", 0, rotateLeft, 0 },
{ "rotate_left_button", "button", 0, rotateLeft, 0 },
{ "rotate_right_key", "key", 0, rotateRight, 0 },
{ "rotate_right_button", "button", 0, rotateRight, 0 },
{ "rotate_left_window_key", "key", 0, rotateLeftWithWindow, 0 },
{ "rotate_left_window_button", "button", 0, rotateLeftWithWindow, 0 },
{ "rotate_right_window_key", "key", 0, rotateRightWithWindow, 0 },
{ "rotate_right_window_button", "button", 0, rotateRightWithWindow, 0 },
{ "edge_flip_pointer", "bool", 0, 0, 0 },
{ "edge_flip_window", "bool", 0, 0, 0 },
{ "edge_flip_dnd", "bool", 0, 0, 0 },
{ "flip_time", "int", "<min>0</min><max>1000</max>", 0, 0 },
{ "rotate_to_1_key", "key", 0, rotateTo, 0 },
{ "rotate_to_2_key", "key", 0, rotateTo, 0 },
{ "rotate_to_3_key", "key", 0, rotateTo, 0 },
{ "rotate_to_4_key", "key", 0, rotateTo, 0 },
{ "rotate_to_5_key", "key", 0, rotateTo, 0 },
{ "rotate_to_6_key", "key", 0, rotateTo, 0 },
{ "rotate_to_7_key", "key", 0, rotateTo, 0 },
{ "rotate_to_8_key", "key", 0, rotateTo, 0 },
{ "rotate_to_9_key", "key", 0, rotateTo, 0 },
{ "rotate_to_10_key", "key", 0, rotateTo, 0 },
{ "rotate_to_11_key", "key", 0, rotateTo, 0 },
{ "rotate_to_12_key", "key", 0, rotateTo, 0 },
{ "rotate_to_1_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_2_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_3_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_4_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_5_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_6_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_7_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_8_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_9_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_10_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_11_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_12_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_to_key", "key", 0, rotateTo, 0 },
{ "rotate_window_key", "key", 0, rotateToWithWindow, 0 },
{ "rotate_flip_left_edge", "edge", 0, rotateEdgeFlipLeft,
rotateFlipTerminate },
{ "rotate_flip_right_edge", "edge", 0, rotateEdgeFlipRight,
rotateFlipTerminate },
{ "raise_on_rotate", "bool", 0, 0, 0 }
};
static Bool
rotateInitDisplay (CompPlugin *p,
CompDisplay *d)
{
RotateDisplay *rd;
if (!checkPluginABI ("core", CORE_ABIVERSION) ||
!checkPluginABI ("cube", CUBE_ABIVERSION))
return FALSE;
if (!getPluginDisplayIndex (d, "cube", &cubeDisplayPrivateIndex))
return FALSE;
rd = malloc (sizeof (RotateDisplay));
if (!rd)
return FALSE;
if (!compInitDisplayOptionsFromMetadata (d,
&rotateMetadata,
rotateDisplayOptionInfo,
rd->opt,
ROTATE_DISPLAY_OPTION_NUM))
{
free (rd);
return FALSE;
}
rd->screenPrivateIndex = allocateScreenPrivateIndex (d);
if (rd->screenPrivateIndex < 0)
{
compFiniDisplayOptions (d, rd->opt, ROTATE_DISPLAY_OPTION_NUM);
free (rd);
return FALSE;
}
WRAP (rd, d, handleEvent, rotateHandleEvent);
d->base.privates[displayPrivateIndex].ptr = rd;
return TRUE;
}
static void
rotateFiniDisplay (CompPlugin *p,
CompDisplay *d)
{
ROTATE_DISPLAY (d);
freeScreenPrivateIndex (d, rd->screenPrivateIndex);
UNWRAP (rd, d, handleEvent);
compFiniDisplayOptions (d, rd->opt, ROTATE_DISPLAY_OPTION_NUM);
free (rd);
}
static const CompMetadataOptionInfo rotateScreenOptionInfo[] = {
{ "invert_y", "bool", 0, 0, 0 },
{ "sensitivity", "float", 0, 0, 0 },
{ "acceleration", "float", "<min>1.0</min>", 0, 0 },
{ "snap_top", "bool", 0, 0, 0 },
{ "snap_bottom", "bool", 0, 0, 0 },
{ "speed", "float", "<min>0.1</min>", 0, 0 },
{ "timestep", "float", "<min>0.1</min>", 0, 0 },
{ "zoom", "float", 0, 0, 0 }
};
static Bool
rotateInitScreen (CompPlugin *p,
CompScreen *s)
{
RotateScreen *rs;
ROTATE_DISPLAY (s->display);
CUBE_SCREEN (s);
rs = malloc (sizeof (RotateScreen));
if (!rs)
return FALSE;
if (!compInitScreenOptionsFromMetadata (s,
&rotateMetadata,
rotateScreenOptionInfo,
rs->opt,
ROTATE_SCREEN_OPTION_NUM))
{
free (rs);
return FALSE;
}
rs->grabIndex = 0;
rs->xrot = 0.0f;
rs->xVelocity = 0.0f;
rs->yrot = 0.0f;
rs->yVelocity = 0.0f;
rs->baseXrot = 0.0f;
rs->moving = FALSE;
rs->moveTo = 0.0f;
rs->moveWindow = 0;
rs->savedPointer.x = 0;
rs->savedPointer.y = 0;
rs->focusDefault = TRUE;
rs->grabbed = FALSE;
rs->snapTop = FALSE;
rs->snapBottom = FALSE;
rs->slow = FALSE;
rs->grabMask = FALSE;
rs->grabWindow = NULL;
rs->pointerSensitivity =
rs->opt[ROTATE_SCREEN_OPTION_POINTER_SENSITIVITY].value.f *
ROTATE_POINTER_SENSITIVITY_FACTOR;
rs->rotateHandle = 0;
rs->progress = 0.0;
rs->progressVelocity = 0.0;
rs->zoomTranslate = 0.0;
WRAP (rs, s, preparePaintScreen, rotatePreparePaintScreen);
WRAP (rs, s, donePaintScreen, rotateDonePaintScreen);
WRAP (rs, s, paintOutput, rotatePaintOutput);
WRAP (rs, s, windowGrabNotify, rotateWindowGrabNotify);
WRAP (rs, s, windowUngrabNotify, rotateWindowUngrabNotify);
WRAP (rs, s, activateWindow, rotateActivateWindow);
WRAP (rs, cs, getRotation, rotateGetRotation);
s->base.privates[rd->screenPrivateIndex].ptr = rs;
return TRUE;
}
static void
rotateFiniScreen (CompPlugin *p,
CompScreen *s)
{
CUBE_SCREEN (s);
ROTATE_SCREEN (s);
if (rs->rotateHandle)
compRemoveTimeout (rs->rotateHandle);
UNWRAP (rs, cs, getRotation);
UNWRAP (rs, s, preparePaintScreen);
UNWRAP (rs, s, donePaintScreen);
UNWRAP (rs, s, paintOutput);
UNWRAP (rs, s, windowGrabNotify);
UNWRAP (rs, s, windowUngrabNotify);
UNWRAP (rs, s, activateWindow);
compFiniScreenOptions (s, rs->opt, ROTATE_SCREEN_OPTION_NUM);
free (rs);
}
static CompBool
rotateInitObject (CompPlugin *p,
CompObject *o)
{
static InitPluginObjectProc dispTab[] = {
(InitPluginObjectProc) 0, /* InitCore */
(InitPluginObjectProc) rotateInitDisplay,
(InitPluginObjectProc) rotateInitScreen
};
RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
}
static void
rotateFiniObject (CompPlugin *p,
CompObject *o)
{
static FiniPluginObjectProc dispTab[] = {
(FiniPluginObjectProc) 0, /* FiniCore */
(FiniPluginObjectProc) rotateFiniDisplay,
(FiniPluginObjectProc) rotateFiniScreen
};
DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
}
static CompOption *
rotateGetObjectOptions (CompPlugin *plugin,
CompObject *object,
int *count)
{
static GetPluginObjectOptionsProc dispTab[] = {
(GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
(GetPluginObjectOptionsProc) rotateGetDisplayOptions,
(GetPluginObjectOptionsProc) rotateGetScreenOptions
};
*count = 0;
RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
(void *) count, (plugin, object, count));
}
static CompBool
rotateSetObjectOption (CompPlugin *plugin,
CompObject *object,
const char *name,
CompOptionValue *value)
{
static SetPluginObjectOptionProc dispTab[] = {
(SetPluginObjectOptionProc) 0, /* SetCoreOption */
(SetPluginObjectOptionProc) rotateSetDisplayOption,
(SetPluginObjectOptionProc) rotateSetScreenOption
};
RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), FALSE,
(plugin, object, name, value));
}
static Bool
rotateInit (CompPlugin *p)
{
if (!compInitPluginMetadataFromInfo (&rotateMetadata,
p->vTable->name,
rotateDisplayOptionInfo,
ROTATE_DISPLAY_OPTION_NUM,
rotateScreenOptionInfo,
ROTATE_SCREEN_OPTION_NUM))
return FALSE;
displayPrivateIndex = allocateDisplayPrivateIndex ();
if (displayPrivateIndex < 0)
{
compFiniMetadata (&rotateMetadata);
return FALSE;
}
compAddMetadataFromFile (&rotateMetadata, p->vTable->name);
return TRUE;
}
static void
rotateFini (CompPlugin *p)
{
freeDisplayPrivateIndex (displayPrivateIndex);
compFiniMetadata (&rotateMetadata);
}
static CompMetadata *
rotateGetMetadata (CompPlugin *plugin)
{
return &rotateMetadata;
}
CompPluginVTable rotateVTable = {
"rotate",
rotateGetMetadata,
rotateInit,
rotateFini,
rotateInitObject,
rotateFiniObject,
rotateGetObjectOptions,
rotateSetObjectOption
};
CompPluginVTable *
getCompPluginInfo20070830 (void)
{
return &rotateVTable;
}