/*
* Copyright © 2005 Novell, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Author: David Reveman <davidr@novell.com>
*/
#include <stdlib.h>
#include <string.h>
#include <beryl.h>
#include <math.h>
#define FADE_SPEED_DEFAULT 7.0f
#define FADE_SPEED_MIN 0.1f
#define FADE_SPEED_MAX 10.0f
#define FADE_SPEED_PRECISION 0.1f
#define URGENT_SPEED_DEFAULT 15
#define URGENT_SPEED_MAX 50
#define URGENT_SPEED_MIN 5
#define URGENT_SPEED_O (fs->opt[FADE_SCREEN_OPTION_URGENT_SPEED].value.i*100)
#define URGENT_COUNT_DEFAULT 5
#define URGENT_COUNT_MIN 0
#define URGENT_COUNT_MAX 15
#define URGENT_COUNT_O fs->opt[FADE_SCREEN_OPTION_URGENT_COUNT].value.i
#define URGENT_CENTER_DEFAULT 70
#define URGENT_CENTER_MIN 0
#define URGENT_CENTER_MAX 100
#define URGENT_CENTER_O (fs->opt[FADE_SCREEN_OPTION_URGENT_CENTER].value.i/100.0)
#define URGENT_SWING_DEFAULT 20
#define URGENT_SWING_MIN 0
#define URGENT_SWING_MAX 100
#define URGENT_SWING_O (fs->opt[FADE_SCREEN_OPTION_URGENT_SWING].value.i/100.0)
#define URGENT_DEFAULT TRUE
#define URGENT_O fs->opt[FADE_SCREEN_OPTION_URGENT].value.b
#define FADE_VISUAL_BELL_DEFAULT FALSE
#define FADE_FULLSCREEN_VISUAL_BELL_DEFAULT FALSE
static int displayPrivateIndex;
typedef struct _FadeDisplay
{
int screenPrivateIndex;
} FadeDisplay;
#define FADE_SCREEN_OPTION_FADE_SPEED 0
#define FADE_SCREEN_OPTION_NUM 1
typedef struct _FadeScreen
{
int windowPrivateIndex;
int fadeTime;
int msec;
CompOption opt[FADE_SCREEN_OPTION_NUM];
PreparePaintScreenProc preparePaintScreen;
PaintWindowProc paintWindow;
} FadeScreen;
typedef struct _FadeWindow
{
GLushort opacity;
GLushort brightness;
GLushort saturation;
int animStep;
int count;
int steps;
} FadeWindow;
/* Steps is in fade window to make sure painting only happens once per step */
#define GET_FADE_DISPLAY(d) \
((FadeDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define FADE_DISPLAY(d) \
FadeDisplay *fd = GET_FADE_DISPLAY (d)
#define GET_FADE_SCREEN(s, fd) \
((FadeScreen *) (s)->privates[(fd)->screenPrivateIndex].ptr)
#define FADE_SCREEN(s) \
FadeScreen *fs = GET_FADE_SCREEN (s, GET_FADE_DISPLAY (s->display))
#define GET_FADE_WINDOW(w, fs) \
((FadeWindow *) (w)->privates[(fs)->windowPrivateIndex].ptr)
#define FADE_WINDOW(w) \
FadeWindow *fw = GET_FADE_WINDOW (w, \
GET_FADE_SCREEN (w->screen, \
GET_FADE_DISPLAY (w->screen->display)))
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static void fadeScreenInitOptions(FadeScreen * fs)
{
CompOption *o;
o = &fs->opt[FADE_SCREEN_OPTION_FADE_SPEED];
o->advanced = False;
o->name = "fade_speed";
o->group = N_("Misc. options");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Fade Speed");
o->longDesc = N_("How fast the windows Fade in and out.");
o->type = CompOptionTypeFloat;
o->value.f = FADE_SPEED_DEFAULT;
o->rest.f.min = FADE_SPEED_MIN;
o->rest.f.max = FADE_SPEED_MAX;
o->rest.f.precision = FADE_SPEED_PRECISION;
}
static CompOption *fadeGetScreenOptions(CompScreen * screen, int *count)
{
if (screen)
{
FADE_SCREEN(screen);
*count = NUM_OPTIONS(fs);
return fs->opt;
}
else
{
FadeScreen *fs = malloc(sizeof(FadeScreen));
fadeScreenInitOptions(fs);
*count = NUM_OPTIONS(fs);
return fs->opt;
}
}
static Bool
fadeSetScreenOption(CompScreen * screen, char *name, CompOptionValue * value)
{
CompOption *o;
int index;
FADE_SCREEN(screen);
o = compFindOption(fs->opt, NUM_OPTIONS(fs), name, &index);
if (!o)
return FALSE;
switch (index)
{
case FADE_SCREEN_OPTION_FADE_SPEED:
if (compSetFloatOption(o, value))
{
fs->fadeTime = 1000.0f / o->value.f;
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
static void fadePreparePaintScreen(CompScreen * s, int msSinceLastPaint)
{
CompWindow *w;
int steps;
FADE_SCREEN(s);
fs->msec = msSinceLastPaint;
steps = (msSinceLastPaint * OPAQUE) / fs->fadeTime;
if (steps < 12)
steps = 12;
for (w = s->windows; w; w = w->next)
{
GET_FADE_WINDOW(w, fs)->steps = steps;
}
UNWRAP(fs, s, preparePaintScreen);
(*s->preparePaintScreen) (s, msSinceLastPaint);
WRAP(fs, s, preparePaintScreen, fadePreparePaintScreen);
}
static Bool
fadePaintWindow(CompWindow * w,
const WindowPaintAttrib * attrib,
Region region, unsigned int mask)
{
CompScreen *s = w->screen;
Bool status;
FADE_SCREEN(s);
FADE_WINDOW(w);
if (!w->screen->canDoSlightlySaturated)
fw->saturation = attrib->saturation;
if (fw->opacity != attrib->opacity ||
fw->brightness != attrib->brightness ||
fw->saturation != attrib->saturation)
{
GLint opacity;
GLint brightness;
GLint saturation;
opacity = fw->opacity;
if (attrib->opacity > fw->opacity)
{
opacity = fw->opacity + fw->steps;
if (opacity > attrib->opacity)
opacity = attrib->opacity;
}
else if (attrib->opacity < fw->opacity)
{
opacity = fw->opacity - fw->steps;
if (opacity < attrib->opacity)
opacity = attrib->opacity;
}
brightness = fw->brightness;
if (attrib->brightness > fw->brightness)
{
brightness = fw->brightness + (fw->steps / 12);
if (brightness > attrib->brightness)
brightness = attrib->brightness;
}
else if (attrib->brightness < fw->brightness)
{
brightness = fw->brightness - (fw->steps / 12);
if (brightness < attrib->brightness)
brightness = attrib->brightness;
}
saturation = fw->saturation;
if (attrib->saturation > fw->saturation)
{
saturation = fw->saturation + (fw->steps / 6);
if (saturation > attrib->saturation)
saturation = attrib->saturation;
}
else if (attrib->saturation < fw->saturation)
{
saturation = fw->saturation - (fw->steps / 6);
if (saturation < attrib->saturation)
saturation = attrib->saturation;
}
WindowPaintAttrib fAttrib = *attrib;
fAttrib.opacity = opacity;
fAttrib.brightness = brightness;
fAttrib.saturation = saturation;
UNWRAP(fs, s, paintWindow);
status = (*s->paintWindow) (w, &fAttrib, region, mask);
WRAP(fs, s, paintWindow, fadePaintWindow);
fw->opacity = opacity;
fw->brightness = brightness;
fw->saturation = saturation;
fw->steps = 0;
if (opacity != attrib->opacity ||
brightness != attrib->brightness ||
saturation != attrib->saturation)
addWindowDamage(w);
}
else
{
UNWRAP(fs, s, paintWindow);
status = (*s->paintWindow) (w, attrib, region, mask);
WRAP(fs, s, paintWindow, fadePaintWindow);
}
return status;
}
static Bool fadeInitDisplay(CompPlugin * p, CompDisplay * d)
{
FadeDisplay *fd;
fd = malloc(sizeof(FadeDisplay));
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 fadeFiniDisplay(CompPlugin * p, CompDisplay * d)
{
FADE_DISPLAY(d);
freeScreenPrivateIndex(d, fd->screenPrivateIndex);
free(fd);
}
static Bool fadeInitScreen(CompPlugin * p, CompScreen * s)
{
FadeScreen *fs;
FADE_DISPLAY(s->display);
fs = malloc(sizeof(FadeScreen));
if (!fs)
return FALSE;
fs->windowPrivateIndex = allocateWindowPrivateIndex(s);
if (fs->windowPrivateIndex < 0)
{
free(fs);
return FALSE;
}
fs->fadeTime = 1000.0f / FADE_SPEED_DEFAULT;
fadeScreenInitOptions(fs);
WRAP(fs, s, preparePaintScreen, fadePreparePaintScreen);
WRAP(fs, s, paintWindow, fadePaintWindow);
s->privates[fd->screenPrivateIndex].ptr = fs;
return TRUE;
}
static void fadeFiniScreen(CompPlugin * p, CompScreen * s)
{
FADE_SCREEN(s);
freeWindowPrivateIndex(s, fs->windowPrivateIndex);
UNWRAP(fs, s, preparePaintScreen);
UNWRAP(fs, s, paintWindow);
free(fs);
}
static Bool fadeInitWindow(CompPlugin * p, CompWindow * w)
{
FadeWindow *fw;
FADE_SCREEN(w->screen);
fw = malloc(sizeof(FadeWindow));
if (!fw)
return FALSE;
fw->opacity = w->paint.opacity;
fw->brightness = w->paint.brightness;
fw->saturation = w->paint.saturation;
w->privates[fs->windowPrivateIndex].ptr = fw;
return TRUE;
}
static void fadeFiniWindow(CompPlugin * p, CompWindow * w)
{
FADE_WINDOW(w);
free(fw);
}
static Bool fadeInit(CompPlugin * p)
{
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void fadeFini(CompPlugin * p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
CompPluginDep fadeDeps[] = {
{CompPluginRuleAfter, "animation"}
,
{CompPluginRuleAfter, "decoration"}
,
{CompPluginRuleAfter, "wobbly"}
,
};
static CompPluginVTable fadeVTable = {
"fade",
N_("Fading Windows"),
N_("Fade in windows when mapped and fade out windows when unmapped"),
fadeInit,
fadeFini,
fadeInitDisplay,
fadeFiniDisplay,
fadeInitScreen,
fadeFiniScreen,
fadeInitWindow,
fadeFiniWindow,
0, /* GetDisplayOptions */
0, /* SetDisplayOption */
fadeGetScreenOptions,
fadeSetScreenOption,
fadeDeps,
sizeof(fadeDeps) / sizeof(fadeDeps[0]),
0,
0,
BERYL_ABI_INFO,
"beryl-plugins",
"effects",
0,
0,
True,
};
CompPluginVTable *getCompPluginInfo(void)
{
return &fadeVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1