diff options
-rw-r--r-- | Makefile | 533 | ||||
-rw-r--r-- | dummy | 0 | ||||
-rw-r--r-- | mousetrails.c | 941 | ||||
-rw-r--r-- | mousetrails.xml.in | 97 | ||||
-rw-r--r-- | plugin.info | 3 |
5 files changed, 1574 insertions, 0 deletions
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/mousetrails.c b/mousetrails.c new file mode 100644 index 0000000..63451cd --- /dev/null +++ b/mousetrails.c @@ -0,0 +1,941 @@ +/* + * + * Compiz mouse cursor trails plugin + * + * mousetrails.c + * + * Copyright : (C) 2008 by Erik Johnson + * + * From code originally written by Dennis Kasprzyk + * + * 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 <math.h> +#include <string.h> + +#include <compiz-core.h> +#include <compiz-mousepoll.h> + +#include "mousetrails_options.h" + +#define GET_MOUSETRAILS_DISPLAY(d) \ + ((mousetrailsDisplay *) (d)->base.privates[displayPrivateIndex].ptr) + +#define MOUSETRAILS_DISPLAY(d) \ + mousetrailsDisplay *sd = GET_MOUSETRAILS_DISPLAY (d) + +#define GET_MOUSETRAILS_SCREEN(s, sd) \ + ((mousetrailsScreen *) (s)->base.privates[(sd)->screenPrivateIndex].ptr) + +#define MOUSETRAILS_SCREEN(s) \ + mousetrailsScreen *ss = GET_MOUSETRAILS_SCREEN (s, GET_MOUSETRAILS_DISPLAY (s->display)) + +// in theory the texture array size should be >= trail size +#define TEXTURES_SIZE 64 + +int mousetrailsCursorUpdate (CompScreen *s); + +typedef struct _Particle +{ + float life; // particle life + float fade; // fade speed + float width; // particle width + float height; // particle height + float w_mod; // particle size modification during life + float h_mod; // particle size modification during life + float r; // red value + float g; // green value + float b; // blue value + float a; // alpha value + float x; // X position + float y; // Y position + float z; // Z position + int cursorIndex; // array index of cursor serial number +} Particle; + +typedef struct _MouseCursor +{ + GLuint texture; + unsigned long cursor_serial; + unsigned short xhot; + unsigned short yhot; + unsigned short width; + unsigned short height; +} MouseCursor; + +typedef struct _ParticleSystem +{ + int numParticles; + Particle *particles; + float slowdown; + float threshold; + Bool active; + int x, y; + GLuint blendMode; + + int lastx, lasty; + float delta; + int numDisplayedParticles; + int lastGen; + float initialAlpha; + int sizeFactor; + + // for random colors + int colorcounter; + float r; // red value + float g; // green value + float b; // blue value + float r2; // red value + float g2; // green value + float b2; // blue value + int colorrate; + + // Cursor data + MouseCursor cursors[TEXTURES_SIZE]; // rolling array of cursors grabbed from x + int lastTextureFilled; // last slot used in textures + unsigned long lastCursorSerial; // last cursor serial number grabbed from X + int lastCursorIndex; // ...and its associated array index + + // Moved from drawParticles to get rid of spurious malloc's + GLfloat *vertices_cache; + int vertex_cache_count; + GLfloat *coords_cache; + int coords_cache_count; + GLfloat *colors_cache; + int color_cache_count; + + +} ParticleSystem; + + +static int displayPrivateIndex = 0; + +typedef struct _mousetrailsDisplay +{ + int screenPrivateIndex; + + MousePollFunc *mpFunc; +} +mousetrailsDisplay; + +typedef struct _mousetrailsScreen +{ + int posX; + int posY; + + Bool active; + + ParticleSystem *ps; + + PositionPollingHandle pollHandle; + + PreparePaintScreenProc preparePaintScreen; + DonePaintScreenProc donePaintScreen; + PaintOutputProc paintOutput; +} +mousetrailsScreen; + +static void +initParticles (int numParticles, ParticleSystem * ps) +{ + + if (ps->particles) + free(ps->particles); + ps->particles = calloc(numParticles, sizeof(Particle)); + + ps->numParticles = numParticles; + ps->numDisplayedParticles = 0; + ps->slowdown = 1; + ps->active = FALSE; + ps->lastx = 0; + ps->lasty = 0; + ps->lastGen = 0; + ps->initialAlpha = 1; + ps->sizeFactor = 10; + ps->colorcounter = 0; + + ps->lastTextureFilled = -1; + ps->lastCursorIndex = 0; + ps->lastCursorSerial = 0; + + // Initialize cache + ps->vertices_cache = NULL; + ps->colors_cache = NULL; + ps->coords_cache = NULL; + ps->vertex_cache_count = 0; + ps->color_cache_count = 0; + ps->coords_cache_count = 0; + + Particle *part = ps->particles; + int i; + for (i = 0; i < numParticles; i++, part++) + part->life = 0.0f; + + for (i = 0; i < TEXTURES_SIZE; i++){ + ps->cursors[i].cursor_serial = 0; + ps->cursors[i].xhot = 0; + ps->cursors[i].yhot = 0; + ps->cursors[i].width = 0; + ps->cursors[i].height = 0; + } + + for (i = 0; i < TEXTURES_SIZE; i++) glGenTextures(1, &ps->cursors[i].texture); + +} + +static void +drawParticles (CompScreen * s, ParticleSystem * ps) +{ + + glEnable(GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glEnableClientState(GL_COLOR_ARRAY); + glBlendFunc(GL_SRC_ALPHA, ps->blendMode); + glEnable(GL_TEXTURE_2D); + + + // Check that the caches are correct size + + if (ps->vertex_cache_count != 1) + { + ps->vertices_cache = + realloc(ps->vertices_cache, + 4 * 3 * sizeof(GLfloat)); + ps->vertex_cache_count = 1; + } + + if (ps->coords_cache_count != 1) + { + ps->coords_cache = + realloc(ps->coords_cache, + 4 * 2 * sizeof(GLfloat)); + ps->coords_cache_count = 1; + } + + if (ps->color_cache_count != 1) + { + ps->colors_cache = + realloc(ps->colors_cache, + 4 * 4 * sizeof(GLfloat)); + ps->color_cache_count = 1; + } + + + GLfloat *vertices = ps->vertices_cache; + GLfloat *coords = ps->coords_cache; + GLfloat *colors = ps->colors_cache; + + int cornersSize = sizeof (GLfloat) * 8; + int colorSize = sizeof (GLfloat) * 4; + + GLfloat cornerCoords[8] = {0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0, + 1.0, 0.0}; + + int numActive = 0; + + Particle *part = ps->particles; + int i; + for (i = 0; i < ps->numParticles; i++, part++) + { + if (part->life > 0.0f) + { + numActive += 4; + + float w = part->width / 2; + float h = part->height / 2; + + w += (w * part->w_mod) * (1- part->life); + h += (h * part->h_mod) * (1- part->life); + + vertices[0] = part->x - w; + vertices[1] = part->y - h; + vertices[2] = part->z; + + vertices[3] = part->x - w; + vertices[4] = part->y + h; + vertices[5] = part->z; + + vertices[6] = part->x + w; + vertices[7] = part->y + h; + vertices[8] = part->z; + + vertices[9] = part->x + w; + vertices[10] = part->y - h; + vertices[11] = part->z; + + //vertices += 12; + + memcpy (coords, cornerCoords, cornersSize); + + //coords += 8; + + colors[0] = part->r; + colors[1] = part->g; + colors[2] = part->b; + colors[3] = part->life * part->a * ps->initialAlpha; + memcpy (colors + 4, colors, colorSize); + memcpy (colors + 8, colors, colorSize); + memcpy (colors + 12, colors, colorSize); + + //colors += 16; + + if (ps->cursors[part->cursorIndex].texture) + { + glPushMatrix(); + + glBindTexture(GL_TEXTURE_2D, ps->cursors[part->cursorIndex].texture); + + glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), ps->coords_cache); + glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), ps->vertices_cache); + glColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), ps->colors_cache); + + // draw particles + glDrawArrays(GL_QUADS, 0, numActive); + + glPopMatrix(); + } + + } + + } + + + glDisableClientState(GL_COLOR_ARRAY); + glColor4usv(defaultColor); + screenTexEnvMode(s, GL_REPLACE); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + +} + +static void +updateParticles (ParticleSystem * ps, float time) +{ + int i; + Particle *part; + float speed = (time / 50.0); + + ps->active = FALSE; + + part = ps->particles; + + for (i = 0; i < ps->numParticles; i++, part++) + { + if (part->life > 0.0f) + { + // modify life + part->life -= part->fade * speed; + ps->active = TRUE; + } + } +} + +static void +finiParticles (ParticleSystem * ps) +{ + free(ps->particles); + if (ps->vertices_cache) + free(ps->vertices_cache); + if (ps->colors_cache) + free(ps->colors_cache); + if (ps->coords_cache) + free(ps->coords_cache); + + int i; + for (i = 0; i < TEXTURES_SIZE; i++) glDeleteTextures(1, &ps->cursors[i].texture); + +} + +static void +genNewParticles(CompScreen *s, + ParticleSystem *ps, + int time) +{ + + MOUSETRAILS_SCREEN(s); + + + Bool rColor = mousetrailsGetRandom (s); + float life = mousetrailsGetLife (s); + int sizeFactor = ps->sizeFactor; + float threshold = ps->threshold; + float lifeNeg = 1 - life; + float fadeExtra = 0.2f * (1.01 - life); + float max_new = 0; + int cursorIndex = 0; + + unsigned short *c = mousetrailsGetColor (s); + + float colr1 = (float)c[0] / 0xffff; + float colg1 = (float)c[1] / 0xffff; + float colb1 = (float)c[2] / 0xffff; + float cola = (float)c[3] / 0xffff; + + float partw = ps->cursors[ps->lastCursorIndex].width; + float parth = ps->cursors[ps->lastCursorIndex].height; + + float partoffw = ps->cursors[ps->lastCursorIndex].xhot; + float partoffh = ps->cursors[ps->lastCursorIndex].yhot; + + int newx = (float)(ss->posX + partw/2 - partoffw); + int newy = (float)(ss->posY + parth/2 - partoffh); + int deltax = newx - ps->lastx; + int deltay = newy - ps->lasty; + int delta = deltax * deltax + deltay * deltay; + + // possibly crashy + /*if (mousetrailsGetNumParticles(s) != ps->numParticles){ + initParticles(mousetrailsGetNumParticles (s), ss->ps); + }*/ + + Particle *part = ps->particles; + int i; + + if (delta > threshold * threshold) max_new = 1; + + int nextGen = (ps->lastGen + 1) % ps->numParticles; + + for (i = 0; i < ps->numParticles && max_new > 0; i++, part++) + { + if (i == nextGen) + { + // record the particle number being generated + ps->lastGen = i; + + cursorIndex = mousetrailsCursorUpdate(s); + + ps->slowdown = mousetrailsGetSlowdown (s); + ps->initialAlpha = mousetrailsGetAlpha (s) ; + ps->sizeFactor = mousetrailsGetSize (s) ; + ps->threshold = mousetrailsGetThreshold (s) ; + ss->ps->colorrate = mousetrailsGetColorrate (s) ; + + // set the cursor array index + part->cursorIndex = ps->lastCursorIndex = cursorIndex; + + // give gt new life + part->life = 1.0f; + part->fade = (sqrt(ps->slowdown-0.9)/50.0) * lifeNeg + fadeExtra; + + // set size + part->width = partw; + part->height = parth; + part->w_mod = part->h_mod = ((float)sizeFactor - 10.0) / 10.0; + + // set position + part->x = newx; + part->y = newy; + ps->lastx = newx; + ps->lasty = newy; + part->z = 0.0; + + if (rColor) + { + if (ps->colorcounter == 0) + { + ps->r2 = (float)(random() & 0xff) / 255; + ps->g2 = (float)(random() & 0xff) / 255; + ps->b2 = (float)(random() & 0xff) / 255; + } + ps->r = ((float)ps->colorrate - ps->colorcounter)/(float)ps->colorrate * ps->r + ps->colorcounter/(float)ps->colorrate * ps->r2; + ps->g = ((float)ps->colorrate - ps->colorcounter)/(float)ps->colorrate * ps->g + ps->colorcounter/(float)ps->colorrate * ps->g2; + ps->b = ((float)ps->colorrate - ps->colorcounter)/(float)ps->colorrate * ps->b + ps->colorcounter/(float)ps->colorrate * ps->b2; + part->r = ps->r; + part->g = ps->g; + part->b = ps->b; + ps->colorcounter = (ps->colorcounter + 1) % ps->colorrate; + } + else + { + part->r = colr1; + part->g = colg1; + part->b = colb1; + } + // set transparancy + part->a = cola; + + ps->active = TRUE; + max_new -= 1; + } + } +} + + +static void +damageRegion (CompScreen *s) +{ + REGION r; + int i; + Particle *p; + float w, h, x1, x2, y1, y2; + + MOUSETRAILS_SCREEN (s); + + if (!ss->ps) + return; + + x1 = s->width; + x2 = 0; + y1 = s->height; + y2 = 0; + + p = ss->ps->particles; + + for (i = 0; i < ss->ps->numParticles; i++, p++) + { + w = p->width / 2; + h = p->height / 2; + + w += (w * p->w_mod) * p->life; + h += (h * p->h_mod) * p->life; + + x1 = MIN (x1, p->x - w); + x2 = MAX (x2, p->x + w); + y1 = MIN (y1, p->y - h); + y2 = MAX (y2, p->y + h); + } + + r.rects = &r.extents; + r.numRects = r.size = 1; + + r.extents.x1 = floor (x1); + r.extents.x2 = ceil (x2); + r.extents.y1 = floor (y1); + r.extents.y2 = ceil (y2); + + damageScreenRegion (s, &r); +} + + +int mousetrailsCursorUpdate (CompScreen *s) +{ + MOUSETRAILS_SCREEN (s); + + Display * dpy = s->display->display; + XFixesCursorImage *ci = XFixesGetCursorImage(dpy); + /* Hack to avoid changing to an invisible (bugged)cursor image. + * Example: The animated firefox cursors. + */ + if (ci->width <= 1 && ci->height <= 1) + { + XFree (ci); + return ss->ps->lastCursorIndex; + } + + // only update cursor if necessary (instead of all the time) + if (ci->cursor_serial == ss->ps->lastCursorSerial) + { + XFree (ci); + return ss->ps->lastCursorIndex; + } + + // see if cursor already exists in textures + int i; + for (i = 0; i < TEXTURES_SIZE; i++){ + if (ci->cursor_serial == ss->ps->cursors[i].cursor_serial){ + ss->ps->lastCursorSerial = ci->cursor_serial; + XFree (ci); + return i; + } + } + + // otherwise grab the new cursor into textures + int fillTexture = (ss->ps->lastTextureFilled + 1) % TEXTURES_SIZE; + + unsigned char *pixels = malloc(ci->width * ci->height * 4); + + for (i = 0; i < ci->width * ci->height; i++) + { + unsigned long pix = ci->pixels[i]; + pixels[i * 4] = pix & 0xff; + pixels[(i * 4) + 1] = (pix >> 8) & 0xff; + pixels[(i * 4) + 2] = (pix >> 16) & 0xff; + pixels[(i * 4) + 3] = (pix >> 24) & 0xff; + } + + glBindTexture(GL_TEXTURE_2D, ss->ps->cursors[fillTexture].texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ci->width, ci->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, pixels); + glBindTexture(GL_TEXTURE_2D, 0); + + // save data for this cursor + ss->ps->cursors[fillTexture].cursor_serial = ss->ps->lastCursorSerial = ci->cursor_serial; + ss->ps->cursors[fillTexture].xhot = ci->xhot; + ss->ps->cursors[fillTexture].yhot = ci->yhot; + ss->ps->cursors[fillTexture].width = ci->width; + ss->ps->cursors[fillTexture].height = ci->height; + ss->ps->lastTextureFilled = fillTexture; + + XFree (ci); + free (pixels); + + return fillTexture; +} + + +static void +positionUpdate (CompScreen *s, + int x, + int y) +{ + MOUSETRAILS_SCREEN (s); + + ss->posX = x; + ss->posY = y; +} + + + +static void +mousetrailsPreparePaintScreen (CompScreen *s, + int time) +{ + + MOUSETRAILS_SCREEN (s); + MOUSETRAILS_DISPLAY (s->display); + + if (ss->active && !ss->pollHandle) + { + (*sd->mpFunc->getCurrentPosition) (s, &ss->posX, &ss->posY); + ss->pollHandle = (*sd->mpFunc->addPositionPolling) (s, positionUpdate); + } + + if (ss->active && !ss->ps) + { + ss->ps = calloc(1, sizeof(ParticleSystem)); + if (!ss->ps) + { + UNWRAP (ss, s, preparePaintScreen); + (*s->preparePaintScreen) (s, time); + WRAP (ss, s, preparePaintScreen, mousetrailsPreparePaintScreen); + return; + } + initParticles(mousetrailsGetNumParticles (s), ss->ps); + + ss->ps->slowdown = mousetrailsGetSlowdown (s); + ss->ps->initialAlpha = mousetrailsGetAlpha (s) ; + ss->ps->threshold = mousetrailsGetThreshold (s) ; + ss->ps->colorrate = mousetrailsGetColorrate (s) ; + ss->ps->sizeFactor = mousetrailsGetSize (s) ; + ss->ps->blendMode = GL_ONE_MINUS_SRC_ALPHA; + + mousetrailsCursorUpdate(s); + + } + + + if (ss->ps && ss->ps->active) + { + updateParticles (ss->ps, time); + damageRegion (s); + } + + if (ss->ps && ss->active) + genNewParticles (s, ss->ps, time); + + UNWRAP (ss, s, preparePaintScreen); + (*s->preparePaintScreen) (s, time); + WRAP (ss, s, preparePaintScreen, mousetrailsPreparePaintScreen); + +} + + +static void +mousetrailsDonePaintScreen (CompScreen *s) +{ + MOUSETRAILS_SCREEN (s); + MOUSETRAILS_DISPLAY (s->display); + + if (ss->active || (ss->ps && ss->ps->active)) + damageRegion (s); + + if (!ss->active && ss->pollHandle) + { + (*sd->mpFunc->removePositionPolling) (s, ss->pollHandle); + ss->pollHandle = 0; + } + + if (!ss->active && ss->ps && !ss->ps->active) + { + finiParticles (ss->ps); + free (ss->ps); + ss->ps = NULL; + } + + UNWRAP (ss, s, donePaintScreen); + (*s->donePaintScreen) (s); + WRAP (ss, s, donePaintScreen, mousetrailsDonePaintScreen); +} + +static Bool +mousetrailsPaintOutput (CompScreen *s, + const ScreenPaintAttrib *sa, + const CompTransform *transform, + Region region, + CompOutput *output, + unsigned int mask) +{ + Bool status; + CompTransform sTransform; + + MOUSETRAILS_SCREEN (s); + + UNWRAP (ss, s, paintOutput); + status = (*s->paintOutput) (s, sa, transform, region, output, mask); + WRAP (ss, s, paintOutput, mousetrailsPaintOutput); + + if (!ss->ps || !ss->ps->active) + return status; + + matrixGetIdentity (&sTransform); + + transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform); + + glPushMatrix (); + glLoadMatrixf (sTransform.m); + + drawParticles (s, ss->ps); + + glPopMatrix(); + + glColor4usv (defaultColor); + + return status; +} + +static Bool +mousetrailsTerminate (CompDisplay *d, + CompAction *action, + CompActionState state, + CompOption *option, + int nOption) +{ + CompScreen *s; + Window xid; + + xid = getIntOptionNamed (option, nOption, "root", 0); + + s = findScreenAtDisplay (d, xid); + if (s) + { + MOUSETRAILS_SCREEN (s); + + ss->active = FALSE; + damageRegion (s); + + return TRUE; + } + return FALSE; +} + +static Bool +mousetrailsInitiate (CompDisplay *d, + CompAction *action, + CompActionState state, + CompOption *option, + int nOption) +{ + + CompScreen *s; + Window xid; + + xid = getIntOptionNamed (option, nOption, "root", 0); + + s = findScreenAtDisplay (d, xid); + if (s) + { + MOUSETRAILS_SCREEN (s); + + if (ss->active) + return mousetrailsTerminate (d, action, state, option, nOption); + + ss->active = TRUE; + + return TRUE; + } + return FALSE; +} + + +static Bool +mousetrailsInitScreen (CompPlugin *p, + CompScreen *s) +{ + + MOUSETRAILS_DISPLAY (s->display); + + mousetrailsScreen *ss = (mousetrailsScreen *) calloc (1, sizeof (mousetrailsScreen) ); + + if (!ss) + return FALSE; + + s->base.privates[sd->screenPrivateIndex].ptr = ss; + + WRAP (ss, s, paintOutput, mousetrailsPaintOutput); + WRAP (ss, s, preparePaintScreen, mousetrailsPreparePaintScreen); + WRAP (ss, s, donePaintScreen, mousetrailsDonePaintScreen); + + ss->active = FALSE; + + ss->pollHandle = 0; + + ss->ps = NULL; + + return TRUE; +} + + +static void +mousetrailsFiniScreen (CompPlugin *p, + CompScreen *s) +{ + MOUSETRAILS_SCREEN (s); + MOUSETRAILS_DISPLAY (s->display); + + //Restore the original function + UNWRAP (ss, s, paintOutput); + UNWRAP (ss, s, preparePaintScreen); + UNWRAP (ss, s, donePaintScreen); + + if (ss->pollHandle) + (*sd->mpFunc->removePositionPolling) (s, ss->pollHandle); + + if (ss->ps && ss->ps->active) + damageScreen (s); + + //Free the pointer + free (ss); +} + +static Bool +mousetrailsInitDisplay (CompPlugin *p, + CompDisplay *d) +{ + + //Generate a mousetrails display + mousetrailsDisplay *sd; + int index; + + if (!checkPluginABI ("core", CORE_ABIVERSION) || + !checkPluginABI ("mousepoll", MOUSEPOLL_ABIVERSION)) + return FALSE; + + if (!getPluginDisplayIndex (d, "mousepoll", &index)) + return FALSE; + + sd = (mousetrailsDisplay *) malloc (sizeof (mousetrailsDisplay)); + + if (!sd) + return FALSE; + + //Allocate a private index + sd->screenPrivateIndex = allocateScreenPrivateIndex (d); + + //Check if its valid + if (sd->screenPrivateIndex < 0) + { + //Its invalid so free memory and return + free (sd); + return FALSE; + } + + sd->mpFunc = d->base.privates[index].ptr; + + mousetrailsSetInitiateInitiate (d, mousetrailsInitiate); + mousetrailsSetInitiateTerminate (d, mousetrailsTerminate); + + //Record the display + d->base.privates[displayPrivateIndex].ptr = sd; + return TRUE; +} + +static void +mousetrailsFiniDisplay (CompPlugin *p, + CompDisplay *d) +{ + MOUSETRAILS_DISPLAY (d); + //Free the private index + freeScreenPrivateIndex (d, sd->screenPrivateIndex); + //Free the pointer + free (sd); +} + + + +static Bool +mousetrailsInit (CompPlugin * p) +{ + displayPrivateIndex = allocateDisplayPrivateIndex(); + + if (displayPrivateIndex < 0) + return FALSE; + + return TRUE; +} + +static void +mousetrailsFini (CompPlugin * p) +{ + if (displayPrivateIndex >= 0) + freeDisplayPrivateIndex (displayPrivateIndex); +} + +static CompBool +mousetrailsInitObject (CompPlugin *p, + CompObject *o) +{ + static InitPluginObjectProc dispTab[] = { + (InitPluginObjectProc) 0, /* InitCore */ + (InitPluginObjectProc) mousetrailsInitDisplay, + (InitPluginObjectProc) mousetrailsInitScreen + }; + + RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o)); +} + +static void +mousetrailsFiniObject (CompPlugin *p, + CompObject *o) +{ + static FiniPluginObjectProc dispTab[] = { + (FiniPluginObjectProc) 0, /* FiniCore */ + (FiniPluginObjectProc) mousetrailsFiniDisplay, + (FiniPluginObjectProc) mousetrailsFiniScreen + }; + + DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o)); +} + +CompPluginVTable mousetrailsVTable = { + "mousetrails", + 0, + mousetrailsInit, + mousetrailsFini, + mousetrailsInitObject, + mousetrailsFiniObject, + 0, + 0 +}; + +CompPluginVTable * +getCompPluginInfo (void) +{ + return &mousetrailsVTable; +} diff --git a/mousetrails.xml.in b/mousetrails.xml.in new file mode 100644 index 0000000..dea4b5f --- /dev/null +++ b/mousetrails.xml.in @@ -0,0 +1,97 @@ +<?xml version="1.0"?> +<compiz> + <plugin name="mousetrails" useBcop="true"> + <_short>Mouse Trails</_short> + <_long>Adds trails that follow the mouse pointer</_long> + <category>Accessibility</category> + <deps> + <relation type="after"> + <plugin>cube</plugin> + </relation> + <requirement> + <plugin>mousepoll</plugin> + </requirement> + </deps> + <display> + <group> + <_short>General</_short> + <option name="initiate" type="key"> + <_short>Initiate</_short> + <_long>Toggle the mouse pointer trail.</_long> + <default><Super>t</default> + </option> + </group> + </display> + <screen> + <group> + <_short>Trail Options</_short> + <option name="num_particles" type="int"> + <_short>Trail Length</_short> + <_long>Length of the mouse trail</_long> + <default>20</default> + <min>1</min> + <max>50</max> + </option> + <option name="alpha" type="float"> + <_short>Initial Opacity</_short> + <_long>Initial opacity of the trails elements.</_long> + <default>0.5</default> + <min>0.1</min> + <max>1.0</max> + <precision>0.1</precision> + </option> + <option name="slowdown" type="float"> + <_short>Fade Rate</_short> + <_long>The rate that trail elements fade out.</_long> + <default>5</default> + <min>1</min> + <max>10</max> + </option> + <option name="threshold" type="int"> + <_short>Threshold</_short> + <_long>The minimum distance from the current mouse position before creating a trail element.</_long> + <default>5</default> + <min>1</min> + <max>100</max> + </option> + <option name="size" type="int"> + <_short>Size</_short> + <_long>The size of the cursor elements in the trail.</_long> + <default>10</default> + <min>1</min> + <max>10</max> + </option> + <option name="life" type="float"> + <_short>Trail Life</_short> + <_long>Trail life.</_long> + <default>0.4</default> + <min>0.1</min> + <max>1</max> + <precision>0.1</precision> + </option> + <option name="color" type="color"> + <_short>Trail Color</_short> + <_long>Trail color.</_long> + <default> + <red>0xffff</red> + <green>0xffff</green> + <blue>0xffff</blue> + <alpha>0xffff</alpha> + </default> + </option> + <option name="random" type="bool"> + <_short>Randomly Colored Trails</_short> + <_long>Have random colors for the trails.</_long> + <default>false</default> + </option> + <option name="colorrate" type="int"> + <_short>Color Change Rate</_short> + <_long>Rate the colors change.</_long> + <default>10</default> + <min>2</min> + <max>1000</max> + </option> + </group> + </screen> + </plugin> +</compiz> diff --git a/plugin.info b/plugin.info new file mode 100644 index 0000000..f174f18 --- /dev/null +++ b/plugin.info @@ -0,0 +1,3 @@ +PLUGIN = mousetrails +PKG_DEP = compiz-mousepoll +CHK_HEADERS = compiz-mousepoll.h |