/* * * 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. * * Authors: * - Diogo Ferreira (playerX) * * * Copyright (c) 2007 Diogo "playerX" Ferreira * * This wouldn't have been possible without: * - Ideas from the compiz community (mainly throughnothing's) * - David Reveman's work * * */ #include #include #include #include #include #define WIN_X(w) ((w)->attrib.x - (w)->input.left) #define WIN_Y(w) ((w)->attrib.y - (w)->input.top) #define WIN_W(w) ((w)->width + (w)->input.left + (w)->input.right) #define WIN_H(w) ((w)->height + (w)->input.top + (w)->input.bottom) #define OFF_LEFT(w) ((w)->width + (w)->input.right) #define OFF_RIGHT(w) ((w)->input.left) #define OFF_TOP(w) ((w)->height + (w)->input.bottom) #define OFF_BOTTOM(w) ((w)->input.top) #define MOVE_LEFT(w) ((WIN_X(w) + (WIN_W(w)/2)) < ((w)->screen->width/2)) #define MOVE_UP(w) ((WIN_Y(w) + (WIN_H(w)/2)) < ((w)->screen->height/2)) #define SD_INITIATE_KEY_DEFAULT "F6" #define SD_INITIATE_MODIFIERS_DEFAULT 0 #define SD_DISPLAY_OPTION_INITIATE 0 #define SD_DISPLAY_OPTION_NUM 1 #define SD_SCREEN_OPTION_SPEED 0 #define SD_SCREEN_OPTION_TIMESTEP 1 #define SD_SCREEN_OPTION_DIRECTION 2 #define SD_SCREEN_OPTION_WINDOW_TYPE 3 #define SD_SCREEN_OPTION_USE_SCALE_SETTINGS 4 #define SD_SCREEN_OPTION_WINDOW_OPACITY 5 #define SD_SCREEN_OPTION_WINDOW_PART_SIZE 6 #define SD_SCREEN_OPTION_NUM 7 typedef enum _SdDirection { SdDirectionUp, SdDirectionDown, SdDirectionLeft, SdDirectionRight, SdDirectionUpDown, SdDirectionLeftRight, SdDirectionCorners, } SdDirection; char *sdDirections[] = { N_("Up"), N_("Down"), N_("Left"), N_("Right"), N_("UpDown"), N_("LeftRight"), N_("Corners"), }; #define SD_DIRECTION_DEFAULT SdDirectionCorners #define NUM_SD_DIRECTIONS 7 #define SD_SPEED_DEFAULT 1.2f #define SD_SPEED_MIN 0.1f #define SD_SPEED_MAX 50.0f #define SD_SPEED_PRECISION 0.1f #define SD_TIMESTEP_DEFAULT 0.1f #define SD_TIMESTEP_MIN 0.1f #define SD_TIMESTEP_MAX 50.0f #define SD_TIMESTEP_PRECISION 0.1f #define SD_USE_SCALE_SETTINGS_DEFAULT FALSE #define SD_WINDOW_OPACITY_DEFAULT 0.3 #define SD_WINDOW_OPACITY_MIN 0.1 #define SD_WINDOW_OPACITY_MAX 1.0 #define SD_WINDOW_OPACITY_PRECISION 0.01 #define SD_WINDOW_PART_SIZE_DEFAULT 20 #define SD_WINDOW_PART_SIZE_MIN 0 #define SD_WINDOW_PART_SIZE_MAX 300 #define SD_STATE_OFF 0 #define SD_STATE_ACTIVATING 1 #define SD_STATE_ON 2 #define SD_STATE_DEACTIVATING 3 #define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption)) /* window types */ static char *winType[] = { N_("Toolbar"), N_("Utility"), N_("Dialog"), N_("ModalDialog"), N_("Fullscreen"), N_("Normal") }; #define N_WIN_TYPE (sizeof (winType) / sizeof (winType[0])) /* necessary plugin structs */ typedef struct _ShowdesktopPlacer { int placed; int onScreenX, onScreenY; int offScreenX, offScreenY; int origViewportX; int origViewportY; } ShowdesktopPlacer; typedef struct _ShowdesktopDisplay { int screenPrivateIndex; CompOption opt[SD_DISPLAY_OPTION_NUM]; HandleEventProc handleEvent; } ShowdesktopDisplay; typedef struct _ShowdesktopScreen { int windowPrivateIndex; PreparePaintScreenProc preparePaintScreen; DonePaintScreenProc donePaintScreen; SetScreenOptionForPluginProc setScreenOptionForPlugin; CompOption opt[SD_SCREEN_OPTION_NUM]; int state; int moreAdjust; float speed; float timestep; float windowOpacity; int windowPartSize; int direction; int wMask; int sdActiveAtom; int grabIndex; Bool ignoreNextTerminateEvent; } ShowdesktopScreen; typedef struct _ShowdesktopWindow { int sid; int distance; ShowdesktopPlacer placer; GLfloat xVelocity, yVelocity; GLfloat tx, ty; GLfloat oldOpacity; float delta; Bool adjust; } ShowdesktopWindow; /* shortcut macros, usually named X_DISPLAY, X_SCREEN and X_WINDOW * these might seem overly complicated but they are shortcuts so we don't have to access the privates arrays all the time * */ #define GET_SHOWDESKTOP_DISPLAY(d) \ ((ShowdesktopDisplay *) (d)->privates[displayPrivateIndex].ptr) #define SD_DISPLAY(d) \ ShowdesktopDisplay *sd = GET_SHOWDESKTOP_DISPLAY (d) #define GET_SHOWDESKTOP_SCREEN(s, fd) \ ((ShowdesktopScreen *) (s)->privates[(fd)->screenPrivateIndex].ptr) #define SD_SCREEN(s) \ ShowdesktopScreen *ss = GET_SHOWDESKTOP_SCREEN (s, GET_SHOWDESKTOP_DISPLAY (s->display)) #define GET_SHOWDESKTOP_WINDOW(w, ss) \ ((ShowdesktopWindow *) (w)->privates[(ss)->windowPrivateIndex].ptr) #define SD_WINDOW(w) \ ShowdesktopWindow *sw = GET_SHOWDESKTOP_WINDOW (w, \ GET_SHOWDESKTOP_SCREEN (w->screen, \ GET_SHOWDESKTOP_DISPLAY (w->screen->display))) /* plugin private index */ static int displayPrivateIndex; /* non interfacing code, aka the logic of the plugin */ static Bool isSDWin(CompWindow * w) { SD_SCREEN(w->screen); if (!(*w->screen->focusWindow) (w)) return FALSE; if (!(ss->wMask & w->type)) return FALSE; if (w->wmType & (CompWindowTypeDockMask | CompWindowTypeDesktopMask)) return FALSE; if (w->state & CompWindowStateSkipPagerMask) return FALSE; return TRUE; } static Bool showdesktopTerminate(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) { SD_SCREEN(s); if (ss->state == SD_STATE_ON || ss->state == SD_STATE_ACTIVATING) { CompWindow *w; for (w = s->windows; w; w = w->next) { SD_WINDOW(w); if (sw->placer.placed) { sw->adjust = TRUE; sw->xVelocity = sw->yVelocity = 0.0f; w->paint.opacity = sw->oldOpacity; /* adjust onscreen position to handle viewport changes */ sw->placer.onScreenX += (sw->placer.origViewportX - w->screen->x) * w->screen->width; sw->placer.onScreenY += (sw->placer.origViewportY - w->screen->y) * w->screen->height; } } ss->state = SD_STATE_DEACTIVATING; if (ss->grabIndex) removeScreenGrab(s, ss->grabIndex, NULL); ss->grabIndex = pushScreenGrab(s, s->invisibleCursor, "showdesktop"); } focusDefaultWindow(s->display); } return FALSE; } static void repositionSDPlacer(CompWindow * w, int oldState) { SD_SCREEN(w->screen); SD_WINDOW(w); if (oldState == SD_STATE_OFF) { sw->placer.onScreenX = w->attrib.x; sw->placer.onScreenY = w->attrib.y; sw->placer.origViewportX = w->screen->x; sw->placer.origViewportY = w->screen->y; } switch (ss->direction) { case SdDirectionUp: sw->placer.offScreenX = w->attrib.x; sw->placer.offScreenY = w->screen->workArea.y - OFF_TOP(w) + ss->windowPartSize; break; case SdDirectionDown: sw->placer.offScreenX = w->attrib.x; sw->placer.offScreenY = w->screen->workArea.y + w->screen->workArea.height + OFF_BOTTOM(w) - ss->windowPartSize; break; case SdDirectionLeft: sw->placer.offScreenX = w->screen->workArea.x - OFF_LEFT(w) + ss->windowPartSize; sw->placer.offScreenY = w->attrib.y; break; case SdDirectionRight: sw->placer.offScreenX = w->screen->workArea.x + w->screen->workArea.width + OFF_RIGHT(w) - ss->windowPartSize; sw->placer.offScreenY = w->attrib.y; break; case SdDirectionUpDown: sw->placer.offScreenX = w->attrib.x; if (MOVE_UP(w)) sw->placer.offScreenY = w->screen->workArea.y - OFF_TOP(w) + ss->windowPartSize; else sw->placer.offScreenY = w->screen->workArea.y + w->screen->workArea.height + OFF_BOTTOM(w) - ss->windowPartSize; break; case SdDirectionLeftRight: sw->placer.offScreenY = w->attrib.y; if (MOVE_LEFT(w)) sw->placer.offScreenX = w->screen->workArea.x - OFF_LEFT(w) + ss->windowPartSize; else sw->placer.offScreenX = w->screen->workArea.x + w->screen->workArea.width + OFF_RIGHT(w) - ss->windowPartSize; break; case SdDirectionCorners: if (MOVE_LEFT(w)) sw->placer.offScreenX = w->screen->workArea.x - OFF_LEFT(w) + ss->windowPartSize; else sw->placer.offScreenX = w->screen->workArea.x + w->screen->workArea.width + OFF_RIGHT(w) - ss->windowPartSize; if (MOVE_UP(w)) sw->placer.offScreenY = w->screen->workArea.y - OFF_TOP(w) + ss->windowPartSize; else sw->placer.offScreenY = w->screen->workArea.y + w->screen->workArea.height + OFF_BOTTOM(w) - ss->windowPartSize; break; } } static Bool prepareSDWindows(CompScreen * s, int oldState) { CompWindow *w; CompWindow *desktopWindow; SD_SCREEN(s); desktopWindow = 0; for (w = s->windows; w; w = w->next) { SD_WINDOW(w); if (getWindowType(s->display, w->id) == CompWindowTypeDesktopMask) desktopWindow = w; if (!isSDWin(w)) continue; if (sw->placer.placed) { sw->tx = sw->ty = 0; syncWindowPosition(w); sw->placer.placed = FALSE; } repositionSDPlacer(w, oldState); sw->tx = sw->ty = sw->xVelocity = sw->yVelocity = 0.0f; sw->adjust = TRUE; sw->placer.placed = TRUE; sw->oldOpacity = w->paint.opacity; w->paint.opacity = ss->windowOpacity * OPAQUE; } if (desktopWindow) activateWindow(desktopWindow); return TRUE; } static Bool showdesktopInitiate(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 && !otherScreenGrabExist(s, 0)) { SD_SCREEN(s); if (ss->state == SD_STATE_OFF || ss->state == SD_STATE_DEACTIVATING) { if (prepareSDWindows(s, ss->state)) { XSetInputFocus(d->display, d->screens->root, RevertToPointerRoot, CurrentTime); ss->state = SD_STATE_ACTIVATING; IPCS_SetBool(IPCS_OBJECT(s), ss->sdActiveAtom, TRUE); if (ss->grabIndex) removeScreenGrab(s, ss->grabIndex, NULL); ss->grabIndex = pushScreenGrab(s, s->invisibleCursor, "showdesktop"); } if (state & CompActionStateInitButton) action->state |= CompActionStateTermButton; if (state & CompActionStateInitKey) action->state |= CompActionStateTermKey; } else { return showdesktopTerminate(d, action, state, option, nOption); } } return FALSE; } /* gconf entries */ static void showdesktopDisplayInitOptions(ShowdesktopDisplay * sd) { CompOption *o; o = &sd->opt[SD_DISPLAY_OPTION_INITIATE]; o->advanced = False; o->name = "initiate"; o->group = N_("Binding"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Initiate showdesktop mode"); o->longDesc = N_("Initiate showdesktop mode"); o->type = CompOptionTypeAction; o->value.action.initiate = showdesktopInitiate; o->value.action.terminate = showdesktopInitiate; o->value.action.bell = FALSE; o->value.action.edgeMask = (1 << SCREEN_EDGE_BOTTOMRIGHT); o->value.action.state = CompActionStateInitEdge; o->value.action.type = CompBindingTypeKey; o->value.action.state |= CompActionStateInitKey; o->value.action.key.modifiers = SD_INITIATE_MODIFIERS_DEFAULT; o->value.action.key.keysym = XStringToKeysym(SD_INITIATE_KEY_DEFAULT); } static void showdesktopScreenInitOptions(ShowdesktopScreen * ss) { CompOption *o; int i; o = &ss->opt[SD_SCREEN_OPTION_SPEED]; o->advanced = False; o->name = "speed"; o->group = N_("Misc. Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Speed"); o->longDesc = N_("Window speed"); o->type = CompOptionTypeFloat; o->value.f = SD_SPEED_DEFAULT; o->rest.f.min = SD_SPEED_MIN; o->rest.f.max = SD_SPEED_MAX; o->rest.f.precision = SD_SPEED_PRECISION; o = &ss->opt[SD_SCREEN_OPTION_TIMESTEP]; o->advanced = False; o->name = "timestep"; o->group = N_("Misc. Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Timestep"); o->longDesc = N_("Showdesktop timestep"); o->type = CompOptionTypeFloat; o->value.f = SD_TIMESTEP_DEFAULT; o->rest.f.min = SD_TIMESTEP_MIN; o->rest.f.max = SD_TIMESTEP_MAX; o->rest.f.precision = SD_TIMESTEP_PRECISION; o = &ss->opt[SD_SCREEN_OPTION_DIRECTION]; o->advanced = False; o->name = "direction"; o->group = N_("Behaviour"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Window direction"); o->longDesc = N_ ("0 - Up, 1 - Down, 2 - Left, 3 - Right, 4 - Up/Down, 5 - Left/Right"); o->type = CompOptionTypeString; o->value.s = strdup(sdDirections[SD_DIRECTION_DEFAULT]); o->rest.s.string = sdDirections; o->rest.s.nString = NUM_SD_DIRECTIONS; o = &ss->opt[SD_SCREEN_OPTION_WINDOW_TYPE]; o->advanced = False; o->name = "window_types"; o->group = N_("Behaviour"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Window Types"); o->longDesc = N_("Window types that should go away in showdesktop mode"); o->type = CompOptionTypeList; o->value.list.type = CompOptionTypeString; o->value.list.nValue = N_WIN_TYPE; o->value.list.value = malloc(sizeof(CompOptionValue) * N_WIN_TYPE); for (i = 0; i < N_WIN_TYPE; i++) o->value.list.value[i].s = strdup(winType[i]); o->rest.s.string = (char **)windowTypeString; o->rest.s.nString = nWindowTypeString; ss->wMask = compWindowTypeMaskFromStringList(&o->value); o = &ss->opt[SD_SCREEN_OPTION_USE_SCALE_SETTINGS]; o->advanced = False; o->name = "use_scale_settings"; o->group = N_("Misc. Options"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Use scale settings"); o->longDesc = N_ ("Use scale speed/timestep settings instead of the ones specified here"); o->type = CompOptionTypeBool; o->value.b = SD_USE_SCALE_SETTINGS_DEFAULT; o = &ss->opt[SD_SCREEN_OPTION_WINDOW_OPACITY]; o->advanced = False; o->name = "window_opacity"; o->group = N_("Appearance"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Window opacity when showdesktop'd"); o->longDesc = N_("Window opacity when showdesktop'd"); o->type = CompOptionTypeFloat; o->value.f = SD_WINDOW_OPACITY_DEFAULT; o->rest.f.min = SD_WINDOW_OPACITY_MIN; o->rest.f.max = SD_WINDOW_OPACITY_MAX; o->rest.f.precision = SD_WINDOW_OPACITY_PRECISION; o = &ss->opt[SD_SCREEN_OPTION_WINDOW_PART_SIZE]; o->advanced = False; o->name = "window_part_size"; o->group = N_("Appearance"); o->subGroup = N_(""); o->displayHints = ""; o->shortDesc = N_("Window part size when showdesktop'd"); o->longDesc = N_("Window part size when showdesktop'd"); o->type = CompOptionTypeInt; o->value.i = SD_WINDOW_PART_SIZE_DEFAULT; o->rest.i.min = SD_WINDOW_PART_SIZE_MIN; o->rest.i.max = SD_WINDOW_PART_SIZE_MAX; } /* plugin initialization */ static Bool showdesktopInit(CompPlugin * p) { displayPrivateIndex = allocateDisplayPrivateIndex(); if (displayPrivateIndex < 0) return FALSE; return TRUE; } /* plugin finalization */ static void showdesktopFini(CompPlugin * p) { if (displayPrivateIndex >= 0) freeDisplayPrivateIndex(displayPrivateIndex); } /* Handle event function * I have intentions of using this in the future **/ static void showdesktopHandleEvent(CompDisplay * d, XEvent * event) { SD_DISPLAY(d); CompWindow *w; switch (event->type) { case DestroyNotify: w = findWindowAtDisplay(d, event->xdestroywindow.window); if (w) { SD_SCREEN(w->screen); ss->ignoreNextTerminateEvent = TRUE; } break; case ReparentNotify: { w = findWindowAtDisplay(d, event->xreparent.window); if (w) { SD_SCREEN(w->screen); ss->ignoreNextTerminateEvent = TRUE; } break; } case FocusIn: { w = findWindowAtDisplay(d, event->xfocus.window); if (w && w->managed && w->id != d->activeWindow) { SD_SCREEN(w->screen); SD_WINDOW(w); if (ss->ignoreNextTerminateEvent) { ss->ignoreNextTerminateEvent = FALSE; break; } if (sw->placer.placed && (ss->state == SD_STATE_ON || ss->state == SD_STATE_ACTIVATING)) { CompOption o[1]; o[0].type = CompOptionTypeInt; o[0].name = "root"; o[0].value.i = w->screen->root; showdesktopTerminate(d, NULL, 0, o, 1); } } break; } } UNWRAP(sd, d, handleEvent); (*d->handleEvent) (d, event); WRAP(sd, d, handleEvent, showdesktopHandleEvent); } /* adjust velocity for each animation step (adapted from the scale plugin) */ static int adjustSDVelocity(CompWindow * w) { float dx, dy, adjust, amount; float x1, y1; SD_WINDOW(w); SD_SCREEN(w->screen); x1 = y1 = 0.0; if (!sw->placer.placed) return 0; if (ss->state == SD_STATE_ACTIVATING) { x1 = sw->placer.offScreenX; y1 = sw->placer.offScreenY; } else if (ss->state == SD_STATE_DEACTIVATING) { x1 = sw->placer.onScreenX; y1 = sw->placer.onScreenY; } dx = x1 - (w->serverX + sw->tx); adjust = dx * 0.15f; amount = fabs(dx) * 1.5f; if (amount < 0.5f) amount = 0.5f; else if (amount > 5.0f) amount = 5.0f; sw->xVelocity = (amount * sw->xVelocity + adjust) / (amount + 1.0f); dy = y1 - (w->serverY + sw->ty); adjust = dy * 0.15f; amount = fabs(dy) * 1.5f; if (amount < 0.5f) amount = 0.5f; else if (amount > 5.0f) amount = 5.0f; sw->yVelocity = (amount * sw->yVelocity + adjust) / (amount + 1.0f); if (fabs(dx) < 0.1f && fabs(sw->xVelocity) < 0.2f && fabs(dy) < 0.1f && fabs(sw->yVelocity) < 0.2f) { sw->xVelocity = sw->yVelocity = 0.0f; sw->tx = x1 - w->serverX; sw->ty = y1 - w->serverY; return 0; } return 1; } /* this function gets called periodically (about every 15ms on this machine), * animation takes place here */ static void showdesktopPreparePaintScreen(CompScreen * s, int msSinceLastPaint) { SD_SCREEN(s); if ((ss->state != SD_STATE_OFF) && screenGrabExist(s, "scale", 0)) { CompOption o[1]; o[0].type = CompOptionTypeInt; o[0].name = "root"; o[0].value.i = s->root; showdesktopTerminate(s->display, NULL, 0, o, 1); } UNWRAP(ss, s, preparePaintScreen); (*s->preparePaintScreen) (s, msSinceLastPaint); WRAP(ss, s, preparePaintScreen, showdesktopPreparePaintScreen); if (ss->state == SD_STATE_ACTIVATING || ss->state == SD_STATE_DEACTIVATING) { CompWindow *w; int steps, dx, dy; float amount, chunk; amount = msSinceLastPaint * 0.05f * ss->speed; steps = amount / (0.5f * ss->timestep); if (!steps) steps = 1; chunk = amount / (float)steps; while (steps--) { ss->moreAdjust = 0; for (w = s->windows; w; w = w->next) { SD_WINDOW(w); if (sw->placer.placed && sw->adjust) { sw->adjust = adjustSDVelocity(w); ss->moreAdjust |= sw->adjust; sw->tx += sw->xVelocity * chunk; sw->ty += sw->yVelocity * chunk; dx = (w->serverX + sw->tx) - w->attrib.x; dy = (w->serverY + sw->ty) - w->attrib.y; moveWindow(w, dx, dy, FALSE, FALSE); } } if (!ss->moreAdjust) break; } } } /* this one gets called after the one above and periodically, * here the plugin checks if windows reached the end */ static void showdesktopDonePaintScreen(CompScreen * s) { SD_SCREEN(s); if (ss->moreAdjust) { damageScreen(s); } else { if (ss->state == SD_STATE_ACTIVATING || ss->state == SD_STATE_DEACTIVATING) { CompWindow *w; for (w = s->windows; w; w = w->next) { SD_WINDOW(w); syncWindowPosition(w); if (ss->state == SD_STATE_DEACTIVATING) sw->placer.placed = FALSE; } if (ss->state == SD_STATE_ACTIVATING) ss->state = SD_STATE_ON; if (ss->state == SD_STATE_DEACTIVATING) { ss->state = SD_STATE_OFF; IPCS_SetBool(IPCS_OBJECT(s), ss->sdActiveAtom, FALSE); } if (ss->grabIndex) { removeScreenGrab(s, ss->grabIndex, NULL); ss->grabIndex = 0; } } } UNWRAP(ss, s, donePaintScreen); (*s->donePaintScreen) (s); WRAP(ss, s, donePaintScreen, showdesktopDonePaintScreen); } /* display initialization */ static Bool showdesktopInitDisplay(CompPlugin * p, CompDisplay * d) { ShowdesktopDisplay *sd; sd = malloc(sizeof(ShowdesktopDisplay)); /* allocate the display */ if (!sd) return FALSE; sd->screenPrivateIndex = allocateScreenPrivateIndex(d); if (sd->screenPrivateIndex < 0) { free(sd); return FALSE; } showdesktopDisplayInitOptions(sd); WRAP(sd, d, handleEvent, showdesktopHandleEvent); d->privates[displayPrivateIndex].ptr = sd; return TRUE; } /* display finalization * free resources * */ static void showdesktopFiniDisplay(CompPlugin * p, CompDisplay * d) { SD_DISPLAY(d); freeScreenPrivateIndex(d, sd->screenPrivateIndex); UNWRAP(sd, d, handleEvent); free(sd); } static void showdesktopUpdateScaleOptions(CompScreen * s) { CompPlugin *p; SD_SCREEN(s); if (!ss->opt[SD_SCREEN_OPTION_USE_SCALE_SETTINGS].value.b) return; p = findActivePlugin("scale"); if (p && p->vTable->getScreenOptions) { CompOption *options, *option; int nOptions; options = (*p->vTable->getScreenOptions) (s, &nOptions); option = compFindOption(options, nOptions, "speed", 0); if (option) ss->speed = option->value.f; option = compFindOption(options, nOptions, "timestep", 0); if (option) ss->timestep = option->value.f; option = compFindOption(options, nOptions, "window_types", 0); if (option) ss->wMask = compWindowTypeMaskFromStringList(&option->value); } } static Bool showdesktopSetScreenOptionForPlugin(CompScreen * s, char *plugin, char *name, CompOptionValue * value) { Bool status; SD_SCREEN(s); UNWRAP(ss, s, setScreenOptionForPlugin); status = (*s->setScreenOptionForPlugin) (s, plugin, name, value); WRAP(ss, s, setScreenOptionForPlugin, showdesktopSetScreenOptionForPlugin); if (status && strcmp(plugin, "scale") == 0) if (strcmp(name, "speed") == 0 || strcmp(name, "timestep") == 0 || strcmp(name, "window_types") == 0) showdesktopUpdateScaleOptions(s); return status; } /* screen initialization * */ static Bool showdesktopInitScreen(CompPlugin * p, CompScreen * s) { ShowdesktopScreen *ss; SD_DISPLAY(s->display); ss = malloc(sizeof(ShowdesktopScreen)); if (!ss) return FALSE; ss->windowPrivateIndex = allocateWindowPrivateIndex(s); if (ss->windowPrivateIndex < 0) { free(ss); return FALSE; } showdesktopScreenInitOptions(ss); ss->state = SD_STATE_OFF; ss->moreAdjust = 0; ss->speed = SD_SPEED_DEFAULT; ss->timestep = SD_TIMESTEP_DEFAULT; ss->direction = SD_DIRECTION_DEFAULT; ss->windowOpacity = SD_WINDOW_OPACITY_DEFAULT; ss->windowPartSize = SD_WINDOW_PART_SIZE_DEFAULT; ss->ignoreNextTerminateEvent = FALSE; ss->grabIndex = 0; ss->sdActiveAtom = IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "SHOWDESKTOP_ACTIVE", TRUE); IPCS_SetBool(IPCS_OBJECT(s), ss->sdActiveAtom, FALSE); addScreenAction(s, &sd->opt[SD_DISPLAY_OPTION_INITIATE].value.action); WRAP(ss, s, preparePaintScreen, showdesktopPreparePaintScreen); WRAP(ss, s, donePaintScreen, showdesktopDonePaintScreen); WRAP(ss, s, setScreenOptionForPlugin, showdesktopSetScreenOptionForPlugin); s->privates[sd->screenPrivateIndex].ptr = ss; showdesktopUpdateScaleOptions(s); return TRUE; } /* Free screen resources */ static void showdesktopFiniScreen(CompPlugin * p, CompScreen * s) { SD_SCREEN(s); SD_DISPLAY(s->display); UNWRAP(ss, s, preparePaintScreen); UNWRAP(ss, s, donePaintScreen); UNWRAP(ss, s, setScreenOptionForPlugin); removeScreenAction(s, &sd->opt[SD_DISPLAY_OPTION_INITIATE].value.action); IPCS_Unset(IPCS_OBJECT(s), ss->sdActiveAtom); freeWindowPrivateIndex(s, ss->windowPrivateIndex); free(ss); } /* window init */ static Bool showdesktopInitWindow(CompPlugin * p, CompWindow * w) { ShowdesktopWindow *sw; SD_SCREEN(w->screen); sw = malloc(sizeof(ShowdesktopWindow)); if (!sw) return FALSE; sw->tx = sw->ty = 0.0f; sw->adjust = FALSE; sw->xVelocity = sw->yVelocity = 0.0f; sw->delta = 1.0f; sw->placer.placed = FALSE; sw->placer.offScreenX = sw->placer.offScreenY = 0; sw->placer.onScreenX = sw->placer.onScreenY = 0; w->privates[ss->windowPrivateIndex].ptr = sw; return TRUE; } /* Free window resources */ static void showdesktopFiniWindow(CompPlugin * p, CompWindow * w) { SD_WINDOW(w); free(sw); } static CompOption *showdesktopGetDisplayOptions(CompDisplay * display, int *count) { if (display) { SD_DISPLAY(display); *count = NUM_OPTIONS(sd); return sd->opt; } else { ShowdesktopDisplay *sd = malloc(sizeof(ShowdesktopDisplay)); showdesktopDisplayInitOptions(sd); *count = NUM_OPTIONS(sd); return sd->opt; } } static Bool showdesktopSetDisplayOption(CompDisplay * display, char *name, CompOptionValue * value) { CompOption *o; int index; SD_DISPLAY(display); o = compFindOption(sd->opt, NUM_OPTIONS(sd), name, &index); if (!o) return FALSE; switch (index) { case SD_DISPLAY_OPTION_INITIATE: if (setDisplayAction(display, o, value)) return TRUE; default: break; } return FALSE; } static CompOption *showdesktopGetScreenOptions(CompScreen * screen, int *count) { if (screen) { SD_SCREEN(screen); *count = NUM_OPTIONS(ss); return ss->opt; } else { ShowdesktopScreen *ss = malloc(sizeof(ShowdesktopScreen)); showdesktopScreenInitOptions(ss); *count = NUM_OPTIONS(ss); return ss->opt; } } static Bool showdesktopSetScreenOption(CompScreen * screen, char *name, CompOptionValue * value) { CompOption *o; int index; SD_SCREEN(screen); o = compFindOption(ss->opt, NUM_OPTIONS(ss), name, &index); if (!o) return FALSE; switch (index) { case SD_SCREEN_OPTION_SPEED: if (compSetFloatOption(o, value)) { if (!ss->opt[SD_SCREEN_OPTION_USE_SCALE_SETTINGS].value.b) ss->speed = o->value.f; return TRUE; } break; case SD_SCREEN_OPTION_TIMESTEP: if (compSetFloatOption(o, value)) { if (!ss->opt[SD_SCREEN_OPTION_USE_SCALE_SETTINGS].value.b) ss->timestep = o->value.f; return TRUE; } break; case SD_SCREEN_OPTION_DIRECTION: if (compSetStringOption(o, value)) { int i; for (i = 0; i < o->rest.s.nString; i++) { if (strcmp(sdDirections[i], o->value.s) == 0) ss->direction = (SdDirection) i; } return TRUE; } break; case SD_SCREEN_OPTION_WINDOW_TYPE: if (compSetOptionList(o, value)) { if (!ss->opt[SD_SCREEN_OPTION_USE_SCALE_SETTINGS].value.b) ss->wMask = compWindowTypeMaskFromStringList(&o->value); return TRUE; } break; case SD_SCREEN_OPTION_USE_SCALE_SETTINGS: if (compSetBoolOption(o, value)) { if (o->value.b) { showdesktopUpdateScaleOptions(screen); } else { ss->speed = ss->opt[SD_SCREEN_OPTION_SPEED].value.f; ss->timestep = ss->opt[SD_SCREEN_OPTION_TIMESTEP].value.f; ss->wMask = compWindowTypeMaskFromStringList(& (ss-> opt [SD_SCREEN_OPTION_WINDOW_TYPE]. value)); } return TRUE; } break; case SD_SCREEN_OPTION_WINDOW_OPACITY: if (compSetFloatOption(o, value)) { ss->windowOpacity = o->value.f; return TRUE; } break; case SD_SCREEN_OPTION_WINDOW_PART_SIZE: if (compSetIntOption(o, value)) { ss->windowPartSize = o->value.i; return TRUE; } break; } return FALSE; } CompPluginFeature sdFeatures[] = { {"showdesktop"} , }; /* plugin vtable */ static CompPluginVTable showdesktopVTable = { "showdesktop", N_("Show desktop"), N_("Access your desktop easily"), showdesktopInit, showdesktopFini, showdesktopInitDisplay, showdesktopFiniDisplay, showdesktopInitScreen, showdesktopFiniScreen, showdesktopInitWindow, showdesktopFiniWindow, showdesktopGetDisplayOptions, showdesktopSetDisplayOption, showdesktopGetScreenOptions, showdesktopSetScreenOption, 0, /* deps fade */ 0, /* sizeof (fadeDeps) / sizeof (fadeDeps[0]) */ sdFeatures, sizeof(sdFeatures)/sizeof(sdFeatures[0]), BERYL_ABI_INFO, "beryl-plugins-unsupported", "desktop", 0, 0, False, }; /* send plugin info */ CompPluginVTable *getCompPluginInfo(void) { return &showdesktopVTable; }