/**
*
* Beryl fade to desktop plugin
*
* fadedesktop.c
*
* Copyright (c) 2006 Robert Carr <racarr@beryl-project.org>
*
* 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.
*
**/
#include <stdlib.h>
#include <string.h>
#include <beryl.h>
#include <beryl_ipcs.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#define FD_INITIATE_KEY_DEFAULT "F6"
#define FD_INITIATE_MODIFIERS_DEFAULT CompSuperMask
#define FD_INITIATE_EDGE_DEFAULT 0
#define FD_SPEED_DEFAULT 20
#define FD_SPEED_MIN 1
#define FD_SPEED_MAX 100
#define FD_DISPLAY_OPTION_INITIATE 0
#define FD_DISPLAY_OPTION_NUM 1
#define FD_SCREEN_OPTION_SPEED 0
#define FD_SCREEN_OPTION_NUM 1
typedef struct _FadeDesktopDisplay
{
int screenPrivateIndex;
CompOption opt[FD_DISPLAY_OPTION_NUM];
} FadeDesktopDisplay;
typedef struct _FadeDesktopScreen
{
int windowPrivateIndex;
PreparePaintScreenProc preparePaintScreen;
DonePaintScreenProc donePaintScreen;
CompOption opt[FD_SCREEN_OPTION_NUM];
Bool showingDesktop;
Bool reverting;
} FadeDesktopScreen;
typedef struct _FadeDesktopWindow
{
Bool isHidden;
} FadeDesktopWindow;
#define GET_FADEDESKTOP_DISPLAY(d) \
((FadeDesktopDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define FD_DISPLAY(d) \
FadeDesktopDisplay *fd = GET_FADEDESKTOP_DISPLAY (d)
#define GET_FADEDESKTOP_SCREEN(s, fd) \
((FadeDesktopScreen *) (s)->privates[(fd)->screenPrivateIndex].ptr)
#define FD_SCREEN(s) \
FadeDesktopScreen *fs = GET_FADEDESKTOP_SCREEN (s, GET_FADEDESKTOP_DISPLAY (s->display))
#define GET_FADEDESKTOP_WINDOW(w, fs) \
((FadeDesktopWindow *) (w)->privates[(fs)->windowPrivateIndex].ptr)
#define FD_WINDOW(w) \
FadeDesktopWindow *fw = GET_FADEDESKTOP_WINDOW(w, \
GET_FADEDESKTOP_SCREEN (w->screen, GET_FADEDESKTOP_DISPLAY (w->screen->display)))
static int displayPrivateIndex;
static Bool isFDWin(CompWindow *w)
{
//w->screen->focusWindow ?
if (w->state & CompWindowStateOffscreenMask)
return FALSE;
if (w->wmType & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
return FALSE;
if (w->type & (CompWindowTypeNormalMask | CompWindowTypeDialogMask ) )
{
return TRUE;
}
return FALSE;
}
static Bool
fadeDesktopTerminate(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)
{
FD_SCREEN(s);
fs->reverting = TRUE;
CompWindow *w;
for (w=s->windows; w; w=w->next)
{
FD_WINDOW(w);
if (fw->isHidden && (w->state & CompWindowStateOffscreenMask))
{
moveWindowOnscreen(w);
}
fw->isHidden = FALSE;
}
}
return TRUE;
}
static Bool
fadeDesktopInitiate(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)
{
FD_SCREEN(s);
if (fs->showingDesktop)
{
fs->showingDesktop = FALSE;
fadeDesktopTerminate(d, action, state, option, nOption);
return TRUE;
}
else if (fs->reverting)
{
fs->reverting = FALSE;
}
fs->showingDesktop = TRUE;
unsigned long data = 0;
XChangeProperty(s->display->display, s->root,
s->display->showingDesktopAtom,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&data, 1);
}
return TRUE;
}
static void
fadeDesktopPreparePaintScreen(CompScreen *s, int msSinceLastPaint)
{
FD_SCREEN(s);
#define SPEED ((fs->opt[FD_SCREEN_OPTION_SPEED].value.i ? fs->opt[FD_SCREEN_OPTION_SPEED].value.i : 1))
int numWins=0;
int numReverts=0;
CompWindow *w;
for (w=s->windows; w; w=w->next)
{
if (isFDWin(w))
{
if (fs->showingDesktop)
{
if (w->paint.opacity > OPAQUE/SPEED)
{
setWindowOpacity(w,w->paint.opacity-OPAQUE/SPEED,PL_TEMP_HELLO);
}
else if (w->paint.opacity != 0)
{
FD_WINDOW(w);
moveWindowOffscreen(w);
fw->isHidden = TRUE;
}
}
if (fs->reverting)
{
if (w->paint.opacity + OPAQUE/SPEED <= w->opacity)
{
setWindowOpacity(w,w->paint.opacity + OPAQUE/SPEED,PL_TEMP_HELLO);
}
else
{
resetWindowOpacity(w, PL_TEMP_HELLO);
numReverts++;
}
}
numWins++;
}
}
if (numWins == numReverts)
{
fs->reverting = FALSE;
unsigned long data = 0;
XChangeProperty(s->display->display, s->root,
s->display->showingDesktopAtom,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&data, 1);
}
UNWRAP(fs,s,preparePaintScreen);
(*s->preparePaintScreen) (s,msSinceLastPaint);
WRAP(fs,s,preparePaintScreen,fadeDesktopPreparePaintScreen);
}
static void fadeDesktopDonePaintScreen(CompScreen *s)
{
FD_SCREEN(s);
if (fs->showingDesktop || fs->reverting)
{
damageScreen(s);
}
UNWRAP(fs,s,donePaintScreen);
(*s->donePaintScreen)(s);
WRAP(fs,s,donePaintScreen,fadeDesktopDonePaintScreen);
}
static void
fadeDesktopDisplayInitOptions(FadeDesktopDisplay *fd)
{
CompOption *o;
o = &fd->opt[FD_DISPLAY_OPTION_INITIATE];
o->advanced = False;
o->name = "initiate";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Initiate Fade to Desktop");
o->longDesc = N_("Initiate Fade to Desktop mode.");
o->type = CompOptionTypeAction;
o->value.action.initiate= fadeDesktopInitiate;
o->value.action.terminate = fadeDesktopTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = FD_INITIATE_EDGE_DEFAULT;
o->value.action.type = CompBindingTypeKey;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitEdge;
o->value.action.key.modifiers = FD_INITIATE_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(FD_INITIATE_KEY_DEFAULT);
}
static void fadeDesktopScreenInitOptions(FadeDesktopScreen * fs)
{
CompOption *o;
o = &fs->opt[FD_SCREEN_OPTION_SPEED];
o->advanced = False;
o->name = "speed";
o->group = N_("Misc. Options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Time to Fade");
o->longDesc = N_("Time to Fade.");
o->type = CompOptionTypeInt;
o->value.i = FD_SPEED_DEFAULT;
o->rest.i.min = FD_SPEED_MIN;
o->rest.i.max = FD_SPEED_MAX;
}
static Bool fadeDesktopInit(CompPlugin *p)
{
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void fadeDesktopFini(CompPlugin *p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
static Bool fadeDesktopInitDisplay(CompPlugin *p, CompDisplay *d)
{
FadeDesktopDisplay *fd;
fd = malloc(sizeof(FadeDesktopDisplay));
if (!fd)
return FALSE;
fd->screenPrivateIndex = allocateScreenPrivateIndex(d);
if (fd->screenPrivateIndex < 0)
{
free(fd);
return FALSE;
}
fadeDesktopDisplayInitOptions(fd);
d->privates[displayPrivateIndex].ptr = fd;
return TRUE;
}
static void fadeDesktopFiniDisplay(CompPlugin *p, CompDisplay *d)
{
FD_DISPLAY(d);
freeScreenPrivateIndex(d, fd->screenPrivateIndex);
free(fd);
}
static Bool fadeDesktopInitScreen(CompPlugin *p, CompScreen *s)
{
FadeDesktopScreen *fs;
FD_DISPLAY(s->display);
fs = malloc(sizeof(FadeDesktopScreen));
if (!fs)
return FALSE;
fs->windowPrivateIndex = allocateWindowPrivateIndex(s);
if (fs->windowPrivateIndex < 0)
{
free(fs);
return FALSE;
}
fadeDesktopScreenInitOptions(fs);
fs->showingDesktop = FALSE;
addScreenAction(s, &fd->opt[FD_DISPLAY_OPTION_INITIATE].value.action);
WRAP(fs,s,preparePaintScreen,fadeDesktopPreparePaintScreen);
WRAP(fs,s,donePaintScreen,fadeDesktopDonePaintScreen);
s->privates[fd->screenPrivateIndex].ptr = fs;
return TRUE;
}
static void fadeDesktopFiniScreen(CompPlugin *p, CompScreen *s)
{
FD_SCREEN(s);
FD_DISPLAY(s->display);
UNWRAP(fs,s,preparePaintScreen);
UNWRAP(fs,s,donePaintScreen);
removeScreenAction(s, &fd->opt[FD_DISPLAY_OPTION_INITIATE].value.action);
freeWindowPrivateIndex(s, fs->windowPrivateIndex);
free (fs);
}
static Bool fadeDesktopInitWindow(CompPlugin *p, CompWindow *w)
{
FadeDesktopWindow *fw;
FD_SCREEN(w->screen);
fw = malloc(sizeof(FadeDesktopWindow));
if (!fw)
return FALSE;
fw->isHidden = FALSE;
w->privates[fs->windowPrivateIndex].ptr = fw;
return TRUE;
}
static void fadeDesktopFiniWindow(CompPlugin *p, CompWindow *w)
{
FD_WINDOW(w);
FD_SCREEN(w->screen);
free (fw);
}
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static CompOption *fadeDesktopGetDisplayOptions(CompDisplay *display, int *count)
{
if (display)
{
FD_DISPLAY(display);
*count = NUM_OPTIONS(fd);
return fd->opt;
}
else
{
FadeDesktopDisplay *fd = malloc(sizeof(FadeDesktopDisplay));
fadeDesktopDisplayInitOptions(fd);
*count = NUM_OPTIONS(fd);
return fd->opt;
}
}
static Bool
fadeDesktopSetDisplayOption(CompDisplay *display, char * name, CompOptionValue *value)
{
FD_DISPLAY(display);
CompOption *o;
int index;
o = compFindOption(fd->opt,FD_DISPLAY_OPTION_NUM,name,&index);
if (!o)
return FALSE;
switch (index)
{
case FD_DISPLAY_OPTION_INITIATE:
if (setDisplayAction(display,o,value))
return TRUE;
default:
break;
}
return FALSE;
}
static CompOption *fadeDesktopGetScreenOptions(CompScreen * screen,
int *count)
{
if (screen)
{
FD_SCREEN(screen);
*count = FD_SCREEN_OPTION_NUM;
return fs->opt;
}
else
{
FadeDesktopScreen *fs = malloc(sizeof(FadeDesktopScreen));
fadeDesktopScreenInitOptions(fs);
*count = FD_SCREEN_OPTION_NUM;
return fs->opt;
}
}
static Bool
fadeDesktopSetScreenOption(CompScreen *screen, char *name, CompOptionValue *value)
{
CompOption *o;
int index;
FD_SCREEN(screen);
o = compFindOption(fs->opt,FD_SCREEN_OPTION_NUM,name,&index);
if (!o)
return FALSE;
switch (index)
{
case FD_SCREEN_OPTION_SPEED:
if (compSetIntOption(o,value))
{
return TRUE;
}
break;
}
return FALSE;
}
CompPluginFeature fdFeatures[] = {
{"showdesktop"}
,
};
static CompPluginVTable fadeDesktopVTable = {
"fadeDesktop",
N_("Fade to Desktop"),
N_("Easily access your desktop"),
fadeDesktopInit,
fadeDesktopFini,
fadeDesktopInitDisplay,
fadeDesktopFiniDisplay,
fadeDesktopInitScreen,
fadeDesktopFiniScreen,
fadeDesktopInitWindow,
fadeDesktopFiniWindow,
fadeDesktopGetDisplayOptions,
fadeDesktopSetDisplayOption,
fadeDesktopGetScreenOptions,
fadeDesktopSetScreenOption,
0,
0,
fdFeatures,
sizeof(fdFeatures) / sizeof(fdFeatures[0]),
BERYL_ABI_INFO,
"beryl-plugins",
"desktop",
0,
0,
True,
};
CompPluginVTable * getCompPluginInfo(void)
{
return &fadeDesktopVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1