/*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Author: David Reveman <davidr@novell.com>
*/
#define _GNU_SOURCE /* for asprintf */
#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 <beryl.h>
#define ROTATE_POINTER_INVERT_Y_DEFAULT FALSE
#define ROTATE_POINTER_SENSITIVITY_DEFAULT 1.0f
#define ROTATE_POINTER_SENSITIVITY_MIN 0.01f
#define ROTATE_POINTER_SENSITIVITY_MAX 100.0f
#define ROTATE_POINTER_SENSITIVITY_PRECISION 0.01f
#define ROTATE_POINTER_SENSITIVITY_FACTOR 0.05f
#define ROTATE_ACCELERATION_DEFAULT 6.0f
#define ROTATE_ACCELERATION_MIN 1.0f
#define ROTATE_ACCELERATION_MAX 20.0f
#define ROTATE_ACCELERATION_PRECISION 0.1f
#define ROTATE_INITIATE_BUTTON_DEFAULT Button1
#define ROTATE_INITIATE_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define ROTATE_INITIATE_STICKY_BUTTON_DEFAULT Button2
#define ROTATE_INITIATE_STICKY_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define ROTATE_INITIATEDESKTOP_BUTTON_DEFAULT Button2
#define ROTATE_INITIATEDESKTOP_MODIFIERS_DEFAULT 0
#define ROTATE_WHEELINGS_DEFAULT 1
#define ROTATE_WHEELINGS_MIN 1
#define ROTATE_WHEELINGS_MAX 20
#define ROTATE_WHEEL_ON_EDGES_DEFAULT FALSE
#define ROTATE_WHEELMAXDIST_DEFAULT 5
#define ROTATE_WHEELMAXDIST_MIN 1
#define ROTATE_WHEELMAXDIST_MAX 300
#define ROTATE_LEFT_WHEEL_DEFAULT Button4
#define ROTATE_LEFT_WHEEL_MODIFIERS_DEFAULT 0
#define ROTATE_RIGHT_WHEEL_DEFAULT Button5
#define ROTATE_RIGHT_WHEEL_MODIFIERS_DEFAULT 0
#define ROTATE_LEFT_KEY_DEFAULT "Left"
#define ROTATE_LEFT_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define ROTATE_RIGHT_KEY_DEFAULT "Right"
#define ROTATE_RIGHT_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define ROTATE_UP_KEY_DEFAULT "Up"
#define ROTATE_UP_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define ROTATE_DOWN_KEY_DEFAULT "Down"
#define ROTATE_DOWN_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define ROTATE_LEFT_WINDOW_KEY_DEFAULT "Left"
#define ROTATE_LEFT_WINDOW_MODIFIERS_DEFAULT \
(ShiftMask | ControlMask | CompAltMask)
#define ROTATE_RIGHT_WINDOW_KEY_DEFAULT "Right"
#define ROTATE_RIGHT_WINDOW_MODIFIERS_DEFAULT \
(ShiftMask | ControlMask | CompAltMask)
#define ROTATE_SNAP_TOP_DEFAULT TRUE
#define ROTATE_SNAP_BOTTOM_DEFAULT TRUE
#define ROTATE_SPEED_DEFAULT 2.5f
#define ROTATE_SPEED_MIN 0.1f
#define ROTATE_SPEED_MAX 50.0f
#define ROTATE_SPEED_PRECISION 0.1f
#define ROTATE_TIMESTEP_DEFAULT 0.9f
#define ROTATE_TIMESTEP_MIN 0.1f
#define ROTATE_TIMESTEP_MAX 50.0f
#define ROTATE_TIMESTEP_PRECISION 0.1f
#define ROTATE_MANTIMESTEP_DEFAULT 2.5f
#define ROTATE_MANTIMESTEP_MIN 0.1f
#define ROTATE_MANTIMESTEP_MAX 50.0f
#define ROTATE_MANTIMESTEP_PRECISION 0.1f
#define ROTATE_EDGEFLIP_POINTER_DEFAULT FALSE
#define ROTATE_EDGEFLIP_WINDOW_DEFAULT TRUE
#define ROTATE_EDGEFLIP_DND_DEFAULT TRUE
#define ROTATE_FLIPTIME_DEFAULT 250
#define ROTATE_FLIPTIME_MIN 0
#define ROTATE_FLIPTIME_MAX 1000
#define ROTATE_ZOOM_DEFAULT 0.0f
#define ROTATE_ZOOM_MIN 0.0f
#define ROTATE_ZOOM_MAX 15.0f
#define ROTATE_ZOOM_PRECISION 0.1f
#define ROTATE_ZOOM_BEFORE_ROTATE_DEFAULT FALSE
static int displayPrivateIndex;
#define ROTATE_DISPLAY_OPTION_INITIATE 0
#define ROTATE_DISPLAY_OPTION_LEFT 1
#define ROTATE_DISPLAY_OPTION_RIGHT 2
#define ROTATE_DISPLAY_OPTION_LEFT_WINDOW 3
#define ROTATE_DISPLAY_OPTION_RIGHT_WINDOW 4
#define ROTATE_DISPLAY_OPTION_EDGEFLIP_POINTER 5
#define ROTATE_DISPLAY_OPTION_EDGEFLIP_WINDOW 6
#define ROTATE_DISPLAY_OPTION_EDGEFLIP_DND 7
#define ROTATE_DISPLAY_OPTION_FLIPTIME 8
#define ROTATE_DISPLAY_OPTION_TO_1 9
#define ROTATE_DISPLAY_OPTION_TO_2 10
#define ROTATE_DISPLAY_OPTION_TO_3 11
#define ROTATE_DISPLAY_OPTION_TO_4 12
#define ROTATE_DISPLAY_OPTION_TO_5 13
#define ROTATE_DISPLAY_OPTION_TO_6 14
#define ROTATE_DISPLAY_OPTION_TO_7 15
#define ROTATE_DISPLAY_OPTION_TO_8 16
#define ROTATE_DISPLAY_OPTION_TO_9 17
#define ROTATE_DISPLAY_OPTION_TO_10 18
#define ROTATE_DISPLAY_OPTION_TO_11 19
#define ROTATE_DISPLAY_OPTION_TO_12 20
#define ROTATE_DISPLAY_OPTION_TO_1_WINDOW 21
#define ROTATE_DISPLAY_OPTION_TO_2_WINDOW 22
#define ROTATE_DISPLAY_OPTION_TO_3_WINDOW 23
#define ROTATE_DISPLAY_OPTION_TO_4_WINDOW 24
#define ROTATE_DISPLAY_OPTION_TO_5_WINDOW 25
#define ROTATE_DISPLAY_OPTION_TO_6_WINDOW 26
#define ROTATE_DISPLAY_OPTION_TO_7_WINDOW 27
#define ROTATE_DISPLAY_OPTION_TO_8_WINDOW 28
#define ROTATE_DISPLAY_OPTION_TO_9_WINDOW 29
#define ROTATE_DISPLAY_OPTION_TO_10_WINDOW 30
#define ROTATE_DISPLAY_OPTION_TO_11_WINDOW 31
#define ROTATE_DISPLAY_OPTION_TO_12_WINDOW 32
#define ROTATE_DISPLAY_OPTION_TO 33
#define ROTATE_DISPLAY_OPTION_WINDOW 34
#define ROTATE_DISPLAY_OPTION_WHEELINGS 35
#define ROTATE_DISPLAY_OPTION_LEFT_WHEEL 36
#define ROTATE_DISPLAY_OPTION_RIGHT_WHEEL 37
#define ROTATE_DISPLAY_OPTION_UP 38
#define ROTATE_DISPLAY_OPTION_DOWN 39
#define ROTATE_DISPLAY_OPTION_INITIATEDESKTOP 40
#define ROTATE_DISPLAY_OPTION_STICKY_INITIATE 41
#define ROTATE_DISPLAY_OPTION_FLIP_LEFT 42
#define ROTATE_DISPLAY_OPTION_FLIP_RIGHT 43
#define ROTATE_DISPLAY_OPTION_NUM 44
typedef struct _RotateDisplay
{
int screenPrivateIndex;
HandleEventProc handleEvent;
CompOption opt[ROTATE_DISPLAY_OPTION_NUM];
unsigned int leftWheelings, rightWheelings;
} 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_SPEED 4
#define ROTATE_SCREEN_OPTION_TIMESTEP 5
#define ROTATE_SCREEN_OPTION_MANTIMESTEP 6
#define ROTATE_SCREEN_OPTION_ZOOM 7
#define ROTATE_SCREEN_OPTION_SNAP_BOTTOM 8
#define ROTATE_SCREEN_OPTION_ZOOM_BEFORE_ROTATE 9
#define ROTATE_SCREEN_OPTION_ZOOM_ONLY_ON_INITIATE 10
#define ROTATE_SCREEN_OPTION_WHEEL_ON_EDGES 11
#define ROTATE_SCREEN_OPTION_WHEELMAXDIST 12
#define ROTATE_SCREEN_OPTION_NUM 13
typedef struct _RotateScreen
{
PreparePaintScreenProc preparePaintScreen;
DonePaintScreenProc donePaintScreen;
PaintScreenProc paintScreen;
SetScreenOptionForPluginProc setScreenOptionForPlugin;
WindowGrabNotifyProc windowGrabNotify;
WindowUngrabNotifyProc windowUngrabNotify;
CompOption opt[ROTATE_SCREEN_OPTION_NUM];
float pointerSensitivity;
Bool snapTop;
Bool snapBottom;
float zoom;
int grabIndex;
GLfloat xrot, xVelocity;
GLfloat yrot, yVelocity;
float zoomTranslate;
GLfloat zoomVelocity;
GLfloat baseXrot;
GLfloat baseYrot;
Bool moving;
GLfloat moveTo;
Bool zooming;
Bool rotating;
Bool movingVert;
GLfloat moveToY;
int invert;
Window moveWindow;
int moveWindowX;
XPoint savedPointer;
Bool grabbed;
int manualAtom;
CompTimeoutHandle rotateHandle;
Bool slow;
unsigned int grabMask;
CompWindow *grabWindow;
int previousRotationAtom;
int snapTopBottomAtom;
} RotateScreen;
#define GET_ROTATE_DISPLAY(d) \
((RotateDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define ROTATE_DISPLAY(d) \
RotateDisplay *rd = GET_ROTATE_DISPLAY (d)
#define GET_ROTATE_SCREEN(s, rd) \
((RotateScreen *) (s)->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 Bool
rotateSetScreenOption(CompScreen * screen,
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_INVERT_Y:
case ROTATE_SCREEN_OPTION_ZOOM_BEFORE_ROTATE:
case ROTATE_SCREEN_OPTION_ZOOM_ONLY_ON_INITIATE:
case ROTATE_SCREEN_OPTION_WHEEL_ON_EDGES:
if (compSetBoolOption(o, value))
return TRUE;
break;
case ROTATE_SCREEN_OPTION_POINTER_SENSITIVITY:
if (compSetFloatOption(o, value))
{
rs->pointerSensitivity = o->value.f *
ROTATE_POINTER_SENSITIVITY_FACTOR;
return TRUE;
}
break;
case ROTATE_SCREEN_OPTION_SNAP_TOP:
if (compSetBoolOption(o, value))
{
rs->snapTop = o->value.b;
return TRUE;
}
break;
case ROTATE_SCREEN_OPTION_SNAP_BOTTOM:
if (compSetBoolOption(o, value))
{
rs->snapBottom = o->value.b;
return TRUE;
}
break;
case ROTATE_SCREEN_OPTION_ACCELERATION:
case ROTATE_SCREEN_OPTION_SPEED:
case ROTATE_SCREEN_OPTION_TIMESTEP:
case ROTATE_SCREEN_OPTION_MANTIMESTEP:
if (compSetFloatOption(o, value))
return TRUE;
break;
case ROTATE_SCREEN_OPTION_ZOOM:
if (compSetFloatOption(o, value))
{
if (o->value.f < 0.05f)
{
rs->zooming = FALSE;
rs->zoom = 0.0f;
}
else
{
rs->zooming = TRUE;
rs->zoom = o->value.f / 30.0f;
}
return TRUE;
}
break;
case ROTATE_SCREEN_OPTION_WHEELMAXDIST:
if (compSetIntOption(o, value))
return TRUE;
default:
break;
}
return FALSE;
}
static void rotateScreenInitOptions(RotateScreen * rs)
{
CompOption *o;
o = &rs->opt[ROTATE_SCREEN_OPTION_POINTER_INVERT_Y];
o->advanced = False;
o->name = "invert_y";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Pointer Invert Y");
o->longDesc =
N_("Invert Y axis for Pointer movement while Rotating the Cube.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_POINTER_INVERT_Y_DEFAULT;
o = &rs->opt[ROTATE_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 = ROTATE_POINTER_SENSITIVITY_DEFAULT;
o->rest.f.min = ROTATE_POINTER_SENSITIVITY_MIN;
o->rest.f.max = ROTATE_POINTER_SENSITIVITY_MAX;
o->rest.f.precision = ROTATE_POINTER_SENSITIVITY_PRECISION;
o = &rs->opt[ROTATE_SCREEN_OPTION_ACCELERATION];
o->advanced = False;
o->name = "acceleration";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Acceleration");
o->longDesc = N_("Acceleration of Cube Rotation.");
o->type = CompOptionTypeFloat;
o->value.f = ROTATE_ACCELERATION_DEFAULT;
o->rest.f.min = ROTATE_ACCELERATION_MIN;
o->rest.f.max = ROTATE_ACCELERATION_MAX;
o->rest.f.precision = ROTATE_ACCELERATION_PRECISION;
o = &rs->opt[ROTATE_SCREEN_OPTION_SNAP_TOP];
o->advanced = False;
o->name = "snap_top";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Snap To Top Face");
o->longDesc = N_("Snap Cube Rotation to Top Face.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_SNAP_TOP_DEFAULT;
o = &rs->opt[ROTATE_SCREEN_OPTION_SNAP_BOTTOM];
o->advanced = False;
o->name = "snap_bottom";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Snap To Bottom Face");
o->longDesc = N_("Snap Cube Rotation to Bottom Face.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_SNAP_BOTTOM_DEFAULT;
o = &rs->opt[ROTATE_SCREEN_OPTION_SPEED];
o->advanced = False;
o->name = "speed";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Rotation Speed");
o->longDesc = N_("Rotation Speed.");
o->type = CompOptionTypeFloat;
o->value.f = ROTATE_SPEED_DEFAULT;
o->rest.f.min = ROTATE_SPEED_MIN;
o->rest.f.max = ROTATE_SPEED_MAX;
o->rest.f.precision = ROTATE_SPEED_PRECISION;
o = &rs->opt[ROTATE_SCREEN_OPTION_TIMESTEP];
o->advanced = False;
o->name = "timestep";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Auto Timestep");
o->longDesc = N_("Rotation Timestep on Automatic Rotation.");
o->type = CompOptionTypeFloat;
o->value.f = ROTATE_TIMESTEP_DEFAULT;
o->rest.f.min = ROTATE_TIMESTEP_MIN;
o->rest.f.max = ROTATE_TIMESTEP_MAX;
o->rest.f.precision = ROTATE_TIMESTEP_PRECISION;
o = &rs->opt[ROTATE_SCREEN_OPTION_MANTIMESTEP];
o->advanced = False;
o->name = "mantimestep";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Manual Timestep");
o->longDesc = N_("Rotation Timestep on Manual Rotation.");
o->type = CompOptionTypeFloat;
o->value.f = ROTATE_MANTIMESTEP_DEFAULT;
o->rest.f.min = ROTATE_MANTIMESTEP_MIN;
o->rest.f.max = ROTATE_MANTIMESTEP_MAX;
o->rest.f.precision = ROTATE_MANTIMESTEP_PRECISION;
o = &rs->opt[ROTATE_SCREEN_OPTION_ZOOM];
o->advanced = False;
o->name = "zoom";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Zoom");
o->longDesc =
N_("Distance desktop should be Zoomed out while Rotating.");
o->type = CompOptionTypeFloat;
o->value.f = ROTATE_ZOOM_DEFAULT;
o->rest.f.min = ROTATE_ZOOM_MIN;
o->rest.f.max = ROTATE_ZOOM_MAX;
o->rest.f.precision = ROTATE_ZOOM_PRECISION;
o = &rs->opt[ROTATE_SCREEN_OPTION_ZOOM_BEFORE_ROTATE];
o->advanced = False;
o->name = "zoom_before_rotate";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Zoom Before Rotate");
o->longDesc = N_("Zoom out before doing Rotation.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_ZOOM_BEFORE_ROTATE_DEFAULT;
o = &rs->opt[ROTATE_SCREEN_OPTION_ZOOM_ONLY_ON_INITIATE];
o->advanced = False;
o->name = "zoom_initiate_only";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Zoom Only on Initiate");
o->longDesc =
N_
("Zoom out only when the 'Initiate' key/mouse combo is pressed.");
o->type = CompOptionTypeBool;
o->value.b = FALSE;
o = &rs->opt[ROTATE_SCREEN_OPTION_WHEEL_ON_EDGES];
o->advanced = False;
o->name = "wheel_on_edges";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Rotate With Wheel Near Edges");
o->longDesc = N_("Enable Rotate through Mouse Wheel near screen Edges.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_WHEEL_ON_EDGES_DEFAULT;
o = &rs->opt[ROTATE_SCREEN_OPTION_WHEELMAXDIST];
o->advanced = False;
o->name = "wheel_max_dist";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Max Distance From Edge to Rotate");
o->longDesc =
N_
("Maximum cursor Distance from Edges to initiate Rotate with wheel.");
o->type = CompOptionTypeInt;
o->value.i = ROTATE_WHEELMAXDIST_DEFAULT;
o->rest.i.min = ROTATE_WHEELMAXDIST_MIN;
o->rest.i.max = ROTATE_WHEELMAXDIST_MAX;
}
static CompOption *rotateGetScreenOptions(CompScreen * screen, int *count)
{
if (screen)
{
ROTATE_SCREEN(screen);
*count = NUM_OPTIONS(rs);
return rs->opt;
}
else
{
RotateScreen *rs = malloc(sizeof(RotateScreen));
rotateScreenInitOptions(rs);
*count = NUM_OPTIONS(rs);
return rs->opt;
}
}
static int adjustVelocity(CompScreen * s, RotateScreen * rs, int size)
{
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;
IPCS_SetBool(IPCS_OBJECT(s), rs->snapTopBottomAtom, TRUE);
}
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);
if (rs->movingVert)
{
yrot = rs->moveToY + (rs->yrot + rs->baseYrot);
}
else
{
if (rs->snapTop && s->hsize > 2 && rs->yrot > 50.0f)
{
yrot = -(90.f - rs->yrot);
}
else if (rs->snapBottom && s->hsize > 2 && rs->yrot < -50.0f)
{
yrot = (90.0f + rs->yrot);
}
else
{
yrot = rs->yrot;
}
}
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);
Bool performZooming = FALSE;
if (rs->zooming && (!otherScreenGrabExist(s, "rotate", 0) ||
(rs->zoomTranslate != 0.0f
&& rs->zoomTranslate != rs->zoom)))
performZooming = TRUE;
if (rs->grabIndex || rs->moving || rs->movingVert)
{
int steps, stepsCount;
float amount, chunk;
amount = msSinceLastPaint * 0.05f *
rs->opt[ROTATE_SCREEN_OPTION_SPEED].value.f;
steps = stepsCount =
amount / (0.5f *
(rs->grabbed ? rs->
opt[ROTATE_SCREEN_OPTION_MANTIMESTEP].value.
f : rs->opt[ROTATE_SCREEN_OPTION_TIMESTEP].value.
f));
if (!steps)
steps = stepsCount = 1;
chunk = amount / (float)steps;
if (performZooming &&
rs->opt[ROTATE_SCREEN_OPTION_ZOOM_BEFORE_ROTATE].value.
b && rs->rotating)
{
steps = stepsCount;
while (steps--)
{
float dt, adjust, tamount;
dt = rs->zoom - rs->zoomTranslate;
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->zoomVelocity =
(tamount * rs->zoomVelocity + adjust) / (tamount +
1.0f);
if (fabs(dt) < 0.1f && fabs(rs->zoomVelocity) < 0.0005f)
{
rs->zoomTranslate = rs->zoom;
break;
}
rs->zoomTranslate += rs->zoomVelocity * chunk;
}
if (rs->zoomTranslate != rs->zoom)
{
UNWRAP(rs, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP(rs, s, preparePaintScreen, rotatePreparePaintScreen);
return;
}
}
steps = stepsCount;
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 (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(s, rs, s->hsize))
{
rs->xVelocity = 0.0f;
rs->yVelocity = 0.0f;
damageScreen(s);
if ((fabs(rs->yrot) < 0.1f))
//&& !screenGrabExist(s, "scale", 0))
{
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;
if (s->hsize == 4)
{
float previousRotation = IPCS_GetFloat(IPCS_OBJECT(s),
rs->
previousRotationAtom);
IPCS_SetFloat(IPCS_OBJECT(s),
rs->previousRotationAtom,
previousRotation + tx);
}
compDisplayClearRequestFlagForPlugin
(s->display, "rotate", "ENABLE_3D");
moveScreenViewport(s, tx, 0, TRUE);
rs->xrot = 0.0f;
rs->yrot = 0.0f;
rs->baseXrot = rs->moveTo = 0.0f;
rs->baseYrot = rs->moveToY = 0.0f;
rs->moving = FALSE;
rs->movingVert = 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
focusDefaultWindow(s->display);
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, FALSE);
}
}
}
if (fabs(rs->xrot) < 0.01f && fabs(rs->yrot) < 0.01f && !rs->grabbed)
rs->rotating = FALSE;
else
rs->rotating = TRUE;
if (performZooming
&& !rs->opt[ROTATE_SCREEN_OPTION_ZOOM_BEFORE_ROTATE].value.b
&& (rs->rotating || rs->zoomTranslate != 0.0f)
&& !(rs->opt[ROTATE_SCREEN_OPTION_ZOOM_ONLY_ON_INITIATE].value.
b && !(rs->grabbed || rs->zoomTranslate != 0.0f)))
{
int steps, stepsCount;
float amount, chunk;
amount = msSinceLastPaint * 0.05f *
rs->opt[ROTATE_SCREEN_OPTION_SPEED].value.f;
steps = stepsCount =
amount / (0.5f *
rs->opt[ROTATE_SCREEN_OPTION_TIMESTEP].value.f);
if (!steps)
steps = stepsCount = 1;
chunk = amount / (float)steps;
Bool zoomOut = FALSE;
if (rs->moving
&& fabs(rs->xrot + rs->baseXrot + rs->moveTo) >
(360.0 / (s->hsize * 2.0)))
{
zoomOut = TRUE;
}
if (rs->movingVert
&& fabs(rs->yrot + rs->baseYrot + rs->moveToY) > 45.0)
{
zoomOut = TRUE;
}
if (rs->grabbed)
zoomOut = TRUE;
while (steps--)
{
float dt, adjust, tamount;
if (rs->rotating && zoomOut)
dt = rs->zoom - rs->zoomTranslate;
else
dt = 0.0f - rs->zoomTranslate;
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->zoomVelocity =
(tamount * rs->zoomVelocity + adjust) / (tamount + 1.0f);
if (fabs(dt) < 0.1f && fabs(rs->zoomVelocity) < 0.0005f)
{
if (rs->rotating && zoomOut)
rs->zoomTranslate = rs->zoom;
else
rs->zoomTranslate = 0.0f;
break;
}
rs->zoomTranslate += rs->zoomVelocity * chunk;
}
}
if (performZooming
&& rs->opt[ROTATE_SCREEN_OPTION_ZOOM_BEFORE_ROTATE].value.b
&& !rs->rotating && rs->zoomTranslate != 0.0f && rs->yrot == 0.0f)
{
int steps, stepsCount;
float amount, chunk;
amount = msSinceLastPaint * 0.05f *
rs->opt[ROTATE_SCREEN_OPTION_SPEED].value.f;
steps = stepsCount =
amount / (0.5f *
rs->opt[ROTATE_SCREEN_OPTION_TIMESTEP].value.f);
if (!steps)
steps = stepsCount = 1;
chunk = amount / (float)steps;
while (steps--)
{
float dt, adjust, tamount;
dt = 0.0f - rs->zoomTranslate;
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->zoomVelocity =
(tamount * rs->zoomVelocity + adjust) / (tamount + 1.0f);
if (fabs(dt) < 0.1f && fabs(rs->zoomVelocity) < 0.0005f)
{
rs->zoomTranslate = 0.0f;
break;
}
rs->zoomTranslate += rs->zoomVelocity * chunk;
}
if (rs->zoomTranslate != 0.0f)
{
UNWRAP(rs, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP(rs, s, preparePaintScreen, rotatePreparePaintScreen);
return;
}
}
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->movingVert)
{
if ((!rs->grabbed && !rs->snapTop && !rs->snapBottom)
|| rs->xVelocity || rs->yVelocity || rs->zooming)
damageScreen(s);
}
else if (rs->zooming && rs->zoomTranslate != 0.0f)
damageScreen(s);
UNWRAP(rs, s, donePaintScreen);
(*s->donePaintScreen) (s);
WRAP(rs, s, donePaintScreen, rotateDonePaintScreen);
}
static Bool
rotatePaintScreen(CompScreen * s,
const ScreenPaintAttrib * sAttrib,
Region region, int output, unsigned int mask)
{
Bool status;
ROTATE_SCREEN(s);
if (rs->grabIndex || rs->moving || rs->movingVert)
{
ScreenPaintAttrib sa = *sAttrib;
if (rs->zooming)
sa.zCamera -= rs->zoomTranslate;
sa.xRotate += rs->baseXrot + rs->xrot;
sa.vRotate += rs->baseYrot + rs->yrot;
mask &= ~PAINT_SCREEN_REGION_MASK;
mask |= PAINT_SCREEN_TRANSFORMED_MASK;
UNWRAP(rs, s, paintScreen);
status = (*s->paintScreen) (s, &sa, region, output, mask);
WRAP(rs, s, paintScreen, rotatePaintScreen);
}
else if (rs->zooming && rs->zoomTranslate != 0.0f)
{
ScreenPaintAttrib sa = *sAttrib;
sa.zCamera -= rs->zoomTranslate;
mask &= ~PAINT_SCREEN_REGION_MASK;
mask |= PAINT_SCREEN_TRANSFORMED_MASK;
UNWRAP(rs, s, paintScreen);
status = (*s->paintScreen) (s, &sa, region, output, mask);
WRAP(rs, s, paintScreen, rotatePaintScreen);
}
else
{
UNWRAP(rs, s, paintScreen);
status = (*s->paintScreen) (s, sAttrib, region, output, mask);
WRAP(rs, s, paintScreen, rotatePaintScreen);
}
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);
IPCS_SetBool(IPCS_OBJECT(s), rs->snapTopBottomAtom, FALSE);
if (s->hsize < 2)
return FALSE;
if (rs->rotateHandle && rs->grabWindow)
{
if (otherScreenGrabExist(s, "rotate", "move", 0))
return FALSE;
}
else
{
if (otherScreenGrabExist(s, "rotate", "switcher", "cube", 0))
return FALSE;
}
rs->moving = FALSE;
rs->slow = FALSE;
rs->movingVert = FALSE;
rs->moveTo = 0.0f;
rs->moveToY = 0.0f;
compDisplaySetRequestFlagForPlugin(s->display, "rotate", "ENABLE_3D");
rs->rotating = FALSE;
if ((state & CompActionStateInitButton))
{
IPCS_SetBool(IPCS_OBJECT(s), rs->manualAtom, TRUE);
}
else
{
IPCS_SetBool(IPCS_OBJECT(s), rs->manualAtom, FALSE);
}
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->moveToY = 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
rotateInitiateDesktop(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
CompScreen *s = findScreenAtDisplay(d,
getIntOptionNamed(option, nOption,
"root", 0));
if (s)
{
int x, y;
x = getIntOptionNamed(option, nOption, "x", 0);
y = getIntOptionNamed(option, nOption, "y", 0);
if (pointerOnlyOnDesktop(s, x, y) || screenGrabExist(s, "rotate", 0))
return rotateInitiate(d, action, state, option, nOption);
}
return FALSE;
}
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;
rs->rotating = FALSE;
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", "cube", "scale", "group-drag",
0))
return FALSE;
/* FIXME: this is sort of a hack - we check if
the state of scale is "waiting for user
we definitely need a better communication
mechanism here... */
int *scaleState = (int *)IPCS_GetVPtrND(IPCS_OBJECT(s),
"SCALE_STATE_INT_PTR", NULL);
if (scaleState && (*scaleState == 2))
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->moving = TRUE;
rs->moveTo += (360.0f / s->hsize) * direction;
rs->grabbed = FALSE;
damageScreen(s);
}
return FALSE;
}
static Bool
rotateVert(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 && s->hsize > 2)
{
int direction;
ROTATE_SCREEN(s);
if (otherScreenGrabExist(s, "rotate", "move", "switcher", "cube", 0))
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);
}
if (fabs(rs->moveToY) == 90.0f
&& (rs->moveToY + -90.0f * direction) != 0.0f)
{
direction = -direction;
rs->moving = TRUE;
rs->moveTo += 180.0f * direction;
}
rs->movingVert = TRUE;
rs->moveToY += -90.0f * 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;
xid = getIntOptionNamed(option, nOption, "root", 0);
s = findScreenAtDisplay(d, xid);
if (s)
{
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);
w = findWindowAtScreen(s, xid);
if (w)
{
if (!
(w->
type & (CompWindowTypeDesktopMask |
CompWindowTypeDockMask)))
{
if (!(w->state & CompWindowStateStickyMask))
{
rs->moveWindow = w->id;
rs->moveWindowX = w->attrib.x;
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 TRUE;
}
static Bool
pointerNearScreenEdge(CompScreen * s, int x, int y, int maxDistance)
{
if (((x - s->x) >= -maxDistance && (x - s->x) <= maxDistance)
|| ((s->x + s->width - x) >= -maxDistance
&& (s->x + s->width - x) <= maxDistance)
|| ((y - s->y) >= -maxDistance && (y - s->y) <= maxDistance)
|| ((s->y + s->height - y) >= -maxDistance
&& (s->y + s->height - y) <= maxDistance))
return TRUE;
return FALSE;
}
static Bool
rotateWheel(CompDisplay * d, int direction, CompOption * option, int nOption)
{
ROTATE_DISPLAY(d);
CompScreen *s = findScreenAtDisplay(d,
getIntOptionNamed(option,
nOption,
"root", 0));
if (s)
{
ROTATE_SCREEN(s);
int x, y;
unsigned int *wheelings;
if (direction == -1)
{
wheelings = &rd->rightWheelings;
rd->leftWheelings = 0;
}
else
{
wheelings = &rd->leftWheelings;
rd->rightWheelings = 0;
}
x = getIntOptionNamed(option, nOption, "x", 0);
y = getIntOptionNamed(option, nOption, "y", 0);
if (pointerOnlyOnDesktop(s, x, y)
|| (rs->opt[ROTATE_SCREEN_OPTION_WHEEL_ON_EDGES].value.
b
&& pointerNearScreenEdge(s, x, y,
rs->
opt
[ROTATE_SCREEN_OPTION_WHEELMAXDIST].
value.i)))
{
if (++(*wheelings) ==
rd->opt[ROTATE_DISPLAY_OPTION_WHEELINGS].value.i)
{
*wheelings = 0;
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 = direction;
rotate(d, NULL, 0, o, 4);
}
}
else
*wheelings = 0;
}
return FALSE;
}
static Bool
rotateRightWheel(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateWheel(d, 1, option, nOption);
}
static Bool
rotateLeftWheel(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateWheel(d, -1, option, nOption);
}
static Bool
rotateReal(CompDisplay * d, Bool vert, int direction,
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 = direction;
if (vert)
rotateVert(d, NULL, 0, o, 4);
else
rotate(d, NULL, 0, o, 4);
return FALSE;
}
static Bool
rotateLeft(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateReal(d, FALSE, -1, option, nOption);
}
static Bool
rotateRight(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateReal(d, FALSE, 1, option, nOption);
}
static Bool
rotateTop(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateReal(d, TRUE, 1, option, nOption);
}
static Bool
rotateDown(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateReal(d, TRUE, -1, option, nOption);
}
static Bool
rotateWithWindowReal(CompDisplay * d, int direction, 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 = direction;
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
rotateLeftWithWindow(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateWithWindowReal(d, -1, option, nOption);
}
static Bool
rotateRightWithWindow(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
return rotateWithWindowReal(d, 1, option, nOption);
}
static Bool rotateFlip(CompScreen * s, int direction)
{
int warpX;
CompOption o[4];
ROTATE_SCREEN(s);
rs->moveTo = 0.0f;
rs->slow = FALSE;
if (otherScreenGrabExist(s, "rotate", "move", "group-drag", 0))
return FALSE;
if (direction == 1)
{
//rotation to right
warpX = s->display->pointerX - s->width;
warpPointer(s->display, 10 - s->width, 0);
s->display->lastPointerX = warpX;
}
else
{
warpX = s->display->pointerX + s->width;
warpPointer(s->display, s->width - 10, 0);
s->display->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 = s->display->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 = direction;
rotate(s->display, NULL, 0, o, 4);
XWarpPointer(s->display->display, None, None, 0, 0, 0, 0, direction, 0);
if (direction == 1)
rs->savedPointer.x = s->display->lastPointerX + 9;
else
rs->savedPointer.x = s->display->lastPointerX - 9;
rs->rotateHandle = 0;
return FALSE;
}
static Bool rotateFlipLeft(void *closure)
{
CompScreen *s = closure;
return rotateFlip(s, -1);
}
static Bool rotateFlipRight(void *closure)
{
CompScreen *s = closure;
return rotateFlip(s, 1);
}
static void
rotateEdgeFlip(CompScreen * s,
int edge,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
CompOption o[4];
int direction;
ROTATE_DISPLAY(s->display);
ROTATE_SCREEN(s);
if (s->hsize < 2)
return;
if (otherScreenGrabExist(s, "rotate", "move", "group-drag", 0))
return;
if (state & CompActionStateInitEdgeDnd)
{
if (!rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_DND].value.b)
return;
if (otherScreenGrabExist(s, "rotate", 0))
return;
}
else if (screenGrabExist(s, "move", 0))
{
if (!rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_WINDOW].value.b)
return;
if (!rs->grabWindow)
return;
/* bail out if window is horizontally maximized or fullscreen */
if (rs->grabWindow->
state & (CompWindowStateMaximizedHorzMask |
CompWindowStateFullscreenMask))
return;
}
else if (screenGrabExist(s, "group-drag", 0))
{
if (!rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_DND].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 = s->display->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)
direction = -1;
else
direction = 1;
if (rd->opt[ROTATE_DISPLAY_OPTION_FLIPTIME].value.i == 0
|| (rs->moving && !rs->slow))
{
int pointerDx, warpX;
if (edge == SCREEN_EDGE_LEFT)
{
pointerDx = s->display->pointerX - s->display->lastPointerX;
warpX = s->display->pointerX + s->width;
warpPointer(s->display, s->width - 10, 0);
s->display->lastPointerX = warpX - pointerDx;
}
else
{
pointerDx = s->display->pointerX - s->display->lastPointerX;
warpX = s->display->pointerX - s->width;
warpPointer(s->display, 10 - s->width, 0);
s->display->lastPointerX = warpX - pointerDx;
}
o[3].value.i = direction;
rotate(s->display, NULL, 0, o, 4);
XWarpPointer(s->display->display, None, None, 0, 0, 0, 0,
direction, 0);
rs->savedPointer.x = s->display->lastPointerX + (direction * 9);
}
else
{
if (!rs->rotateHandle)
rs->rotateHandle =
compAddTimeout(rd->
opt
[ROTATE_DISPLAY_OPTION_FLIPTIME].
value.i,
(edge ==
SCREEN_EDGE_LEFT) ?
rotateFlipLeft : rotateFlipRight, s);
rs->moving = TRUE;
rs->moveTo += (direction * 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;
ROTATE_DISPLAY(s->display);
while (i <= ROTATE_DISPLAY_OPTION_TO_12)
{
if (action == &rd->opt[i].value.action)
{
face = i - ROTATE_DISPLAY_OPTION_TO_1;
break;
}
i++;
}
if (face < 0)
face = getIntOptionNamed(option, nOption, "face", s->x);
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i =
getIntOptionNamed(option, nOption, "x", s->display->pointerX);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i =
getIntOptionNamed(option, nOption, "y", s->display->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;
ROTATE_DISPLAY(s->display);
while (i <= ROTATE_DISPLAY_OPTION_TO_12_WINDOW)
{
if (action == &rd->opt[i].value.action)
{
face = i - ROTATE_DISPLAY_OPTION_TO_1_WINDOW;
break;
}
i++;
}
if (face < 0)
face = getIntOptionNamed(option, nOption, "face", s->x);
o[0].type = CompOptionTypeInt;
o[0].name = "x";
o[0].value.i =
getIntOptionNamed(option, nOption, "x", s->display->pointerX);
o[1].type = CompOptionTypeInt;
o[1].name = "y";
o[1].value.i =
getIntOptionNamed(option, nOption, "y", s->display->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);
if (rs->grabIndex)
{
if (rs->grabbed)
{
GLfloat pointerDx, 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 (rs->
opt[ROTATE_SCREEN_OPTION_POINTER_INVERT_Y].value.b)
pointerDy = -pointerDy;
rs->xVelocity +=
pointerDx * rs->pointerSensitivity * rs->invert;
rs->yVelocity += pointerDy * rs->pointerSensitivity;
damageScreen(s);
}
else
{
rs->savedPointer.x += d->pointerX - d->lastPointerX;
rs->savedPointer.y += d->pointerY - d->lastPointerY;
}
}
}
break;
case ClientMessage:
if (event->xclient.message_type == d->winActiveAtom)
{
CompWindow *w;
w = findWindowAtDisplay(d, event->xclient.window);
if (w)
{
int dx;
ROTATE_SCREEN(w->screen);
s = w->screen;
/* window must be placed */
if (!w->placed)
break;
if (w->state & CompWindowStateOffscreenMask)
break;
if (otherScreenGrabExist
(s, "rotate", "switcher", "cube", "scale", 0))
break;
/* reset movement */
rs->moving = FALSE;
rs->moveTo = 0.0f;
rs->movingVert = FALSE;
rs->moveToY = 0.0f;
defaultViewportForWindow(w, &dx, NULL);
dx -= 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 > (s->hsize + 1) / 2)
dx -= s->hsize;
else if (dx < -(s->hsize + 1) / 2)
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);
}
}
}
else if (event->xclient.message_type == d->desktopViewportAtom)
{
s = findScreenAtDisplay(d, event->xclient.window);
if (s)
{
int dx;
if (otherScreenGrabExist
(s, "rotate", "switcher", "cube", "scale", 0))
break;
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 > (s->hsize + 1) / 2)
dx -= s->hsize;
else if (dx < -(s->hsize + 1) / 2)
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
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 void rotateUpdateCubeOptions(CompScreen * s)
{
CompPlugin *p;
ROTATE_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)
rs->invert = option->value.b ? -1 : 1;
}
}
static Bool
rotateSetScreenOptionForPlugin(CompScreen * s,
char *plugin,
char *name, CompOptionValue * value)
{
Bool status;
ROTATE_SCREEN(s);
UNWRAP(rs, s, setScreenOptionForPlugin);
status = (*s->setScreenOptionForPlugin) (s, plugin, name, value);
WRAP(rs, s, setScreenOptionForPlugin, rotateSetScreenOptionForPlugin);
if (status && strcmp(plugin, "cube") == 0 && strcmp(name, "in") == 0)
rotateUpdateCubeOptions(s);
return status;
}
static Bool
rotateSetDisplayOption(CompDisplay * display,
char *name, CompOptionValue * value)
{
CompOption *o;
int index;
ROTATE_DISPLAY(display);
o = compFindOption(rd->opt, NUM_OPTIONS(rd), name, &index);
if (!o)
return FALSE;
switch (index)
{
case ROTATE_DISPLAY_OPTION_INITIATE:
case ROTATE_DISPLAY_OPTION_LEFT:
case ROTATE_DISPLAY_OPTION_RIGHT:
case ROTATE_DISPLAY_OPTION_UP:
case ROTATE_DISPLAY_OPTION_DOWN:
case ROTATE_DISPLAY_OPTION_TO_1:
case ROTATE_DISPLAY_OPTION_TO_2:
case ROTATE_DISPLAY_OPTION_TO_3:
case ROTATE_DISPLAY_OPTION_TO_4:
case ROTATE_DISPLAY_OPTION_TO_5:
case ROTATE_DISPLAY_OPTION_TO_6:
case ROTATE_DISPLAY_OPTION_TO_7:
case ROTATE_DISPLAY_OPTION_TO_8:
case ROTATE_DISPLAY_OPTION_TO_9:
case ROTATE_DISPLAY_OPTION_TO_10:
case ROTATE_DISPLAY_OPTION_TO_11:
case ROTATE_DISPLAY_OPTION_TO_12:
case ROTATE_DISPLAY_OPTION_LEFT_WINDOW:
case ROTATE_DISPLAY_OPTION_RIGHT_WINDOW:
case ROTATE_DISPLAY_OPTION_LEFT_WHEEL:
case ROTATE_DISPLAY_OPTION_RIGHT_WHEEL:
case ROTATE_DISPLAY_OPTION_TO_1_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_2_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_3_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_4_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_5_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_6_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_7_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_8_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_9_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_10_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_11_WINDOW:
case ROTATE_DISPLAY_OPTION_TO_12_WINDOW:
case ROTATE_DISPLAY_OPTION_FLIP_LEFT:
case ROTATE_DISPLAY_OPTION_FLIP_RIGHT:
case ROTATE_DISPLAY_OPTION_INITIATEDESKTOP:
case ROTATE_DISPLAY_OPTION_STICKY_INITIATE:
if (setDisplayAction(display, o, value))
return TRUE;
break;
case ROTATE_DISPLAY_OPTION_WHEELINGS:
case ROTATE_DISPLAY_OPTION_FLIPTIME:
if (compSetIntOption(o, value))
return TRUE;
break;
case ROTATE_DISPLAY_OPTION_TO:
case ROTATE_DISPLAY_OPTION_WINDOW:
if (compSetActionOption(o, value))
return TRUE;
break;
case ROTATE_DISPLAY_OPTION_EDGEFLIP_POINTER:
case ROTATE_DISPLAY_OPTION_EDGEFLIP_WINDOW:
case ROTATE_DISPLAY_OPTION_EDGEFLIP_DND:
if (compSetBoolOption(o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static void rotateDisplayInitOptions(RotateDisplay * rd)
{
CompOption *o;
char *str;
o = &rd->opt[ROTATE_DISPLAY_OPTION_INITIATE];
o->advanced = False;
o->name = "initiate";
o->group = N_("Bindings");
o->subGroup = N_("Initiate");
o->displayHints = "";
o->shortDesc = N_("Initiate Rotation");
o->longDesc = N_("Start Rotation.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateInitiate;
o->value.action.terminate = rotateTerminate;
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 = ROTATE_INITIATE_MODIFIERS_DEFAULT;
o->value.action.button.button = ROTATE_INITIATE_BUTTON_DEFAULT;
o = &rd->opt[ROTATE_DISPLAY_OPTION_STICKY_INITIATE];
o->advanced = False;
o->name = "initiate_sticky";
o->group = N_("Bindings");
o->subGroup = N_("Initiate");
o->displayHints = "";
o->shortDesc = N_("Initiate Sticky");
o->longDesc =
N_
("Start Rotation and don't finish it until specifily terminated by"
" the normal Initiate.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateInitiate;
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 =
ROTATE_INITIATE_STICKY_MODIFIERS_DEFAULT;
o->value.action.button.button = ROTATE_INITIATE_STICKY_BUTTON_DEFAULT;
o = &rd->opt[ROTATE_DISPLAY_OPTION_WHEELINGS];
o->advanced = False;
o->name = "rotate_wheelings";
o->group = N_("Behaviour");
o->subGroup = N_("General");
o->displayHints = "";
o->shortDesc = N_("Mouse Wheel Scrolls for Rotation");
o->longDesc = N_("Number of Mouse Wheel Scrolls required for Rotation.");
o->type = CompOptionTypeInt;
o->value.i = ROTATE_WHEELINGS_DEFAULT;
o->rest.i.min = ROTATE_WHEELINGS_MIN;
o->rest.i.max = ROTATE_WHEELINGS_MAX;
o = &rd->opt[ROTATE_DISPLAY_OPTION_LEFT_WHEEL];
o->advanced = False;
o->name = "rotate_left_wheel";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Left");
o->displayHints = "";
o->shortDesc = N_("Rotate Left with Mouse Wheel");
o->longDesc = N_("Rotate Left with Mouse Wheel.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateLeftWheel;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitButton;
o->value.action.type = CompBindingTypeButton;
o->value.action.button.modifiers = ROTATE_LEFT_WHEEL_MODIFIERS_DEFAULT;
o->value.action.button.button = ROTATE_LEFT_WHEEL_DEFAULT;
o = &rd->opt[ROTATE_DISPLAY_OPTION_RIGHT_WHEEL];
o->advanced = False;
o->name = "rotate_right_wheel";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Right");
o->displayHints = "";
o->shortDesc = N_("Rotate Right with Mouse Wheel");
o->longDesc = N_("Rotate Right with Mouse Wheel.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateRightWheel;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitButton;
o->value.action.type = CompBindingTypeButton;
o->value.action.button.modifiers = ROTATE_RIGHT_WHEEL_MODIFIERS_DEFAULT;
o->value.action.button.button = ROTATE_RIGHT_WHEEL_DEFAULT;
o = &rd->opt[ROTATE_DISPLAY_OPTION_LEFT];
o->advanced = False;
o->name = "rotate_left";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Left");
o->displayHints = "";
o->shortDesc = N_("Rotate Left");
o->longDesc = N_("Rotate Left.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateLeft;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = ROTATE_LEFT_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(ROTATE_LEFT_KEY_DEFAULT);
o = &rd->opt[ROTATE_DISPLAY_OPTION_RIGHT];
o->advanced = False;
o->name = "rotate_right";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Right");
o->displayHints = "";
o->shortDesc = N_("Rotate Right");
o->longDesc = N_("Rotate Right.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateRight;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = ROTATE_RIGHT_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(ROTATE_RIGHT_KEY_DEFAULT);
o = &rd->opt[ROTATE_DISPLAY_OPTION_UP];
o->advanced = False;
o->name = "rotate_up";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Up");
o->displayHints = "";
o->shortDesc = N_("Rotate Up");
o->longDesc = N_("Rotate Up.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateTop;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = ROTATE_UP_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(ROTATE_UP_KEY_DEFAULT);
o = &rd->opt[ROTATE_DISPLAY_OPTION_DOWN];
o->advanced = False;
o->name = "rotate_down";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Down");
o->displayHints = "";
o->shortDesc = N_("Rotate Down");
o->longDesc = N_("Rotate Down.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateDown;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = ROTATE_DOWN_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(ROTATE_DOWN_KEY_DEFAULT);
o = &rd->opt[ROTATE_DISPLAY_OPTION_LEFT_WINDOW];
o->advanced = False;
o->name = "rotate_left_window";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Left");
o->displayHints = "";
o->shortDesc = N_("Rotate Left with Window");
o->longDesc = N_("Rotate Left and bring the active Window along.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateLeftWithWindow;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = ROTATE_LEFT_WINDOW_MODIFIERS_DEFAULT;
o->value.action.key.keysym =
XStringToKeysym(ROTATE_LEFT_WINDOW_KEY_DEFAULT);
o = &rd->opt[ROTATE_DISPLAY_OPTION_RIGHT_WINDOW];
o->advanced = False;
o->name = "rotate_right_window";
o->group = N_("Bindings");
o->subGroup = N_("Rotate Right");
o->displayHints = "";
o->shortDesc = N_("Rotate Right with Window");
o->longDesc = N_("Rotate Right and bring the active Window along.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateRightWithWindow;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = ROTATE_RIGHT_WINDOW_MODIFIERS_DEFAULT;
o->value.action.key.keysym =
XStringToKeysym(ROTATE_RIGHT_WINDOW_KEY_DEFAULT);
#define ROTATE_TO_SHORT N_("Rotate To Face %d")
#define ROTATE_TO_LONG N_("Rotate to face %d")
#define ROTATE_TO_WINDOW_SHORT N_("Rotate To Face %d with Window")
#define ROTATE_TO_WINDOW_LONG N_("Rotate to face %d and bring active " \
"window along")
#define ROTATE_TO_OPTION(n) \
o = &rd->opt[ROTATE_DISPLAY_OPTION_TO_ ## n]; \
o->advanced=False;\
o->name = "rotate_to_" #n; \
asprintf (&str, ROTATE_TO_SHORT, n); \
o->group=N_("Bindings");\
o->subGroup=N_("Face shortcuts");\
o->displayHints="";\
o->shortDesc = str; \
asprintf (&str, ROTATE_TO_LONG, n); \
o->longDesc = str; \
o->type = CompOptionTypeAction; \
o->value.action.initiate = rotateTo; \
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 = CompBindingTypeNone; \
\
o = &rd->opt[ROTATE_DISPLAY_OPTION_TO_ ## n ## _WINDOW]; \
o->advanced=False;\
o->name = "rotate_to_" #n "_window"; \
asprintf (&str, ROTATE_TO_WINDOW_SHORT, n); \
o->group=N_("Bindings");\
o->subGroup=N_("Face shortcuts");\
o->displayHints="";\
o->shortDesc = str; \
asprintf (&str, ROTATE_TO_WINDOW_LONG, n); \
o->longDesc = str; \
o->type = CompOptionTypeAction; \
o->value.action.initiate = rotateToWithWindow; \
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 = CompBindingTypeNone
ROTATE_TO_OPTION(1);
ROTATE_TO_OPTION(2);
ROTATE_TO_OPTION(3);
ROTATE_TO_OPTION(4);
ROTATE_TO_OPTION(5);
ROTATE_TO_OPTION(6);
ROTATE_TO_OPTION(7);
ROTATE_TO_OPTION(8);
ROTATE_TO_OPTION(9);
ROTATE_TO_OPTION(10);
ROTATE_TO_OPTION(11);
ROTATE_TO_OPTION(12);
o = &rd->opt[ROTATE_DISPLAY_OPTION_TO];
o->advanced = False;
o->name = "rotate_to";
o->group = N_("");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Rotate To");
o->longDesc = N_("Rotate to Viewport.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateTo;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = 0;
o->value.action.type = CompBindingTypeNone;
o = &rd->opt[ROTATE_DISPLAY_OPTION_WINDOW];
o->advanced = False;
o->name = "rotate_window";
o->group = N_("");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Rotate Window");
o->longDesc = N_("Rotate with Window.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateToWithWindow;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.state = 0;
o->value.action.type = CompBindingTypeNone;
o = &rd->opt[ROTATE_DISPLAY_OPTION_FLIP_LEFT];
o->advanced = False;
o->name = "rotate_flip_left";
o->group = N_("Bindings");
o->subGroup = N_("Edge Flip");
o->displayHints = "";
o->shortDesc = N_("Rotate Flip Left");
o->longDesc = N_("Flip to Left Viewport and warp pointer.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateEdgeFlipLeft;
o->value.action.terminate = rotateFlipTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 1 << SCREEN_EDGE_LEFT;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeNone;
o = &rd->opt[ROTATE_DISPLAY_OPTION_FLIP_RIGHT];
o->advanced = False;
o->name = "rotate_flip_right";
o->group = N_("Bindings");
o->subGroup = N_("Edge Flip");
o->displayHints = "";
o->shortDesc = N_("Rotate Flip Right");
o->longDesc = N_("Flip to Right Viewport and warp pointer.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateEdgeFlipRight;
o->value.action.terminate = rotateFlipTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 1 << SCREEN_EDGE_RIGHT;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeNone;
o = &rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_POINTER];
o->advanced = False;
o->name = "edge_flip_pointer";
o->group = N_("Behaviour");
o->subGroup = N_("Edge Flip");
o->displayHints = "";
o->shortDesc = N_("Edge Flip Pointer");
o->longDesc =
N_("Flip to Next Viewport when moving Pointer to Screen Edge.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_EDGEFLIP_POINTER_DEFAULT;
o = &rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_WINDOW];
o->advanced = False;
o->name = "edge_flip_move";
o->group = N_("Behaviour");
o->subGroup = N_("Edge Flip");
o->displayHints = "";
o->shortDesc = N_("Edge Flip Move");
o->longDesc =
N_("Flip to Next Viewport when moving Window to Screen Edge.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_EDGEFLIP_WINDOW_DEFAULT;
o = &rd->opt[ROTATE_DISPLAY_OPTION_EDGEFLIP_DND];
o->advanced = False;
o->name = "edge_flip_dnd";
o->group = N_("Behaviour");
o->subGroup = N_("Edge Flip");
o->displayHints = "";
o->shortDesc = N_("Edge Flip DnD");
o->longDesc =
N_("Flip to Next Viewport when Dragging object "
"to Screen Edge.");
o->type = CompOptionTypeBool;
o->value.b = ROTATE_EDGEFLIP_DND_DEFAULT;
o = &rd->opt[ROTATE_DISPLAY_OPTION_FLIPTIME];
o->advanced = False;
o->name = "flip_time";
o->group = N_("Behaviour");
o->subGroup = N_("Edge Flip");
o->displayHints = "";
o->shortDesc = N_("Flip Time");
o->longDesc = N_("Timeout before Flipping viewport.");
o->type = CompOptionTypeInt;
o->value.i = ROTATE_FLIPTIME_DEFAULT;
o->rest.i.min = ROTATE_FLIPTIME_MIN;
o->rest.i.max = ROTATE_FLIPTIME_MAX;
o = &rd->opt[ROTATE_DISPLAY_OPTION_INITIATEDESKTOP];
o->advanced = False;
o->name = "initiatedesktop";
o->group = N_("Bindings");
o->subGroup = N_("Initiate");
o->displayHints = "";
o->shortDesc = N_("Initiate on Desktop");
o->longDesc = N_("Start Rotation, but only when issued over Desktop.");
o->type = CompOptionTypeAction;
o->value.action.initiate = rotateInitiateDesktop;
o->value.action.terminate = rotateTerminate;
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 =
ROTATE_INITIATEDESKTOP_MODIFIERS_DEFAULT;
o->value.action.button.button = ROTATE_INITIATEDESKTOP_BUTTON_DEFAULT;
}
static CompOption *rotateGetDisplayOptions(CompDisplay * display, int *count)
{
if (display)
{
ROTATE_DISPLAY(display);
*count = NUM_OPTIONS(rd);
return rd->opt;
}
else
{
RotateDisplay *rd = malloc(sizeof(RotateDisplay));
rotateDisplayInitOptions(rd);
*count = NUM_OPTIONS(rd) - 2;
return rd->opt;
}
}
static Bool rotateInitDisplay(CompPlugin * p, CompDisplay * d)
{
RotateDisplay *rd;
rd = malloc(sizeof(RotateDisplay));
if (!rd)
return FALSE;
rd->screenPrivateIndex = allocateScreenPrivateIndex(d);
if (rd->screenPrivateIndex < 0)
{
free(rd);
return FALSE;
}
rd->leftWheelings = 0;
rd->rightWheelings = 0;
rotateDisplayInitOptions(rd);
WRAP(rd, d, handleEvent, rotateHandleEvent);
d->privates[displayPrivateIndex].ptr = rd;
return TRUE;
}
static void rotateFiniDisplay(CompPlugin * p, CompDisplay * d)
{
ROTATE_DISPLAY(d);
freeScreenPrivateIndex(d, rd->screenPrivateIndex);
UNWRAP(rd, d, handleEvent);
free(rd);
}
static Bool rotateInitScreen(CompPlugin * p, CompScreen * s)
{
RotateScreen *rs;
ROTATE_DISPLAY(s->display);
rs = malloc(sizeof(RotateScreen));
if (!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->baseYrot = 0.0f;
rs->moving = FALSE;
rs->moveTo = 0.0f;
rs->movingVert = FALSE;
rs->moveToY = 0.0f;
rs->moveWindow = 0;
rs->savedPointer.x = 0;
rs->savedPointer.y = 0;
rs->grabbed = FALSE;
rs->snapTop = FALSE;
rs->snapBottom = FALSE;
rs->slow = FALSE;
rs->grabMask = FALSE;
rs->grabWindow = NULL;
rs->manualAtom =
IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "MOUSE_INITIATED_ROTATE",
TRUE);
rs->pointerSensitivity =
ROTATE_POINTER_SENSITIVITY_DEFAULT *
ROTATE_POINTER_SENSITIVITY_FACTOR;
rs->zoom = ROTATE_ZOOM_DEFAULT / 30.0f;
rs->zooming = (ROTATE_ZOOM_DEFAULT > 0.05f) ? TRUE : FALSE;
rs->zoomTranslate = 0.0f;
rs->zoomVelocity = 0.0f;
rs->rotateHandle = 0;
rs->rotating = FALSE;
rs->previousRotationAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_FLOAT,
"PREVIOUS_ROTATION", TRUE);
rs->snapTopBottomAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL,
"CUBE_SNAP_TOP_BOTTOM", TRUE);
rotateScreenInitOptions(rs);
addScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_INITIATE].value.action);
addScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_LEFT].value.action);
addScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_RIGHT].value.action);
addScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_UP].value.action);
addScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_DOWN].value.action);
addScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_LEFT_WINDOW].value.action);
addScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_RIGHT_WINDOW].value.
action);
addScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_FLIP_LEFT].value.action);
addScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_FLIP_RIGHT].value.action);
addScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_LEFT_WHEEL].value.action);
addScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_RIGHT_WHEEL].value.action);
addScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_INITIATEDESKTOP].value.
action);
WRAP(rs, s, preparePaintScreen, rotatePreparePaintScreen);
WRAP(rs, s, donePaintScreen, rotateDonePaintScreen);
WRAP(rs, s, paintScreen, rotatePaintScreen);
WRAP(rs, s, setScreenOptionForPlugin, rotateSetScreenOptionForPlugin);
WRAP(rs, s, windowGrabNotify, rotateWindowGrabNotify);
WRAP(rs, s, windowUngrabNotify, rotateWindowUngrabNotify);
s->privates[rd->screenPrivateIndex].ptr = rs;
rotateUpdateCubeOptions(s);
return TRUE;
}
static void rotateFiniScreen(CompPlugin * p, CompScreen * s)
{
ROTATE_SCREEN(s);
ROTATE_DISPLAY(s->display);
UNWRAP(rs, s, preparePaintScreen);
UNWRAP(rs, s, donePaintScreen);
UNWRAP(rs, s, paintScreen);
UNWRAP(rs, s, setScreenOptionForPlugin);
UNWRAP(rs, s, windowGrabNotify);
UNWRAP(rs, s, windowUngrabNotify);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_INITIATE].value.action);
removeScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_LEFT].value.action);
removeScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_RIGHT].value.action);
removeScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_UP].value.action);
removeScreenAction(s, &rd->opt[ROTATE_DISPLAY_OPTION_DOWN].value.action);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_LEFT_WINDOW].
value.action);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_RIGHT_WINDOW].
value.action);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_FLIP_LEFT].value.
action);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_FLIP_RIGHT].
value.action);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_LEFT_WHEEL].
value.action);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_RIGHT_WHEEL].
value.action);
removeScreenAction(s,
&rd->opt[ROTATE_DISPLAY_OPTION_INITIATEDESKTOP].value.
action);
free(rs);
}
static Bool rotateInit(CompPlugin * p)
{
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void rotateFini(CompPlugin * p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
CompPluginDep rotateDeps[] = {
{CompPluginRuleAfter, "cube"}
,
{CompPluginRuleRequire, "cube"}
};
CompPluginVTable rotateVTable = {
"rotate",
N_("Rotate Cube"),
N_("Rotate desktop cube"),
rotateInit,
rotateFini,
rotateInitDisplay,
rotateFiniDisplay,
rotateInitScreen,
rotateFiniScreen,
0, /* InitWindow */
0, /* FiniWindow */
rotateGetDisplayOptions,
rotateSetDisplayOption,
rotateGetScreenOptions,
rotateSetScreenOption,
rotateDeps,
sizeof(rotateDeps) / sizeof(rotateDeps[0]),
0,
0,
BERYL_ABI_INFO,
"beryl-plugins",
"desktop",
0,
0,
True,
};
CompPluginVTable *getCompPluginInfo(void)
{
return &rotateVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1