summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Kasprzyk <onestone@beryl-project.org>2007-05-17 13:03:09 +0200
committerDennis Kasprzyk <onestone@beryl-project.org>2007-05-17 13:03:09 +0200
commitd57e311305741538dd1f3be662eb035d024feb8f (patch)
tree37b12457daa3da9089356e86c911d93713ba381a
parent2be25a0c887de5c22057b41de9ce71d8fd6e0cb2 (diff)
downloadshowdesktop-d57e311305741538dd1f3be662eb035d024feb8f.tar.gz
showdesktop-d57e311305741538dd1f3be662eb035d024feb8f.tar.bz2
initial commit
-rw-r--r--Makefile218
-rw-r--r--dummy0
-rw-r--r--showdesktop.c821
-rw-r--r--showdesktop.xml88
4 files changed, 1127 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e2a98a2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,218 @@
+##
+#
+# Compiz plugin Makefile
+#
+# Copyright : (C) 2006 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.
+#
+##
+
+## configuration
+
+#enter plugin name here
+PLUGIN = showdesktop
+
+#enter dependencies here
+PKG_DEP =
+
+## end of configuration
+
+#enter beryl or compiz here
+TARGET = compiz
+
+ifeq ($(BUILD_GLOBAL),true)
+ DESTDIR = $(shell pkg-config --variable=libdir compiz)/compiz
+ XMLDIR = $(shell pkg-config --variable=prefix compiz)/share/compiz
+else
+ DESTDIR = $(HOME)/.$(TARGET)/plugins
+ XMLDIR = $(HOME)/.$(TARGET)/metadata
+endif
+
+BUILDDIR = build
+
+CC = gcc
+LIBTOOL = libtool
+INSTALL = install
+
+BCOP = `pkg-config --variable=bin bcop`
+
+CFLAGS = -g -Wall `pkg-config --cflags $(PKG_DEP) $(TARGET) `
+LDFLAGS = `pkg-config --libs $(PKG_DEP) $(TARGET) `
+
+is-bcop-target := $(shell if [ -e $(PLUGIN).xml ]; then cat $(PLUGIN).xml | grep "useBcop=\"true\"";fi )
+
+bcop-target := $(shell if [ -n "$(is-bcop-target)" ]; then echo $(PLUGIN).xml; fi )
+bcop-target-src := $(shell if [ -n "$(is-bcop-target)" ]; then echo $(PLUGIN)_options.c; fi )
+bcop-target-hdr := $(shell if [ -n "$(is-bcop-target)" ]; then echo $(PLUGIN)_options.h; fi )
+
+gen-schemas := $(shell if [ -e $(PLUGIN).xml ] && [ -n `pkg-config --variable=xsltdir compiz-gconf` ]; then echo true; fi )
+schema-target := $(shell if [ -n "$(gen-schemas)" ]; then echo $(PLUGIN).xml; fi )
+schema-output := $(shell if [ -n "$(gen-schemas)" ]; then echo compiz-$(PLUGIN).schema; fi )
+
+# find all the object files (including those from .moc.cpp files)
+
+c-objs := $(patsubst %.c,%.lo,$(shell find -name '*.c' 2> /dev/null | grep -v "$(BUILDDIR)/" | sed -e 's/^.\///'))
+c-objs := $(filter-out $(bcop-target-src:.c=.lo),$(c-objs))
+c-objs += $(bcop-target-src:.c=.lo)
+
+# 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)
+
+# default color settings
+color := $(shell if [ $$TERM = "dumb" ]; then echo "no"; else echo "yes"; fi)
+
+#
+# Do it.
+#
+
+.PHONY: $(BUILDDIR) build-dir bcop-build schema-creation c-build-objs c-link-plugin
+
+all: $(BUILDDIR) build-dir bcop-build schema-creation c-build-objs c-link-plugin
+
+bcop-build: $(bcop-target-hdr) $(bcop-target-src)
+
+schema-creation: $(schema-output)
+
+c-build-objs: $(addprefix $(BUILDDIR)/,$(cxx-objs))
+
+c-link-plugin: $(BUILDDIR)/lib$(PLUGIN).la
+
+#
+# Create build directory
+#
+
+$(BUILDDIR) :
+ @mkdir -p $(BUILDDIR)
+
+$(DESTDIR) :
+ @mkdir -p $(DESTDIR)
+
+#
+# BCOP'ing
+
+%_options.h: %.xml
+ @if [ '$(color)' != 'no' ]; then \
+ echo -e -n "\033[0;1;5mbcop'ing \033[0;1;37m: \033[0;32m$< \033[0;1;37m-> \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
+
+%_options.c: %.xml
+ @if [ '$(color)' != 'no' ]; then \
+ echo -e -n "\033[0;1;5mbcop'ing \033[0;1;37m: \033[0;32m$< \033[0;1;37m-> \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
+
+compiz-%.schema: %.xml
+ @if [ '$(color)' != 'no' ]; then \
+ echo -e -n "\033[0;1;5mschema \033[0;1;37m: \033[0;32m$< \033[0;1;37m-> \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
+
+
+
+#
+# Compiling
+#
+
+$(BUILDDIR)/%.lo: %.c
+ @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
+
+#
+# Linking
+#
+
+cxx-rpath-prefix := -Wl,-rpath,
+
+$(BUILDDIR)/lib$(PLUGIN).la: $(addprefix $(BUILDDIR)/,$(c-objs))
+ @if [ '$(color)' != 'no' ]; then \
+ echo -e -n "\033[0;1;5mlinking -> \033[0;31m$@\033[0m"; \
+ else \
+ echo "linking -> $@"; \
+ fi
+ @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) -rpath $(DESTDIR) -o $@ $(addprefix $(BUILDDIR)/,$(c-objs))
+ @if [ '$(color)' != 'no' ]; then \
+ echo -e "\r\033[0mlinking -> \033[34m$@\033[0m"; \
+ fi
+
+
+clean:
+ rm -rf $(BUILDDIR)
+ rm -f $(bcop-target-src)
+ rm -f $(bcop-target-hdr)
+ rm -f $(schema-output)
+
+install: $(DESTDIR) 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
+ @if [ -e $(PLUGIN).xml ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ echo -n -e "\033[0;1;5minstall \033[0;1;37m: \033[0;31m$(XMLDIR)/$(PLUGIN).xml\033[0m"; \
+ else \
+ echo "install : $(XMLDIR)/$(PLUGIN).xml"; \
+ fi; \
+ mkdir -p $(XMLDIR); \
+ cp $(PLUGIN).xml $(XMLDIR)/$(PLUGIN).xml; \
+ if [ '$(color)' != 'no' ]; then \
+ echo -e "\r\033[0minstall : \033[34m$(XMLDIR)/$(PLUGIN).xml\033[0m"; \
+ fi; \
+ fi
+ @if [ -e $(schema-output) ]; then \
+ if [ '$(color)' != 'no' ]; then \
+ echo -n -e "\033[0;1;5minstall \033[0;1;37m: \033[0;31m$(schema-output)\033[0m"; \
+ else \
+ echo "install : $(schema-output)"; \
+ fi; \
+ gconftool-2 --install-schema-file=$(schema-output) > /dev/null; \
+ if [ '$(color)' != 'no' ]; then \
+ echo -e "\r\033[0minstall : \033[34m$(schema-output)\033[0m"; \
+ fi; \
+ fi
+
+
+
+
diff --git a/dummy b/dummy
deleted file mode 100644
index e69de29..0000000
--- a/dummy
+++ /dev/null
diff --git a/showdesktop.c b/showdesktop.c
new file mode 100644
index 0000000..a1554d0
--- /dev/null
+++ b/showdesktop.c
@@ -0,0 +1,821 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * Give credit where credit is due, keep the authors message below.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * - Diogo Ferreira (playerX) <diogo@beryl-project.org>
+ * - Danny Baumann <maniac@beryl-project.org>
+ *
+ *
+ * Copyright (c) 2007 Diogo "playerX" Ferreira
+ *
+ * This wouldn't have been possible without:
+ * - Ideas from the compiz community (mainly throughnothing's)
+ * - David Reveman's work
+ *
+ * */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <compiz.h>
+#include "showdesktop_options.h"
+
+#include <math.h>
+
+#define WIN_X(w) ((w)->attrib.x - (w)->input.left)
+#define WIN_Y(w) ((w)->attrib.y - (w)->input.top)
+#define WIN_W(w) ((w)->width + (w)->input.left + (w)->input.right)
+#define WIN_H(w) ((w)->height + (w)->input.top + (w)->input.bottom)
+
+#define OFF_LEFT(w) ((w)->width + (w)->input.right)
+#define OFF_RIGHT(w) ((w)->input.left)
+#define OFF_TOP(w) ((w)->height + (w)->input.bottom)
+#define OFF_BOTTOM(w) ((w)->input.top)
+
+#define MOVE_LEFT(w) ((WIN_X(w) + (WIN_W(w)/2)) < ((w)->screen->width/2))
+#define MOVE_UP(w) ((WIN_Y(w) + (WIN_H(w)/2)) < ((w)->screen->height/2))
+
+#define SD_STATE_OFF 0
+#define SD_STATE_ACTIVATING 1
+#define SD_STATE_ON 2
+#define SD_STATE_DEACTIVATING 3
+
+/* necessary plugin structs */
+typedef struct _ShowdesktopPlacer
+{
+ int placed;
+ int onScreenX, onScreenY;
+ int offScreenX, offScreenY;
+ int origViewportX;
+ int origViewportY;
+} ShowdesktopPlacer;
+
+typedef struct _ShowdesktopDisplay
+{
+ int screenPrivateIndex;
+
+ HandleEventProc handleEvent;
+} ShowdesktopDisplay;
+
+typedef struct _ShowdesktopScreen
+{
+ int windowPrivateIndex;
+
+ PreparePaintScreenProc preparePaintScreen;
+ PaintScreenProc paintScreen;
+ DonePaintScreenProc donePaintScreen;
+ PaintWindowProc paintWindow;
+ EnterShowDesktopModeProc enterShowDesktopMode;
+ LeaveShowDesktopModeProc leaveShowDesktopMode;
+
+ int state;
+ int moreAdjust;
+
+ Bool ignoreNextTerminateEvent;
+} ShowdesktopScreen;
+
+typedef struct _ShowdesktopWindow
+{
+ int sid;
+ int distance;
+
+ ShowdesktopPlacer *placer;
+
+ GLfloat xVelocity, yVelocity;
+ GLfloat tx, ty;
+
+ float delta;
+ Bool adjust;
+} ShowdesktopWindow;
+
+/* shortcut macros, usually named X_DISPLAY, X_SCREEN and X_WINDOW
+ * these might seem overly complicated but they are shortcuts so we don't have to access the privates arrays all the time
+ * */
+#define GET_SHOWDESKTOP_DISPLAY(d) \
+ ((ShowdesktopDisplay *) (d)->privates[displayPrivateIndex].ptr)
+
+#define SD_DISPLAY(d) \
+ ShowdesktopDisplay *sd = GET_SHOWDESKTOP_DISPLAY (d)
+
+#define GET_SHOWDESKTOP_SCREEN(s, fd) \
+ ((ShowdesktopScreen *) (s)->privates[(fd)->screenPrivateIndex].ptr)
+
+#define SD_SCREEN(s) \
+ ShowdesktopScreen *ss = GET_SHOWDESKTOP_SCREEN (s, GET_SHOWDESKTOP_DISPLAY (s->display))
+
+#define GET_SHOWDESKTOP_WINDOW(w, ss) \
+ ((ShowdesktopWindow *) (w)->privates[(ss)->windowPrivateIndex].ptr)
+
+#define SD_WINDOW(w) \
+ ShowdesktopWindow *sw = GET_SHOWDESKTOP_WINDOW (w, \
+ GET_SHOWDESKTOP_SCREEN (w->screen, \
+ GET_SHOWDESKTOP_DISPLAY (w->screen->display)))
+/* plugin private index */
+static int displayPrivateIndex;
+
+
+/* non interfacing code, aka the logic of the plugin */
+static Bool isSDWin(CompWindow * w)
+{
+ if (!(*w->screen->focusWindow) (w))
+ return FALSE;
+
+ if (!matchEval(showdesktopGetWindowMatch(w->screen), w))
+ return FALSE;
+
+ if (w->state & CompWindowStateSkipPagerMask)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void setSkipPagerHint(CompWindow *w, Bool enable)
+{
+ unsigned int state = w->state;
+
+ if (enable)
+ state |= CompWindowStateSkipPagerMask;
+ else
+ state &= ~CompWindowStateSkipPagerMask;
+
+ changeWindowState(w, state);
+}
+
+static void repositionSDPlacer(CompWindow * w, int oldState)
+{
+ SD_WINDOW(w);
+
+ if (!sw->placer)
+ return;
+
+ if (oldState == SD_STATE_OFF)
+ {
+ sw->placer->onScreenX = w->attrib.x;
+ sw->placer->onScreenY = w->attrib.y;
+ sw->placer->origViewportX = w->screen->x;
+ sw->placer->origViewportY = w->screen->y;
+ }
+
+ switch (showdesktopGetDirection(w->screen))
+ {
+ case DirectionUp:
+ sw->placer->offScreenX = w->attrib.x;
+ sw->placer->offScreenY = w->screen->workArea.y - OFF_TOP(w) +
+ showdesktopGetWindowPartSize(w->screen);
+ break;
+ case DirectionDown:
+ sw->placer->offScreenX = w->attrib.x;
+ sw->placer->offScreenY = w->screen->workArea.y + w->screen->workArea.height +
+ OFF_BOTTOM(w) - showdesktopGetWindowPartSize(w->screen);
+ break;
+ case DirectionLeft:
+ sw->placer->offScreenX = w->screen->workArea.x - OFF_LEFT(w) +
+ showdesktopGetWindowPartSize(w->screen);
+ sw->placer->offScreenY = w->attrib.y;
+ break;
+ case DirectionRight:
+ sw->placer->offScreenX = w->screen->workArea.x + w->screen->workArea.width +
+ OFF_RIGHT(w) - showdesktopGetWindowPartSize(w->screen);
+ sw->placer->offScreenY = w->attrib.y;
+ break;
+ case DirectionUpDown:
+ sw->placer->offScreenX = w->attrib.x;
+ if (MOVE_UP(w))
+ sw->placer->offScreenY = w->screen->workArea.y - OFF_TOP(w) +
+ showdesktopGetWindowPartSize(w->screen);
+ else
+ sw->placer->offScreenY = w->screen->workArea.y +
+ w->screen->workArea.height + OFF_BOTTOM(w) -
+ showdesktopGetWindowPartSize(w->screen);
+ break;
+ case DirectionLeftRight:
+ sw->placer->offScreenY = w->attrib.y;
+ if (MOVE_LEFT(w))
+ sw->placer->offScreenX = w->screen->workArea.x - OFF_LEFT(w) +
+ showdesktopGetWindowPartSize(w->screen);
+ else
+ sw->placer->offScreenX = w->screen->workArea.x +
+ w->screen->workArea.width + OFF_RIGHT(w) -
+ showdesktopGetWindowPartSize(w->screen);
+ break;
+ case DirectionToCorners:
+ if (MOVE_LEFT(w))
+ sw->placer->offScreenX = w->screen->workArea.x - OFF_LEFT(w) +
+ showdesktopGetWindowPartSize(w->screen);
+ else
+ sw->placer->offScreenX = w->screen->workArea.x +
+ w->screen->workArea.width + OFF_RIGHT(w) -
+ showdesktopGetWindowPartSize(w->screen);
+ if (MOVE_UP(w))
+ sw->placer->offScreenY = w->screen->workArea.y - OFF_TOP(w) +
+ showdesktopGetWindowPartSize(w->screen);
+ else
+ sw->placer->offScreenY = w->screen->workArea.y +
+ w->screen->workArea.height + OFF_BOTTOM(w) -
+ showdesktopGetWindowPartSize(w->screen);
+ break;
+ default:
+ break;
+ }
+}
+
+static int prepareSDWindows(CompScreen * s, int oldState)
+{
+ CompWindow *w;
+ CompWindow *desktopWindow;
+ int count = 0;
+
+ desktopWindow = 0;
+
+ for (w = s->windows; w; w = w->next)
+ {
+ SD_WINDOW(w);
+
+ if (getWindowType(s->display, w->id) == CompWindowTypeDesktopMask)
+ desktopWindow = w;
+
+ if (!isSDWin(w))
+ continue;
+
+ if (!sw->placer)
+ sw->placer = malloc(sizeof(ShowdesktopPlacer));
+
+ repositionSDPlacer(w, oldState);
+
+ sw->placer->placed = TRUE;
+ sw->adjust = TRUE;
+ w->inShowDesktopMode = TRUE;
+ setSkipPagerHint(w, TRUE);
+
+ if (sw->tx)
+ sw->tx -= (sw->placer->onScreenX - sw->placer->offScreenX);
+ if (sw->ty)
+ sw->ty -= (sw->placer->onScreenY - sw->placer->offScreenY);
+
+ moveWindow(w,
+ sw->placer->offScreenX - w->attrib.x,
+ sw->placer->offScreenY - w->attrib.y,
+ TRUE, TRUE);
+ syncWindowPosition(w);
+
+ count++;
+ }
+
+ if (desktopWindow)
+ activateWindow(desktopWindow);
+
+ return count;
+}
+
+/* plugin initialization */
+
+static Bool showdesktopInit(CompPlugin * p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex();
+
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* plugin finalization */
+static void showdesktopFini(CompPlugin * p)
+{
+
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex(displayPrivateIndex);
+}
+
+/* adjust velocity for each animation step (adapted from the scale plugin) */
+static int adjustSDVelocity(CompWindow * w)
+{
+ float dx, dy, adjust, amount;
+ float x1, y1;
+ float baseX, baseY;
+
+ SD_WINDOW(w);
+ SD_SCREEN(w->screen);
+
+ x1 = y1 = 0.0;
+
+ if (ss->state == SD_STATE_ACTIVATING)
+ {
+ x1 = sw->placer->offScreenX;
+ y1 = sw->placer->offScreenY;
+ baseX = sw->placer->onScreenX;
+ baseY = sw->placer->onScreenY;
+ }
+ else
+ {
+ x1 = sw->placer->onScreenX;
+ y1 = sw->placer->onScreenY;
+ baseX = sw->placer->offScreenX;
+ baseY = sw->placer->offScreenY;
+ }
+
+ dx = x1 - (baseX + sw->tx);
+
+ adjust = dx * 0.15f;
+ amount = fabs(dx) * 1.5f;
+ if (amount < 0.5f)
+ amount = 0.5f;
+ else if (amount > 5.0f)
+ amount = 5.0f;
+
+ sw->xVelocity = (amount * sw->xVelocity + adjust) / (amount + 1.0f);
+
+ dy = y1 - (baseY + sw->ty);
+
+ adjust = dy * 0.15f;
+ amount = fabs(dy) * 1.5f;
+ if (amount < 0.5f)
+ amount = 0.5f;
+ else if (amount > 5.0f)
+ amount = 5.0f;
+
+ sw->yVelocity = (amount * sw->yVelocity + adjust) / (amount + 1.0f);
+
+ if (fabs(dx) < 0.1f && fabs(sw->xVelocity) < 0.2f &&
+ fabs(dy) < 0.1f && fabs(sw->yVelocity) < 0.2f)
+ {
+ sw->xVelocity = sw->yVelocity = 0.0f;
+ sw->tx = x1 - baseX;
+ sw->ty = y1 - baseY;
+
+ return 0;
+ }
+ return 1;
+}
+
+/* this function gets called periodically (about every 15ms on this machine),
+ * animation takes place here */
+static void
+showdesktopPreparePaintScreen(CompScreen * s, int msSinceLastPaint)
+{
+ SD_SCREEN(s);
+
+ UNWRAP(ss, s, preparePaintScreen);
+ (*s->preparePaintScreen) (s, msSinceLastPaint);
+ WRAP(ss, s, preparePaintScreen, showdesktopPreparePaintScreen);
+
+ if ((ss->state == SD_STATE_ACTIVATING) ||
+ (ss->state == SD_STATE_DEACTIVATING))
+ {
+ CompWindow *w;
+ int steps;
+ float amount, chunk;
+
+ amount = msSinceLastPaint * 0.05f * showdesktopGetSpeed(s);
+ steps = amount / (0.5f * showdesktopGetTimestep(s));
+ if (!steps)
+ steps = 1;
+ chunk = amount / (float)steps;
+
+ while (steps--)
+ {
+ ss->moreAdjust = 0;
+
+ for (w = s->windows; w; w = w->next)
+ {
+ SD_WINDOW(w);
+
+ if (sw->adjust)
+ {
+ sw->adjust = adjustSDVelocity(w);
+
+ ss->moreAdjust |= sw->adjust;
+
+ sw->tx += sw->xVelocity * chunk;
+ sw->ty += sw->yVelocity * chunk;
+ }
+ }
+ if (!ss->moreAdjust)
+ break;
+ }
+
+ }
+}
+
+static Bool
+showdesktopPaintScreen(CompScreen * s,
+ const ScreenPaintAttrib * sAttrib,
+ const CompTransform *transform,
+ Region region, int output, unsigned int mask)
+{
+ Bool status;
+
+ SD_SCREEN(s);
+
+ if ((ss->state == SD_STATE_ACTIVATING) || (ss->state == SD_STATE_DEACTIVATING))
+ mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
+
+ UNWRAP(ss, s, paintScreen);
+ status = (*s->paintScreen) (s, sAttrib, transform, region, output, mask);
+ WRAP(ss, s, paintScreen, showdesktopPaintScreen);
+
+ return status;
+}
+
+/* this one gets called after the one above and periodically,
+ * here the plugin checks if windows reached the end */
+static void showdesktopDonePaintScreen(CompScreen * s)
+{
+ SD_SCREEN(s);
+
+ if (ss->moreAdjust)
+ {
+ damageScreen(s);
+ }
+ else
+ {
+ if ((ss->state == SD_STATE_ACTIVATING) ||
+ (ss->state == SD_STATE_DEACTIVATING))
+ {
+ CompWindow *w;
+ if (ss->state == SD_STATE_ACTIVATING)
+ {
+ ss->state = SD_STATE_ON;
+ }
+ else
+ {
+ Bool inSDMode = FALSE;
+
+ for (w = s->windows; w; w = w->next)
+ {
+ if (w->inShowDesktopMode)
+ inSDMode = TRUE;
+ else
+ {
+ SD_WINDOW(w);
+ if (sw->placer)
+ {
+ free(sw->placer);
+ sw->placer = NULL;
+ }
+ }
+ }
+
+ if (inSDMode)
+ ss->state = SD_STATE_ON;
+ else
+ ss->state = SD_STATE_OFF;
+ }
+
+ damageScreen(s);
+ }
+ }
+
+ UNWRAP(ss, s, donePaintScreen);
+ (*s->donePaintScreen) (s);
+ WRAP(ss, s, donePaintScreen, showdesktopDonePaintScreen);
+}
+
+static Bool showdesktopPaintWindow(CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ const CompTransform *transform,
+ Region region, unsigned int mask)
+{
+ SD_SCREEN(w->screen);
+ Bool status;
+
+ if ((ss->state == SD_STATE_ACTIVATING) || (ss->state == SD_STATE_DEACTIVATING))
+ {
+ SD_WINDOW(w);
+
+ CompTransform wTransform = *transform;
+ WindowPaintAttrib wAttrib = *attrib;
+
+ if (sw->adjust)
+ {
+ float offsetX, offsetY;
+
+ offsetX = (ss->state == SD_STATE_DEACTIVATING) ?
+ (sw->placer->offScreenX - sw->placer->onScreenX) :
+ (sw->placer->onScreenX - sw->placer->offScreenX);
+ offsetY = (ss->state == SD_STATE_DEACTIVATING) ?
+ (sw->placer->offScreenY - sw->placer->onScreenY) :
+ (sw->placer->onScreenY - sw->placer->offScreenY);
+
+ wAttrib.opacity = OPAQUE;
+
+ mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+
+ matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0.0f);
+ matrixScale (&wTransform, 1.0f, 1.0f, 0.0f);
+ matrixTranslate (&wTransform, sw->tx + offsetX - w->attrib.x,
+ sw->ty + offsetY - w->attrib.y, 0.0f);
+ }
+
+ UNWRAP(ss, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, &wAttrib, &wTransform, region, mask);
+ WRAP(ss, w->screen, paintWindow, showdesktopPaintWindow);
+ }
+ else if (ss->state == SD_STATE_ON)
+ {
+ WindowPaintAttrib wAttrib = *attrib;
+
+ if (w->inShowDesktopMode)
+ wAttrib.opacity = wAttrib.opacity * showdesktopGetWindowOpacity(w->screen);
+
+ UNWRAP(ss, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, &wAttrib, transform, region, mask);
+ WRAP(ss, w->screen, paintWindow, showdesktopPaintWindow);
+ }
+ else
+ {
+ UNWRAP(ss, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, attrib, transform, region, mask);
+ WRAP(ss, w->screen, paintWindow, showdesktopPaintWindow);
+ }
+
+ return status;
+}
+
+static void showdesktopHandleEvent(CompDisplay *d, XEvent *event)
+{
+ SD_DISPLAY(d);
+
+ switch(event->type)
+ {
+ case ButtonPress:
+ {
+ CompScreen *s = findScreenAtDisplay(d, event->xbutton.root);
+ if (s)
+ {
+ SD_SCREEN(s);
+ if (ss->state != SD_STATE_OFF)
+ event->xbutton.window = None;
+ }
+ }
+ break;
+ case ClientMessage:
+ if ((event->xclient.message_type == d->restackWindowAtom) ||
+ (event->xclient.message_type == d->moveResizeWindowAtom))
+ {
+ CompWindow *w = findWindowAtDisplay(d, event->xclient.window);
+ if (w)
+ {
+ SD_SCREEN(w->screen);
+ if (ss->state != SD_STATE_OFF)
+ event->xclient.window = None;
+ }
+ }
+ break;
+ case PropertyNotify:
+ if (event->xproperty.atom == d->desktopViewportAtom)
+ {
+ CompScreen *s = findScreenAtDisplay(d, event->xproperty.window);
+ if (s)
+ {
+ SD_SCREEN(s);
+
+ if ((ss->state == SD_STATE_ON) || (ss->state == SD_STATE_ACTIVATING))
+ (*s->leaveShowDesktopMode)(s, NULL);
+ }
+ }
+ break;
+ }
+
+ UNWRAP(sd, d, handleEvent);
+ (*d->handleEvent)(d, event);
+ WRAP(sd, d, handleEvent, showdesktopHandleEvent);
+}
+
+static void showdesktopEnterShowDesktopMode(CompScreen *s)
+{
+ SD_SCREEN(s);
+ int count = 0;
+
+ if (ss->state == SD_STATE_OFF || ss->state == SD_STATE_DEACTIVATING)
+ {
+ count = prepareSDWindows(s, ss->state);
+ if (count > 0)
+ {
+ XSetInputFocus(s->display->display, s->root,
+ RevertToPointerRoot, CurrentTime);
+ ss->state = SD_STATE_ACTIVATING;
+ damageScreen(s);
+ }
+ }
+
+ UNWRAP(ss, s, enterShowDesktopMode);
+ (*s->enterShowDesktopMode)(s);
+ WRAP(ss, s, enterShowDesktopMode, showdesktopEnterShowDesktopMode);
+}
+
+static void showdesktopLeaveShowDesktopMode(CompScreen *s, CompWindow *w)
+{
+ SD_SCREEN(s);
+
+ if (ss->state != SD_STATE_OFF)
+ {
+ CompWindow *cw;
+
+ for (cw = s->windows; cw; cw = cw->next)
+ {
+ SD_WINDOW(cw);
+
+ if (w && (w->id != cw->id))
+ continue;
+
+ if (sw->placer && sw->placer->placed)
+ {
+ sw->adjust = TRUE;
+ sw->placer->placed = FALSE;
+
+ /* adjust onscreen position to
+ handle viewport changes
+ */
+ sw->tx += (sw->placer->onScreenX - sw->placer->offScreenX);
+ sw->ty += (sw->placer->onScreenY - sw->placer->offScreenY);
+
+ sw->placer->onScreenX += (sw->placer->origViewportX -
+ cw->screen->x) * cw->screen->width;
+ sw->placer->onScreenY += (sw->placer->origViewportY -
+ cw->screen->y) * cw->screen->height;
+
+ moveWindow(cw, sw->placer->onScreenX - cw->attrib.x,
+ sw->placer->onScreenY - cw->attrib.y, TRUE, TRUE);
+ syncWindowPosition(cw);
+
+ setSkipPagerHint(cw, FALSE);
+ cw->inShowDesktopMode = FALSE;
+ }
+ }
+ ss->state = SD_STATE_DEACTIVATING;
+ damageScreen(s);
+ }
+
+ UNWRAP(ss, s, leaveShowDesktopMode);
+ (*s->leaveShowDesktopMode)(s, w);
+ WRAP(ss, s, leaveShowDesktopMode, showdesktopLeaveShowDesktopMode);
+}
+
+/* display initialization */
+
+static Bool showdesktopInitDisplay(CompPlugin * p, CompDisplay * d)
+{
+ ShowdesktopDisplay *sd;
+
+ sd = malloc(sizeof(ShowdesktopDisplay)); /* allocate the display */
+ if (!sd)
+ return FALSE;
+
+ sd->screenPrivateIndex = allocateScreenPrivateIndex(d);
+ if (sd->screenPrivateIndex < 0)
+ {
+ free(sd);
+ return FALSE;
+ }
+
+ WRAP(sd, d, handleEvent, showdesktopHandleEvent);
+
+ d->privates[displayPrivateIndex].ptr = sd;
+
+ return TRUE;
+}
+
+static void showdesktopFiniDisplay(CompPlugin * p, CompDisplay * d)
+{
+ SD_DISPLAY(d);
+
+ freeScreenPrivateIndex(d, sd->screenPrivateIndex);
+
+ UNWRAP(sd, d, handleEvent);
+
+ free(sd);
+}
+
+static Bool showdesktopInitScreen(CompPlugin * p, CompScreen * s)
+{
+ ShowdesktopScreen *ss;
+
+ SD_DISPLAY(s->display);
+
+ ss = malloc(sizeof(ShowdesktopScreen));
+ if (!ss)
+ return FALSE;
+
+ ss->windowPrivateIndex = allocateWindowPrivateIndex(s);
+ if (ss->windowPrivateIndex < 0)
+ {
+ free(ss);
+ return FALSE;
+ }
+
+ ss->state = SD_STATE_OFF;
+ ss->moreAdjust = 0;
+ ss->ignoreNextTerminateEvent = FALSE;
+
+ WRAP(ss, s, preparePaintScreen, showdesktopPreparePaintScreen);
+ WRAP(ss, s, paintScreen, showdesktopPaintScreen);
+ WRAP(ss, s, donePaintScreen, showdesktopDonePaintScreen);
+ WRAP(ss, s, paintWindow, showdesktopPaintWindow);
+ WRAP(ss, s, enterShowDesktopMode, showdesktopEnterShowDesktopMode);
+ WRAP(ss, s, leaveShowDesktopMode, showdesktopLeaveShowDesktopMode);
+
+ s->privates[sd->screenPrivateIndex].ptr = ss;
+
+ return TRUE;
+
+}
+
+/* Free screen resources */
+static void showdesktopFiniScreen(CompPlugin * p, CompScreen * s)
+{
+ SD_SCREEN(s);
+
+ UNWRAP(ss, s, preparePaintScreen);
+ UNWRAP(ss, s, paintScreen);
+ UNWRAP(ss, s, donePaintScreen);
+ UNWRAP(ss, s, paintWindow);
+ UNWRAP(ss, s, enterShowDesktopMode);
+ UNWRAP(ss, s, leaveShowDesktopMode);
+
+ freeWindowPrivateIndex(s, ss->windowPrivateIndex);
+
+ free(ss);
+}
+
+
+/* window init */
+static Bool showdesktopInitWindow(CompPlugin * p, CompWindow * w)
+{
+ ShowdesktopWindow *sw;
+
+ SD_SCREEN(w->screen);
+
+ sw = malloc(sizeof(ShowdesktopWindow));
+ if (!sw)
+ return FALSE;
+
+ sw->tx = sw->ty = 0.0f;
+ sw->adjust = FALSE;
+ sw->xVelocity = sw->yVelocity = 0.0f;
+ sw->delta = 1.0f;
+ sw->placer = NULL;
+
+ w->privates[ss->windowPrivateIndex].ptr = sw;
+
+ return TRUE;
+}
+
+/* Free window resources */
+static void showdesktopFiniWindow(CompPlugin * p, CompWindow * w)
+{
+ SD_WINDOW(w);
+
+ free(sw);
+}
+
+static int
+showdesktopGetVersion (CompPlugin *plugin, int version)
+{
+ return ABIVERSION;
+}
+
+/* plugin vtable */
+static CompPluginVTable showdesktopVTable = {
+ "showdesktop",
+ showdesktopGetVersion,
+ 0,
+ showdesktopInit,
+ showdesktopFini,
+ showdesktopInitDisplay,
+ showdesktopFiniDisplay,
+ showdesktopInitScreen,
+ showdesktopFiniScreen,
+ showdesktopInitWindow,
+ showdesktopFiniWindow,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0, /* deps */
+ 0, /* sizeof (deps) / sizeof (deps[0]) */
+ 0,
+ 0
+};
+
+/* send plugin info */
+CompPluginVTable *getCompPluginInfo(void)
+{
+ return &showdesktopVTable;
+}
diff --git a/showdesktop.xml b/showdesktop.xml
new file mode 100644
index 0000000..846b456
--- /dev/null
+++ b/showdesktop.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<compiz>
+ <plugin name="showdesktop" useBcop="true">
+ <short>Show desktop</short>
+ <long>Access your desktop easily</long>
+ <category>Desktop</category>
+ <feature>showdesktop</feature>
+ <screen>
+ <group>
+ <short>Misc. Options</short>
+ <option name="speed" type="float">
+ <short>Speed</short>
+ <long>Window movement speed</long>
+ <default>1.2</default>
+ <min>0.1</min>
+ <max>50.0</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="timestep" type="float">
+ <short>Timestep</short>
+ <long>Window movement timestep</long>
+ <default>0.1</default>
+ <min>0.1</min>
+ <max>50.0</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="direction" type="int">
+ <short>Movement Direction</short>
+ <long>Direction of window movement</long>
+ <default>6</default>
+ <min>0</min>
+ <max>6</max>
+ <desc>
+ <value>0</value>
+ <name>Up</name>
+ </desc>
+ <desc>
+ <value>1</value>
+ <name>Down</name>
+ </desc>
+ <desc>
+ <value>2</value>
+ <name>Left</name>
+ </desc>
+ <desc>
+ <value>3</value>
+ <name>Right</name>
+ </desc>
+ <desc>
+ <value>4</value>
+ <name>Up/Down</name>
+ </desc>
+ <desc>
+ <value>5</value>
+ <name>Left/Right</name>
+ </desc>
+ <desc>
+ <value>6</value>
+ <name>To Corners</name>
+ </desc>
+ </option>
+ <option name="window_match" type="match">
+ <short>Window Types</short>
+ <long>Window types that should be moved out of sight when entering showdesktop mode</long>
+ <default>type=toolbar | type=utility | type=dialog | type=normal</default>
+ </option>
+ </group>
+ <group>
+ <short>Appearance</short>
+ <option name="window_opacity" type="float">
+ <short>Window Opacity</short>
+ <long>Window opacity when showdesktop'd</long>
+ <default>0.3</default>
+ <min>0.1</min>
+ <max>1.0</max>
+ <precision>0.01</precision>
+ </option>
+ <option name="window_part_size" type="int">
+ <short>Window Part Size</short>
+ <long>Window part size when showdesktop'd</long>
+ <default>20</default>
+ <min>0</min>
+ <max>300</max>
+ </option>
+ </group>
+ </screen>
+ </plugin>
+</compiz>