summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Janlert <janlert@ardendo.se>2008-05-12 20:22:27 +1000
committerMagnus Janlert <janlert@ardendo.se>2008-05-12 20:22:27 +1000
commit5cb808bded60d87b17394b72b36d689c0d0e29ae (patch)
treef3de6d55ab278f47f162016b689fac149fee9f4e
downloadvigo-5cb808bded60d87b17394b72b36d689c0d0e29ae.tar.gz
vigo-5cb808bded60d87b17394b72b36d689c0d0e29ae.tar.bz2
initial commit
-rw-r--r--CMakeLists.txt3
-rw-r--r--Makefile533
-rw-r--r--plugin.info1
-rw-r--r--vigo.c1050
-rw-r--r--vigo.xml.in61
5 files changed, 1648 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..f549800
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,3 @@
+include (CompizFusion)
+
+compiz_fusion_plugin (vigo)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d9a07cf
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,533 @@
+##
+#
+# Compiz plugin Makefile
+#
+# Copyright : (C) 2007 by Dennis Kasprzyk
+# E-mail : onestone@deltatauchi.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.
+#
+##
+
+# plugin.info file contents
+#
+# PLUGIN = foo
+# PKG_DEP = pango
+# LDFLAGS_ADD = -lGLU
+# CFLAGS_ADD = -I/usr/include/foo
+# CHK_HEADERS = compiz-cube.h
+#
+
+#load config file
+
+ECHO = `which echo`
+
+# default color settings
+color := $(shell if [ $$TERM = "dumb" ]; then $(ECHO) "no"; else $(ECHO) "yes"; fi)
+
+ifeq ($(shell if [ -f plugin.info ]; then $(ECHO) -n "found"; fi ),found)
+include plugin.info
+else
+$(error $(shell if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\033[1;31m[ERROR]\033[0m \"plugin.info\" file not found"; \
+ else \
+ $(ECHO) "[ERROR] \"plugin.info\" file not found"; \
+ fi;))
+endif
+
+ifneq ($(shell if pkg-config --exists compiz; then $(ECHO) -n "found"; fi ),found)
+$(error $(shell if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[1;31m[ERROR]\033[0m Compiz not installed"; \
+ else \
+ $(ECHO) -n "[ERROR] Compiz not installed"; \
+ fi))
+endif
+
+
+ifneq ($(shell if [ -n "$(PKG_DEP)" ]; then if pkg-config --exists $(PKG_DEP); then $(ECHO) -n "found"; fi; \
+ else $(ECHO) -n "found"; fi ),found)
+$(error $(shell if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[1;31m[ERROR]\033[0m "; \
+ else \
+ $(ECHO) -n "[ERROR] "; \
+ fi; \
+ pkg-config --print-errors --short-errors --errors-to-stdout $(PKG_DEP); ))
+endif
+
+
+ifeq ($(BUILD_GLOBAL),true)
+ PREFIX = $(shell pkg-config --variable=prefix compiz)
+ CLIBDIR = $(shell pkg-config --variable=libdir compiz)
+ CINCDIR = $(shell pkg-config --variable=includedir compiz)
+ PKGDIR = $(CLIBDIR)/pkgconfig
+ DESTDIR = $(shell pkg-config --variable=libdir compiz)/compiz
+ XMLDIR = $(shell pkg-config --variable=prefix compiz)/share/compiz
+ IMAGEDIR = $(shell pkg-config --variable=prefix compiz)/share/compiz
+ DATADIR = $(shell pkg-config --variable=prefix compiz)/share/compiz
+else
+ DESTDIR = $(HOME)/.compiz/plugins
+ XMLDIR = $(HOME)/.compiz/metadata
+ IMAGEDIR = $(HOME)/.compiz/images
+ DATADIR = $(HOME)/.compiz/data
+endif
+
+BUILDDIR = build
+
+CC = gcc
+CPP = g++
+LIBTOOL = libtool
+INSTALL = install
+
+BCOP = `pkg-config --variable=bin bcop`
+
+CFLAGS = -g -Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -fno-strict-aliasing `pkg-config --cflags $(PKG_DEP) compiz ` $(CFLAGS_ADD)
+LDFLAGS = `pkg-config --libs $(PKG_DEP) compiz ` $(LDFLAGS_ADD)
+
+DEFINES = -DIMAGEDIR=\"$(IMAGEDIR)\" -DDATADIR=\"$(DATADIR)\"
+
+POFILEDIR = $(shell if [ -n "$(PODIR)" ]; then $(ECHO) $(PODIR); else $(ECHO) ./po;fi )
+
+COMPIZ_HEADERS = compiz.h compiz-core.h
+COMPIZ_INC = $(shell pkg-config --variable=includedir compiz)/compiz/
+
+is-bcop-target := $(shell if [ -e $(PLUGIN).xml.in ]; then cat $(PLUGIN).xml.in | grep "useBcop=\"true\""; \
+ else if [ -e $(PLUGIN).xml ]; then cat $(PLUGIN).xml | grep "useBcop=\"true\""; fi; fi)
+
+trans-target := $(shell if [ -e $(PLUGIN).xml.in -o -e $(PLUGIN).xml ]; then $(ECHO) $(BUILDDIR)/$(PLUGIN).xml;fi )
+
+bcop-target := $(shell if [ -n "$(is-bcop-target)" ]; then $(ECHO) $(BUILDDIR)/$(PLUGIN).xml; fi )
+bcop-target-src := $(shell if [ -n "$(is-bcop-target)" ]; then $(ECHO) $(BUILDDIR)/$(PLUGIN)_options.c; fi )
+bcop-target-hdr := $(shell if [ -n "$(is-bcop-target)" ]; then $(ECHO) $(BUILDDIR)/$(PLUGIN)_options.h; fi )
+
+gen-schemas := $(shell if [ \( -e $(PLUGIN).xml.in -o -e $(PLUGIN).xml \) -a -n "`pkg-config --variable=xsltdir compiz-gconf`" ]; then $(ECHO) true; fi )
+schema-target := $(shell if [ -n "$(gen-schemas)" ]; then $(ECHO) $(BUILDDIR)/$(PLUGIN).xml; fi )
+schema-output := $(shell if [ -n "$(gen-schemas)" ]; then $(ECHO) $(BUILDDIR)/compiz-$(PLUGIN).schema; fi )
+
+ifeq ($(BUILD_GLOBAL),true)
+ pkg-target := $(shell if [ -e compiz-$(PLUGIN).pc.in -a -n "$(PREFIX)" -a -d "$(PREFIX)" ]; then $(ECHO) "$(BUILDDIR)/compiz-$(PLUGIN).pc"; fi )
+ hdr-install-target := $(shell if [ -e compiz-$(PLUGIN).pc.in -a -n "$(PREFIX)" -a -d "$(PREFIX)" -a -e compiz-$(PLUGIN).h ]; then $(ECHO) "compiz-$(PLUGIN).h"; fi )
+endif
+
+# find all the object files
+
+c-objs := $(patsubst %.c,%.lo,$(shell find -name '*.c' 2> /dev/null | grep -v "$(BUILDDIR)/" | sed -e 's/^.\///'))
+c-objs += $(patsubst %.cpp,%.lo,$(shell find -name '*.cpp' 2> /dev/null | grep -v "$(BUILDDIR)/" | sed -e 's/^.\///'))
+c-objs += $(patsubst %.cxx,%.lo,$(shell find -name '*.cxx' 2> /dev/null | grep -v "$(BUILDDIR)/" | sed -e 's/^.\///'))
+c-objs := $(filter-out $(bcop-target-src:.c=.lo),$(c-objs))
+
+h-files := $(shell find -name '*.h' 2> /dev/null | grep -v "$(BUILDDIR)/" | sed -e 's/^.\///')
+h-files += $(bcop-target-hdr)
+h-files += $(foreach file,$(COMPIZ_HEADERS) $(CHK_HEADERS),$(shell $(ECHO) -n "$(COMPIZ_INC)$(file)"))
+
+all-c-objs := $(addprefix $(BUILDDIR)/,$(c-objs))
+all-c-objs += $(bcop-target-src:.c=.lo)
+
+# additional files
+
+data-files := $(shell find data/ -name '*' -type f 2> /dev/null | sed -e 's/data\///')
+image-files := $(shell find images/ -name '*' -type f 2> /dev/null | sed -e 's/images\///')
+
+# system include path parameter, -isystem doesn't work on old gcc's
+inc-path-param = $(shell if [ -z "`gcc --version | head -n 1 | grep ' 3'`" ]; then $(ECHO) "-isystem"; else $(ECHO) "-I"; fi)
+
+# Tests
+ifeq ($(shell if [ -n "$(is-bcop-target)" -a -z "$(BCOP)" ]; then $(ECHO) -n "error"; fi ),error)
+$(error $(shell if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[1;31m[ERROR]\033[0m BCOP not installed but is needed to build plugin"; \
+ else \
+ $(ECHO) -n "[ERROR] BCOP not installed but is needed to build plugin"; \
+ fi))
+endif
+
+ifeq ($(shell if [ "x$(BUILD_GLOBAL)" != "xtrue" -a -e compiz-$(PLUGIN).pc.in ]; then $(ECHO) -n "warn"; fi ),warn)
+$(warning $(shell if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[1;31m[WARNING]\033[0m This plugin might be needed by other plugins. Install it with \"BUILD_GLOBAL=true sudo make install\" "; \
+ else \
+ $(ECHO) -n "[WARNING] This plugin might be needed by other plugins. Install it with \"BUILD_GLOBAL=true sudo make install\""; \
+ fi))
+endif
+
+#
+# Do it.
+#
+
+.PHONY: $(BUILDDIR) build-dir trans-target bcop-build pkg-creation schema-creation c-build-objs c-link-plugin
+
+all: $(BUILDDIR) build-dir trans-target bcop-build pkg-creation schema-creation c-build-objs c-link-plugin
+
+trans-build: $(trans-target)
+
+bcop-build: $(bcop-target-hdr) $(bcop-target-src)
+
+schema-creation: $(schema-output)
+
+c-build-objs: $(all-c-objs)
+
+c-link-plugin: $(BUILDDIR)/lib$(PLUGIN).la
+
+pkg-creation: $(pkg-target)
+
+#
+# Create build directory
+#
+
+$(BUILDDIR) :
+ @mkdir -p $(BUILDDIR)
+
+$(DESTDIR) :
+ @mkdir -p $(DESTDIR)
+
+#
+# fallback if xml.in doesn't exists
+#
+$(BUILDDIR)/%.xml: %.xml
+ @cp $< $@
+
+#
+# Translating
+#
+$(BUILDDIR)/%.xml: %.xml.in
+ @if [ -d $(POFILEDIR) ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mtranslate \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "translate $< -> $@"; \
+ fi; \
+ intltool-merge -x -u $(POFILEDIR) $< $@ > /dev/null; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mtranslate : \033[34m$< -> $@\033[0m"; \
+ fi; \
+ else \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mconvert \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "convert $< -> $@"; \
+ fi; \
+ cat $< | sed -e 's;<_;<;g' -e 's;</_;</;g' > $@; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mconvert : \033[34m$< -> $@\033[0m"; \
+ fi; \
+ fi
+
+#
+# BCOP'ing
+
+$(BUILDDIR)/%_options.h: $(BUILDDIR)/%.xml
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mbcop'ing \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "bcop'ing $< -> $@"; \
+ fi
+ @$(BCOP) --header=$@ $<
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mbcop'ing : \033[34m$< -> $@\033[0m"; \
+ fi
+
+$(BUILDDIR)/%_options.c: $(BUILDDIR)/%.xml
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mbcop'ing \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "bcop'ing $< -> $@"; \
+ fi
+ @$(BCOP) --source=$@ $<
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mbcop'ing : \033[34m$< -> $@\033[0m"; \
+ fi
+
+#
+# Schema generation
+
+$(BUILDDIR)/compiz-%.schema: $(BUILDDIR)/%.xml
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mschema'ing\033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "schema'ing $< -> $@"; \
+ fi
+ @xsltproc `pkg-config --variable=xsltdir compiz-gconf`/schemas.xslt $< > $@
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mschema : \033[34m$< -> $@\033[0m"; \
+ fi
+
+#
+# pkg config file generation
+
+$(BUILDDIR)/compiz-%.pc: compiz-%.pc.in
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mpkgconfig \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "pkgconfig $< -> $@"; \
+ fi
+ @COMPIZREQUIRES=`cat $(PKGDIR)/compiz.pc | grep Requires | sed -e 's;Requires: ;;g'`; \
+ COMPIZCFLAGS=`cat $(PKGDIR)/compiz.pc | grep Cflags | sed -e 's;Cflags: ;;g'`; \
+ sed -e 's;@prefix@;$(PREFIX);g' -e 's;\@libdir@;$(CLIBDIR);g' \
+ -e 's;@includedir@;$(CINCDIR);g' -e 's;\@VERSION@;0.0.1;g' \
+ -e "s;@COMPIZ_REQUIRES@;$$COMPIZREQUIRES;g" \
+ -e "s;@COMPIZ_CFLAGS@;$$COMPIZCFLAGS;g" $< > $@;
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mpkgconfig : \033[34m$< -> $@\033[0m"; \
+ fi
+
+#
+# Compiling
+#
+
+$(BUILDDIR)/%.lo: %.c $(h-files)
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5mcompiling \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "compiling $< -> $@"; \
+ fi
+ @$(LIBTOOL) --quiet --mode=compile $(CC) $(CFLAGS) $(DEFINES) -I$(BUILDDIR) -c -o $@ $<
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \
+ fi
+
+$(BUILDDIR)/%.lo: $(BUILDDIR)/%.c $(h-files)
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5mcompiling \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "compiling $< -> $@"; \
+ fi
+ @$(LIBTOOL) --quiet --mode=compile $(CC) $(CFLAGS) $(DEFINES) -I$(BUILDDIR) -c -o $@ $<
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \
+ fi
+
+$(BUILDDIR)/%.lo: %.cpp $(h-files)
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5mcompiling \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "compiling $< -> $@"; \
+ fi
+ @$(LIBTOOL) --quiet --mode=compile $(CPP) $(CFLAGS) $(DEFINES) -I$(BUILDDIR) -c -o $@ $<
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \
+ fi
+
+$(BUILDDIR)/%.lo: %.cxx $(h-files)
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5mcompiling \033[0m: \033[0;32m$< \033[0m-> \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "compiling $< -> $@"; \
+ fi
+ @$(LIBTOOL) --quiet --mode=compile $(CPP) $(CFLAGS) $(DEFINES) -I$(BUILDDIR) -c -o $@ $<
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \
+ fi
+
+#
+# Linking
+#
+
+cxx-rpath-prefix := -Wl,-rpath,
+
+$(BUILDDIR)/lib$(PLUGIN).la: $(all-c-objs)
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mlinking \033[0m: \033[0;31m$@\033[0m"; \
+ else \
+ $(ECHO) "linking : $@"; \
+ fi
+ @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) -rpath $(DESTDIR) -o $@ $(all-c-objs)
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mlinking : \033[34m$@\033[0m"; \
+ fi
+
+
+clean:
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e -n "\033[0;1;5mremoving \033[0m: \033[0;31m./$(BUILDDIR)\033[0m"; \
+ else \
+ $(ECHO) "removing : ./$(BUILDDIR)"; \
+ fi
+ @rm -rf $(BUILDDIR)
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0mremoving : \033[34m./$(BUILDDIR)\033[0m"; \
+ fi
+
+
+install: $(DESTDIR) all
+ @if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5minstall \033[0m: \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
+ @if [ -e $(BUILDDIR)/$(PLUGIN).xml ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5minstall \033[0m: \033[0;31m$(XMLDIR)/$(PLUGIN).xml\033[0m"; \
+ else \
+ $(ECHO) "install : $(XMLDIR)/$(PLUGIN).xml"; \
+ fi; \
+ mkdir -p $(XMLDIR); \
+ $(INSTALL) $(BUILDDIR)/$(PLUGIN).xml $(XMLDIR)/$(PLUGIN).xml; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0minstall : \033[34m$(XMLDIR)/$(PLUGIN).xml\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(hdr-install-target)" ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5minstall \033[0m: \033[0;31m$(CINCDIR)/compiz/$(hdr-install-target)\033[0m"; \
+ else \
+ $(ECHO) "install : $(CINCDIR)/compiz/$(hdr-install-target)"; \
+ fi; \
+ $(INSTALL) --mode=u=rw,go=r,a-s $(hdr-install-target) $(CINCDIR)/compiz/$(hdr-install-target); \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0minstall : \033[34m$(CINCDIR)/compiz/$(hdr-install-target)\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(pkg-target)" ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5minstall \033[0m: \033[0;31m$(PKGDIR)/compiz-$(PLUGIN).pc\033[0m"; \
+ else \
+ $(ECHO) "install : $(PKGDIR)/compiz-$(PLUGIN).pc"; \
+ fi; \
+ $(INSTALL) --mode=u=rw,go=r,a-s $(pkg-target) $(PKGDIR)/compiz-$(PLUGIN).pc; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0minstall : \033[34m$(PKGDIR)/compiz-$(PLUGIN).pc\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(schema-output)" -a -e "$(schema-output)" ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5minstall \033[0m: \033[0;31m$(schema-output)\033[0m"; \
+ else \
+ $(ECHO) "install : $(schema-output)"; \
+ fi; \
+ if [ "x$(USER)" = "xroot" ]; then \
+ GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source` \
+ gconftool-2 --makefile-install-rule $(schema-output) > /dev/null; \
+ else \
+ gconftool-2 --install-schema-file=$(schema-output) > /dev/null; \
+ fi; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0minstall : \033[34m$(schema-output)\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(data-files)" ]; then \
+ mkdir -p $(DATADIR); \
+ for FILE in $(data-files); do \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5minstall \033[0m: \033[0;31m$(DATADIR)/$$FILE\033[0m"; \
+ else \
+ $(ECHO) "install : $(DATADIR)/$$FILE"; \
+ fi; \
+ FILEDIR="$(DATADIR)/`dirname "$$FILE"`"; \
+ mkdir -p "$$FILEDIR"; \
+ $(INSTALL) --mode=u=rw,go=r,a-s data/$$FILE $(DATADIR)/$$FILE; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0minstall : \033[34m$(DATADIR)/$$FILE\033[0m"; \
+ fi; \
+ done \
+ fi
+ @if [ -n "$(image-files)" ]; then \
+ mkdir -p $(IMAGEDIR); \
+ for FILE in $(image-files); do \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5minstall \033[0m: \033[0;31m$(IMAGEDIR)/$$FILE\033[0m"; \
+ else \
+ $(ECHO) "install : $(IMAGEDIR)/$$FILE"; \
+ fi; \
+ FILEDIR="$(IMAGEDIR)/`dirname "$$FILE"`"; \
+ mkdir -p "$$FILEDIR"; \
+ $(INSTALL) --mode=u=rw,go=r,a-s images/$$FILE $(IMAGEDIR)/$$FILE; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0minstall : \033[34m$(IMAGEDIR)/$$FILE\033[0m"; \
+ fi; \
+ done \
+ fi
+
+uninstall:
+ @if [ -e $(DESTDIR)/lib$(PLUGIN).so ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5muninstall \033[0m: \033[0;31m$(DESTDIR)/lib$(PLUGIN).so\033[0m"; \
+ else \
+ $(ECHO) "uninstall : $(DESTDIR)/lib$(PLUGIN).so"; \
+ fi; \
+ rm -f $(DESTDIR)/lib$(PLUGIN).so; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0muninstall : \033[34m$(DESTDIR)/lib$(PLUGIN).so\033[0m"; \
+ fi; \
+ fi
+ @if [ -e $(XMLDIR)/$(PLUGIN).xml ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5muninstall \033[0m: \033[0;31m$(XMLDIR)/$(PLUGIN).xml\033[0m"; \
+ else \
+ $(ECHO) "uninstall : $(XMLDIR)/$(PLUGIN).xml"; \
+ fi; \
+ rm -f $(XMLDIR)/$(PLUGIN).xml; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0muninstall : \033[34m$(XMLDIR)/$(PLUGIN).xml\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(hdr-install-target)" -a -e $(CINCDIR)/compiz/$(hdr-install-target) ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5muninstall \033[0m: \033[0;31m$(CINCDIR)/compiz/$(hdr-install-target)\033[0m"; \
+ else \
+ $(ECHO) "uninstall : $(CINCDIR)/compiz/$(hdr-install-target)"; \
+ fi; \
+ rm -f $(CINCDIR)/compiz/$(hdr-install-target); \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0muninstall : \033[34m$(CINCDIR)/compiz/$(hdr-install-target)\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(pkg-target)" -a -e $(PKGDIR)/compiz-$(PLUGIN).pc ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5muninstall \033[0m: \033[0;31m$(PKGDIR)/compiz-$(PLUGIN).pc\033[0m"; \
+ else \
+ $(ECHO) "uninstall : $(PKGDIR)/compiz-$(PLUGIN).pc"; \
+ fi; \
+ rm -f $(PKGDIR)/compiz-$(PLUGIN).pc; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0muninstall : \033[34m$(PKGDIR)/compiz-$(PLUGIN).pc\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(schema-output)" -a -e "$(schema-output)" -a 'x$(USER)' = 'xroot' ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5muninstall \033[0m: \033[0;31m$(schema-output)\033[0m"; \
+ else \
+ $(ECHO) "uninstall : $(schema-output)"; \
+ fi; \
+ GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source` \
+ gconftool-2 --makefile-uninstall-rule $(schema-output) > /dev/null; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0muninstall : \033[34m$(schema-output)\033[0m"; \
+ fi; \
+ fi
+ @if [ -n "$(data-files)" ]; then \
+ for FILE in $(data-files); do \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5muninstall \033[0m: \033[0;31m$(DATADIR)/$$FILE\033[0m"; \
+ else \
+ $(ECHO) "uninstall : $(DATADIR)/$$FILE"; \
+ fi; \
+ rm -f $(DATADIR)/$$FILE; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0muninstall : \033[34m$(DATADIR)/$$FILE\033[0m"; \
+ fi; \
+ done \
+ fi
+ @if [ -n "$(image-files)" ]; then \
+ for FILE in $(image-files); do \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -n -e "\033[0;1;5muninstall \033[0m: \033[0;31m$(IMAGEDIR)/$$FILE\033[0m"; \
+ else \
+ $(ECHO) "uninstall : $(IMAGEDIR)/$$FILE"; \
+ fi; \
+ rm -f $(IMAGEDIR)/$$FILE; \
+ if [ '$(color)' != 'no' ]; then \
+ $(ECHO) -e "\r\033[0muninstall : \033[34m$(IMAGEDIR)/$$FILE\033[0m"; \
+ fi; \
+ done \
+ fi
diff --git a/plugin.info b/plugin.info
new file mode 100644
index 0000000..bc22c67
--- /dev/null
+++ b/plugin.info
@@ -0,0 +1 @@
+PLUGIN = vigo
diff --git a/vigo.c b/vigo.c
new file mode 100644
index 0000000..0b0e3ad
--- /dev/null
+++ b/vigo.c
@@ -0,0 +1,1050 @@
+/* Compiz vigo plugin
+ *
+ * Allows you to navigate between windows by direction;
+ * up, down left and right (in/out exists as well, although i dont
+ * find them very useful). Some extra features are thrown
+ * in as well; bookmarking of windows (inspired by
+ * the mX and 'X vi commands) and "raise or lower".
+ *
+ * copyright (c) 2008 magnus janlert <janlert@acc.umu.se>
+ *
+ * I used the tile plugin as a template at the start, so there
+ * is probably a few lines or code left from there, the
+ * tile plugin is:
+ * Copyright (c) 2006 Atie H. <atie.at.matrix@gmail.com>
+ * Copyright (c) 2006 Michal Fojtik <pichalsi(at)gmail.com>
+ * Copyright (c) 2007 Danny Baumann <maniac@beryl-project.org>
+ *
+ * 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.
+ */
+
+#include <X11/keysymdef.h>
+#include <compiz-core.h>
+#include <string.h>
+#include "vigo_options.h"
+#include <math.h>
+
+static int displayPrivateIndex;
+
+typedef struct _VigoDisplay
+{
+ HandleEventProc handleEvent;
+ int screenPrivateIndex;
+} VigoDisplay;
+
+typedef struct _VigoScreen
+{
+ int windowPrivateIndex;
+ int grab;
+ int grabIndex;
+ CompWindow *grabWin;
+ CompWindow *nextFocus;
+ ActivateWindowProc activateWindow;
+} VigoScreen;
+
+typedef struct _VigoROLData
+{
+ CompWindow *w;
+ CompScreen *s;
+ Region v;
+} VigoROLData;
+
+#define VIGO_KSLEN 25
+typedef struct _VigoWindow
+{
+ char mark[VIGO_KSLEN];
+} VigoWindow;
+
+typedef struct _VigoPoint
+{
+ int x, y;
+} VigoPoint;
+
+typedef struct _VigoWinExtra VigoWinExtra;
+struct _VigoWinExtra
+{
+ CompWindow *w;
+ Region v;
+ XRectangle bbox;
+ VigoWinExtra *next;
+};
+
+#define VIGO_GRAB_NONE 0
+#define VIGO_GRAB_MARK 1
+#define VIGO_GRAB_GOTO 2
+
+#define GET_VIGO_DISPLAY(d) \
+ ((VigoDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
+
+#define VIGO_DISPLAY(d) \
+ VigoDisplay *vd = GET_VIGO_DISPLAY (d)
+
+#define GET_VIGO_WINDOW(w, vs) \
+ ((VigoWindow *) (w)->base.privates[(vs)->windowPrivateIndex].ptr)
+
+#define VIGO_WINDOW(w) \
+ VigoWindow *vw = GET_VIGO_WINDOW (w, \
+ GET_VIGO_SCREEN (w->screen, \
+ GET_VIGO_DISPLAY (w->screen->display)))
+
+#define GET_VIGO_SCREEN(s, vd) \
+ ((VigoScreen *) (s)->base.privates[(vd)->screenPrivateIndex].ptr)
+
+#define VIGO_SCREEN(s) \
+ VigoScreen *vs = GET_VIGO_SCREEN (s, GET_VIGO_DISPLAY (s->display))
+
+
+#define GET_DATA \
+ CompScreen *s;\
+ CompWindow *w;\
+ Window xid; \
+ xid = getIntOptionNamed (option, nOption, "root", 0); \
+ s = findScreenAtDisplay (d, xid); \
+ if (!s) \
+ return FALSE; \
+ xid = getIntOptionNamed (option, nOption, "window", 0); \
+ w = findWindowAtDisplay (d, xid); \
+ if (!w) return FALSE;
+
+#define VIGO_NORTH 1
+#define VIGO_SOUTH 2
+#define VIGO_WEST 3
+#define VIGO_EAST 4
+
+
+static void
+vigoWinRect (CompWindow *w, XRectangle *r)
+{
+ if (!(w && r))
+ return;
+ r->x = w->attrib.x - w->input.left;
+ r->y = w->attrib.y - w->input.top;
+ r->width = w->width + w->input.left + w->input.right;
+ r->height = w->height + w->input.top + w->input.bottom;
+ return;
+}
+
+static void
+vigoWinRegion (CompWindow *w, Region r)
+{
+ if (!(w && r))
+ return;
+ XRectangle rc;
+ vigoWinRect (w, &rc);
+ XUnionRectWithRegion (&rc, r, r);
+}
+
+static void
+vigoGrabRelease (CompScreen *s,
+ VigoScreen *vs)
+{
+ if (vs->grabIndex)
+ {
+ removeScreenGrab (s, vs->grabIndex, NULL);
+ vs->grabIndex = 0;
+ }
+}
+
+static Bool
+vigoGrabScreen (CompScreen *s,
+ int grabMode,
+ CompWindow *w)
+{
+ VIGO_SCREEN (s);
+ if (!vs->grabIndex)
+ {
+ if (otherScreenGrabExist (s, "vigo", 0))
+ return FALSE;
+ vs->grab = grabMode;
+ vs->grabWin = w;
+ vs->grabIndex = pushScreenGrab (s, s->invisibleCursor, "vigo");
+ }
+ return TRUE;
+}
+
+static Bool
+vigoIsCandidate (CompWindow *w)
+{
+ if (!w->mapNum || w->attrib.map_state != IsViewable)
+ return FALSE;
+
+ if (w->invisible || w->hidden || w->minimized)
+ return FALSE;
+
+ if (!(w->inputHint || (w->protocols & CompWindowProtocolTakeFocusMask)))
+ return FALSE;
+
+ if (w->attrib.override_redirect)
+ return FALSE;
+
+ if (w->state & CompWindowStateSkipTaskbarMask)
+ return FALSE;
+
+ if (w->wmType & (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
+ return FALSE;
+
+ if (!(*w->screen->focusWindow) (w))
+ return FALSE;
+
+ if (!matchEval (vigoGetMoveMatch (w->screen->display), w))
+ return FALSE;
+
+ return TRUE;
+}
+
+// If this window can hide other windows
+static Bool
+vigoHidesWin (CompWindow *w) {
+ if (!w->mapNum)
+ return FALSE;
+ if (w->invisible || w->hidden || w->minimized)
+ return FALSE;
+ if (!matchEval (vigoGetMoveMatch (w->screen->display), w))
+ return FALSE;
+ return TRUE;
+}
+
+// Calculate visible region of window w
+static Region
+vigoVisible (CompWindow *w) {
+ Region v = XCreateRegion ();
+ Region h = XCreateRegion ();
+ if (!(v && h && w))
+ return NULL;
+ vigoWinRegion (w, v);
+ for (w = w->next; w; w = w->next)
+ {
+ if (vigoHidesWin (w))
+ {
+ vigoWinRegion (w, h);
+ }
+ }
+ XSubtractRegion (v, h, v);
+ XDestroyRegion (h);
+ return v;
+}
+
+static CompWindow *
+vigoFindOverlapping (CompWindow *w,
+ Bool up)
+{
+ CompWindow *i = w;
+ Region wr = XCreateRegion ();
+ Region ol = XCreateRegion ();
+ if (!(w && wr && ol))
+ return NULL;
+ vigoWinRegion (w, wr);
+ while (1)
+ {
+ i = up ? i->next : i->prev;
+ if (!i)
+ break;
+ if (!vigoIsCandidate (i))
+ continue;
+ vigoWinRegion (i, ol);
+ XIntersectRegion (wr, ol, ol);
+ // If they overlap
+ if (!XEmptyRegion (ol))
+ {
+ // Avoid hidden windows
+ Region v = vigoVisible (i);
+ if (!v)
+ return NULL;
+ Bool hidden = XEmptyRegion (v);
+ XDestroyRegion (v);
+ if (!hidden)
+ break;
+ }
+ }
+ XDestroyRegion (ol);
+ XDestroyRegion (wr);
+ return i;
+}
+
+static VigoPoint
+vigoCenterOfMass (Region r)
+{
+ VigoPoint c;
+ int m = 0;
+ int j;
+ c.x = 0;
+ c.y = 0;
+ /* i should probably NOT be poking around in the Region-struct
+ * but.. i will anyway */
+ for (j = 0; j < r->numRects; j++)
+ {
+ BOX *b = &(r->rects[j]);
+ int w = (MAX (b->x1, b->x2) - MIN (b->x1, b->x2));
+ int h = (MAX (b->y1, b->y2) - MIN (b->y1, b->y2));
+ int bm = w * h;
+ c.x += bm * (b->x1 + b->x2) / 2;
+ c.y += bm * (b->y1 + b->y2) / 2;
+ m += bm;
+ }
+ c.x /= m;
+ c.y /= m;
+ return c;
+}
+
+static Bool
+vigoInsideRegion (int x,
+ int y,
+ VigoWinExtra *e)
+{
+ return XPointInRegion (e->v, x, y);
+}
+
+static Bool
+vigoInsideRect (int x,
+ int y,
+ VigoWinExtra *e)
+{
+ return (x >= e->bbox.x && x <= e->bbox.x + e->bbox.width &&
+ y >= e->bbox.y && y <= e->bbox.y + e->bbox.height);
+}
+
+static float
+vigoClosestBBox (int x,
+ int y,
+ VigoWinExtra *e)
+{
+ float dmin = -1.0;
+ for (; e; e = e->next)
+ {
+ int xm = e->bbox.x + e->bbox.width / 2;
+ int ym = e->bbox.y + e->bbox.height / 2;
+ float dx = fabs (xm - x);
+ float dy = fabs (ym - y);
+ float w = e->bbox.width/2;
+ float h = e->bbox.height/2;
+ float d = sqrt (dx*dx + dy*dy) - sqrt (w*w + h*h);
+ if (d <= 0.0)
+ return 0.0;
+
+ if (d > 0.0 && (dmin < 0.0 || d < dmin))
+ dmin = d;
+ }
+ return dmin < 1.0 ? 0.0 : dmin;
+}
+
+static VigoWinExtra *
+vigoRaySlow (int x1,
+ int y1,
+ float alpha,
+ VigoWinExtra *extra,
+ float *d)
+{
+ VigoWinExtra *e;
+ // how long since we last saw a bbox
+ float lastbb = 0.0;
+ float dd = 10.0;
+ while (lastbb < 41.0)
+ {
+ int x2 = x1 + sin (alpha) * (*d);
+ int y2 = y1 + cos (alpha) * (*d);
+ for (e = extra; e; e = e->next)
+ {
+ if (vigoInsideRect (x2, y2, e))
+ {
+ lastbb = 0.0;
+ if (vigoInsideRegion (x2, y2, e))
+ {
+ // Avoid very thin regions
+ int x3 = x1 + sin (alpha) * (*d + 40);
+ int y3 = y1 + cos (alpha) * (*d + 40);
+ if (vigoInsideRegion (x3, y3, e))
+ return e;
+ }
+ }
+ }
+ lastbb += dd;
+ *d += dd;
+ }
+ return NULL;
+}
+
+static VigoWinExtra *
+vigoRay (int x1,
+ int y1,
+ float alpha,
+ VigoWinExtra *extra,
+ float *d)
+{
+ VigoWinExtra *e;
+ while (*d < 2000)
+ {
+ int x2 = x1 + sin (alpha) * (*d);
+ int y2 = y1 + cos (alpha) * (*d);
+ // Check if we in a region right now
+ for (e = extra; e; e = e->next)
+ {
+ if (vigoInsideRect (x2, y2, e) && vigoInsideRegion (x2, y2, e))
+ return e;
+ }
+ // So we're currently not inside any bbox
+ float dd = vigoClosestBBox (x2, y2, extra);
+ if (dd < 10) {
+ // yes, x1/y1, not x2/y2, we always use the start point as ref.
+ e = vigoRaySlow (x1, y1, alpha, extra, d);
+ if (e)
+ return e;
+ }
+ else
+ {
+ *d += dd;
+ }
+ }
+ return NULL;
+}
+
+static float
+vigoScoreFuncX (float alpha,
+ float d)
+{
+ // should probably be adjusted a bit
+ float v = pow (fabs (cos (alpha)), 4);
+ int x = 5000 - d ;
+ return v * x;
+}
+
+static float
+vigoGetTheta (int dir)
+{
+ switch (dir)
+ {
+ case VIGO_SOUTH: return 0;
+ case VIGO_NORTH: return M_PI;
+ case VIGO_WEST: return M_PI + M_PI_2;
+ case VIGO_EAST: return M_PI_2;
+ }
+ return 0;
+}
+
+static CompWindow *
+vigoScoreWindows (VigoPoint s,
+ CompWindow *cw,
+ int dir,
+ VigoWinExtra *extra)
+{
+ float theta = vigoGetTheta (dir);;
+ int rays = 4;
+ float dt = M_PI_4 / (2 * rays);
+ float alpha;
+ float bestScore = -1.0;
+ VigoWinExtra *bestWin = NULL;
+ int i;
+ for (i = -rays; i <= rays; i ++)
+ {
+ float d = 0.0;
+ alpha = theta + i * dt;
+ VigoWinExtra *hit = vigoRay (s.x, s.y, theta + i * dt, extra, &d);
+ if (hit)
+ {
+ float s = vigoScoreFuncX (fabs (i * dt), d);
+ if (bestScore < 0 || s > bestScore) {
+ bestScore = s;
+ bestWin = hit;
+ }
+ }
+ }
+ if (bestWin)
+ return bestWin->w;
+ return NULL;
+}
+
+static VigoWinExtra *
+vigoBuildWinExtra (CompWindow *w,
+ VigoWinExtra *next) {
+ VigoWinExtra *tmp = malloc (sizeof (VigoWinExtra));
+ if (!tmp)
+ return NULL;
+ tmp->next = next;
+ tmp->w = w;
+ tmp->v = vigoVisible (w);
+ if (!tmp->v)
+ {
+ free (tmp);
+ return NULL;
+ }
+ XClipBox (tmp->v, &(tmp->bbox));
+ return tmp;
+}
+
+static VigoWinExtra *
+vigoFreeWinExtra (VigoWinExtra *extra)
+{
+ VigoWinExtra *next = extra->next;
+ XDestroyRegion (extra->v);
+ free (extra);
+ return next;
+}
+
+static void
+vigoGetScaleFactor (int dir,
+ int *x,
+ int *y)
+{
+ switch (dir)
+ {
+ case VIGO_SOUTH: *x = 0; *y = 1; return;
+ case VIGO_NORTH: *x = 0; *y = -1; return;
+ case VIGO_WEST: *x = -1; *y = 0; return;
+ case VIGO_EAST: *x = 1; *y = 0; return;
+ }
+}
+
+static VigoPoint vigoFindStart (VigoWinExtra *cextra,
+ int dir,
+ VigoWinExtra *extra)
+{
+ // our first guess is the center of mass
+ // works well when the window is mostly visible
+ VigoPoint com = vigoCenterOfMass (cextra->v);
+ if (vigoInsideRegion (com.x , com.y, cextra))
+ {
+ // if the com is in the visible region, its probably
+ // a good guess
+ return com;
+ // TODO maybe try and shift toward the direction we're moving
+ // could help with high/thin or wide/short windows
+ }
+ else
+ {
+ // So that didnt work, try and find if there anything
+ // in our visible area along our axis of movement
+ // this should take care of the "L-case"
+ // xxxx x = current window, a = other window
+ // xaaaa
+ // xaaaa
+ // aaaa
+ //
+ // trying to avoid looking inside Region, so do a stupid for-loop
+ VigoPoint start;
+ int sx, sy, xstart, ystart;
+ vigoGetScaleFactor (dir, &sx, &sy);
+ int len;
+ if (dir == VIGO_NORTH || dir == VIGO_SOUTH)
+ {
+ xstart = com.x;
+ ystart = cextra->bbox.y;
+ len = cextra->bbox.height;
+ if (dir == VIGO_SOUTH)
+ ystart += cextra->bbox.height;
+
+ }
+ if (dir == VIGO_EAST || dir == VIGO_WEST)
+ {
+ xstart = cextra->bbox.x;
+ ystart = com.y;
+ len = cextra->bbox.width;
+ if (dir == VIGO_EAST)
+ xstart += cextra->bbox.width;
+
+ }
+ int i;
+ int delta = 25;
+ for (i = delta / 2; i <= len; i += delta)
+ {
+ start.x = xstart - sx * i;
+ start.y = ystart - sy * i;
+ if (vigoInsideRegion (start.x, start.y, cextra))
+ return start;
+ }
+
+ // Ok, this is nasty one, probably some kind or cross-shape
+ // aa x = current window, a/b/c/d = other window
+ // xxaaxx
+ //dddaacccc just subtract x (all, not just visible) from
+ //dddbbcccc all regions, to clear som space
+ // xxbbxx
+ // bb
+ //
+ Region wr = XCreateRegion ();
+ vigoWinRegion (cextra->w, wr);
+ VigoWinExtra *j;
+ for (j = extra; j; j = j->next)
+ {
+ XSubtractRegion (j->v, wr, j->v);
+ XClipBox (j->v, &(j->bbox));
+ }
+ XDestroyRegion (wr);
+ return com;
+ }
+}
+
+static CompWindow *
+vigoGetWindow (CompWindow *cw,
+ int dir)
+{
+ CompWindow *h;
+ CompWindow *bestWin = NULL;
+ VigoWinExtra *extra = NULL;
+
+ VigoWinExtra *cextra = vigoBuildWinExtra (cw, NULL);
+ if (!cextra)
+ return NULL;
+
+ // Build the extra-struct
+ for (h = cw->screen->windows; h; h = h->next)
+ {
+ if (h == cw || !vigoIsCandidate (h))
+ continue;
+ VigoWinExtra *e2 = vigoBuildWinExtra (h, extra);
+ if (!e2)
+ {
+ vigoFreeWinExtra (extra);
+ vigoFreeWinExtra (cextra);
+ return NULL;
+ }
+ extra = e2;
+ }
+
+ // Find a starting point and get the best scoring window
+ VigoPoint origin = vigoFindStart (cextra, dir, extra);
+ bestWin = vigoScoreWindows (origin, cw, dir, extra);
+
+ // free extra-struct
+ while (extra)
+ {
+ extra = vigoFreeWinExtra (extra);
+ }
+ return bestWin;
+}
+
+static void
+vigoRefocus (CompWindow *w)
+{
+ CompScreen *s = w->screen;
+ VIGO_SCREEN (s);
+ UNWRAP (vs, s, activateWindow);
+ (*s->activateWindow) (w);
+ CompWindow *foc = vs->nextFocus;
+ if (foc)
+ {
+ // The warpPointer should not be needed, but there is a bug
+ // in the wall plugin apparently, fixed with
+ // http://gitweb.compiz-fusion.org/?p=fusion/plugins/wall;a=commit;h=7c3265a7a984cfbf9e16913fd804f53d8b11894f
+ warpPointer (s, -10000, -10000);
+ warpPointer (s, foc->serverX + 10, foc->serverY + 10);
+ // Also, this seems to fail every once in a while
+ // havnt been able to find any pattern though
+ moveInputFocusToWindow (foc);
+ vs->nextFocus = NULL;
+ }
+ return;
+}
+
+static void
+vigoMoveToMark (CompDisplay *d,
+ char *mark)
+{
+ CompWindow *w;
+ CompWindow *hit = NULL;
+ CompScreen *s;
+ for (s = d->screens; s; s = s->next)
+ {
+ for (w = s->windows; w; w = w->next)
+ {
+ VIGO_WINDOW (w);
+ if (!strcmp (mark, vw->mark))
+ {
+ hit = w;
+ break;
+ }
+ }
+ if (hit)
+ break;
+ }
+ if (hit)
+ {
+ s = hit->screen;
+ int x, y;
+ defaultViewportForWindow (hit, &x, &y);
+ if (x != hit->screen->x || y != hit->screen->y)
+ {
+ VIGO_SCREEN (s);
+ vs->nextFocus = hit;
+ WRAP (vs, s, activateWindow, vigoRefocus);
+ }
+ sendWindowActivationRequest (s, hit->id);
+ }
+}
+
+
+static void
+vigoRemoveMark (CompDisplay *d,
+ char *mark)
+{
+ CompScreen *s;
+ CompWindow *h;
+ for (s = d->screens; s; s = s->next)
+ {
+ for (h = s->windows; h; h = h->next)
+ {
+ VIGO_WINDOW (h);
+ if (!strcmp (mark, vw->mark))
+ strcpy (vw->mark, "");
+ }
+ }
+}
+
+static void
+vigoMarkWindow (CompDisplay *d,
+ CompWindow *w,
+ char *mark)
+{
+ vigoRemoveMark (d, mark);
+ VIGO_WINDOW (w);
+ strcpy (vw->mark, mark);
+}
+
+static void
+vigoHandleEvent (CompDisplay *d,
+ XEvent *event)
+{
+ VIGO_DISPLAY (d);
+ char kstr[VIGO_KSLEN];
+ Bool dropEvent = FALSE;
+
+ if (event->type == KeyPress)
+ {
+ CompScreen *s = findScreenAtDisplay (d, event->xkey.root);
+ CompWindow *w = findWindowAtDisplay (d, event->xfocus.window);
+ if (s && w)
+ {
+ VIGO_SCREEN (s);
+ vigoGrabRelease (s, vs);
+ XKeyEvent *keyEvent = (XKeyEvent *) event;
+ int n = XLookupString (keyEvent, kstr, VIGO_KSLEN - 1, NULL, NULL);
+ kstr[n] = '\0';
+ if (n && vs->grabWin)
+ {
+ switch (vs->grab)
+ {
+ case VIGO_GRAB_MARK:
+ vigoMarkWindow (d, vs->grabWin, kstr);
+ dropEvent = TRUE;
+ break;
+ case VIGO_GRAB_GOTO:
+ dropEvent = TRUE;
+ vigoMoveToMark (d, kstr);
+ break;
+ }
+ }
+ }
+ }
+ if (!dropEvent)
+ {
+ UNWRAP (vd, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (vd, d, handleEvent, vigoHandleEvent);
+ }
+}
+
+static Bool
+vigoGotoMark (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ GET_DATA;
+ vigoGrabScreen (s, VIGO_GRAB_GOTO, w);
+ return TRUE;
+}
+
+static Bool
+vigoMark (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ GET_DATA;
+ vigoGrabScreen (s, VIGO_GRAB_MARK, w);
+ return TRUE;
+}
+
+
+// Called a bit after we've raised the window, and
+// the s->windows list has hopefully been updated, so check
+// if anything changed
+static Bool
+vigoROL2 (void *rd_)
+{
+ VigoROLData *rd = (VigoROLData *) rd_;
+ if (rd)
+ {
+ CompWindow *w;
+ // Make sure the window still exists
+ for (w = rd->s->windows; w; w = w->next)
+ {
+ if (w == rd->w)
+ {
+ Region v = vigoVisible (rd->w);
+ if (v)
+ {
+ Bool e = XEqualRegion (v, rd->v);
+ XDestroyRegion (v);
+ XDestroyRegion (rd->v);
+ if (e)
+ lowerWindow (rd->w);
+ free (rd);
+ return FALSE;
+ }
+ }
+ }
+ free (rd);
+ }
+ return FALSE;
+}
+
+// Raise Or Lower
+static Bool
+vigoROL (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ GET_DATA;
+ if (w)
+ {
+ VigoROLData *rd = malloc (sizeof (VigoROLData));
+ if (!rd)
+ return FALSE;
+ rd->w = w;
+ rd->s = w->screen;
+ rd->v = vigoVisible (w);
+ if (!rd->v)
+ {
+ free (rd);
+ return FALSE;
+ }
+ raiseWindow (w);
+ // wait a bit and see if anything happened, if not, we want to lower it
+ // uuuugly
+ compAddTimeout (5, vigoROL2, rd);
+ }
+
+ return TRUE;
+}
+
+static Bool
+vigoGoInOut (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ GET_DATA;
+ if (w)
+ {
+ CompWindow *tw = NULL;
+ if (action == vigoGetMoveIn (w->screen->display))
+ tw = vigoFindOverlapping (w, False);
+ if (action == vigoGetMoveOut (w->screen->display))
+ tw = vigoFindOverlapping (w, True);
+ if (tw)
+ moveInputFocusToWindow (tw);
+ }
+
+ return TRUE;
+}
+
+
+static Bool
+vigoGoto (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ GET_DATA;
+ if (w)
+ {
+ CompWindow *nw = NULL;
+ if (action == vigoGetMoveLeft (w->screen->display))
+ nw = vigoGetWindow (w, VIGO_WEST);
+ if (action == vigoGetMoveRight (w->screen->display))
+ nw = vigoGetWindow (w, VIGO_EAST);
+ if (action == vigoGetMoveUp (w->screen->display))
+ nw = vigoGetWindow (w, VIGO_NORTH);
+ if (action == vigoGetMoveDown (w->screen->display))
+ nw = vigoGetWindow (w, VIGO_SOUTH);
+ if (nw)
+ moveInputFocusToWindow (nw);
+ }
+
+ return TRUE;
+}
+
+
+static Bool
+vigoInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ VigoDisplay *vd;
+
+ if (!checkPluginABI ("core", CORE_ABIVERSION))
+ return FALSE;
+
+ vd = malloc (sizeof (VigoDisplay));
+ if (!vd)
+ return FALSE;
+
+ vd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (vd->screenPrivateIndex < 0)
+ {
+ free (vd);
+ return FALSE;
+ }
+
+ d->base.privates[displayPrivateIndex].ptr = vd;
+
+ vigoSetRaiseOrLowerInitiate (d, vigoROL);
+ vigoSetMoveInInitiate (d, vigoGoInOut);
+ vigoSetMoveOutInitiate (d, vigoGoInOut);
+ vigoSetMoveLeftInitiate (d, vigoGoto);
+ vigoSetMoveRightInitiate (d, vigoGoto);
+ vigoSetMoveUpInitiate (d, vigoGoto);
+ vigoSetMoveDownInitiate (d, vigoGoto);
+ vigoSetMarkWindowInitiate (d, vigoMark);
+ vigoSetMarkGotoInitiate (d, vigoGotoMark);
+
+ WRAP (vd, d, handleEvent, vigoHandleEvent);
+
+ return TRUE;
+}
+
+static Bool
+vigoInitWindow (CompPlugin *p,
+ CompWindow *w)
+{
+ VigoWindow *vw;
+ VIGO_SCREEN (w->screen);
+ vw = malloc (sizeof (VigoWindow));
+ if (!vw)
+ return FALSE;
+ w->base.privates[vs->windowPrivateIndex].ptr = vw;
+ return TRUE;
+}
+
+static void
+vigoFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ VIGO_DISPLAY (d);
+ UNWRAP (vd, d, handleEvent);
+ freeScreenPrivateIndex (d, vd->screenPrivateIndex);
+ free (vd);
+}
+
+static void
+vigoFiniWindow (CompPlugin *p,
+ CompWindow *w)
+{
+ VIGO_WINDOW (w);
+ free (vw);
+}
+
+static Bool
+vigoInitScreen (CompPlugin *p,
+ CompScreen *s) {
+ VigoScreen *vs;
+ VIGO_DISPLAY (s->display);
+ vs = malloc (sizeof (VigoScreen));
+ if (!vs)
+ return FALSE;
+ vs->windowPrivateIndex = allocateWindowPrivateIndex (s);
+ vs->grabIndex = 0;
+ vs->grab = VIGO_GRAB_NONE;
+ vs->grabWin = NULL;
+ vs->nextFocus = NULL;
+ if (vs->windowPrivateIndex < 0)
+ {
+ free (vs);
+ return FALSE;
+ }
+ s->base.privates[vd->screenPrivateIndex].ptr = vs;
+ return TRUE;
+}
+
+static void
+vigoFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ VIGO_SCREEN (s);
+ freeWindowPrivateIndex (s, vs->windowPrivateIndex);
+ free (vs);
+}
+
+static Bool
+vigoInit (CompPlugin *p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+vigoFini (CompPlugin *p)
+{
+ freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+static CompBool
+vigoInitObject (CompPlugin *p,
+ CompObject *o)
+{
+ static InitPluginObjectProc dispTab[] = {
+ (InitPluginObjectProc) 0, /* InitCore */
+ (InitPluginObjectProc) vigoInitDisplay,
+ (InitPluginObjectProc) vigoInitScreen,
+ (InitPluginObjectProc) vigoInitWindow,
+ };
+ RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
+}
+
+static void
+vigoFiniObject (CompPlugin *p,
+ CompObject *o)
+{
+ static FiniPluginObjectProc dispTab[] = {
+ (FiniPluginObjectProc) 0, /* FiniCore */
+ (FiniPluginObjectProc) vigoFiniDisplay,
+ (FiniPluginObjectProc) vigoFiniScreen,
+ (FiniPluginObjectProc) vigoFiniWindow,
+ };
+
+ DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
+}
+
+CompPluginVTable vigoVTable = {
+ "vigo",
+ 0,
+ vigoInit,
+ vigoFini,
+ vigoInitObject,
+ vigoFiniObject,
+ 0,
+ 0
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ return &vigoVTable;
+}
+
+// vim: formatoptions=croqlt ts=8 softtabstop=4 shiftwidth=4 cindent tw=80 cino=(0,t0
diff --git a/vigo.xml.in b/vigo.xml.in
new file mode 100644
index 0000000..8519d1b
--- /dev/null
+++ b/vigo.xml.in
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<compiz>
+ <plugin name="vigo" useBcop="true">
+ <_short>Vigo</_short>
+ <_long>Go to window in specific direction</_long>
+ <category>Window Management</category>
+ <display>
+ <group>
+ <_short>Options</_short>
+ <option name="move_left" type="key">
+ <_short>Go left</_short>
+ <_long>Go left</_long>
+ <default>&lt;Super&gt;Left</default>
+ </option>
+ <option name="move_right" type="key">
+ <_short>Go right</_short>
+ <_long>Go right</_long>
+ <default>&lt;Super&gt;Right</default>
+ </option>
+ <option name="move_up" type="key">
+ <_short>Go up</_short>
+ <_long>Go up</_long>
+ <default>&lt;Super&gt;Up</default>
+ </option>
+ <option name="move_down" type="key">
+ <_short>Go down</_short>
+ <_long>Go down</_long>
+ <default>&lt;Super&gt;Down</default>
+ </option>
+ <option name="raise_or_lower" type="key">
+ <_short>Raise or lower</_short>
+ <_long>Raise or lower</_long>
+ <default>&lt;Super&gt;space</default>
+ </option>
+ <option name="move_in" type="key">
+ <_short>Go in</_short>
+ <_long>Go in</_long>
+ </option>
+ <option name="move_out" type="key">
+ <_short>Go out</_short>
+ <_long>Go out</_long>
+ </option>
+ <option name="mark_window" type="key">
+ <_short>Mark window</_short>
+ <_long>Mark window, next key you press is the mark</_long>
+ <default>&lt;Super&gt;m</default>
+ </option>
+ <option name="mark_goto" type="key">
+ <_short>Go to a mark</_short>
+ <_long>Go to a mark, next key you press is the mark</_long>
+ <default>&lt;Super&gt;g</default>
+ </option>
+ <option name="move_match" type="match">
+ <_short>Window Match</_short>
+ <_long>Windows we may go to </_long>
+ <default>type=Toolbar | Normal | Dialog | Utility | Unknown</default>
+ </option>
+ </group>
+ </display>
+ </plugin>
+</compiz>