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

state.c

/*
 * state plugin for beryl
 *
 * Copyright (C) 2006 John Wall <wall_john@sohu.com> (http://wall_john.blogeden.cn)
 *
 * 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.
 *
 * Authors:
 *  John Wall <wall_john@sohu.com> (http://wall_john.blogeden.cn)
 *  Kristian LyngstĂžl <kristian@beryl-project.org> (Locking).
 */

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>

#include <beryl.h>

#include <glib.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#define _GNU_SOURCE
#include <regex.h>
#include <fnmatch.h>

typedef struct _MwmHints
{
      unsigned long flags;
      unsigned long functions;
      unsigned long decorations;
} MwmHints;


static int displayPrivateIndex;

typedef struct _StateDisplay
{
      int screenPrivateIndex;
      HandleEventProc handleEvent;
      Atom wmPidAtom;
      Atom wmVisibleNameAtom;
      Atom wmNameAtom;
      Atom utf8String;
      Atom nameAtom;
} StateDisplay;

typedef enum _StateOption
{
      STATE_SCREEN_OPTION_OPACITY,
      STATE_SCREEN_OPTION_SATURATION,
      STATE_SCREEN_OPTION_BRIGHTNESS,
      STATE_SCREEN_OPTION_OPACITY_ABS,
      STATE_SCREEN_OPTION_SATURATION_ABS,
      STATE_SCREEN_OPTION_BRIGHTNESS_ABS,
      STATE_SCREEN_OPTION_VIEWPORT,
//    STATE_SCREEN_OPTION_WIDGET,
      STATE_SCREEN_OPTION_POSITION,
      STATE_SCREEN_OPTION_BORDER,
      STATE_SCREEN_OPTION_NOARGB,
      STATE_SCREEN_OPTION_NUM
} StateOption;

#define STATE_SCREEN_OPTION_OPACITY_MAX 100
#define STATE_SCREEN_OPTION_OPACITY_MIN 0

#define STATE_SCREEN_OPTION_BRIGHTNESS_MAX 100
#define STATE_SCREEN_OPTION_BRIGHTNESS_MIN 0

#define STATE_SCREEN_OPTION_SATURATION_MAX 100
#define STATE_SCREEN_OPTION_SATURATION_MIN 0

typedef enum _StateType
{
      NIL, WINDOW, TITLE, PROGRAM, CLASS, NAME, ROLE
} StateType;

typedef struct _StateIntValue
{
      StateType type;
      char *name;
      int value;
      Bool is_regex;
      regex_t match;
} StateIntValue;

typedef struct _StateIntValues
{
      StateIntValue **values;
      int count;
} StateIntValues;

typedef struct _StateScreen
{
      CompOption opt[STATE_SCREEN_OPTION_NUM];
      DamageWindowRectProc damageWindowRect;

      StateIntValues *opacities;
      StateIntValues *brightnesses;
      StateIntValues *saturations;
      StateIntValues *opacitiesabs;
      StateIntValues *brightnessesabs;
      StateIntValues *saturationsabs;
      StateIntValues *viewports;
      StateIntValues *widgets;
      StateIntValues *positions;
      StateIntValues *borders;
      StateIntValues *noargb;

      MwmHints mwmHints;
} StateScreen;

#define GET_STATE_DISPLAY(d)                         \
    ((StateDisplay *) (d)->privates[displayPrivateIndex].ptr)

#define STATE_DISPLAY(d)                     \
    StateDisplay *fd = GET_STATE_DISPLAY (d)

#define GET_STATE_SCREEN(s, fd)                              \
    ((StateScreen *) (s)->privates[(fd)->screenPrivateIndex].ptr)

#define STATE_SCREEN(s)                                     \
    StateScreen *fs = GET_STATE_SCREEN (s, GET_STATE_DISPLAY (s->display))

#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))

static int stateClipValue(int value, int min, int max)
{
      if (value < min)
            value = min;
      if (value > max)
            value = max;
      return value;
}

