/** * * Compiz fade to desktop plugin * * fadedesktop.c * * Copyright (c) 2006 Robert Carr * 2007 Danny Baumann * * 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 "fadedesktop_options.h" #include #include #include #include typedef enum { FD_STATE_OFF = 0, FD_STATE_OUT, FD_STATE_ON, FD_STATE_IN } FadeDesktopState; typedef struct _FadeDesktopDisplay { int screenPrivateIndex; } FadeDesktopDisplay; typedef struct _FadeDesktopScreen { int windowPrivateIndex; PreparePaintScreenProc preparePaintScreen; DonePaintScreenProc donePaintScreen; PaintWindowProc paintWindow; EnterShowDesktopModeProc enterShowDesktopMode; LeaveShowDesktopModeProc leaveShowDesktopMode; FadeDesktopState state; int fadeTime; } FadeDesktopScreen; typedef struct _FadeDesktopWindow { Bool fading; Bool isHidden; GLushort opacity; } 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 void fadeDesktopActivateEvent (CompScreen *s, Bool activating) { CompOption o[2]; o[0].type = CompOptionTypeInt; o[0].name = "root"; o[0].value.i = s->root; o[1].type = CompOptionTypeBool; o[1].name = "active"; o[1].value.b = activating; (*s->display->handleCompizEvent) (s->display, "fadedesktop", "activate", o, 2); } static Bool isFDWin(CompWindow *w) { if (w->attrib.override_redirect) return FALSE; if (!w->managed) return FALSE; if (!matchEval(fadedesktopGetWindowMatch(w->screen), w)) return FALSE; return TRUE; } static void fadeDesktopPreparePaintScreen(CompScreen *s, int msSinceLastPaint) { FD_SCREEN(s); Bool doFade; fs->fadeTime -= msSinceLastPaint; if (fs->fadeTime < 0) fs->fadeTime = 0; if ((fs->state == FD_STATE_OUT) || (fs->state == FD_STATE_IN)) { CompWindow *w; for (w = s->windows; w; w = w->next) { FD_WINDOW(w); if (fs->state == FD_STATE_OUT) doFade = fw->fading && w->inShowDesktopMode; else doFade = fw->fading && !w->inShowDesktopMode; if (doFade) { fw->opacity = w->opacity * (float)((fs->state == FD_STATE_OUT) ? fs->fadeTime : fadedesktopGetFadetime(s) - fs->fadeTime) / (float)fadedesktopGetFadetime(s); } } } UNWRAP (fs, s, preparePaintScreen); (*s->preparePaintScreen) (s, msSinceLastPaint); WRAP (fs, s, preparePaintScreen, fadeDesktopPreparePaintScreen); } static void fadeDesktopDonePaintScreen(CompScreen *s) { FD_SCREEN(s); if ((fs->state == FD_STATE_OUT) || (fs->state == FD_STATE_IN)) { if (fs->fadeTime <= 0) { CompWindow *w; Bool isStillSD = FALSE; for (w = s->windows; w; w = w->next) { FD_WINDOW(w); if (fw->fading) { if (fs->state == FD_STATE_OUT) { hideWindow(w); fw->isHidden = TRUE; } fw->fading = FALSE; } if (w->inShowDesktopMode) isStillSD = TRUE; } if ((fs->state == FD_STATE_OUT) || isStillSD) fs->state = FD_STATE_ON; else fs->state = FD_STATE_OFF; fadeDesktopActivateEvent (s, FALSE); } else damageScreen(s); } UNWRAP (fs, s, donePaintScreen); (*s->donePaintScreen)(s); WRAP (fs, s, donePaintScreen, fadeDesktopDonePaintScreen); } static Bool fadeDesktopPaintWindow (CompWindow *w, const WindowPaintAttrib *attrib, const CompTransform *transform, Region region, unsigned int mask) { Bool status; CompScreen *s = w->screen; FD_WINDOW(w); FD_SCREEN(s); if (fw->fading || fw->isHidden) { WindowPaintAttrib wAttrib = *attrib; wAttrib.opacity = fw->opacity; UNWRAP (fs, s, paintWindow); status = (*s->paintWindow) (w, &wAttrib, transform, region, mask); WRAP (fs, s, paintWindow, fadeDesktopPaintWindow); } else { UNWRAP (fs, s, paintWindow); status = (*s->paintWindow) (w, attrib, transform, region, mask); WRAP (fs, s, paintWindow, fadeDesktopPaintWindow); } return status; } static void fadeDesktopEnterShowDesktopMode(CompScreen *s) { FD_SCREEN(s); CompWindow *w; if ((fs->state == FD_STATE_OFF) || (fs->state == FD_STATE_IN)) { if (fs->state == FD_STATE_OFF) fadeDesktopActivateEvent (s, TRUE); fs->state = FD_STATE_OUT; fs->fadeTime = fadedesktopGetFadetime(s) - fs->fadeTime; for (w = s->windows; w; w = w->next) { if (isFDWin(w)) { FD_WINDOW(w); fw->fading = TRUE; w->inShowDesktopMode = TRUE; fw->opacity = w->opacity; } } damageScreen(s); } UNWRAP(fs, s, enterShowDesktopMode); (*s->enterShowDesktopMode)(s); WRAP(fs, s, enterShowDesktopMode, fadeDesktopEnterShowDesktopMode); } static void fadeDesktopLeaveShowDesktopMode(CompScreen *s, CompWindow *w) { FD_SCREEN(s); if (fs->state != FD_STATE_OFF) { CompWindow *cw; if (fs->state != FD_STATE_IN) { if (fs->state == FD_STATE_ON) fadeDesktopActivateEvent (s, TRUE); fs->state = FD_STATE_IN; fs->fadeTime = fadedesktopGetFadetime(s) - fs->fadeTime; } for (cw = s->windows; cw; cw = cw->next) { if (w && (w->id != cw->id)) continue; FD_WINDOW(cw); if (fw->isHidden) { cw->inShowDesktopMode = FALSE; showWindow(cw); fw->isHidden = FALSE; fw->fading = TRUE; } else if (fw->fading) { cw->inShowDesktopMode = FALSE; } } damageScreen(s); } UNWRAP (fs, s, leaveShowDesktopMode); (*s->leaveShowDesktopMode)(s, w); WRAP (fs, s, leaveShowDesktopMode, fadeDesktopLeaveShowDesktopMode); } 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; } 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; } fs->state = FD_STATE_OFF; fs->fadeTime = 0; WRAP(fs, s, paintWindow, fadeDesktopPaintWindow); WRAP(fs, s, preparePaintScreen, fadeDesktopPreparePaintScreen); WRAP(fs, s, donePaintScreen, fadeDesktopDonePaintScreen); WRAP(fs, s, enterShowDesktopMode, fadeDesktopEnterShowDesktopMode); WRAP(fs, s, leaveShowDesktopMode, fadeDesktopLeaveShowDesktopMode); s->privates[fd->screenPrivateIndex].ptr = fs; return TRUE; } static void fadeDesktopFiniScreen(CompPlugin *p, CompScreen *s) { FD_SCREEN(s); UNWRAP(fs, s, paintWindow); UNWRAP(fs, s, preparePaintScreen); UNWRAP(fs, s, donePaintScreen); UNWRAP(fs, s, enterShowDesktopMode); UNWRAP(fs, s, leaveShowDesktopMode); 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; fw->fading = FALSE; w->privates[fs->windowPrivateIndex].ptr = fw; return TRUE; } static void fadeDesktopFiniWindow(CompPlugin *p, CompWindow *w) { FD_WINDOW(w); free (fw); } static int fadeDesktopGetVersion(CompPlugin *p, int version) { return ABIVERSION; } static CompPluginVTable fadeDesktopVTable = { "fadedesktop", fadeDesktopGetVersion, 0, fadeDesktopInit, fadeDesktopFini, fadeDesktopInitDisplay, fadeDesktopFiniDisplay, fadeDesktopInitScreen, fadeDesktopFiniScreen, fadeDesktopInitWindow, fadeDesktopFiniWindow, NULL, NULL, NULL, NULL }; CompPluginVTable * getCompPluginInfo(void) { return &fadeDesktopVTable; }