/* * Copyright (c) 2006 Darryll Truchan * * 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 #include #include #include #include #include /* 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; }