static StateIntValue *stateParseIntValue(char *s)
{
      StateIntValue *value = NULL;
      char *sep1, *sep2;

      if (s && *s)
      {
            value = (StateIntValue *) malloc(sizeof(StateIntValue));
            value->name = NULL;
            value->is_regex = False;
            if (s[0] == 'w')
                  value->type = WINDOW;
            else if (s[0] == 't')
                  value->type = TITLE;
            else if (s[0] == 'p')
                  value->type = PROGRAM;
            else if (s[0] == 'c')
                  value->type = CLASS;
            else if (s[0] == 'r')
                  value->type = ROLE;
            else if (s[0] == 'n')
                  value->type = NAME;
            else
                  goto err;

            if (strlen(s) < 3)
                  goto err;
            if (s[1] == ':')
            {
                  sep1 = s + 2;
                  sep2 = strchr(sep1, ':');
                  if (!sep2)
                        goto err;

                  value->name = (char *)malloc(sizeof(char) * (sep2 - sep1 + 1));
                  strncpy(value->name, sep1, sep2 - sep1);
                  value->name[sep2 - sep1] = 0;

                  value->value = atoi(sep2 + 1);
            }
            else if (s[1] == '/')
            {
                  //now we have to search the rest of the string until we find a
                  //'/' that's not preceeded by a '\'
                  sep1 = s + 2;
                  sep2 = sep1;
                  while ((sep2 = strchr(sep2, '/')) && sep2[-1] == '\\');
                  if (!sep2)
                        goto err;
                  value->name = (char *)malloc(sizeof(char) * (sep2 - sep1 + 1));
                  strncpy(value->name, sep1, sep2 - sep1);
                  value->name[sep2 - sep1] = 0;
                  value->value = atoi(sep2 + 1);
                  if (regcomp(&value->match, value->name, REG_EXTENDED | REG_NOSUB))
                        goto err;
                  value->is_regex = True;
            }
            return value;
      }
  err:
      if (value)
      {
            if (value->name)
                  free(value->name);
            if (value->is_regex)
                  regfree(&value->match);
            free(value);
      }
      return NULL;
}

static StateIntValues *stateLoadIntValuesFromStringList(CompOptionValue *
                                                                                    value, int min,
                                                                                    int max)
{
      StateIntValue *ivalue;
      StateIntValues *values;
      int i, count = 0;

      if (value->list.nValue > 0)
      {
            values = (StateIntValues *) malloc(sizeof(StateIntValues));
            values->values =
                        (StateIntValue **) malloc(sizeof(StateIntValue *) *
                                                              value->list.nValue);
            for (i = 0; i < value->list.nValue; i++)
            {
                  ivalue = stateParseIntValue(value->list.value[i].s);
                  if (ivalue)
                  {
                        ivalue->value = stateClipValue(ivalue->value, min, max);
                        values->values[count++] = ivalue;
                  }
            }
            if (count == 0)
            {
                  free(values->values);
                  free(values);
                  return NULL;
            }
            else
            {
                  values->count = count;
                  return values;
            }
      }
      return NULL;
}

static void stateFreeIntValues(StateIntValues * values)
{
      int i;

      if (values != NULL)
      {
            for (i = 0; i < values->count; ++i)
            {
                  if (values->values[i]->is_regex)
                        regfree(&values->values[i]->match);
                  free(values->values[i]->name);
                  free(values->values[i]);
            }
            free(values);
      }
}

