/** * * Beryl fade to desktop plugin * * fadedesktop.c * * Copyright (c) 2006 Robert Carr * * 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 #include #include #include #include #include #include #include #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 { PreparePaintScreenProc preparePaintScreen; DonePaintScreenProc donePaintScreen; CompOption opt[FD_SCREEN_OPTION_NUM]; Bool showingDesktop; Bool reverting; } FadeDesktopScreen; #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)) 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) { if (w->state & CompWindowStateOffscreenMask) { moveWindowOnscreen(w); } } } 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) { moveWindowOffscreen(w); } } 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; 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); free (fs); } #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, 0, 0, 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; }