/* * 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 */ #define _GNU_SOURCE /* for asprintf */ #include #include #include #include #include #include #include #include #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; }