static void stateScreenInitOptions(StateScreen * fs)
{
      CompOption *o;

      o = &fs->opt[STATE_SCREEN_OPTION_OPACITY];
      o->advanced = False;
      o->name = "opacity";
      o->group = N_("Rules");
      o->subGroup = N_("Window Opacity");
      o->displayHints = "";
      o->shortDesc = N_("Window Opacity");
      o->longDesc = N_("Set Window Opacity by conditions.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_BRIGHTNESS];
      o->advanced = False;
      o->name = "brightness";
      o->group = N_("Rules");
      o->subGroup = N_("Window Brightness");
      o->displayHints = "";
      o->shortDesc = N_("Window Brightness");
      o->longDesc = N_("Set Window Brightness by conditions.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_SATURATION];
      o->advanced = False;
      o->name = "saturation";
      o->group = N_("Rules");
      o->subGroup = N_("Window Saturation");
      o->displayHints = "";
      o->shortDesc = N_("Window Saturation");
      o->longDesc = N_("Set Window Saturation by conditions.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_OPACITY_ABS];
      o->advanced = False;
      o->name = "opacityabs";
      o->group = N_("Rules");
      o->subGroup = N_("Window Opacity");
      o->displayHints = "";
      o->shortDesc = N_("Absoloute Window Opacity");
      o->longDesc = N_("Set Window Opacity by conditions, this "
                               "overrides plugins like Opacify.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_BRIGHTNESS_ABS];
      o->advanced = False;
      o->name = "brightnessabs";
      o->group = N_("Rules");
      o->subGroup = N_("Window Brightness");
      o->displayHints = "";
      o->shortDesc = N_("Absoloute Window Brightness");
      o->longDesc = N_("Set Window Brightness by conditions, this "
                               "overrides plugins like Opacify.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_SATURATION_ABS];
      o->advanced = False;
      o->name = "saturationabs";
      o->group = N_("Rules");
      o->subGroup = N_("Window Saturation");
      o->displayHints = "";
      o->shortDesc = N_("Absoloute Window Saturation");
      o->longDesc = N_("Set Window Saturation by conditions, this "
                               "overrides plugins like Opacify.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_VIEWPORT];
      o->advanced = False;
      o->name = "viewport";
      o->group = N_("Rules");
      o->subGroup = N_("Initial Viewport");
      o->displayHints = "";
      o->shortDesc = N_("Initial Viewport");
      o->longDesc = N_("Set Initial Viewport for windows by conditions.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_POSITION];
      o->advanced = False;
      o->name = "position";
      o->group = N_("Rules");
      o->subGroup = N_("Position");
      o->displayHints = "";
      o->shortDesc = N_("Position");
      o->longDesc =
                  N_("Set the initial window position.");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_BORDER];
      o->advanced = False;
      o->name = "border";
      o->group = N_("Rules");
      o->subGroup = N_("Border");
      o->displayHints = "";
      o->shortDesc = N_("Disable window border");
      o->longDesc = N_("Enable or disable window border");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */

      o = &fs->opt[STATE_SCREEN_OPTION_NOARGB];
      o->advanced = False;
      o->name = "noargb";
      o->group = N_("Rules");
      o->subGroup = N_("Disable ARGB visual");
      o->displayHints = "";
      o->shortDesc = N_("Disable ARGB visual");
      o->longDesc = N_("Enable or disable ARGB visual");
      o->type = CompOptionTypeList;
      o->value.list.type = CompOptionTypeString;
      o->value.list.nValue = 0;
      o->value.list.value = 0;      /* NULL; */
      o->rest.s.string = 0;         /* windowTypeString; */
      o->rest.s.nString = 0;        /* nWindowTypeString; */
}

static CompOption *stateGetScreenOptions(CompScreen * screen, int *count)
{
      if (screen)
      {
            STATE_SCREEN(screen);

            *count = NUM_OPTIONS(fs);
            return fs->opt;
      }
      else
      {
            StateScreen *fs = malloc(sizeof(StateScreen));

            stateScreenInitOptions(fs);
            *count = NUM_OPTIONS(fs);
            return fs->opt;
      }
}


static void stateChangeWindowOpacity(CompWindow * w, int opacity)
{
      opacity = OPAQUE * opacity / 100;
      setDefaultWindowOpacity(w, opacity, PL_PLUGIN_ONE);
}

static void stateChangeWindowBrightness(CompWindow * w, int brightness)
{
      brightness = BRIGHT * brightness / 100;
      setDefaultWindowBrightness(w, brightness, PL_PLUGIN_ONE);
}

static void stateChangeWindowSaturation(CompWindow * w, int saturation)
{
      saturation = COLOR * saturation / 100;
      setDefaultWindowSaturation(w, saturation, PL_PLUGIN_ONE);
}

static unsigned int stateWindowTypeMaskFromString(char *value)
{
      unsigned int mask = 0;

      if (strcasecmp(value, "desktop") == 0)
            mask |= CompWindowTypeDesktopMask;
      else if (strcasecmp(value, "dock") == 0)
            mask |= CompWindowTypeDockMask;
      else if (strcasecmp(value, "toolbar") == 0)
            mask |= CompWindowTypeToolbarMask;
      else if (strcasecmp(value, "menu") == 0)
            mask |= CompWindowTypeMenuMask;
      else if (strcasecmp(value, "utility") == 0)
            mask |= CompWindowTypeUtilMask;
      else if (strcasecmp(value, "splash") == 0)
            mask |= CompWindowTypeSplashMask;
      else if (strcasecmp(value, "dialog") == 0)
            mask |= CompWindowTypeDialogMask;
      else if (strcasecmp(value, "modaldialog") == 0)
            mask |= CompWindowTypeModalDialogMask;
      else if (strcasecmp(value, "normal") == 0)
            mask |= CompWindowTypeNormalMask;
      else if (strcasecmp(value, "fullscreen") == 0)
            mask |= CompWindowTypeFullscreenMask;
      else if (strcasecmp(value, "unknown") == 0)
            mask |= CompWindowTypeUnknownMask;
      else if (strcasecmp(value, "dropdownmenu") == 0)
            mask |= CompWindowTypeDropdownMenuMask;
      else if (strcasecmp(value, "popupmenu") == 0)
            mask |= CompWindowTypePopupMenuMask;
      else if (strcasecmp(value, "tooltip") == 0)
            mask |= CompWindowTypeTooltipMask;
      else if (strcasecmp(value, "notification") == 0)
            mask |= CompWindowTypeNotificationMask;
      else if (strcasecmp(value, "combo") == 0)
            mask |= CompWindowTypeComboMask;
      else if (strcasecmp(value, "dnd") == 0)
            mask |= CompWindowTypeDndMask;

      return mask;
}

static char *stateGetProgramPathFromPid(int pid)
{
      int len;
      char *path;

      if (pid >= 0)
      {
            path = (char *)malloc(sizeof(char) * 256);
            sprintf(path, "/proc/%d/exe", pid);
            if (access(path, F_OK) == 0 && (len = readlink(path, path, 256)) > 0)
            {
                  path[len] = 0;
                  return path;
            }
            free(path);
      }
      return NULL;
}

static Bool stateGetXPropertyCardinal(CompWindow * win, Atom atom, int *val)
{
      Atom type;
      int format;
      unsigned long nitems;
      unsigned long bytes_after;
      unsigned long *num;
      int result;

      *val = 0;

      type = None;
      result = XGetWindowProperty(win->screen->display->display,
                                                win->id,
                                                atom,
                                                0, LONG_MAX,
                                                False, XA_CARDINAL, &type, &format,
                                                &nitems, &bytes_after, (void *)&num);
      if (result != Success)
            return FALSE;

      if (type != XA_CARDINAL)
      {
            XFree(num);
            return FALSE;
      }

      *val = *num;
      XFree(num);
      return TRUE;
}

static char *stateGetXPropertyUtf8(CompWindow * win, Atom atom)
{
      Atom type;
      int format;
      unsigned long nitems;
      unsigned long bytes_after;
      unsigned long *val;
      int result;
      char *retval;
      Atom utf8_string;

      STATE_DISPLAY(win->screen->display);

      utf8_string = fd->utf8String;

      type = None;
      val = NULL;
      result = XGetWindowProperty(win->screen->display->display,
                                                win->id,
                                                atom,
                                                0, LONG_MAX,
                                                False, utf8_string,
                                                &type, &format, &nitems,
                                                &bytes_after, (unsigned char **)&val);

      if (result != Success)
            return NULL;

      if (type != utf8_string || format != 8 || nitems == 0)
      {
            if (val)
                  XFree(val);
            return NULL;
      }


      retval = (char *)malloc(sizeof(char) * (nitems + 1));
      strncpy(retval, (char *)val, nitems);
      retval[nitems] = '\0';

      XFree(val);

      return retval;
}

static char *stateGetXPropertyString(CompWindow * win, Atom atom)
{
      Atom type;
      int format;
      unsigned long nitems;
      unsigned long bytes_after;
      unsigned long *val;
      int result;
      char *retval;
      Atom string;

      string = XInternAtom(win->screen->display->display, "STRING", 0);

      type = None;
      val = NULL;
      result = XGetWindowProperty(win->screen->display->display,
                                                win->id,
                                                atom,
                                                0, LONG_MAX,
                                                False, string,
                                                &type, &format, &nitems,
                                                &bytes_after, (unsigned char **)&val);

      if (result != Success)
            return NULL;

      if (type != string || nitems == 0)
      {
            if (val)
                  XFree(val);
            return NULL;
      }


      retval = (char *)malloc(sizeof(char) * (nitems + 1));
      strncpy(retval, (char *)val, nitems);
      retval[nitems] = '\0';

      XFree(val);

      return retval;
}

static char *stateGetWindowRole(CompWindow * w)
{
      return stateGetXPropertyString(w,
                                                   XInternAtom(w->screen->display->
                                                                     display, "WM_WINDOW_ROLE", 0));
}

static char *stateGetWindowTitle(CompWindow * w)
{
      char *title;

      STATE_DISPLAY(w->screen->display);

      title = stateGetXPropertyUtf8(w, fd->wmVisibleNameAtom);

      if (title == NULL)
            title = stateGetXPropertyUtf8(w, fd->wmNameAtom);

      if (title == NULL)
            title = stateGetXPropertyString(w, fd->nameAtom);

      return title;
}

static int stateGetWindowPid(CompWindow * w)
{
      int val;

      STATE_DISPLAY(w->screen->display);

      if (!stateGetXPropertyCardinal(w, fd->wmPidAtom, &val))
            return -1;
      else
            return val;
}

static char *strchrr(char *chars, char ch)
{
      int pos = -1;
      char *tmp = chars;

      if (chars == NULL)
            return NULL;
      while (*tmp)
      {
            if (*tmp == ch)
                  pos = tmp - chars;
            tmp++;
      }
      if (pos != -1)
            return chars + pos + 1;
      return NULL;
}

static Bool stateMatch(char *match, StateIntValue * value)
{
      if (value->is_regex)
            return regexec(&value->match, match, 0, 0, 0) != REG_NOMATCH;
      else
            return fnmatch(value->name, match, FNM_CASEFOLD) == 0;
}

static signed int
stateGetParamForWindow(CompWindow * w, StateIntValues * params)
{
      signed int ret = -1;
      StateType changed;
      StateType type;
      char *name;
      char *title;
      char *progr;
      char *sname;
      char *role;
      int dret;
      int i;
      unsigned int mask;


      if (!params)
            return -1;
      changed = NIL;
      title = stateGetWindowTitle(w);
      progr = stateGetProgramPathFromPid(stateGetWindowPid(w));

      role = stateGetWindowRole(w);

      sname = strchrr(progr, '/');
      for (i = 0; i < params->count; ++i)
      {
            type = params->values[i]->type;
            name = params->values[i]->name;
            dret = params->values[i]->value;
            if (type == WINDOW)
            {
                  mask = stateWindowTypeMaskFromString(name);
                  if ((w->type & mask) && changed <= WINDOW)
                  {
                        ret = dret;
                        changed = WINDOW;
                  }
            }
            else if (type == TITLE)
            {
                  if (title
                        && stateMatch(title, params->values[i]) && changed <= TITLE)
                  {
                        ret = dret;
                        changed = TITLE;
                  }

            }
            else if (type == PROGRAM)
            {
                  if (progr
                        &&
                        (stateMatch(progr, params->values[i])
                         || stateMatch(sname, params->values[i])))
                  {
                        ret = dret;
                        changed = PROGRAM;
                  }
            }
            else if (type == CLASS)
            {
                  if (w->resClass
                        &&
                        (stateMatch
                         (w->resClass, params->values[i]) && changed <= CLASS))
                  {
                        ret = dret;
                        changed = CLASS;
                  }
            }
            else if (type == ROLE)
            {
                  if (role
                        && stateMatch(role, params->values[i]) && changed <= ROLE)
                  {
                        ret = dret;
                        changed = ROLE;
                  }
            }
            else if (type == NAME)
            {
                  if (w->resName
                        &&
                        (stateMatch
                         (w->resName, params->values[i]) && changed <= NAME))
                  {
                        ret = dret;
                        changed = NAME;
                  }
            }
      }
      if (title)
            free(title);
      if (progr)
            free(progr);
      if (role)
            free(role);

      return ret;
}

static void stateAdjustWindowPaintParams(CompWindow * w)
{
      STATE_SCREEN(w->screen);
      signed int val;

      val = stateGetParamForWindow(w, fs->opacities);
      if (val != -1)
            stateChangeWindowOpacity(w, val);
      val = stateGetParamForWindow(w, fs->saturations);
      if (val != -1)
            stateChangeWindowSaturation(w, val);
      val = stateGetParamForWindow(w, fs->brightnesses);
      if (val != -1)
            stateChangeWindowBrightness(w, val);
      val = stateGetParamForWindow(w, fs->opacitiesabs);
      if (val != -1)
            setWindowOpacity(w, val * OPAQUE / 100, PL_PLUGIN_ONE);
      val = stateGetParamForWindow(w, fs->saturationsabs);
      if (val != -1)
            setWindowSaturation(w, val * COLOR / 100, PL_PLUGIN_ONE);
      val = stateGetParamForWindow(w, fs->brightnessesabs);
      if (val != -1)
            setWindowBrightness(w, val * BRIGHT / 100, PL_PLUGIN_ONE);
}

static void stateResetWindowPaintParams(CompWindow * w)
{
      STATE_SCREEN(w->screen);
      signed int val;

      val = stateGetParamForWindow(w, fs->opacities);
      if (val != -1)
            setWindowBailoutOpacity(w, PL_PLUGIN_ONE);
      val = stateGetParamForWindow(w, fs->saturations);
      if (val != -1)
            setWindowBailoutSaturation(w, PL_PLUGIN_ONE);
      val = stateGetParamForWindow(w, fs->brightnesses);
      if (val != -1)
            setWindowBailoutBrightness(w, PL_PLUGIN_ONE);
      val = stateGetParamForWindow(w, fs->opacitiesabs);
      if (val != -1)
            resetWindowOpacity(w, PL_PLUGIN_ONE);
      val = stateGetParamForWindow(w, fs->saturationsabs);
      if (val != -1)
            resetWindowSaturation(w, PL_PLUGIN_ONE);
      val = stateGetParamForWindow(w, fs->brightnessesabs);
      if (val != -1)
            resetWindowBrightness(w, PL_PLUGIN_ONE);
}

static void stateAdjustAllWindowsPaintParams(CompScreen * screen)
{
      CompWindow *w = screen->windows;

      while (w)
      {
            stateAdjustWindowPaintParams(w);
            w = w->next;
      }
}

static void stateResetAllWindowsPaintParams(CompScreen * s)
{
      CompWindow *w;

      for (w = s->windows; w; w = w->next)
            stateResetWindowPaintParams(w);
}

/*
static void
updateWidgetStatusForWindow (CompWindow * w)
{
    Atom a = XInternAtom (w->screen->display->display, "_BERYL_WIDGET",
                          FALSE);
    STATE_SCREEN (w->screen);
    signed int val = stateGetParamForWindow (w, fs->widgets);
    if (val != -1)
    {
        if (val == 0)
        {
            XDeleteProperty (w->screen->display->display, w->id, a);
        }
        else
        {
            if (w->inShowDesktopMode || w->mapNum ||
                w->attrib.map_state == IsViewable || w->minimized)
            {
                if (w->minimized || w->inShowDesktopMode)
                    unminimizeWindow (w);
                XChangeProperty (w->screen->display->display, w->id, a,
                                 XA_STRING, 8, PropModeReplace,
                                 (unsigned char *)&val, 1);
            }
        }
    }
}

static void
updateWidgetStatus (CompScreen * screen)
{
    CompWindow *w = screen->windows;
    while (w)
    {
        updateWidgetStatusForWindow (w);
        w = w->next;
    }
}
*/

static Bool
stateSetScreenOption(CompScreen * screen, char *name, CompOptionValue * value)
{
      CompOption *o;
      int index;

      STATE_SCREEN(screen);

      o = compFindOption(fs->opt, NUM_OPTIONS(fs), name, &index);
      if (!o)
            return FALSE;

      switch (index)
      {
      case STATE_SCREEN_OPTION_OPACITY:
            if (compSetOptionList(o, value))
            {
                  stateResetAllWindowsPaintParams(screen);
                  stateFreeIntValues(fs->opacities);
                  fs->opacities =
                              stateLoadIntValuesFromStringList
                              (&o->value, STATE_SCREEN_OPTION_OPACITY_MIN,
                               STATE_SCREEN_OPTION_OPACITY_MAX);
                  stateAdjustAllWindowsPaintParams(screen);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_BRIGHTNESS:
            if (compSetOptionList(o, value))
            {
                  stateResetAllWindowsPaintParams(screen);
                  stateFreeIntValues(fs->brightnesses);
                  fs->brightnesses =
                              stateLoadIntValuesFromStringList
                              (&o->value, STATE_SCREEN_OPTION_BRIGHTNESS_MIN,
                               STATE_SCREEN_OPTION_BRIGHTNESS_MAX);
                  stateAdjustAllWindowsPaintParams(screen);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_SATURATION:
            if (compSetOptionList(o, value))
            {
                  stateResetAllWindowsPaintParams(screen);
                  stateFreeIntValues(fs->saturations);
                  fs->saturations =
                              stateLoadIntValuesFromStringList
                              (&o->value, STATE_SCREEN_OPTION_SATURATION_MIN,
                               STATE_SCREEN_OPTION_SATURATION_MAX);
                  stateAdjustAllWindowsPaintParams(screen);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_OPACITY_ABS:
            if (compSetOptionList(o, value))
            {
                  stateResetAllWindowsPaintParams(screen);
                  stateFreeIntValues(fs->opacitiesabs);
                  fs->opacitiesabs =
                              stateLoadIntValuesFromStringList
                              (&o->value, STATE_SCREEN_OPTION_OPACITY_MIN,
                               STATE_SCREEN_OPTION_OPACITY_MAX);
                  stateAdjustAllWindowsPaintParams(screen);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_BRIGHTNESS_ABS:
            if (compSetOptionList(o, value))
            {
                  stateResetAllWindowsPaintParams(screen);
                  stateFreeIntValues(fs->brightnessesabs);
                  fs->brightnessesabs =
                              stateLoadIntValuesFromStringList
                              (&o->value, STATE_SCREEN_OPTION_BRIGHTNESS_MIN,
                               STATE_SCREEN_OPTION_BRIGHTNESS_MAX);
                  stateAdjustAllWindowsPaintParams(screen);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_SATURATION_ABS:
            if (compSetOptionList(o, value))
            {
                  stateResetAllWindowsPaintParams(screen);
                  stateFreeIntValues(fs->saturationsabs);
                  fs->saturationsabs =
                              stateLoadIntValuesFromStringList
                              (&o->value, STATE_SCREEN_OPTION_SATURATION_MIN,
                               STATE_SCREEN_OPTION_SATURATION_MAX);
                  stateAdjustAllWindowsPaintParams(screen);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_VIEWPORT:
            if (compSetOptionList(o, value))
            {
                  stateFreeIntValues(fs->viewports);
                  fs->viewports =
                              stateLoadIntValuesFromStringList
                              (&o->value, 1, (screen->hsize * screen->vsize));
                  return TRUE;
            }
            break;
//    case STATE_SCREEN_OPTION_WIDGET:
//        if (compSetOptionList (o, value))
//        {
//            stateFreeIntValues (fs->widgets);
//            fs->widgets = stateLoadIntValuesFromStringList (&o->value, 1, 2);
//            updateWidgetStatus (screen);
//            return TRUE;
//        }
//        break;
      case STATE_SCREEN_OPTION_POSITION:
            if (compSetOptionList(o, value))
            {
                  stateFreeIntValues(fs->positions);
                  fs->positions =
                              stateLoadIntValuesFromStringList(&o->value, 1, 99);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_BORDER:
            if (compSetOptionList(o, value))
            {
                  stateFreeIntValues(fs->borders);
                  fs->borders = stateLoadIntValuesFromStringList(&o->value, 0, 1);

                  return TRUE;
            }
            break;
      case STATE_SCREEN_OPTION_NOARGB:
            if (compSetOptionList(o, value))
            {
                  stateFreeIntValues(fs->noargb);
                  fs->noargb = stateLoadIntValuesFromStringList(&o->value, 0, 1);

                  return TRUE;
            }
            break;
      default:
            break;
      }

      return FALSE;
}

static Bool stateDamageWindowRect(CompWindow * w, Bool initial, BoxPtr rect)
{
      Bool status;
      Bool wasPlaced;

      STATE_SCREEN(w->screen);

      wasPlaced = w->placed;

      UNWRAP(fs, w->screen, damageWindowRect);
      status = (*w->screen->damageWindowRect) (w, initial, rect);
      WRAP(fs, w->screen, damageWindowRect, stateDamageWindowRect);

      if (initial && !w->attrib.override_redirect && w->placed && !wasPlaced)
      {

            int p = stateGetParamForWindow(w, fs->positions);

            if (p != -1)
            {
                  int h = 0;

                  h = p / 10;
                  p = p % 10;

                  // send window to numbered position
                  XClientMessageEvent xev;

                  xev.type = ClientMessage;
                  xev.window = w->id;
                  xev.message_type =
                              XInternAtom(w->screen->display->display,
                                                "_BERYL_PUT_WINDOW", 0);
                  xev.format = 32;
                  xev.data.l[0] = 0;
                  xev.data.l[1] = 0;
                  xev.data.l[2] = 0;
                  xev.data.l[3] = p;
                  xev.data.l[4] = h;

                  XSendEvent(w->screen->display->display,
                                 w->screen->root, 0, StructureNotifyMask,
                                 (XEvent *) & xev);
                  XSync(w->screen->display->display, FALSE);
            }


            signed int v = stateGetParamForWindow(w, fs->viewports);

            if (v != -1)
            {
                  int vx = v;
                  int vy = 0;

                  /*
                   * Check to see if we are using the plane plugin
                   */
                  CompPlugin *plug;

                  for (plug = getPlugins(); plug; plug = plug->next)
                  {
                        if (strcmp(plug->vTable->name, "plane") == 0)
                        {
                              /* split 1D face value into 2D x and y face */
                              vx = v % w->screen->hsize;
                              vy = v / w->screen->hsize;
                              break;
                        }
                  }

                  //check to see first if the window is already
                  //on the right viewport.
                  int x, y;

                  defaultViewportForWindow(w, &x, &y);
                  if (x != vx || y != vy)
                  {
                        /* TODO
                         * take the shortest path
                         */
                        moveWindow(w,
                                       (vx -
                                          w->screen->x) *
                                       w->screen->width,
                                       (vy -
                                          w->screen->y) * w->screen->height, TRUE, TRUE);
                        syncWindowPosition(w);
                  }
            }
      }
      return status;
}

static void stateHandleEvent(CompDisplay * d, XEvent * event)
{
      CompWindow *w;

      STATE_DISPLAY(d);
      w = NULL;
      switch (event->type)
      {
      case MapNotify:
            w = findWindowAtDisplay(d, event->xmap.window);
            if (w && (!w->placed))
            {
                  stateAdjustWindowPaintParams(w);
                  //updateWidgetStatusForWindow (w);
            }
            break;
      default:
            break;
      }

      UNWRAP(fd, d, handleEvent);
      (*d->handleEvent) (d, event);
      WRAP(fd, d, handleEvent, stateHandleEvent);

      switch (event->type)
      {
      case CreateNotify:
      {
            CompWindow *w = findWindowAtDisplay(d,
                                                                  event->xcreatewindow.window);

            if (w)
            {
                  STATE_SCREEN(w->screen);
                  int b = stateGetParamForWindow(w, fs->borders);

                  if (b != -1)
                  {
                        XChangeProperty(w->screen->
                                                display->display,
                                                w->id,
                                                w->screen->
                                                display->
                                                mwmHintsAtom,
                                                w->screen->
                                                display->
                                                mwmHintsAtom, 8,
                                                PropModeReplace,
                                                (unsigned char *)
                                                &fs->mwmHints, sizeof(fs->mwmHints));
                  }
                  b = stateGetParamForWindow(w, fs->noargb);
                  if (b != -1)
                  {
                        w->alpha = FALSE;
                  }
            }
      }
            break;

      default:
            break;
      }
}

static Bool stateInitDisplay(CompPlugin * p, CompDisplay * d)
{
      StateDisplay *fd;

      fd = malloc(sizeof(StateDisplay));
      if (!fd)
            return FALSE;

      fd->screenPrivateIndex = allocateScreenPrivateIndex(d);
      if (fd->screenPrivateIndex < 0)
      {
            free(fd);
            return FALSE;
      }

      fd->utf8String = XInternAtom(d->display, "UTF8_STRING", 0);
      fd->wmPidAtom = XInternAtom(d->display, "_NET_WM_PID", 0);
      fd->wmNameAtom = XInternAtom(d->display, "_NET_WM_NAME", 0);
      fd->nameAtom = XInternAtom(d->display, "WM_NAME", 0);
      fd->wmVisibleNameAtom =
                  XInternAtom(d->display, "_NET_WM_VISIBLE_NAME", 0);

      WRAP(fd, d, handleEvent, stateHandleEvent);

      d->privates[displayPrivateIndex].ptr = fd;

      return TRUE;
}

static void stateFiniDisplay(CompPlugin * p, CompDisplay * d)
{
      STATE_DISPLAY(d);

      freeScreenPrivateIndex(d, fd->screenPrivateIndex);

      UNWRAP(fd, d, handleEvent);

      free(fd);
}

static Bool stateInitScreen(CompPlugin * p, CompScreen * s)
{
      StateScreen *fs;

      STATE_DISPLAY(s->display);

      fs = malloc(sizeof(StateScreen));
      if (!fs)
            return FALSE;

      stateScreenInitOptions(fs);

      fs->opacities = NULL;
      fs->brightnesses = NULL;
      fs->saturations = NULL;
      fs->opacitiesabs = NULL;
      fs->brightnessesabs = NULL;
      fs->saturationsabs = NULL;
      fs->viewports = NULL;
      fs->widgets = NULL;
      fs->positions = NULL;
      fs->borders = NULL;
      fs->noargb = NULL;

      memset(&fs->mwmHints, 0, sizeof(fs->mwmHints));
      fs->mwmHints.flags = (1 << 1);      // MwmHintsDecorations
      fs->mwmHints.decorations = 0; // MwmDecorNone

      s->privates[fd->screenPrivateIndex].ptr = fs;

      WRAP(fs, s, damageWindowRect, stateDamageWindowRect);

      return TRUE;
}

static void stateFiniScreen(CompPlugin * p, CompScreen * s)
{
      STATE_SCREEN(s);
      stateResetAllWindowsPaintParams(s);

      stateFreeIntValues(fs->opacities);
      fs->opacities = NULL;
      stateFreeIntValues(fs->brightnesses);
      fs->brightnesses = NULL;
      stateFreeIntValues(fs->saturations);
      fs->saturations = NULL;
      stateFreeIntValues(fs->opacitiesabs);
      fs->opacitiesabs = NULL;
      stateFreeIntValues(fs->brightnessesabs);
      fs->brightnessesabs = NULL;
      stateFreeIntValues(fs->saturationsabs);
      fs->saturationsabs = NULL;
      stateFreeIntValues(fs->viewports);
      fs->viewports = NULL;
      stateFreeIntValues(fs->widgets);
      fs->widgets = NULL;
      stateFreeIntValues(fs->positions);
      fs->positions = NULL;
      stateFreeIntValues(fs->borders);
      fs->borders = NULL;
      stateFreeIntValues(fs->noargb);
      fs->noargb = NULL;

      UNWRAP(fs, s, damageWindowRect);

      free(fs);
}

static Bool stateInit(CompPlugin * p)
{
      displayPrivateIndex = allocateDisplayPrivateIndex();
      if (displayPrivateIndex < 0)
            return FALSE;

      return TRUE;
}

static void stateFini(CompPlugin * p)
{
      if (displayPrivateIndex >= 0)
            freeDisplayPrivateIndex(displayPrivateIndex);
}

CompPluginDep stateDeps[] = {
      {CompPluginRuleAfter, "place"}
};

static CompPluginVTable stateVTable = {
      "state",
      N_("Set Window Attribs by various criteria"),
      N_("w = window type, c = window class, t = window title, p = owning program, n = class name, r = class role"),
      stateInit,
      stateFini,
      stateInitDisplay,
      stateFiniDisplay,
      stateInitScreen,
      stateFiniScreen,
      0,                                        /* stateInitWindow,        */
      0,                                        /* stateFiniWindow,        */
      0,                                        /* stateGetDisplayOptions, */
      0,                                        /* stateSetDisplayOption,  */
      stateGetScreenOptions,
      stateSetScreenOption,
      stateDeps,
      sizeof(stateDeps) / sizeof(stateDeps[0]),
      0,
      0,
      BERYL_ABI_INFO,
      "beryl-plugins",
      "wm",
      0,
      0,
      False,
};

CompPluginVTable *getCompPluginInfo(void)
{
      return &stateVTable;
}

Generated by  Doxygen 1.6.0   Back to index