summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile177
-rw-r--r--winrules.c918
-rw-r--r--winrules.schema200
3 files changed, 1295 insertions, 0 deletions
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 <stdlib.h>
+#include <stdio.h>
+#include <compiz.h>
+
+#include <X11/Xatom.h>
+
+#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 @@
+<gconfschemafile>
+ <schemalist>
+ <!-- winrules options -->
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/info</key>
+ <applyto>/apps/compiz/plugins/winrules/info</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Windows rules</short>
+ <long>Set windows rules</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/load_before</key>
+ <applyto>/apps/compiz/plugins/winrules/load_before</applyto>
+ <owner>compiz</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[widget]</default>
+ <locale name="C">
+ <short>Plugins that this must load before</short>
+ <long>Do not modify</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/requires</key>
+ <applyto>/apps/compiz/plugins/winrules/requires</applyto>
+ <owner>compiz</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Plugins that this requires</short>
+ <long>Do not modify</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/skiptaskbar_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/skiptaskbar_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Skip taskbar</short>
+ <long>Don't show application in taskbar</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/skippager_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/skippager_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Skip pager</short>
+ <long>Don't show application in pager</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/above_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/above_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Above</short>
+ <long>Above others windows</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/below_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/below_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Below</short>
+ <long>Below others windows</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/sticky_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/sticky_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Sticky</short>
+ <long>Sticky windows</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/fullscreen_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/fullscreen_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Fullscreen</short>
+ <long>Fullscreen windows</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/no_move_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/no_move_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Non movable windows</short>
+ <long>Set window as non movable</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/no_resize_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/no_resize_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Non resizable windows</short>
+ <long>Set window as non resizable</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/no_minimize_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/no_minimize_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Non minimizable windows</short>
+ <long>Set window as non minimizable</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/no_maximize_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/no_maximize_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Non maximizable windows</short>
+ <long>Set window as non maximizable</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/no_close_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/no_close_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Non closable windows</short>
+ <long>Set window as non closable</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/no_focus_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/no_focus_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>No focus</short>
+ <long>Windows will not have focus</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/compiz/plugins/winrules/screen0/options/widget_match</key>
+ <applyto>/apps/compiz/plugins/winrules/screen0/options/widget_match</applyto>
+ <owner>compiz</owner>
+ <type>string</type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Widget</short>
+ <long>Set window as widget</long>
+ </locale>
+ </schema>
+
+ </schemalist>
+</gconfschemafile>