/*
* 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>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/cursorfont.h>
#include <beryl.h>
#define MOVE_INITIATE_BUTTON_DEFAULT Button1
#define MOVE_INITIATE_BUTTON_MODIFIERS_DEFAULT CompAltMask
#define MOVE_INITIATE_KEY_DEFAULT "F7"
#define MOVE_INITIATE_KEY_MODIFIERS_DEFAULT CompAltMask
#define MOVE_OPACITY_DEFAULT 100
#define MOVE_OPACITY_MIN 1
#define MOVE_OPACITY_MAX 100
#define MOVE_CONSTRAIN_Y_TOP_DEFAULT TRUE
#define MOVE_CONSTRAIN_Y_BOTTOM_DEFAULT FALSE
#define MOVE_SNAPOFF_MAXIMIZED_DEFAULT FALSE
#define MOVE_OPACIFY_MIN_OPACITY_DEFAULT 80
#define MOVE_OPACIFY_MIN_OPACITY_MIN 1
#define MOVE_OPACIFY_MIN_OPACITY_MAX 100
#define MOVE_SNAPOFF_DISTANCE_DEFAULT 100
#define MOVE_SNAPOFF_DISTANCE_MIN 1
#define MOVE_SNAPOFF_DISTANCE_MAX 300
#define MOVE_SNAPBACK_DISTANCE_DEFAULT 20
#define MOVE_SNAPBACK_DISTANCE_MIN 1
#define MOVE_SNAPBACK_DISTANCE_MAX 100
struct _MoveKeys
{
char *name;
int dx;
int dy;
} mKeys[] =
{
{
"Left", -1, 0},
{
"Right", 1, 0},
{
"Up", 0, -1},
{
"Down", 0, 1}
};
#define NUM_KEYS (sizeof (mKeys) / sizeof (mKeys[0]))
#define KEY_MOVE_INC 24
static int displayPrivateIndex;
#define MOVE_DISPLAY_OPTION_INITIATE 0
#define MOVE_DISPLAY_OPTION_OPACITY 1
#define MOVE_DISPLAY_OPTION_CONSTRAIN_Y_TOP 2
#define MOVE_DISPLAY_OPTION_CONSTRAIN_Y_BOTTOM 3
#define MOVE_DISPLAY_OPTION_OPACIFY_MIN_OPACITY 4
#define MOVE_DISPLAY_OPTION_SNAPOFF_MAXIMIZED 5
#define MOVE_DISPLAY_OPTION_SNAPOFF_DISTANCE 6
#define MOVE_DISPLAY_OPTION_SNAPBACK_DISTANCE 7
#define MOVE_DISPLAY_OPTION_NUM 8
typedef struct _MoveDisplay
{
int screenPrivateIndex;
HandleEventProc handleEvent;
CompOption opt[MOVE_DISPLAY_OPTION_NUM];
CompWindow *w;
int x;
int y;
Region region;
int status;
KeyCode key[NUM_KEYS];
Bool moveOpacitySet;
GLushort moveOpacity;
GLushort opacifyMinOpacity;
} MoveDisplay;
typedef struct _MoveScreen
{
int grabIndex;
Cursor moveCursor;
unsigned int origState;
int snapOffY;
int snapBackY;
} MoveScreen;
#define GET_MOVE_DISPLAY(d) \
((MoveDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define MOVE_DISPLAY(d) \
MoveDisplay *md = GET_MOVE_DISPLAY (d)
#define GET_MOVE_SCREEN(s, md) \
((MoveScreen *) (s)->privates[(md)->screenPrivateIndex].ptr)
#define MOVE_SCREEN(s) \
MoveScreen *ms = GET_MOVE_SCREEN (s, GET_MOVE_DISPLAY (s->display))
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static Bool
moveInitiate(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
CompWindow *w;
Window xid;
MOVE_DISPLAY(d);
xid = getIntOptionNamed(option, nOption, "window", 0);
w = findWindowAtDisplay(d, xid);
if (w)
{
XRectangle workArea;
unsigned int mods;
int x, y, head;
MOVE_SCREEN(w->screen);
head = screenGetOutputDevForWindow(w);
screenGetOutputDevWorkArea(w->screen, head, &workArea);
mods = getIntOptionNamed(option, nOption, "modifiers", 0);
x = getIntOptionNamed(option, nOption, "x",
w->attrib.x + (w->width / 2));
y = getIntOptionNamed(option, nOption, "y",
w->attrib.y + (w->height / 2));
if (otherScreenGrabExist(w->screen, "move", 0))
return FALSE;
if (md->w)
return FALSE;
if (w->type & (CompWindowTypeDesktopMask |
CompWindowTypeDockMask | CompWindowTypeFullscreenMask))
return FALSE;
if (w->attrib.override_redirect)
return FALSE;
if (state & CompActionStateInitButton)
action->state |= CompActionStateTermButton;
if (md->region)
{
XDestroyRegion(md->region);
md->region = NULL;
}
md->status = RectangleOut;
md->x = 0;
md->y = 0;
d->lastPointerX = x;
d->lastPointerY = y;
ms->origState = w->state;
ms->snapBackY = w->serverY - workArea.y;
ms->snapOffY = y - workArea.y;
if (!ms->grabIndex)
ms->grabIndex = pushScreenGrab(w->screen, ms->moveCursor, "move");
if (ms->grabIndex)
{
md->w = w;
(w->screen->windowGrabNotify) (w, x, y, mods,
CompWindowGrabMoveMask
| CompWindowGrabButtonMask);
if (md->moveOpacity != OPAQUE &&
w->paint.opacity >= md->opacifyMinOpacity)
{
/* modify opacity of windows that are not active */
setWindowOpacity(w, md->moveOpacity, PL_TEMP_HELLO);
md->moveOpacitySet = True;
}
else
md->moveOpacitySet = False;
if (state & CompActionStateInitKey)
{
int xRoot, yRoot;
xRoot = w->attrib.x + (w->width / 2);
yRoot = w->attrib.y + (w->height / 2);
warpPointer(d, xRoot - d->pointerX, yRoot - d->pointerY);
}
}
}
return FALSE;
}
static Bool
moveTerminate(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int nOption)
{
MOVE_DISPLAY(d);
if (md->w)
{
MOVE_SCREEN(md->w->screen);
(md->w->screen->windowUngrabNotify) (md->w);
if (state & CompActionStateCancel)
moveWindow(md->w,
md->w->serverX - md->w->attrib.x,
md->w->serverY - md->w->attrib.y, TRUE, FALSE);
syncWindowPosition(md->w);
if (md->moveOpacitySet)
resetWindowOpacity(md->w, PL_TEMP_HELLO);
damageScreen(md->w->screen);
if (ms->grabIndex)
{
removeScreenGrab(md->w->screen, ms->grabIndex, NULL);
ms->grabIndex = 0;
}
md->w = 0;
}
action->state &= ~(CompActionStateTermKey | CompActionStateTermButton);
return FALSE;
}
static Region moveGetYConstrainRegion(CompScreen * s)
{
CompWindow *w;
Region region;
REGION r;
int i;
region = XCreateRegion();
if (!region)
return NULL;
r.rects = &r.extents;
r.numRects = r.size = 1;
r.extents.x1 = MINSHORT;
r.extents.y1 = 0;
r.extents.x2 = 0;
r.extents.y2 = s->height;
XUnionRegion(&r, region, region);
r.extents.x1 = s->width;
r.extents.x2 = MAXSHORT;
XUnionRegion(&r, region, region);
for (i = 0; i < s->nOutputDev; i++)
XUnionRegion(&s->outputDev[i].region, region, region);
for (w = s->windows; w; w = w->next)
{
if (!w->mapNum)
continue;
if (w->struts)
{
r.extents.x1 = w->struts->top.x;
r.extents.y1 = w->struts->top.y;
r.extents.x2 = r.extents.x1 + w->struts->top.width;
r.extents.y2 = r.extents.y1 + w->struts->top.height;
XSubtractRegion(region, &r, region);
r.extents.x1 = w->struts->bottom.x;
r.extents.y1 = w->struts->bottom.y;
r.extents.x2 = r.extents.x1 + w->struts->bottom.width;
r.extents.y2 = r.extents.y1 + w->struts->bottom.height;
XSubtractRegion(region, &r, region);
}
}
return region;
}
static void moveHandleMotionEvent(CompScreen * s, int xRoot, int yRoot)
{
MOVE_SCREEN(s);
if (ms->grabIndex)
{
CompWindow *w;
int dx, dy;
MOVE_DISPLAY(s->display);
w = md->w;
md->x += xRoot - s->display->lastPointerX;
md->y += yRoot - s->display->lastPointerY;
if (md->w->syncWait)
return;
if (w->type & CompWindowTypeFullscreenMask)
{
dx = dy = 0;
}
else
{
XRectangle workArea;
int min, max;
Bool constrainTop =
md->opt[MOVE_DISPLAY_OPTION_CONSTRAIN_Y_TOP].value.b;
Bool constrainBottom =
md->opt[MOVE_DISPLAY_OPTION_CONSTRAIN_Y_BOTTOM].value.b;
dx = md->x;
dy = md->y;
screenGetOutputDevWorkArea(s, screenGetOutputDevForWindow(w),
&workArea);
if (constrainTop || constrainBottom)
{
if (!md->region)
md->region = moveGetYConstrainRegion(s);
/* make sure that the top frame extents or the top row of
pixels are within what is currently our valid screen
region */
if (md->region)
{
int x, y, width, height;
int status;
if (constrainTop)
{
y = w->attrib.y + dy - w->input.top;
height = w->input.top ? w->input.top : 1;
if (constrainBottom)
height += w->height + w->input.bottom;
}
else /* if (constrainBottom) redundant */
{
y = w->attrib.y + dy + w->height;
height = w->input.bottom ? w->input.bottom : 1;
}
x = w->attrib.x + dx - w->input.left;
width = w->width + w->input.left + w->input.right;
status = XRectInRegion(md->region, x, y, width, height);
/* only constrain movement if previous position was valid */
if (md->status == RectangleIn)
{
int xStatus = status;
while (dx && xStatus != RectangleIn)
{
xStatus =
XRectInRegion(md->region, x, y - dy,
width, height);
if (xStatus != RectangleIn)
dx += (dx < 0) ? 1 : -1;
x = w->attrib.x + dx - w->input.left;
}
while (dy && status != RectangleIn)
{
status = XRectInRegion(md->region,
x, y, width, height);
if (status != RectangleIn)
dy += (dy < 0) ? 1 : -1;
y = w->attrib.y + dy +
(constrainTop ? (-w->input.top) : w->
height);
}
}
else
{
md->status = status;
}
}
}
if (md->opt[MOVE_DISPLAY_OPTION_SNAPOFF_MAXIMIZED].value.b)
{
if (w->state & CompWindowStateMaximizedVertMask)
{
if ((yRoot - workArea.y) -
ms->snapOffY >=
md->opt[MOVE_DISPLAY_OPTION_SNAPOFF_DISTANCE].value.i)
{
XWindowChanges xwc;
syncWindowPosition(w);
xwc.x = w->serverX;
xwc.y = w->serverY;
xwc.width = w->serverWidth;
xwc.height = w->serverHeight;
restoreHorzRestoreData(w, &xwc);
restoreVertRestoreData(w, &xwc);
xwc.x = xRoot - (xwc.width >> 1);
xwc.y = yRoot + (w->input.top >> 1);
saveHorzRestoreData(w, &xwc);
saveVertRestoreData(w, &xwc);
md->x = md->y = 0;
maximizeWindow(w, 0);
ms->snapOffY = ms->snapBackY;
return;
}
}
else if (ms->origState & CompWindowStateMaximizedVertMask)
{
if ((yRoot - workArea.y) -
ms->snapBackY <
md->
opt[MOVE_DISPLAY_OPTION_SNAPBACK_DISTANCE].value.i)
{
if (!otherScreenGrabExist(s, "move", 0))
{
int wy;
/* update server position before maximizing window
again so it is maximized on the correct output */
syncWindowPosition(w);
maximizeWindow(w, ms->origState);
wy = workArea.y + (w->input.top >> 1);
wy += w->sizeHints.height_inc >> 1;
warpPointer(s->
display,
0, wy - s->display->pointerY);
return;
}
}
}
}
if (w->state & CompWindowStateMaximizedVertMask)
{
min = workArea.y + w->input.top;
max = workArea.y + workArea.height -
w->input.bottom - w->serverHeight -
w->serverBorderWidth * 2;
if (w->attrib.y + dy < min)
dy = min - w->attrib.y;
else if (w->attrib.y + dy > max)
dy = max - w->attrib.y;
}
if (w->state & CompWindowStateMaximizedHorzMask)
{
if (w->attrib.x + w->serverWidth + w->serverBorderWidth < 0)
return;
min = workArea.x + w->input.left;
max = workArea.x + workArea.width -
w->input.right - w->serverWidth -
w->serverBorderWidth * 2;
if (w->attrib.x + dx < min)
dx = min - w->attrib.x;
else if (w->attrib.x + dx > max)
dx = max - w->attrib.x;
}
}
moveWindow(md->w, dx, dy, TRUE, FALSE);
damageScreen(s);
md->x -= dx;
md->y -= dy;
}
}
static void moveHandleEvent(CompDisplay * d, XEvent * event)
{
CompScreen *s;
MOVE_DISPLAY(d);
switch (event->type)
{
case ButtonPress:
case ButtonRelease:
s = findScreenAtDisplay(d, event->xbutton.root);
if (s)
{
MOVE_SCREEN(s);
if (ms->grabIndex)
{
moveTerminate(d,
&md->
opt
[MOVE_DISPLAY_OPTION_INITIATE].
value.action, 0, NULL, 0);
}
}
break;
case KeyPress:
case KeyRelease:
s = findScreenAtDisplay(d, event->xkey.root);
if (s)
{
MOVE_SCREEN(s);
if (ms->grabIndex && event->type == KeyPress)
{
int i;
for (i = 0; i < NUM_KEYS; i++)
{
if (event->xkey.keycode == md->key[i])
{
XWarpPointer(d->display,
None, None, 0,
0, 0, 0,
mKeys[i].dx *
KEY_MOVE_INC,
mKeys[i].dy * KEY_MOVE_INC);
break;
}
}
}
}
break;
case MotionNotify:
s = findScreenAtDisplay(d, event->xmotion.root);
if (s)
moveHandleMotionEvent(s, d->pointerX, d->pointerY);
break;
case EnterNotify:
case LeaveNotify:
s = findScreenAtDisplay(d, event->xcrossing.root);
if (s)
moveHandleMotionEvent(s, d->pointerX, d->pointerY);
break;
case ClientMessage:
if (event->xclient.message_type == d->wmMoveResizeAtom)
{
CompWindow *w;
if (event->xclient.data.l[2] == WmMoveResizeMove ||
event->xclient.data.l[2] == WmMoveResizeMoveKeyboard)
{
w = findWindowAtDisplay(d, event->xclient.window);
if (w)
{
CompOption o[4];
int xRoot, yRoot;
CompAction *action =
&md->opt[MOVE_DISPLAY_OPTION_INITIATE].value.
action;
o[0].type = CompOptionTypeInt;
o[0].name = "window";
o[0].value.i = event->xclient.window;
if (event->xclient.data.l[2] == WmMoveResizeMoveKeyboard)
{
moveInitiate(d, action, CompActionStateInitKey, o, 1);
}
else
{
unsigned int mods;
Window root, child;
int i;
XQueryPointer(d->display,
w->screen->
root, &root,
&child, &xRoot, &yRoot, &i, &i, &mods);
/* TODO: not only button 1 */
if (mods & Button1Mask)
{
o[1].type = CompOptionTypeInt;
o[1].name = "modifiers";
o[1].value.i = mods;
o[2].type = CompOptionTypeInt;
o[2].name = "x";
o[2].value.i = event->xclient.data.l[0];
o[3].type = CompOptionTypeInt;
o[3].name = "y";
o[3].value.i = event->xclient.data.l[1];
moveInitiate(d,
action,
CompActionStateInitButton, o, 4);
moveHandleMotionEvent(w->screen, xRoot, yRoot);
}
}
}
}
}
break;
case DestroyNotify:
if (md->w && md->w->id == event->xdestroywindow.window)
moveTerminate(d,
&md->
opt[MOVE_DISPLAY_OPTION_INITIATE].
value.action, 0, NULL, 0);
break;
case UnmapNotify:
if (md->w && md->w->id == event->xunmap.window)
moveTerminate(d,
&md->
opt[MOVE_DISPLAY_OPTION_INITIATE].
value.action, 0, NULL, 0);
default:
break;
}
UNWRAP(md, d, handleEvent);
(*d->handleEvent) (d, event);
WRAP(md, d, handleEvent, moveHandleEvent);
}
static void moveDisplayInitOptions(MoveDisplay * md)
{
CompOption *o;
o = &md->opt[MOVE_DISPLAY_OPTION_INITIATE];
o->advanced = False;
o->name = "initiate";
o->group = N_("Bindings");
o->subGroup = N_("Move window");
o->displayHints = "";
o->shortDesc = N_("Initiate Window Move");
o->longDesc = N_("Start moving Window.");
o->type = CompOptionTypeAction;
o->value.action.initiate = moveInitiate;
o->value.action.terminate = moveTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.type = CompBindingTypeButton;
o->value.action.state = CompActionStateInitButton;
o->value.action.button.modifiers = MOVE_INITIATE_BUTTON_MODIFIERS_DEFAULT;
o->value.action.button.button = MOVE_INITIATE_BUTTON_DEFAULT;
o->value.action.type |= CompBindingTypeKey;
o->value.action.state |= CompActionStateInitKey;
o->value.action.key.modifiers = MOVE_INITIATE_KEY_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(MOVE_INITIATE_KEY_DEFAULT);
o = &md->opt[MOVE_DISPLAY_OPTION_OPACIFY_MIN_OPACITY];
o->advanced = False;
o->name = "opacify_min_opacity";
o->group = N_("Appearance");
o->subGroup = N_("Opacity");
o->displayHints = "";
o->shortDesc = N_("Minimum Opacity for Opacify");
o->longDesc =
N_
("Opacify only windows whose Opacity is higher than this value.");
o->type = CompOptionTypeInt;
o->value.i = MOVE_OPACIFY_MIN_OPACITY_DEFAULT;
o->rest.i.min = MOVE_OPACIFY_MIN_OPACITY_MIN;
o->rest.i.max = MOVE_OPACIFY_MIN_OPACITY_MAX;
o = &md->opt[MOVE_DISPLAY_OPTION_OPACITY];
o->advanced = False;
o->name = "opacity";
o->group = N_("Appearance");
o->subGroup = N_("Opacity");
o->displayHints = "";
o->shortDesc = N_("Opacity");
o->longDesc = N_("Opacity level of Moving windows.");
o->type = CompOptionTypeInt;
o->value.i = MOVE_OPACITY_DEFAULT;
o->rest.i.min = MOVE_OPACITY_MIN;
o->rest.i.max = MOVE_OPACITY_MAX;
o = &md->opt[MOVE_DISPLAY_OPTION_CONSTRAIN_Y_TOP];
o->advanced = False;
o->name = "constrain_y_top";
o->group = N_("Misc. options");
o->subGroup = N_("Movement constraints");
o->displayHints = "";
o->shortDesc = N_("Constrain Y to Top of Screen");
o->longDesc =
N_("Prevent windows from Moving over the Top of the Screen.");
o->type = CompOptionTypeBool;
o->value.b = MOVE_CONSTRAIN_Y_TOP_DEFAULT;
o = &md->opt[MOVE_DISPLAY_OPTION_CONSTRAIN_Y_BOTTOM];
o->advanced = False;
o->name = "constrain_y_bottom";
o->group = N_("Misc. options");
o->subGroup = N_("Movement constraints");
o->displayHints = "";
o->shortDesc = N_("Constrain Y to Bottom of Screen");
o->longDesc =
N_("Prevent windows from Moving past the Bottom of the Screen.");
o->type = CompOptionTypeBool;
o->value.b = MOVE_CONSTRAIN_Y_BOTTOM_DEFAULT;
o = &md->opt[MOVE_DISPLAY_OPTION_SNAPOFF_MAXIMIZED];
o->advanced = False;
o->name = "snapoff_maximized";
o->group = N_("Misc. options");
o->subGroup = N_("Snapoff/snapback");
o->displayHints = "";
o->shortDesc = N_("Snapoff Maximized Windows");
o->longDesc = N_("Snap off and unMaximize Maximized Windows "
"when dragging.");
o->type = CompOptionTypeBool;
o->value.b = MOVE_SNAPOFF_MAXIMIZED_DEFAULT;
o = &md->opt[MOVE_DISPLAY_OPTION_SNAPOFF_DISTANCE];
o->advanced = False;
o->name = "snapoff_distance";
o->group = N_("Misc. options");
o->subGroup = N_("Snapoff/snapback");
o->displayHints = "";
o->shortDesc = N_("Snapoff Distance");
o->longDesc =
N_("Pointer movement Distance after which window is Snapped off.");
o->type = CompOptionTypeInt;
o->value.i = MOVE_SNAPOFF_DISTANCE_DEFAULT;
o->rest.i.min = MOVE_SNAPOFF_DISTANCE_MIN;
o->rest.i.max = MOVE_SNAPOFF_DISTANCE_MAX;
o = &md->opt[MOVE_DISPLAY_OPTION_SNAPBACK_DISTANCE];
o->advanced = False;
o->name = "snapback_distance";
o->group = N_("Misc. options");
o->subGroup = N_("Snapoff/snapback");
o->displayHints = "";
o->shortDesc = N_("Snapback Distance");
o->longDesc = N_("Pointer movement Distance to Snap window back.");
o->type = CompOptionTypeInt;
o->value.i = MOVE_SNAPBACK_DISTANCE_DEFAULT;
o->rest.i.min = MOVE_SNAPBACK_DISTANCE_MIN;
o->rest.i.max = MOVE_SNAPBACK_DISTANCE_MAX;
}
static CompOption *moveGetDisplayOptions(CompDisplay * display, int *count)
{
if (display)
{
MOVE_DISPLAY(display);
*count = NUM_OPTIONS(md);
return md->opt;
}
else
{
MoveDisplay *md = malloc(sizeof(MoveDisplay));
moveDisplayInitOptions(md);
*count = NUM_OPTIONS(md);
return md->opt;
}
}
static Bool
moveSetDisplayOption(CompDisplay * display,
char *name, CompOptionValue * value)
{
CompOption *o;
int index;
MOVE_DISPLAY(display);
o = compFindOption(md->opt, NUM_OPTIONS(md), name, &index);
if (!o)
return FALSE;
switch (index)
{
case MOVE_DISPLAY_OPTION_INITIATE:
if (setDisplayAction(display, o, value))
return TRUE;
break;
case MOVE_DISPLAY_OPTION_OPACITY:
if (compSetIntOption(o, value))
{
md->moveOpacity = (o->value.i * OPAQUE) / 100;
return TRUE;
}
break;
case MOVE_DISPLAY_OPTION_OPACIFY_MIN_OPACITY:
if (compSetIntOption(o, value))
{
md->opacifyMinOpacity = (o->value.i * OPAQUE) / 100;
return TRUE;
}
break;
case MOVE_DISPLAY_OPTION_SNAPOFF_DISTANCE:
case MOVE_DISPLAY_OPTION_SNAPBACK_DISTANCE:
if (compSetIntOption(o, value))
return TRUE;
break;
case MOVE_DISPLAY_OPTION_CONSTRAIN_Y_TOP:
case MOVE_DISPLAY_OPTION_CONSTRAIN_Y_BOTTOM:
case MOVE_DISPLAY_OPTION_SNAPOFF_MAXIMIZED:
if (compSetBoolOption(o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static Bool moveInitDisplay(CompPlugin * p, CompDisplay * d)
{
MoveDisplay *md;
int i;
md = malloc(sizeof(MoveDisplay));
if (!md)
return FALSE;
md->screenPrivateIndex = allocateScreenPrivateIndex(d);
if (md->screenPrivateIndex < 0)
{
free(md);
return FALSE;
}
md->moveOpacity = (MOVE_OPACITY_DEFAULT * OPAQUE) / 100;
md->opacifyMinOpacity = (MOVE_OPACIFY_MIN_OPACITY_DEFAULT * OPAQUE) / 100;
moveDisplayInitOptions(md);
md->w = 0;
md->region = NULL;
for (i = 0; i < NUM_KEYS; i++)
md->key[i] = XKeysymToKeycode(d->display,
XStringToKeysym(mKeys[i].name));
WRAP(md, d, handleEvent, moveHandleEvent);
d->privates[displayPrivateIndex].ptr = md;
return TRUE;
}
static void moveFiniDisplay(CompPlugin * p, CompDisplay * d)
{
MOVE_DISPLAY(d);
freeScreenPrivateIndex(d, md->screenPrivateIndex);
UNWRAP(md, d, handleEvent);
free(md);
}
static Bool moveInitScreen(CompPlugin * p, CompScreen * s)
{
MoveScreen *ms;
MOVE_DISPLAY(s->display);
ms = malloc(sizeof(MoveScreen));
if (!ms)
return FALSE;
ms->grabIndex = 0;
ms->moveCursor = XCreateFontCursor(s->display->display, XC_fleur);
addScreenAction(s, &md->opt[MOVE_DISPLAY_OPTION_INITIATE].value.action);
s->privates[md->screenPrivateIndex].ptr = ms;
return TRUE;
}
static void moveFiniScreen(CompPlugin * p, CompScreen * s)
{
MOVE_SCREEN(s);
MOVE_DISPLAY(s->display);
removeScreenAction(s,
&md->opt[MOVE_DISPLAY_OPTION_INITIATE].value.action);
XFreeCursor(s->display->display, ms->moveCursor);
free(ms);
}
static Bool moveInit(CompPlugin * p)
{
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void moveFini(CompPlugin * p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
CompPluginVTable moveVTable = {
"move",
N_("Move Window"),
N_("Move window"),
moveInit,
moveFini,
moveInitDisplay,
moveFiniDisplay,
moveInitScreen,
moveFiniScreen,
0, /* InitWindow */
0, /* FiniWindow */
moveGetDisplayOptions,
moveSetDisplayOption,
0, /* GetScreenOptions */
0, /* SetScreenOption */
NULL,
0,
0,
0,
BERYL_ABI_INFO,
"beryl-plugins",
"wm",
0,
0,
True,
};
CompPluginVTable *getCompPluginInfo(void)
{
return &moveVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1