/*
* Copyright © 2006 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Author: Soren Sandmann <sandmann@redhat.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>
static int displayPrivateIndex;
#define PLANE_LEFT_KEY_DEFAULT "Left"
#define PLANE_LEFT_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define PLANE_RIGHT_KEY_DEFAULT "Right"
#define PLANE_RIGHT_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define PLANE_UP_KEY_DEFAULT "Up"
#define PLANE_UP_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define PLANE_DOWN_KEY_DEFAULT "Down"
#define PLANE_DOWN_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
#define PLANE_PREVIEW_KEY_DEFAULT "Next"
#define PLANE_PREVIEW_MODIFIERS_DEFAULT (ControlMask | CompAltMask)
enum
{
PLANE_DISPLAY_OPTION_LEFT,
PLANE_DISPLAY_OPTION_RIGHT,
PLANE_DISPLAY_OPTION_DOWN,
PLANE_DISPLAY_OPTION_UP,
PLANE_DISPLAY_OPTION_PREVIEW,
PLANE_DISPLAY_OPTION_TO_1,
PLANE_DISPLAY_OPTION_TO_2,
PLANE_DISPLAY_OPTION_TO_3,
PLANE_DISPLAY_OPTION_TO_4,
PLANE_DISPLAY_OPTION_TO_5,
PLANE_DISPLAY_OPTION_TO_6,
PLANE_DISPLAY_OPTION_TO_7,
PLANE_DISPLAY_OPTION_TO_8,
PLANE_DISPLAY_OPTION_TO_9,
PLANE_DISPLAY_OPTION_TO_10,
PLANE_DISPLAY_OPTION_TO_11,
PLANE_DISPLAY_OPTION_TO_12,
PLANE_N_DISPLAY_OPTIONS
};
typedef struct _PlaneDisplay
{
int screenPrivateIndex;
HandleEventProc handleEvent;
CompOption opt[PLANE_N_DISPLAY_OPTIONS];
int flipTime;
} PlaneDisplay;
#define PLANE_WRAP_DEFAULT FALSE
#define PLANE_SCROLL_TIME_DEFAULT 250
#define PLANE_SCROLL_TIME_MAX 2000
#define PLANE_SCROLL_TIME_MIN 1
#define PLANE_SCROLL_TIME_PRECISION 1
enum
{
PLANE_SCREEN_OPTION_WRAP,
PLANE_SCREEN_OPTION_TIME,
PLANE_SCREEN_OPTION_NUM
};
typedef struct _PlaneScreen
{
CompOption opt[PLANE_SCREEN_OPTION_NUM];
PaintTransformedScreenProc paintTransformedScreen;
PreparePaintScreenProc preparePaintScreen;
DonePaintScreenProc donePaintScreen;
PaintScreenProc paintScreen;
SetScreenOptionForPluginProc setScreenOptionForPlugin;
WindowGrabNotifyProc windowGrabNotify;
WindowUngrabNotifyProc windowUngrabNotify;
CompTimeoutHandle timeout_handle;
int timer;
int preview;
double cur_x;
double cur_y;
double dest_x;
double dest_y;
float initZoom;
} PlaneScreen;
#define GET_PLANE_DISPLAY(d) \
((PlaneDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define PLANE_DISPLAY(d) \
PlaneDisplay *pd = GET_PLANE_DISPLAY (d)
#define GET_PLANE_SCREEN(s, pd) \
((PlaneScreen *) (s)->privates[(pd)->screenPrivateIndex].ptr)
#define PLANE_SCREEN(s) \
PlaneScreen *ps = GET_PLANE_SCREEN (s, GET_PLANE_DISPLAY (s->display))
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static Bool
planeSetScreenOption(CompScreen * screen, char *name, CompOptionValue * value)
{
CompOption *o;
int index;
PLANE_SCREEN(screen);
o = compFindOption(ps->opt, NUM_OPTIONS(ps), name, &index);
if (!o)
return FALSE;
switch (index)
{
case PLANE_SCREEN_OPTION_WRAP:
if (compSetBoolOption(o, value))
return TRUE;
break;
case PLANE_SCREEN_OPTION_TIME:
if (compSetIntOption(o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static void planeScreenInitOptions(PlaneScreen * ps)
{
CompOption *o;
o = &ps->opt[PLANE_SCREEN_OPTION_WRAP];
o->advanced = False;
o->name = "wrap";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Wrap Around");
o->longDesc = N_("Enable Wrapping Around.");
o->type = CompOptionTypeBool;
o->value.b = PLANE_WRAP_DEFAULT;
o = &ps->opt[PLANE_SCREEN_OPTION_TIME];
o->advanced = False;
o->name = "time";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Scrolling Time");
o->longDesc = N_("Scrolling Time when switching desktops.");
o->type = CompOptionTypeInt;
o->value.i = PLANE_SCROLL_TIME_DEFAULT;
o->rest.i.min = PLANE_SCROLL_TIME_MIN;
o->rest.i.max = PLANE_SCROLL_TIME_MAX;
}
static CompOption *planeGetScreenOptions(CompScreen * screen, int *count)
{
if (screen)
{
PLANE_SCREEN(screen);
*count = NUM_OPTIONS(ps);
return ps->opt;
}
else
{
PlaneScreen *ps = malloc(sizeof(PlaneScreen));
planeScreenInitOptions(ps);
*count = NUM_OPTIONS(ps);
return ps->opt;
}
}
static Bool end_move(void *data)
{
CompScreen *screen = data;
PLANE_SCREEN(screen);
//wait until de-scale is finished before setting viewport
if (screenGrabExist(screen, "scale", 0))
{
ps->timeout_handle = compAddTimeout(20, end_move, screen);
return FALSE;
}
moveScreenViewport(screen, -ps->dest_x, -ps->dest_y, TRUE);
ps->dest_x = 0;
ps->dest_y = 0;
ps->timeout_handle = 0;
focusDefaultWindow(screen->display);
return FALSE;
}
static void compute_translation(PlaneScreen * ps, double *x, double *y)
{
double dx, dy;
double elapsed =
1 -
(ps->timer / (double)(ps->opt[PLANE_SCREEN_OPTION_TIME].value.i));
if (elapsed < 0.0)
elapsed = 0.0;
if (elapsed > 1.0)
elapsed = 1.0;
/* Use temporary variables to you can pass in &ps->cur_x */
dx = (ps->dest_x - ps->cur_x) * elapsed + ps->cur_x;
dy = (ps->dest_y - ps->cur_y) * elapsed + ps->cur_y;
*x = dx;
*y = dy;
}
static void move_viewport(CompScreen * screen, int dx, int dy)
{
PLANE_SCREEN(screen);
if (ps->timeout_handle)
{
compute_translation(ps, &ps->cur_x, &ps->cur_y);
ps->dest_x += dx;
ps->dest_y += dy;
compRemoveTimeout(ps->timeout_handle);
}
else
{
ps->cur_x = 0.0;
ps->cur_y = 0.0;
ps->dest_x = dx;
ps->dest_y = dy;
}
if (!ps->opt[PLANE_SCREEN_OPTION_WRAP].value.b)
{
if (ps->dest_x + screen->x > screen->hsize - 1)
ps->dest_x = screen->hsize - screen->x - 1;
if (ps->dest_x + screen->x < 0)
ps->dest_x = -screen->x;
if (ps->dest_y + screen->y > screen->vsize - 1)
ps->dest_y = screen->vsize - screen->y - 1;
if (ps->dest_y + screen->y < 0)
ps->dest_y = -screen->y;
}
ps->timer = ps->opt[PLANE_SCREEN_OPTION_TIME].value.i;
ps->timeout_handle =
compAddTimeout(ps->opt[PLANE_SCREEN_OPTION_TIME].value.i,
end_move, screen);
damageScreen(screen);
}
static void planePreparePaintScreen(CompScreen * s, int msSinceLastPaint)
{
PLANE_SCREEN(s);
ps->timer -= msSinceLastPaint;
UNWRAP(ps, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP(ps, s, preparePaintScreen, planePreparePaintScreen);
}
static void
planePaintTransformedScreen(CompScreen * screen,
const ScreenPaintAttrib * sAttrib,
Region region, int output, unsigned int mask)
{
PLANE_SCREEN(screen);
static Bool notfirst;
/* If it's the first movement store the zCamera, not sure what a sane value would be so this is a stopgap */
if (!notfirst)
{
ps->initZoom = sAttrib->zCamera;
}
UNWRAP(ps, screen, paintTransformedScreen);
mask &= ~PAINT_SCREEN_CLEAR_MASK;
if (ps->preview && !ps->timeout_handle)
{
ScreenPaintAttrib sa = *sAttrib;
(*screen->paintTransformedScreen) (screen, &sa, region, output, mask);
if (sa.zCamera != ps->initZoom)
{
/* If we are not moving zoom back LESS when drawing the current viewport than the others, gives a zoom of sorts to the selected viewport */
sa.zCamera = -1.5;
(*screen->paintTransformedScreen) (screen,
&sa, region, output, mask);
WRAP(ps, screen, paintTransformedScreen,
planePaintTransformedScreen);
return;
}
}
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT);
if (ps->timeout_handle)
{
double dx, dy, tx, ty;
int vx, vy;
clearTargetOutput(screen->display, GL_COLOR_BUFFER_BIT);
/* Find what the x and y change should be as to ensure the movement takes the user specified amount of time */
compute_translation(ps, &dx, &dy);
dx *= -1;
dy *= -1;
tx = dy;
ty = dy;
vx = 0;
vy = 0;
/* Make sure dx and dy are less than 1 and greater than -1 but move the viewports accordingly if they are greater or less than respectively */
while (dx > 1)
{
dx -= 1.0;
moveScreenViewport(screen, 1, 0, FALSE);
vx++;
}
while (dx < -1)
{
dx += 1.0;
moveScreenViewport(screen, -1, 0, FALSE);
vx--;
}
while (dy > 1)
{
dy -= 1.0;
moveScreenViewport(screen, 0, 1, FALSE);
vy++;
}
while (dy < -1)
{
dy += 1.0;
moveScreenViewport(screen, 0, -1, FALSE);
vy--;
}
#if 0
glPushMatrix();
if (dx > 0)
{
glTranslatef(dx, dy, 0.0);
(*screen->paintTransformedScreen) (screen, sAttrib, mask);
glTranslatef(-1.0, 0.0, 0.0);
moveScreenViewport(screen, 1, 0, FALSE);
(*screen->paintTransformedScreen) (screen, sAttrib, mask);
moveScreenViewport(screen, -1, 0, FALSE);
}
else
{
glTranslatef(dx, dy, 0.0);
(*screen->paintTransformedScreen) (screen, sAttrib, mask);
glTranslatef(1.0, 0.0, 0.0);
moveScreenViewport(screen, -1, 0, FALSE);
(*screen->paintTransformedScreen) (screen, sAttrib, mask);
moveScreenViewport(screen, 1, 0, FALSE);
}
glPopMatrix();
#endif
glPushMatrix();
ScreenPaintAttrib *sa = sAttrib;
if (ps->preview)
{
sa->zCamera = -2;
}
else
{
sa->zCamera = ps->initZoom;
}
sAttrib = sa;
/* Provide the effect of scrolling rather than snapping */
glTranslatef(dx, -dy, 0.0);
(*screen->paintTransformedScreen) (screen, sAttrib, region,
output, mask);
/* Draw viewports a bit further apart if we are 'zoomed' */
float s1 = 1.05;
float s2 = -1.05;
if (!ps->preview)
{
s1 = 1;
s2 = -1;
}
/* FIXME: This is a horrible and highly unscalable way to do things. */
if (dx > 0)
{
glTranslatef(s2, 0.0, 0.0);
moveScreenViewport(screen, 1, 0, FALSE);
}
else
{
glTranslatef(s1, 0.0, 0.0);
moveScreenViewport(screen, -1, 0, FALSE);
}
(*screen->paintTransformedScreen) (screen, sAttrib, region,
output, mask);
if (dy > 0)
{
glTranslatef(0.0, s1, 0.0);
moveScreenViewport(screen, 0, 1, FALSE);
}
else
{
glTranslatef(0.0, s2, 0.0);
moveScreenViewport(screen, 0, -1, FALSE);
}
(*screen->paintTransformedScreen) (screen, sAttrib, region,
output, mask);
if (dx > 0)
{
glTranslatef(s1, 0.0, 0.0);
moveScreenViewport(screen, -1, 0, FALSE);
}
else
{
glTranslatef(s2, 0.0, 0.0);
moveScreenViewport(screen, 1, 0, FALSE);
}
(*screen->paintTransformedScreen) (screen, sAttrib, region,
output, mask);
if (dy > 0)
{
glTranslatef(0.0, s2, 0.0);
moveScreenViewport(screen, 0, -1, FALSE);
}
else
{
glTranslatef(0.0, s1, 0.0);
moveScreenViewport(screen, 0, 1, FALSE);
}
glTranslatef(-dx, -dy, 0.0);
glPopMatrix();
moveScreenViewport(screen, -vx, -vy, FALSE);
}
else
{
int i, j;
for (i = -1; i < 2; i++)
{
for (j = -1; j < 2; j++)
{
glTranslatef(i, j, 0);
moveScreenViewport(screen, -i, -j, FALSE);
(*screen->paintTransformedScreen) (screen,
sAttrib,
region, output, mask);
glTranslatef(-i, -j, 0);
moveScreenViewport(screen, i, j, FALSE);
}
}
}
notfirst = TRUE;
WRAP(ps, screen, paintTransformedScreen, planePaintTransformedScreen);
glPopMatrix();
}
static void planeDonePaintScreen(CompScreen * s)
{
PLANE_SCREEN(s);
if (ps->timeout_handle)
damageScreen(s);
UNWRAP(ps, s, donePaintScreen);
(*s->donePaintScreen) (s);
WRAP(ps, s, donePaintScreen, planeDonePaintScreen);
}
static Bool
planePaintScreen(CompScreen * s,
const ScreenPaintAttrib * sAttrib,
Region region, int output, unsigned int mask)
{
Bool status;
PLANE_SCREEN(s);
if (ps->timeout_handle || ps->preview)
{
mask &= ~PAINT_SCREEN_REGION_MASK;
mask |= PAINT_SCREEN_TRANSFORMED_MASK;
}
UNWRAP(ps, s, paintScreen);
status = (*s->paintScreen) (s, sAttrib, region, output, mask);
WRAP(ps, s, paintScreen, planePaintScreen);
return status;
}
static void planeHandleEvent(CompDisplay * d, XEvent * event)
{
CompScreen *s;
PLANE_DISPLAY(d);
switch (event->type)
{
case ClientMessage:
if (event->xclient.message_type == d->winActiveAtom)
{
CompWindow *w;
w = findWindowAtDisplay(d, event->xclient.window);
if (w)
{
int dx, dy;
s = w->screen;
/* window must be placed */
if (!w->placed)
break;
if (otherScreenGrabExist
(s, "plane", "switcher", "cube", "scale", 0))
break;
defaultViewportForWindow(w, &dx, &dy);
dx -= s->x;
dy -= s->y;
move_viewport(s, dx, dy);
}
}
else if (event->xclient.message_type == d->desktopViewportAtom)
{
int dx, dy;
s = findScreenAtDisplay(d, event->xclient.window);
if (!s)
break;
if (otherScreenGrabExist
(s, "plane", "switcher", "cube", "scale", 0))
break;
dx = event->xclient.data.l[0] / s->width - s->x;
dy = event->xclient.data.l[1] / s->height - s->y;
if (!dx && !dy)
break;
move_viewport(s, dx, dy);
}
break;
default:
break;
}
UNWRAP(pd, d, handleEvent);
(*d->handleEvent) (d, event);
WRAP(pd, d, handleEvent, planeHandleEvent);
}
static void
planeWindowGrabNotify(CompWindow * w,
int x, int y, unsigned int state, unsigned int mask)
{
PLANE_SCREEN(w->screen);
UNWRAP(ps, w->screen, windowGrabNotify);
(*w->screen->windowGrabNotify) (w, x, y, state, mask);
WRAP(ps, w->screen, windowGrabNotify, planeWindowGrabNotify);
}
static void planeWindowUngrabNotify(CompWindow * w)
{
PLANE_SCREEN(w->screen);
UNWRAP(ps, w->screen, windowUngrabNotify);
(*w->screen->windowUngrabNotify) (w);
WRAP(ps, w->screen, windowUngrabNotify, planeWindowUngrabNotify);
}
static Bool
planeSetScreenOptionForPlugin(CompScreen * s,
char *plugin,
char *name, CompOptionValue * value)
{
PLANE_SCREEN(s);
Bool status;
UNWRAP(ps, s, setScreenOptionForPlugin);
status = (*s->setScreenOptionForPlugin) (s, plugin, name, value);
WRAP(ps, s, setScreenOptionForPlugin, planeSetScreenOptionForPlugin);
return status;
}
static Bool
planeSetDisplayOption(CompDisplay * display,
char *name, CompOptionValue * value)
{
CompOption *o;
int index;
PLANE_DISPLAY(display);
o = compFindOption(pd->opt, NUM_OPTIONS(pd), name, &index);
if (!o)
return FALSE;
switch (index)
{
case PLANE_DISPLAY_OPTION_LEFT:
case PLANE_DISPLAY_OPTION_RIGHT:
case PLANE_DISPLAY_OPTION_UP:
case PLANE_DISPLAY_OPTION_DOWN:
case PLANE_DISPLAY_OPTION_PREVIEW:
case PLANE_DISPLAY_OPTION_TO_1:
case PLANE_DISPLAY_OPTION_TO_2:
case PLANE_DISPLAY_OPTION_TO_3:
case PLANE_DISPLAY_OPTION_TO_4:
case PLANE_DISPLAY_OPTION_TO_5:
case PLANE_DISPLAY_OPTION_TO_6:
case PLANE_DISPLAY_OPTION_TO_7:
case PLANE_DISPLAY_OPTION_TO_8:
case PLANE_DISPLAY_OPTION_TO_9:
case PLANE_DISPLAY_OPTION_TO_10:
case PLANE_DISPLAY_OPTION_TO_11:
case PLANE_DISPLAY_OPTION_TO_12:
if (setDisplayAction(display, o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static CompScreen *get_screen(CompDisplay * d, CompOption * option,
int n_options)
{
XID root_window = getIntOptionNamed(option, n_options, "root", 0);
return findScreenAtDisplay(d, root_window);
}
static Bool
planeLeft(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int n_options)
{
CompScreen *screen = get_screen(d, option, n_options);
move_viewport(screen, -1, 0);
return FALSE;
}
static Bool
planeRight(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int n_options)
{
CompScreen *screen = get_screen(d, option, n_options);
move_viewport(screen, 1, 0);
return FALSE;
}
static Bool
planeUp(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int n_options)
{
CompScreen *screen = get_screen(d, option, n_options);
move_viewport(screen, 0, -1);
return FALSE;
}
static Bool
planeDown(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int n_options)
{
CompScreen *screen = get_screen(d, option, n_options);
move_viewport(screen, 0, 1);
return FALSE;
}
static Bool
planePreview(CompDisplay * d, CompAction * action, CompActionState state,
CompOption * option, int n_options)
{
static int xView;
static int yView;
CompScreen *screen = get_screen(d, option, n_options);
PLANE_SCREEN(screen);
if (!ps->preview)
{
xView = screen->x / screen->width;
yView = screen->y / screen->height;
}
ps->preview = !ps->preview;
/*if (!ps->preview){
moveScreenViewport(screen,xView,yView,TRUE);
} */
damageScreen(screen);
return FALSE;
}
static Bool
planeTo(CompDisplay * d,
CompAction * action,
CompActionState state, CompOption * option, int n_options)
{
int i, new_x, new_y, cur_x, cur_y;
CompScreen *screen = get_screen(d, option, n_options);
PLANE_DISPLAY(d);
new_x = new_y = -1;
for (i = PLANE_DISPLAY_OPTION_TO_1; i <= PLANE_DISPLAY_OPTION_TO_12; ++i)
{
if (action == &pd->opt[i].value.action)
{
int viewport_no = i - PLANE_DISPLAY_OPTION_TO_1;
new_x = viewport_no % screen->hsize;
new_y = viewport_no / screen->hsize;
break;
}
}
if (new_x == -1 || new_y == -1)
return FALSE;
cur_x = screen->x;
cur_y = screen->y;
move_viewport(screen, new_x - cur_x, new_y - cur_y);
return FALSE;
}
static void planeDisplayInitOptions(PlaneDisplay * pd)
{
CompOption *o;
char *str;
o = &pd->opt[PLANE_DISPLAY_OPTION_LEFT];
o->advanced = False;
o->name = "plane_left";
o->group = N_("Bindings");
o->subGroup = N_("Navigation - Left");
o->displayHints = "";
o->shortDesc = N_("Plane Left");
o->longDesc = N_("Plane Left.");
o->type = CompOptionTypeAction;
o->value.action.initiate = planeLeft;
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 = PLANE_LEFT_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(PLANE_LEFT_KEY_DEFAULT);
o = &pd->opt[PLANE_DISPLAY_OPTION_RIGHT];
o->advanced = False;
o->name = "plane_right";
o->group = N_("Bindings");
o->subGroup = N_("Navigation - Right");
o->displayHints = "";
o->shortDesc = N_("Plane Right");
o->longDesc = N_("Plane Right.");
o->type = CompOptionTypeAction;
o->value.action.initiate = planeRight;
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 = PLANE_RIGHT_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(PLANE_RIGHT_KEY_DEFAULT);
o = &pd->opt[PLANE_DISPLAY_OPTION_DOWN];
o->advanced = False;
o->name = "plane_down";
o->group = N_("Bindings");
o->subGroup = N_("Navigation - Down");
o->displayHints = "";
o->shortDesc = N_("Plane Down");
o->longDesc = N_("Plane Down.");
o->type = CompOptionTypeAction;
o->value.action.initiate = planeDown;
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 = PLANE_DOWN_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(PLANE_DOWN_KEY_DEFAULT);
o = &pd->opt[PLANE_DISPLAY_OPTION_PREVIEW];
o->advanced = False;
o->name = "plane_preview";
o->group = N_("Bindings");
o->subGroup = N_("Plane preview");
o->displayHints = "";
o->shortDesc = N_("Toggle Plane Preview");
o->longDesc = N_("Toggle Plane Preview mode.");
o->type = CompOptionTypeAction;
o->value.action.initiate = planePreview;
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 = PLANE_PREVIEW_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(PLANE_PREVIEW_KEY_DEFAULT);
o = &pd->opt[PLANE_DISPLAY_OPTION_UP];
o->advanced = False;
o->name = "plane_up";
o->group = N_("Bindings");
o->subGroup = N_("Navigation - Up");
o->displayHints = "";
o->shortDesc = N_("Plane Up");
o->longDesc = N_("Plane Up.");
o->type = CompOptionTypeAction;
o->value.action.initiate = planeUp;
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 = PLANE_UP_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(PLANE_UP_KEY_DEFAULT);
#define PLANE_TO_SHORT N_("Plane To Face %d")
#define PLANE_TO_LONG N_("Plane to face %d")
#define PLANE_TO_WINDOW_SHORT N_("Plane To Face %d with Window")
#define PLANE_TO_WINDOW_LONG N_("Plane to face %d and bring active " \
"window along")
#define PLANE_TO_OPTION(n) \
o = &pd->opt[PLANE_DISPLAY_OPTION_TO_ ## n]; \
o->advanced=False;\
o->name = "plane_to_" #n; \
asprintf (&str, PLANE_TO_SHORT, n); \
o->group=N_("Bindings");\
o->subGroup=N_("Face shortcuts");\
o->displayHints="";\
o->shortDesc = str; \
asprintf (&str, PLANE_TO_LONG, n); \
o->longDesc = str; \
o->type = CompOptionTypeAction; \
o->value.action.initiate = planeTo; \
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;
PLANE_TO_OPTION(1);
PLANE_TO_OPTION(2);
PLANE_TO_OPTION(3);
PLANE_TO_OPTION(4);
PLANE_TO_OPTION(5);
PLANE_TO_OPTION(6);
PLANE_TO_OPTION(7);
PLANE_TO_OPTION(8);
PLANE_TO_OPTION(9);
PLANE_TO_OPTION(10);
PLANE_TO_OPTION(11);
PLANE_TO_OPTION(12);
}
static CompOption *planeGetDisplayOptions(CompDisplay * display, int *count)
{
if (display)
{
PLANE_DISPLAY(display);
*count = NUM_OPTIONS(pd);
return pd->opt;
}
else
{
PlaneDisplay *pd = malloc(sizeof(PlaneDisplay));
planeDisplayInitOptions(pd);
*count = NUM_OPTIONS(pd);
return pd->opt;
}
}
static Bool planeInitDisplay(CompPlugin * p, CompDisplay * d)
{
PlaneDisplay *pd;
pd = malloc(sizeof(PlaneDisplay));
if (!pd)
return FALSE;
pd->screenPrivateIndex = allocateScreenPrivateIndex(d);
if (pd->screenPrivateIndex < 0)
{
free(pd);
return FALSE;
}
planeDisplayInitOptions(pd);
WRAP(pd, d, handleEvent, planeHandleEvent);
d->privates[displayPrivateIndex].ptr = pd;
return TRUE;
}
static void planeFiniDisplay(CompPlugin * p, CompDisplay * d)
{
PLANE_DISPLAY(d);
freeScreenPrivateIndex(d, pd->screenPrivateIndex);
UNWRAP(pd, d, handleEvent);
free(pd);
}
static Bool planeInitScreen(CompPlugin * p, CompScreen * s)
{
PlaneScreen *ps;
PLANE_DISPLAY(s->display);
ps = malloc(sizeof(PlaneScreen));
if (!ps)
return FALSE;
ps->preview = 0;
ps->timeout_handle = 0;
planeScreenInitOptions(ps);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_LEFT].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_RIGHT].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_DOWN].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_UP].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_PREVIEW].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_1].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_2].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_3].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_4].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_5].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_6].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_7].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_8].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_9].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_10].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_11].value.action);
addScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_12].value.action);
WRAP(ps, s, paintTransformedScreen, planePaintTransformedScreen);
WRAP(ps, s, preparePaintScreen, planePreparePaintScreen);
WRAP(ps, s, donePaintScreen, planeDonePaintScreen);
WRAP(ps, s, paintScreen, planePaintScreen);
WRAP(ps, s, setScreenOptionForPlugin, planeSetScreenOptionForPlugin);
WRAP(ps, s, windowGrabNotify, planeWindowGrabNotify);
WRAP(ps, s, windowUngrabNotify, planeWindowUngrabNotify);
s->privates[pd->screenPrivateIndex].ptr = ps;
return TRUE;
}
static void planeFiniScreen(CompPlugin * p, CompScreen * s)
{
PLANE_SCREEN(s);
PLANE_DISPLAY(s->display);
UNWRAP(ps, s, paintTransformedScreen);
UNWRAP(ps, s, preparePaintScreen);
UNWRAP(ps, s, donePaintScreen);
UNWRAP(ps, s, paintScreen);
UNWRAP(ps, s, setScreenOptionForPlugin);
UNWRAP(ps, s, windowGrabNotify);
UNWRAP(ps, s, windowUngrabNotify);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_LEFT].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_RIGHT].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_DOWN].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_UP].value.action);
removeScreenAction(s,
&pd->opt[PLANE_DISPLAY_OPTION_PREVIEW].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_1].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_2].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_3].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_4].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_5].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_6].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_7].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_8].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_9].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_10].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_11].value.action);
removeScreenAction(s, &pd->opt[PLANE_DISPLAY_OPTION_TO_12].value.action);
free(ps);
}
static Bool planeInit(CompPlugin * p)
{
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void planeFini(CompPlugin * p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
CompPluginFeature planeFeatures[] = {
{"largedesktop"}
};
CompPluginVTable planeVTable = {
"plane",
N_("Desktop Plane"),
N_("Place windows on a plane"),
planeInit, /* planeInit, */
planeFini, /* planeFini, */
planeInitDisplay,
planeFiniDisplay,
planeInitScreen,
planeFiniScreen,
0, /* InitWindow */
0, /* FiniWindow */
planeGetDisplayOptions,
planeSetDisplayOption,
planeGetScreenOptions,
planeSetScreenOption,
0,
0,
planeFeatures,
sizeof(planeFeatures) / sizeof(planeFeatures[0]),
BERYL_ABI_INFO,
"beryl-plugins-unsupported",
"desktop",
0,
0,
False,
};
CompPluginVTable *getCompPluginInfo(void)
{
return &planeVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1