/*
*
* 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) <diogo@beryl-project.org>
*
*
* 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 <stdlib.h>
#include <string.h>
#include <beryl.h>
#include <beryl_ipcs.h>
#include <math.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1