/*
* Copyright (c) 2006 Darryll Truchan <moppsy@comcast.net>
*
* 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.
*
*/
/*
* I am sure that this is not the right way to do this.
* Any advice would be appreciated. I'm still a junior GL'er
*
* BUGS
* water doesn't draw on things negative
* neg also doesn't honor an apps initial, non-paintAttrib, opacity
*
* comments still need work.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <beryl.h>
/* defaults */
static char *excludeWinType[] = {
N_("Desktop")
};
#define N_EXCLUDE_WIN_TYPE (sizeof (excludeWinType) / sizeof (excludeWinType[0]))
#define NEG_TOGGLE_KEY_DEFAULT "n"
#define NEG_TOGGLE_MODIFIERS_DEFAULT CompSuperMask
#define NEG_TOGGLE_ALL_KEY_DEFAULT "m"
#define NEG_TOGGLE_ALL_MODIFIERS_DEFAULT CompSuperMask
#define NEG_DISPLAY_OPTION_WINDOW_TOGGLE 0
#define NEG_DISPLAY_OPTION_SCREEN_TOGGLE 1
#define NEG_DISPLAY_OPTION_NUM 2
#define NEG_SCREEN_OPTION_EXCLUDE_NULL_WM_CLASS 0
#define NEG_SCREEN_OPTION_EXCLUDE_WINDOW_TYPE 1
#define NEG_SCREEN_OPTION_EXCLUDE_LIST 2
#define NEG_SCREEN_OPTION_NUM 3
#define NEG_EXCLUDE_NULL_WM_CLASS_DEFAULT FALSE
static int displayPrivateIndex;
typedef struct _NEGDisplay
{
int screenPrivateIndex;
CompOption opt[NEG_DISPLAY_OPTION_NUM]; /* array of display options */
} NEGDisplay;
typedef struct _NEGSCreen
{
int windowPrivateIndex;
CompOption opt[NEG_SCREEN_OPTION_NUM]; /* array of screen options */
DrawWindowTextureProc drawWindowTexture; /* function pointer */
DamageWindowRectProc damageWindowRect; /* function pointer */
Bool isNeg; /* negative screen flag */
unsigned int excludeWMask;
} NEGScreen;
typedef struct _NEGWindow
{
Bool isNeg; /* negative window flag */
} NEGWindow;
#define GET_NEG_DISPLAY(d) ((NEGDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define NEG_DISPLAY(d) NEGDisplay *nd = GET_NEG_DISPLAY (d)
#define GET_NEG_SCREEN(s, nd) ((NEGScreen *) (s)->privates[(nd)->screenPrivateIndex].ptr)
#define NEG_SCREEN(s) NEGScreen *ns = GET_NEG_SCREEN (s, GET_NEG_DISPLAY (s->display))
#define GET_NEG_WINDOW(w, ns) ((NEGWindow *) (w)->privates[(ns)->windowPrivateIndex].ptr)
#define NEG_WINDOW(w) NEGWindow *nw = GET_NEG_WINDOW (w, GET_NEG_SCREEN (w->screen, GET_NEG_DISPLAY (w->screen->display)))
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static void NEGToggle(CompWindow * w)
{
CompOption *o;
int i;
NEG_SCREEN(w->screen);
NEG_WINDOW(w);
/* toggle window negative flag */
nw->isNeg = !nw->isNeg;
/* check exclude list */
if (ns->opt[NEG_SCREEN_OPTION_EXCLUDE_NULL_WM_CLASS].value.b &&
(w->resClass == NULL))
nw->isNeg = FALSE;
if (ns->excludeWMask & w->type)
nw->isNeg = FALSE;
o = &ns->opt[NEG_SCREEN_OPTION_EXCLUDE_LIST];
for (i = 0; i < o->value.list.nValue; i++)
{
if (w->resClass
&& (strcmp(o->value.list.value[i].s, w->resClass) == 0))
nw->isNeg = FALSE;
}
/* cause repainting */
addWindowDamage(w);
}
static void NEGToggleScreen(CompScreen * s)
{
CompWindow *w;
NEG_SCREEN(s);
/* toggle screen negative flag */
ns->isNeg = !ns->isNeg;
/* toggle every window */
for (w = s->windows; w; w = w->next)
if (w)
NEGToggle(w);
}
static Bool
negToggle(CompDisplay * d, CompAction * action, CompActionState state,
CompOption * option, int nOption)
{
CompWindow *w;
Window xid;
xid = getIntOptionNamed(option, nOption, "window", 0);
w = findWindowAtDisplay(d, xid);
if (w)
NEGToggle(w);
return TRUE;
}
static Bool
negToggleAll(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)
NEGToggleScreen(s);
return TRUE;
}
static void
NEGDrawWindowTexture(CompWindow * w,
CompTexture * texture,
const WindowPaintAttrib * attrib, unsigned int mask)
{
int filter;
NEG_SCREEN(w->screen);
NEG_WINDOW(w);
/* PAINT_WINDOW_DECORATION_MASK is set when the decorations are being painted
* I didn't want to paint them negative too
*/
if (nw->isNeg && !(mask & PAINT_WINDOW_DECORATION_MASK))
{
/* this is for the most part taken from paint.c */
/* push the current matrix */
glPushMatrix();
/* we need this to handle windows that are not regular, like during scale */
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
{
glTranslatef(w->attrib.x, w->attrib.y, 0.0f);
glScalef(attrib->xScale, attrib->yScale, 0.0f);
glTranslatef(attrib->xTranslate / attrib->xScale -
w->attrib.x,
attrib->yTranslate / attrib->yScale -
w->attrib.y, 0.0f);
filter = w->screen->filter[WINDOW_TRANS_FILTER];
}
else if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
{
filter = w->screen->filter[SCREEN_TRANS_FILTER];
}
else
{
filter = w->screen->filter[NOTHING_TRANS_FILTER];
}
/* if we can addjust saturation, even if it's just on and off */
if (w->screen->canDoSaturated && attrib->saturation != COLOR)
{
GLfloat constant[4];
/* if the paint mask has this set we want to blend */
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
glEnable(GL_BLEND);
/* enable the texture */
enableTexture(w->screen, texture, filter);
/* texture combiner */
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); /* negate */
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
/* make another texture active */
w->screen->activeTexture(GL_TEXTURE1_ARB);
/* enable that texture */
enableTexture(w->screen, texture, filter);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
/* if we can do saturation that is in between min and max */
if (w->screen->canDoSlightlySaturated && attrib->saturation > 0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
constant[0] = 0.5f + 0.5f * RED_SATURATION_WEIGHT;
constant[1] = 0.5f + 0.5f * GREEN_SATURATION_WEIGHT;
constant[2] = 0.5f + 0.5f * BLUE_SATURATION_WEIGHT;
constant[3] = 1.0;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
/* mack another texture active */
w->screen->activeTexture(GL_TEXTURE2_ARB);
/* enable that texture */
enableTexture(w->screen, texture, filter);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); /* negate */
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
/* color constant */
constant[3] = attrib->saturation / 65535.0f;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
/* if we are not opaque or not fully bright */
if (attrib->opacity < OPAQUE || attrib->brightness != BRIGHT)
{
/* activate a new texture */
w->screen->activeTexture(GL_TEXTURE3_ARB);
/* enable that texture */
enableTexture(w->screen, texture, filter);
/* color constant */
constant[3] = attrib->opacity / 65535.0f;
constant[0] = constant[1] =
constant[2] =
constant[3] * attrib->brightness / 65535.0f;
glTexEnvfv(GL_TEXTURE_ENV,
GL_TEXTURE_ENV_COLOR, constant);
glTexEnvf(GL_TEXTURE_ENV,
GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV,
GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV,
GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
/* draw the window geometry */
(*w->screen->drawWindowGeometry) (w);
/* disable the current texture */
disableTexture(w->screen, texture);
/* set texture mode back to replace */
glTexEnvi(GL_TEXTURE_ENV,
GL_TEXTURE_ENV_MODE, GL_REPLACE);
/* re-activate last texture */
w->screen->activeTexture(GL_TEXTURE2_ARB);
}
else
{
/* fully opaque and bright */
/* draw the window geometry */
(*w->screen->drawWindowGeometry) (w);
}
/* disable the current texture */
disableTexture(w->screen, texture);
/* set the texture mode back to replace */
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/* re-activate last texture */
w->screen->activeTexture(GL_TEXTURE1_ARB);
}
else
{
/* fully saturated or fully unsaturated */
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
/* color constant */
constant[3] = attrib->opacity / 65535.0f;
constant[0] = constant[1] = constant[2] =
constant[3] * attrib->brightness / 65535.0f;
constant[0] =
0.5f + 0.5f * RED_SATURATION_WEIGHT * constant[0];
constant[1] =
0.5f + 0.5f * GREEN_SATURATION_WEIGHT * constant[1];
constant[2] =
0.5f + 0.5f * BLUE_SATURATION_WEIGHT * constant[2];
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
/* draw the window geometry */
(*w->screen->drawWindowGeometry) (w);
}
/* disable the current texture */
disableTexture(w->screen, texture);
/* set the texture mode back to replace */
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/* re-activate last texture */
w->screen->activeTexture(GL_TEXTURE0_ARB);
/* disable that texture */
disableTexture(w->screen, texture);
/* set the default color */
glColor4usv(defaultColor);
/* set screens texture mode back to replace */
screenTexEnvMode(w->screen, GL_REPLACE);
/* if it's a translucent window, disable blending */
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
glDisable(GL_BLEND);
}
else
{
/* no saturation adjustments */
/* enable the current texture */
enableTexture(w->screen, texture, filter);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); /* negate */
/* we are not opaque or fully bright */
if ((mask & PAINT_WINDOW_TRANSLUCENT_MASK)
|| attrib->brightness != BRIGHT)
{
GLfloat constant[4];
/* enable blending */
glEnable(GL_BLEND);
/* color constant */
constant[3] = attrib->opacity / 65535.0f;
constant[0] = constant[3] * attrib->brightness / 65535.0f;
constant[1] = constant[3] * attrib->brightness / 65535.0f;
constant[2] = constant[3] * attrib->brightness / 65535.0f;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); /* negate */
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
/* draw the window geometry */
(*w->screen->drawWindowGeometry) (w);
/* disable blending */
glDisable(GL_BLEND);
}
else
{
/* no adjustments to saturation, brightness or opacity */
/* draw the window geometry */
(*w->screen->drawWindowGeometry) (w);
}
/* disable the current texture */
disableTexture(w->screen, texture);
/* set the screens texture mode back to replace */
screenTexEnvMode(w->screen, GL_REPLACE);
}
/* pop previous matrix */
glPopMatrix();
}
else
{
/* not negative */
UNWRAP(ns, w->screen, drawWindowTexture);
(*w->screen->drawWindowTexture) (w, texture, attrib, mask);
WRAP(ns, w->screen, drawWindowTexture, NEGDrawWindowTexture);
}
}
static Bool NEGDamageWindowRect(CompWindow * w, Bool initial, BoxPtr rect)
{
int status;
NEG_SCREEN(w->screen);
NEG_WINDOW(w);
/* the window is initial when it is being mapped */
if (initial)
{
/* if the screen is negative, negate the new window */
if (ns->isNeg && !nw->isNeg)
NEGToggle(w);
}
UNWRAP(ns, w->screen, damageWindowRect);
status = (*w->screen->damageWindowRect) (w, initial, rect);
WRAP(ns, w->screen, damageWindowRect, NEGDamageWindowRect);
return status;
}
static void NEGDisplayInitOptions(NEGDisplay * nd)
{
CompOption *o;
o = &nd->opt[NEG_DISPLAY_OPTION_WINDOW_TOGGLE];
o->advanced = False;
o->name = "window_toggle";
o->group = N_("Bindings");
o->subGroup = N_("Window bindings");
o->displayHints = "";
o->shortDesc = N_("Toggle Window Negative");
o->longDesc = N_("Toggle Window Negative.");
o->type = CompOptionTypeAction;
o->value.action.initiate = negToggle;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.type = CompBindingTypeKey;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.key.modifiers = NEG_TOGGLE_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(NEG_TOGGLE_KEY_DEFAULT);
o = &nd->opt[NEG_DISPLAY_OPTION_SCREEN_TOGGLE];
o->advanced = False;
o->name = "screen_toggle";
o->group = N_("Bindings");
o->subGroup = N_("Screen bindings");
o->displayHints = "";
o->shortDesc = N_("Toggle Screen Negative");
o->longDesc = N_("Toggle Screen Negative.");
o->type = CompOptionTypeAction;
o->value.action.initiate = negToggleAll;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.type = CompBindingTypeKey;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.key.modifiers = NEG_TOGGLE_ALL_MODIFIERS_DEFAULT;
o->value.action.key.keysym = XStringToKeysym(NEG_TOGGLE_ALL_KEY_DEFAULT);
}
static CompOption *NEGGetDisplayOptions(CompDisplay * display, int *count)
{
if (display)
{
NEG_DISPLAY(display);
*count = NUM_OPTIONS(nd);
return nd->opt;
}
else
{
NEGDisplay *nd = malloc(sizeof(NEGDisplay));
NEGDisplayInitOptions(nd);
*count = NUM_OPTIONS(nd);
return nd->opt;
}
}
static Bool
NEGSetDisplayOption(CompDisplay * display, char *name,
CompOptionValue * value)
{
CompOption *o;
int index;
NEG_DISPLAY(display);
o = compFindOption(nd->opt, NUM_OPTIONS(nd), name, &index);
if (!o)
return FALSE;
switch (index)
{
case NEG_DISPLAY_OPTION_WINDOW_TOGGLE:
case NEG_DISPLAY_OPTION_SCREEN_TOGGLE:
if (setDisplayAction(display, o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static Bool NEGInitDisplay(CompPlugin * p, CompDisplay * d)
{
NEGDisplay *nd;
nd = malloc(sizeof(NEGDisplay));
if (!nd)
return FALSE;
nd->screenPrivateIndex = allocateScreenPrivateIndex(d);
if (nd->screenPrivateIndex < 0)
{
free(nd);
return FALSE;
}
/* initialize the display options */
NEGDisplayInitOptions(nd);
d->privates[displayPrivateIndex].ptr = nd;
return TRUE;
}
static void NEGFiniDisplay(CompPlugin * p, CompDisplay * d)
{
NEG_DISPLAY(d);
freeScreenPrivateIndex(d, nd->screenPrivateIndex);
free(nd);
}
static void NEGScreenInitOptions(NEGScreen * ns)
{
CompOption *o;
unsigned int i;
o = &ns->opt[NEG_SCREEN_OPTION_EXCLUDE_NULL_WM_CLASS];
o->advanced = True;
o->name = "exclude_null_wm_class";
o->group = N_("Exclusions");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Exclude Null WM_CLASS");
o->longDesc = N_("Exclude to Negate if WM_CLASS is Null.");
o->type = CompOptionTypeBool;
o->value.b = NEG_EXCLUDE_NULL_WM_CLASS_DEFAULT;
o = &ns->opt[NEG_SCREEN_OPTION_EXCLUDE_WINDOW_TYPE];
o->advanced = False;
o->name = "exclude_window_types";
o->group = N_("Exclusions");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Exclude Window Types");
o->longDesc = N_("Window Types that should not be Negated.");
o->type = CompOptionTypeList;
o->value.list.type = CompOptionTypeString;
o->value.list.nValue = N_EXCLUDE_WIN_TYPE;
o->value.list.value =
malloc(sizeof(CompOptionValue) * N_EXCLUDE_WIN_TYPE);
for (i = 0; i < N_EXCLUDE_WIN_TYPE; i++)
o->value.list.value[i].s = strdup(excludeWinType[i]);
o->rest.s.string = (char **)windowTypeString;
o->rest.s.nString = nWindowTypeString;
ns->excludeWMask = compWindowTypeMaskFromStringList(&o->value);
o = &ns->opt[NEG_SCREEN_OPTION_EXCLUDE_LIST];
o->advanced = False;
o->name = "exclude_list";
o->group = N_("Exclusions");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("WM_CLASS to Exclude");
o->longDesc = N_("Window Classes which should not be Negated.");
o->type = CompOptionTypeList;
o->value.list.type = CompOptionTypeString;
o->value.list.nValue = 0;
o->value.list.value = 0;
o->rest.s.string = 0;
o->rest.s.nString = 0;
}
static CompOption *NEGGetScreenOptions(CompScreen * screen, int *count)
{
if (screen)
{
NEG_SCREEN(screen);
*count = NUM_OPTIONS(ns);
return ns->opt;
}
else
{
NEGScreen *ns = malloc(sizeof(NEGScreen));
NEGScreenInitOptions(ns);
*count = NUM_OPTIONS(ns);
return ns->opt;
}
}
static Bool
NEGSetScreenOption(CompScreen * screen, char *name, CompOptionValue * value)
{
CompOption *o;
int index;
NEG_SCREEN(screen);
o = compFindOption(ns->opt, NUM_OPTIONS(ns), name, &index);
if (!o)
return FALSE;
switch (index)
{
case NEG_SCREEN_OPTION_EXCLUDE_NULL_WM_CLASS:
if (compSetBoolOption(o, value))
return TRUE;
break;
case NEG_SCREEN_OPTION_EXCLUDE_WINDOW_TYPE:
if (compSetOptionList(o, value))
{
ns->excludeWMask = compWindowTypeMaskFromStringList(&o->value);
return TRUE;
}
break;
case NEG_SCREEN_OPTION_EXCLUDE_LIST:
if (compSetOptionList(o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static Bool NEGInitScreen(CompPlugin * p, CompScreen * s)
{
NEGScreen *ns;
NEG_DISPLAY(s->display);
ns = malloc(sizeof(NEGScreen));
if (!ns)
return FALSE;
ns->windowPrivateIndex = allocateWindowPrivateIndex(s);
if (ns->windowPrivateIndex < 0)
{
free(ns);
return FALSE;
}
/* initialize the screen variables
* you know what happens if you don't
*/
ns->isNeg = FALSE;
/* Initialize the screen options */
NEGScreenInitOptions(ns);
/* add screen actions */
addScreenAction(s,
&nd->opt[NEG_DISPLAY_OPTION_WINDOW_TOGGLE].value.action);
addScreenAction(s,
&nd->opt[NEG_DISPLAY_OPTION_SCREEN_TOGGLE].value.action);
/* wrap overloaded functions */
WRAP(ns, s, drawWindowTexture, NEGDrawWindowTexture);
WRAP(ns, s, damageWindowRect, NEGDamageWindowRect);
s->privates[nd->screenPrivateIndex].ptr = ns;
return TRUE;
}
static void NEGFiniScreen(CompPlugin * p, CompScreen * s)
{
NEG_SCREEN(s);
NEG_DISPLAY(s->display);
freeWindowPrivateIndex(s, ns->windowPrivateIndex);
UNWRAP(ns, s, drawWindowTexture);
UNWRAP(ns, s, damageWindowRect);
removeScreenAction(s,
&nd->opt[NEG_DISPLAY_OPTION_WINDOW_TOGGLE].
value.action);
removeScreenAction(s,
&nd->opt[NEG_DISPLAY_OPTION_SCREEN_TOGGLE].
value.action);
free(ns);
}
static Bool NEGInitWindow(CompPlugin * p, CompWindow * w)
{
NEGWindow *nw;
NEG_SCREEN(w->screen);
nw = malloc(sizeof(NEGWindow));
if (!nw)
return FALSE;
nw->isNeg = FALSE;
w->privates[ns->windowPrivateIndex].ptr = nw;
return TRUE;
}
static void NEGFiniWindow(CompPlugin * p, CompWindow * w)
{
NEG_WINDOW(w);
free(nw);
}
static Bool NEGInit(CompPlugin * p)
{
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void NEGFini(CompPlugin * p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
CompPluginVTable NEGVTable = {
"neg",
N_("Negative"),
N_("Used to set a window or the screen negative"),
NEGInit,
NEGFini,
NEGInitDisplay,
NEGFiniDisplay,
NEGInitScreen,
NEGFiniScreen,
NEGInitWindow,
NEGFiniWindow,
NEGGetDisplayOptions,
NEGSetDisplayOption,
NEGGetScreenOptions,
NEGSetScreenOption,
NULL,
0,
0,
0,
BERYL_ABI_INFO,
"beryl-plugins",
"accessibility",
0,
0,
True,
};
CompPluginVTable *getCompPluginInfo(void)
{
return &NEGVTable;
}
syntax highlighted by Code2HTML, v. 0.9.1