/* * state plugin for beryl * * Copyright (C) 2006 John Wall (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 (http://wall_john.blogeden.cn) * Kristian Lyngstøl (Locking). */ #include #include #include #include #include #include #include #include #include #include #define _GNU_SOURCE #include #include 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; }