Logo Search packages:      
Sourcecode: beryl-plugins version File versions

neg.c

/*
 * 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;
}

Generated by  Doxygen 1.6.0   Back to index