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