/*
* 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;
}
syntax highlighted by Code2HTML, v. 0.9.1