From edcd412ca1d63042d3598af9eae4f6be62fe039a Mon Sep 17 00:00:00 2001 From: Bellegarde Cedric Date: Sat, 21 Apr 2007 15:31:09 +0200 Subject: Initial import --- Makefile | 177 +++++++++++ winrules.c | 918 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ winrules.schema | 200 ++++++++++++ 3 files changed, 1295 insertions(+) create mode 100644 Makefile create mode 100644 winrules.c create mode 100644 winrules.schema diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2dcdf8c --- /dev/null +++ b/Makefile @@ -0,0 +1,177 @@ +## +# +# Compiz plugin Makefile +# +# Copyright : (C) 2006 by Dennis Kasprzyk +# E-mail : dennis.kasprzyk@rwth-aachen.de +# +# +# 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. +# +## + +DESTDIR = $(HOME)/.compiz/plugins +PLUGIN = winrules +SHADER = yes + +BUILDDIR = build + +CC = gcc +LIBTOOL = libtool +INSTALL = install + +CGC = /usr/bin/cgc + +#CFLAGS = -g -Wall `pkg-config --cflags x11 compiz` +CFLAGS = -g -Wall -DGL_DEBUG `pkg-config --cflags x11 compiz` +LDFLAGS = `pkg-config --libs x11 ` + +vert-shaders := $(patsubst %.vcg,%.vert,$(shell find -name '*.vcg' 2> /dev/null | sed -e 's/^.\///')) +frag-shaders := $(patsubst %.fcg,%.frag,$(shell find -name '*.fcg' 2> /dev/null | sed -e 's/^.\///')) + +shader_files := $(shell find -name '*.vcg' 2> /dev/null | sed -e 's/^.\///') +shader_files += $(shell find -name '*.fcg' 2> /dev/null | sed -e 's/^.\///') + +headers := $(shell find -name '$(PLUGIN)*.h' 2> /dev/null | sed -e 's/^.\///') +headers := $(filter-out $(PLUGIN)_shader.h,$(headers)) + +shader_header := $(shell if [ -x $(CGC) -a '$(SHADER)' == 'yes' ]; then echo "$(PLUGIN)_shader.h"; fi ) + + +shaders := $(addprefix $(BUILDDIR)/,$(vert-shaders)) +shaders += $(addprefix $(BUILDDIR)/,$(frag-shaders)) + +color := $(shell if [ $$TERM = "dumb" ]; then echo "no"; else echo "yes"; fi) + +.PHONY: $(BUILDDIR)/compiz_$(PLUGIN).csm + +all: $(BUILDDIR) $(shader_header) $(BUILDDIR)/lib$(PLUGIN).la + +$(BUILDDIR) : + @mkdir $(BUILDDIR) + +$(BUILDDIR)/lib$(PLUGIN).lo: $(PLUGIN).c $(headers) $(shader_header) + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5mcompiling \033[0;1;37m: \033[0;32m$< \033[0;1;37m-> \033[0;31m$@\033[0m"; \ + else \ + echo "compiling : $< -> $@"; \ + fi + @$(LIBTOOL) --quiet --mode=compile $(CC) $(CFLAGS) -c -o $@ $< + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \ + fi + +$(BUILDDIR)/lib$(PLUGIN).la: $(BUILDDIR)/lib$(PLUGIN).lo + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5mlinking \033[0;1;37m: \033[0;32m$< \033[0;1;37m-> \033[0;31m$@\033[0m"; \ + else \ + echo "linking : $< -> $@"; \ + fi + @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) -rpath $(DESTDIR) -o $@ $< + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0mlinking : \033[34m$< -> $@\033[0m"; \ + fi + +install: all + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5minstall \033[0;1;37m: \033[0;31m$(DESTDIR)/lib$(PLUGIN).so\033[0m"; \ + else \ + echo "install : $(DESTDIR)/lib$(PLUGIN).so"; \ + fi + @mkdir -p $(DESTDIR) + @$(INSTALL) $(BUILDDIR)/.libs/lib$(PLUGIN).so $(DESTDIR)/lib$(PLUGIN).so + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0minstall : \033[34m$(DESTDIR)/lib$(PLUGIN).so\033[0m"; \ + fi + +clean: + rm -rf $(BUILDDIR) + +csm: $(BUILDDIR) $(BUILDDIR)/compiz_$(PLUGIN).csm + + +csm-install: csm + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5minstall \033[0;1;37m: \033[0;31m$(DESTDIR)/compiz_$(PLUGIN).csm\033[0m"; \ + else \ + echo "install : $(DESTDIR)/lib$(PLUGIN).so"; \ + fi + @mkdir -p $(DESTDIR) + @$(INSTALL) $(BUILDDIR)/compiz_$(PLUGIN).csm $(DESTDIR)/compiz_$(PLUGIN).csm + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0minstall : \033[34m$(DESTDIR)/compiz_$(PLUGIN).csm\033[0m"; \ + fi + +$(BUILDDIR)/compiz_$(PLUGIN).csm: + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5mcreating \033[0;1;37m: \033[0;31m$(DESTDIR)/compiz_$(PLUGIN).csm\033[0m"; \ + else \ + echo "creating : $(DESTDIR)/compiz_$(PLUGIN).csm"; \ + fi + @COMPIZ_SCHEMA_PLUGINS="$(PLUGIN)" COMPIZ_SCHEMA_FILE="$(BUILDDIR)/compiz_$(PLUGIN).csm" compiz --replace $(PLUGIN) csm-dump &> /dev/null + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0mcreating : \033[34m$(DESTDIR)/compiz_$(PLUGIN).csm\033[0m"; \ + fi + +$(BUILDDIR)/%.vert: %.vcg + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5mcompiling \033[0;1;37m: \033[0;32m$< \033[0;1;37m-> \033[0;31m$@\033[0m"; \ + else \ + echo "compiling : $< -> $@"; \ + fi + @$(CGC) -unroll all -quiet -fastmath -fastprecision -profile arbvp1 -o $@ $< + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \ + fi + +$(BUILDDIR)/%.frag: %.fcg + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5mcompiling \033[0;1;37m: \033[0;32m$< \033[0;1;37m-> \033[0;31m$@\033[0m"; \ + else \ + echo "compiling : $< -> $@"; \ + fi + @$(CGC) -unroll all -quiet -fastmath -fastprecision -profile arbfp1 -o $@ $< + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \ + fi + + +$(PLUGIN)_shader.h: $(shaders) + @if [ '$(color)' != 'no' ]; then \ + echo -n -e "\033[0;1;5mcreating \033[0;1;37m: \033[0;31m$@\033[0m"; \ + else \ + echo "creating : $@"; \ + fi + @echo "/**" > $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " *" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " * This file is autogenerated from :" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " * $(shader_files)" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " *" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " * This program is distributed in the hope that it will be useful," >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " * but WITHOUT ANY WARRANTY; without even the implied warranty of" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " * GNU General Public License for more details." >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " *" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo " **/" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo "#ifndef $(PLUGIN)_SHADER_H" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo "#define $(PLUGIN)_SHADER_H" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @for i in $(shaders); do \ + echo >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp; \ + echo "static const char* `basename $$i | sed -s 's/\..*$$//'` = ">> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp; \ + cat $$i | grep -v "^#" | sed -e 's/^/\t"/' | sed -e 's/$$/\\n"/' >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp; \ + echo ";" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp; \ + done + @echo >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @echo "#endif" >> $(BUILDDIR)/$(PLUGIN)_shader.h.tmp + @cp $(BUILDDIR)/$(PLUGIN)_shader.h.tmp $(PLUGIN)_shader.h + @if [ '$(color)' != 'no' ]; then \ + echo -e "\r\033[0mcreating : \033[34m$@\033[0m"; \ + fi diff --git a/winrules.c b/winrules.c new file mode 100644 index 0000000..019cf3f --- /dev/null +++ b/winrules.c @@ -0,0 +1,918 @@ +/* + * winrules plugins for compiz + * + * Copyright (C) 2007 Bellegarde Cedric (gnumdk (at) gmail.com) + * 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. + */ + +#include +#include +#include + +#include + +#define WINRULES_TARGET_WINDOWS (CompWindowTypeNormalMask | \ + CompWindowTypeDialogMask | \ + CompWindowTypeModalDialogMask |\ + CompWindowTypeFullscreenMask | \ + CompWindowTypeUnknownMask) + + +#define WINRULES_SCREEN_OPTION_SKIPTASKBAR_MATCH 0 +#define WINRULES_SCREEN_OPTION_SKIPPAGER_MATCH 1 +#define WINRULES_SCREEN_OPTION_ABOVE_MATCH 2 +#define WINRULES_SCREEN_OPTION_BELOW_MATCH 3 +#define WINRULES_SCREEN_OPTION_STICKY_MATCH 4 +#define WINRULES_SCREEN_OPTION_FULLSCREEN_MATCH 5 +#define WINRULES_SCREEN_OPTION_WIDGET_MATCH 6 +#define WINRULES_SCREEN_OPTION_MOVE_MATCH 7 +#define WINRULES_SCREEN_OPTION_RESIZE_MATCH 8 +#define WINRULES_SCREEN_OPTION_MINIMIZE_MATCH 9 +#define WINRULES_SCREEN_OPTION_MAXIMIZE_MATCH 10 +#define WINRULES_SCREEN_OPTION_CLOSE_MATCH 11 +#define WINRULES_SCREEN_OPTION_NOFOCUS_MATCH 12 +#define WINRULES_SCREEN_OPTION_NUM 13 + +static int displayPrivateIndex; + +typedef struct _WinrulesWindow { + + unsigned int allowedActions; + + /* only remove if set by us*/ + Bool shouldRemoveSkipTaskbar; + Bool shouldRemoveSkipPager; + Bool shouldRemoveAbove; + Bool shouldRemoveBelow; + Bool shouldRemoveSticky; + Bool shouldRemoveFullscreen; + Bool shouldRemoveNofocus; + Bool shouldRemoveWidget; + + Bool firstMap; +} WinrulesWindow; + +typedef struct _WinrulesDisplay { + int screenPrivateIndex; + HandleEventProc handleEvent; +} WinrulesDisplay; + +typedef struct _WinrulesScreen { + int windowPrivateIndex; + GetAllowedActionsForWindowProc getAllowedActionsForWindow; + CompOption opt[WINRULES_SCREEN_OPTION_NUM]; +} WinrulesScreen; + +#define GET_WINRULES_DISPLAY(d) \ + ((WinrulesDisplay *) (d)->privates[displayPrivateIndex].ptr) + +#define WINRULES_DISPLAY(d) \ + WinrulesDisplay *wd = GET_WINRULES_DISPLAY (d) + +#define GET_WINRULES_SCREEN(s, wd) \ + ((WinrulesScreen *) (s)->privates[(wd)->screenPrivateIndex].ptr) + +#define WINRULES_SCREEN(s) \ + WinrulesScreen *ws = GET_WINRULES_SCREEN (s, GET_WINRULES_DISPLAY (s->display)) + +#define GET_WINRULES_WINDOW(w, ws) \ + ((WinrulesWindow *) (w)->privates[(ws)->windowPrivateIndex].ptr) + +#define WINRULES_WINDOW(w) \ + WinrulesWindow *ww = GET_WINRULES_WINDOW (w, \ + GET_WINRULES_SCREEN (w->screen, \ + GET_WINRULES_DISPLAY (w->screen->display))) + +#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption)) + + +static void +winrulesSetProtocols (CompDisplay *display, + unsigned int protocols, + Window id) +{ + Atom *protocol = NULL; + int count = 0; + + if (protocols & CompWindowProtocolDeleteMask) + { + protocol = realloc (protocol, (count + 1) * sizeof(Atom)); + protocol[count++] = display->wmDeleteWindowAtom; + } + if (protocols & CompWindowProtocolTakeFocusMask) + { + protocol = realloc (protocol, (count + 1) * sizeof(Atom)); + protocol[count++] = display->wmTakeFocusAtom; + } + if (protocols & CompWindowProtocolPingMask) + { + protocol = realloc (protocol, (count + 1) * sizeof(Atom)); + protocol[count++] = display->wmPingAtom; + } + if (protocols & CompWindowProtocolSyncRequestMask) + { + protocol = realloc (protocol, (count + 1) * sizeof(Atom)); + protocol[count] = display->wmSyncRequestAtom; + } + XSetWMProtocols (display->display, + id, + protocol, + count); + + XFree (protocol); +} + +/* FIXME? Directly set inputHint, not a problem for now */ +static void +winrulesSetNoFocus (CompWindow *w, + int optNum, + Bool *shouldRemove) +{ + Bool protocolRemoved = FALSE; + + WINRULES_SCREEN (w->screen); + + if (matchEval (&ws->opt[optNum].value.match, w)) + { + w->protocols &= ~CompWindowProtocolTakeFocusMask; + w->inputHint = FALSE; + protocolRemoved = TRUE; + } + else if (*shouldRemove) + { + w->protocols |= CompWindowProtocolTakeFocusMask; + w->inputHint = TRUE; + } + + if (protocolRemoved || *shouldRemove) + { + winrulesSetProtocols (w->screen->display, + w->protocols, + w->id); + + *shouldRemove = protocolRemoved; + } +} + +static void +winrulesUpdateState (CompWindow *w, + int optNum, + int mask, + Bool *shouldRemove) +{ + Bool stateRemoved = FALSE; + + WINRULES_SCREEN (w->screen); + + if (matchEval (&ws->opt[optNum].value.match, w)) + { + w->state |= mask; + stateRemoved = TRUE; + } + else if (*shouldRemove) + w->state &= ~mask; + + if (stateRemoved || shouldRemove) + { + changeWindowState (w, w->state); + *shouldRemove = stateRemoved; + } +} + +static void +winrulesUpdateWidget (CompWindow *w) +{ + Atom compizWidget = XInternAtom (w->screen->display->display, + "_COMPIZ_WIDGET", + FALSE); + + WINRULES_SCREEN (w->screen); + WINRULES_WINDOW (w); + + if (matchEval + (&ws->opt[WINRULES_SCREEN_OPTION_WIDGET_MATCH].value.match, w)) + { + 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, compizWidget, + XA_STRING, 8, PropModeReplace, + (unsigned char *)(int[]){-2}, 1); + ww->shouldRemoveWidget = TRUE; + } + } + else if (ww->shouldRemoveWidget) + { + XDeleteProperty (w->screen->display->display, w->id, compizWidget); + ww->shouldRemoveWidget = FALSE; + } +} + +static void +winrulesSetAllowedActions (CompWindow *w, + int optNum, + int action) +{ + WINRULES_SCREEN (w->screen); + WINRULES_WINDOW (w); + + if (matchEval (&ws->opt[optNum].value.match, w)) + ww->allowedActions &= ~action; + else if ( !(ww->allowedActions & action)) + ww->allowedActions |= action; + + recalcWindowActions (w); +} + +static void +winrulesScreenInitOptions (WinrulesScreen *ws) +{ + CompOption *o; + + o = &ws->opt[WINRULES_SCREEN_OPTION_SKIPTASKBAR_MATCH]; + o->name = "skiptaskbar_match"; + o->shortDesc = N_("Skip taskbar"); + o->longDesc = N_("Don't show application in taskbar"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_SKIPPAGER_MATCH]; + o->name = "skippager_match"; + o->shortDesc = N_("Skip pager"); + o->longDesc = N_("Don't show application in pager"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_ABOVE_MATCH]; + o->name = "above_match"; + o->shortDesc = N_("Above"); + o->longDesc = N_("Above others windows"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_BELOW_MATCH]; + o->name = "below_match"; + o->shortDesc = N_("Below"); + o->longDesc = N_("Below others windows"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_STICKY_MATCH]; + o->name = "sticky_match"; + o->shortDesc = N_("Sticky"); + o->longDesc = N_("Sticky windows"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_FULLSCREEN_MATCH]; + o->name = "fullscreen_match"; + o->shortDesc = N_("Fullscreen"); + o->longDesc = N_("Fullscreen windows"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_MOVE_MATCH]; + o->name = "no_move_match"; + o->shortDesc = N_("Non movable windows"); + o->longDesc = N_("Set window as non movable"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_RESIZE_MATCH]; + o->name = "no_resize_match"; + o->shortDesc = N_("Non resizable windows"); + o->longDesc = N_("Set window as non resizable"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_MINIMIZE_MATCH]; + o->name = "no_minimize_match"; + o->shortDesc = N_("Non minimizable windows"); + o->longDesc = N_("Set window as non minimizable"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_MAXIMIZE_MATCH]; + o->name = "no_maximize_match"; + o->shortDesc = N_("Non maximizable windows"); + o->longDesc = N_("Set window as non maximizable"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_CLOSE_MATCH]; + o->name = "no_close_match"; + o->shortDesc = N_("Non closable windows"); + o->longDesc = N_("Set window as non closable"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_NOFOCUS_MATCH]; + o->name = "no_focus_match"; + o->shortDesc = N_("No focus"); + o->longDesc = N_("Windows will not have focus"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); + + o = &ws->opt[WINRULES_SCREEN_OPTION_WIDGET_MATCH]; + o->name = "widget_match"; + o->shortDesc = N_("Widget"); + o->longDesc = N_("Set window as widget"); + o->type = CompOptionTypeMatch; + matchInit (&o->value.match); + matchAddFromString (&o->value.match, ""); +} + +static CompOption * +winrulesGetScreenOptions (CompPlugin *plugin, + CompScreen *screen, + int *count) +{ + WINRULES_SCREEN (screen); + + *count = NUM_OPTIONS (ws); + return ws->opt; +} + +static Bool +winrulesSetScreenOption (CompPlugin *plugin, + CompScreen *screen, + char *name, + CompOptionValue *value) +{ + CompOption *o; + CompWindow *w; + int index; + + WINRULES_SCREEN (screen); + + o = compFindOption (ws->opt, NUM_OPTIONS (ws), name, &index); + if (!o) + return FALSE; + + switch (index) + { + case WINRULES_SCREEN_OPTION_SKIPTASKBAR_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + WINRULES_WINDOW (w); + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_SKIPTASKBAR_MATCH, + CompWindowStateSkipTaskbarMask, + &ww->shouldRemoveSkipTaskbar); + } + + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_SKIPPAGER_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + WINRULES_WINDOW (w); + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_SKIPPAGER_MATCH, + CompWindowStateSkipPagerMask, + &ww->shouldRemoveSkipPager); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_ABOVE_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + WINRULES_WINDOW (w); + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_ABOVE_MATCH, + CompWindowStateAboveMask, + &ww->shouldRemoveAbove); + if (ww->shouldRemoveAbove) + raiseWindow (w); + + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_BELOW_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + WINRULES_WINDOW (w); + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_BELOW_MATCH, + CompWindowStateBelowMask, + &ww->shouldRemoveBelow); + if (ww->shouldRemoveBelow) + lowerWindow (w); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_STICKY_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + WINRULES_WINDOW (w); + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_STICKY_MATCH, + CompWindowStateStickyMask, + &ww->shouldRemoveSticky); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_FULLSCREEN_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + WINRULES_WINDOW (w); + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_FULLSCREEN_MATCH, + CompWindowStateFullscreenMask, + &ww->shouldRemoveFullscreen); + if (ww->shouldRemoveFullscreen) + maximizeWindow (w, MAXIMIZE_STATE); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_MOVE_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_MOVE_MATCH, + CompWindowActionMoveMask); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_RESIZE_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_RESIZE_MATCH, + CompWindowActionResizeMask); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_MINIMIZE_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_MINIMIZE_MATCH, + CompWindowActionMinimizeMask); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_MAXIMIZE_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_MAXIMIZE_MATCH, + CompWindowActionMaximizeVertMask| + CompWindowActionMaximizeHorzMask); + } + return TRUE; + } + break; + + case WINRULES_SCREEN_OPTION_CLOSE_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_CLOSE_MATCH, + CompWindowActionCloseMask); + } + return TRUE; + } + break; + case WINRULES_SCREEN_OPTION_NOFOCUS_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + WINRULES_WINDOW (w); + winrulesSetNoFocus (w, + WINRULES_SCREEN_OPTION_NOFOCUS_MATCH, + &ww->shouldRemoveNofocus); + } + return TRUE; + } + break; + case WINRULES_SCREEN_OPTION_WIDGET_MATCH: + if (compSetMatchOption (o, value)) + { + for (w = screen->windows; w; w = w->next) + { + if (! w->type & WINRULES_TARGET_WINDOWS) + continue; + + winrulesUpdateWidget (w); + } + return TRUE; + } + break; + + default: + break; + } + + return FALSE; +} + +static void +winrulesHandleEvent (CompDisplay *d, + XEvent *event) +{ + CompWindow *w; + + WINRULES_DISPLAY (d); + + if (event->type == MapNotify) + { + w = findWindowAtDisplay (d, event->xmap.window); + if (w && w->type & WINRULES_TARGET_WINDOWS) + { + WINRULES_WINDOW (w); + /* Only apply at window creation. + * Using CreateNotify not working. + */ + if (ww->firstMap) + { + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_SKIPTASKBAR_MATCH, + CompWindowStateSkipTaskbarMask, + &ww->shouldRemoveSkipTaskbar); + + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_SKIPPAGER_MATCH, + CompWindowStateSkipPagerMask, + &ww->shouldRemoveSkipPager); + + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_ABOVE_MATCH, + CompWindowStateAboveMask, + &ww->shouldRemoveAbove); + + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_BELOW_MATCH, + CompWindowStateBelowMask, + &ww->shouldRemoveBelow); + + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_STICKY_MATCH, + CompWindowStateStickyMask, + &ww->shouldRemoveSticky); + + winrulesUpdateState (w, + WINRULES_SCREEN_OPTION_FULLSCREEN_MATCH, + CompWindowStateFullscreenMask, + &ww->shouldRemoveFullscreen); + + winrulesUpdateWidget (w); + + if (ww->shouldRemoveAbove) + raiseWindow (w); + if (ww->shouldRemoveBelow) + lowerWindow (w); + if (ww->shouldRemoveFullscreen) + maximizeWindow (w, MAXIMIZE_STATE); + + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_MOVE_MATCH, + CompWindowActionMoveMask); + + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_RESIZE_MATCH, + CompWindowActionResizeMask); + + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_MINIMIZE_MATCH, + CompWindowActionMinimizeMask); + + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_MAXIMIZE_MATCH, + CompWindowActionMaximizeVertMask| + CompWindowActionMaximizeHorzMask); + + winrulesSetAllowedActions (w, + WINRULES_SCREEN_OPTION_CLOSE_MATCH, + CompWindowActionCloseMask); + + + } + + ww->firstMap = FALSE; + } + } + else if (event->type == MapRequest) + { + w = findWindowAtDisplay (d, event->xmap.window); + if (w && w->type & WINRULES_TARGET_WINDOWS) + { + + WINRULES_WINDOW (w); + winrulesSetNoFocus (w, + WINRULES_SCREEN_OPTION_NOFOCUS_MATCH, + &ww->shouldRemoveNofocus); + + } + } + UNWRAP (wd, d, handleEvent); + (*d->handleEvent) (d, event); + WRAP (wd, d, handleEvent, winrulesHandleEvent); +} + +static unsigned int +winrulesGetAllowedActionsForWindow (CompWindow *w) +{ + unsigned int actions; + + WINRULES_SCREEN (w->screen); + WINRULES_WINDOW (w); + + UNWRAP (ws, w->screen, getAllowedActionsForWindow); + actions = (*w->screen->getAllowedActionsForWindow) (w); + WRAP (ws, w->screen, getAllowedActionsForWindow, + winrulesGetAllowedActionsForWindow); + + return actions & ww->allowedActions; + +} + +static Bool +winrulesInitDisplay (CompPlugin *p, + CompDisplay *d) +{ + WinrulesDisplay *wd; + + wd = malloc (sizeof (WinrulesDisplay)); + if (!wd) + return FALSE; + + wd->screenPrivateIndex = allocateScreenPrivateIndex (d); + if (wd->screenPrivateIndex < 0) + { + free (wd); + return FALSE; + } + WRAP (wd, d, handleEvent, winrulesHandleEvent); + d->privates[displayPrivateIndex].ptr = wd; + + return TRUE; +} + +static void +winrulesFiniDisplay (CompPlugin *p, + CompDisplay *d) +{ + WINRULES_DISPLAY (d); + + freeScreenPrivateIndex (d, wd->screenPrivateIndex); + UNWRAP (wd, d, handleEvent); + free (wd); +} + +static Bool +winrulesInitScreen (CompPlugin *p, + CompScreen *s) +{ + WinrulesScreen *ws; + int i; + + WINRULES_DISPLAY (s->display); + + ws = malloc (sizeof (WinrulesScreen)); + if (!ws) + return FALSE; + + ws->windowPrivateIndex = allocateWindowPrivateIndex(s); + if (ws->windowPrivateIndex < 0) + { + free(ws); + return FALSE; + } + + + winrulesScreenInitOptions (ws); + for (i=0; i< WINRULES_SCREEN_OPTION_NUM; i++) + { + matchUpdate (s->display, &ws->opt[i].value.match); + } + + WRAP (ws, s, getAllowedActionsForWindow, + winrulesGetAllowedActionsForWindow); + s->privates[wd->screenPrivateIndex].ptr = ws; + + return TRUE; +} + +static void +winrulesFiniScreen (CompPlugin *p, + CompScreen *s) +{ + int i; + WINRULES_SCREEN (s); + + for (i=0; i< WINRULES_SCREEN_OPTION_NUM; i++) + { + matchFini (&ws->opt[i].value.match); + } + + UNWRAP (ws, s, getAllowedActionsForWindow); + + freeWindowPrivateIndex(s, ws->windowPrivateIndex); + + free (ws); +} + +static Bool +winrulesInitWindow (CompPlugin *p, + CompWindow *w) +{ + WINRULES_SCREEN (w->screen); + + WinrulesWindow *ww = malloc (sizeof (WinrulesWindow)); + if (!ww) + { + return FALSE; + } + + ww->shouldRemoveSkipTaskbar = FALSE; + ww->shouldRemoveSkipPager = FALSE; + ww->shouldRemoveAbove = FALSE; + ww->shouldRemoveBelow = FALSE; + ww->shouldRemoveSticky = FALSE; + ww->shouldRemoveFullscreen = FALSE; + ww->shouldRemoveNofocus = FALSE; + ww->shouldRemoveWidget = FALSE; + + ww->allowedActions = ~0; + + ww->firstMap = TRUE; + + w->privates[ws->windowPrivateIndex].ptr = ww; + + return TRUE; +} + +static void +winrulesFiniWindow (CompPlugin *p, + CompWindow *w) +{ + WINRULES_WINDOW (w); + + free (ww); +} + +static Bool +winrulesInit (CompPlugin *p) +{ + displayPrivateIndex = allocateDisplayPrivateIndex (); + if (displayPrivateIndex < 0) + return FALSE; + + return TRUE; +} + +static void +winrulesFini (CompPlugin *p) +{ + if (displayPrivateIndex >= 0) + freeDisplayPrivateIndex (displayPrivateIndex); +} + +CompPluginDep winrulesDeps[] = { + {CompPluginRuleBefore, "widget"} +}; + +static int +winrulesGetVersion (CompPlugin *plugin, + int version) +{ + return ABIVERSION; +} + +static CompPluginVTable winrulesVTable = { + "winrules", + "Window Rules", + "Set windows rules", + winrulesGetVersion, + 0, + winrulesInit, + winrulesFini, + winrulesInitDisplay, + winrulesFiniDisplay, + winrulesInitScreen, + winrulesFiniScreen, + winrulesInitWindow, + winrulesFiniWindow, + 0, /* winrulesGetDisplayOptions, */ + 0, /* winrulesSetDisplayOption, */ + winrulesGetScreenOptions, + winrulesSetScreenOption, + winrulesDeps, + sizeof (winrulesDeps) / sizeof (winrulesDeps[0]), + 0, + 0 +}; + +CompPluginVTable * +getCompPluginInfo (void) +{ + return &winrulesVTable; +} diff --git a/winrules.schema b/winrules.schema new file mode 100644 index 0000000..fd7b8dd --- /dev/null +++ b/winrules.schema @@ -0,0 +1,200 @@ + + + + + + /schemas/apps/compiz/plugins/winrules/info + /apps/compiz/plugins/winrules/info + compiz + string + + + Windows rules + Set windows rules + + + + + /schemas/apps/compiz/plugins/winrules/load_before + /apps/compiz/plugins/winrules/load_before + compiz + list + string + [widget] + + Plugins that this must load before + Do not modify + + + + + /schemas/apps/compiz/plugins/winrules/requires + /apps/compiz/plugins/winrules/requires + compiz + list + string + [] + + Plugins that this requires + Do not modify + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/skiptaskbar_match + /apps/compiz/plugins/winrules/screen0/options/skiptaskbar_match + compiz + string + [] + + Skip taskbar + Don't show application in taskbar + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/skippager_match + /apps/compiz/plugins/winrules/screen0/options/skippager_match + compiz + string + [] + + Skip pager + Don't show application in pager + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/above_match + /apps/compiz/plugins/winrules/screen0/options/above_match + compiz + string + [] + + Above + Above others windows + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/below_match + /apps/compiz/plugins/winrules/screen0/options/below_match + compiz + string + [] + + Below + Below others windows + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/sticky_match + /apps/compiz/plugins/winrules/screen0/options/sticky_match + compiz + string + [] + + Sticky + Sticky windows + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/fullscreen_match + /apps/compiz/plugins/winrules/screen0/options/fullscreen_match + compiz + string + [] + + Fullscreen + Fullscreen windows + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/no_move_match + /apps/compiz/plugins/winrules/screen0/options/no_move_match + compiz + string + [] + + Non movable windows + Set window as non movable + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/no_resize_match + /apps/compiz/plugins/winrules/screen0/options/no_resize_match + compiz + string + [] + + Non resizable windows + Set window as non resizable + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/no_minimize_match + /apps/compiz/plugins/winrules/screen0/options/no_minimize_match + compiz + string + [] + + Non minimizable windows + Set window as non minimizable + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/no_maximize_match + /apps/compiz/plugins/winrules/screen0/options/no_maximize_match + compiz + string + [] + + Non maximizable windows + Set window as non maximizable + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/no_close_match + /apps/compiz/plugins/winrules/screen0/options/no_close_match + compiz + string + [] + + Non closable windows + Set window as non closable + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/no_focus_match + /apps/compiz/plugins/winrules/screen0/options/no_focus_match + compiz + string + [] + + No focus + Windows will not have focus + + + + + /schemas/apps/compiz/plugins/winrules/screen0/options/widget_match + /apps/compiz/plugins/winrules/screen0/options/widget_match + compiz + string + [] + + Widget + Set window as widget + + + + + -- cgit v1.1