diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | Makefile | 36 | ||||
-rw-r--r-- | plugin.info | 1 | ||||
-rw-r--r-- | tile.c | 1290 | ||||
-rw-r--r-- | tile.cpp | 1075 | ||||
-rw-r--r-- | tile.h | 255 | ||||
-rw-r--r-- | tile.xml.in | 94 |
7 files changed, 1402 insertions, 1351 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d9b6005..ce24058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,3 @@ include (CompizFusion) -compiz_fusion_plugin (tile) +compiz_fusion_plugin (tile PLUGINDEPS composite opengl) @@ -89,14 +89,14 @@ 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) +CFLAGS = -g -Wall -Wpointer-arith -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_HEADERS = compiz.h core/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\""; \ @@ -105,7 +105,6 @@ is-bcop-target := $(shell if [ -e $(PLUGIN).xml.in ]; then cat $(PLUGIN).xml.in 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 ) @@ -119,17 +118,14 @@ 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 %.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 @@ -280,28 +276,6 @@ $(BUILDDIR)/compiz-%.pc: compiz-%.pc.in # 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"; \ @@ -319,7 +293,7 @@ $(BUILDDIR)/%.lo: %.cxx $(h-files) else \ $(ECHO) "compiling $< -> $@"; \ fi - @$(LIBTOOL) --quiet --mode=compile $(CPP) $(CFLAGS) $(DEFINES) -I$(BUILDDIR) -c -o $@ $< + @$(LIBTOOL) --mode=compile $(CPP) $(CFLAGS) $(DEFINES) -I$(BUILDDIR) -c -o $@ $< @if [ '$(color)' != 'no' ]; then \ $(ECHO) -e "\r\033[0mcompiling : \033[34m$< -> $@\033[0m"; \ fi @@ -336,7 +310,7 @@ $(BUILDDIR)/lib$(PLUGIN).la: $(all-c-objs) else \ $(ECHO) "linking : $@"; \ fi - @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) -rpath $(DESTDIR) -o $@ $(all-c-objs) + @$(LIBTOOL) --quiet --mode=link $(CC) $(LDFLAGS) -rpath $(DESTDIR) -o $@ $(all-c-objs) -R `pkg-config --variable=libdir compiz`/compiz @if [ '$(color)' != 'no' ]; then \ $(ECHO) -e "\r\033[0mlinking : \033[34m$@\033[0m"; \ fi diff --git a/plugin.info b/plugin.info index a97a15b..97e06f4 100644 --- a/plugin.info +++ b/plugin.info @@ -1 +1,2 @@ PLUGIN = tile +PKG_DEP = compiz-composite compiz-opengl @@ -1,1290 +0,0 @@ -/** - * - * Compiz tile plugin - * - * tile.c - * - * 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. - * - * TODO - * - change vertical and horizontal tiling to similar behavior as Left - * - fix bugs - * - make vertical and horizontal maximization be saved when tiling - * - **/ - -#include <string.h> -#include <math.h> -#include <compiz-core.h> -#include "tile_options.h" - -static int displayPrivateIndex = 0; - -typedef enum { - NoAnimation = 0, - Animating, - AnimationDone -} WindowAnimationType; - -typedef struct _TileDisplay { - int screenPrivateIndex; -} TileDisplay; - -typedef struct _TileScreen { - int windowPrivateIndex; - - int grabIndex; - int oneDuration; // duration of animation for one window - int msResizing; // number of ms elapsed from start of resizing animation - - TileTileToggleTypeEnum tileType; - - PaintWindowProc paintWindow; - WindowResizeNotifyProc windowResizeNotify; - PreparePaintScreenProc preparePaintScreen; - PaintScreenProc paintScreen; - DonePaintScreenProc donePaintScreen; - PaintOutputProc paintOutput; -} TileScreen; - -typedef struct _TileWindow { - Bool isTiled; - - XRectangle savedCoords; - XRectangle prevCoords; - XRectangle newCoords; - unsigned int savedMaxState; - Bool savedValid; - - Bool needConfigure; - Bool alreadyResized; - - WindowAnimationType animationType; - unsigned int animationNum; - - GLushort outlineColor[3]; -} TileWindow; - -#define GET_TILE_DISPLAY(d) \ - ((TileDisplay *) (d)->base.privates[displayPrivateIndex].ptr) -#define TILE_DISPLAY(d) \ - TileDisplay *td = GET_TILE_DISPLAY (d) - -#define GET_TILE_SCREEN(s, td) \ - ((TileScreen *) (s)->base.privates[(td)->screenPrivateIndex].ptr) -#define TILE_SCREEN(s) \ - TileScreen *ts = GET_TILE_SCREEN (s, GET_TILE_DISPLAY (s->display)) - -#define GET_TILE_WINDOW(w, ts) \ - ((TileWindow *) (w)->base.privates[(ts)->windowPrivateIndex].ptr) -#define TILE_WINDOW(w) \ - TileWindow *tw = GET_TILE_WINDOW (w, \ - GET_TILE_SCREEN (w->screen, \ - GET_TILE_DISPLAY (w->screen->display))) - -static Bool placeWin (CompWindow *w, int x, int y, int width, int height); -static Bool tileSetNewWindowSize (CompWindow *w); - -/* window painting function, draws animation */ -static Bool -tilePaintWindow(CompWindow *w, - const WindowPaintAttrib *attrib, - const CompTransform *transform, - Region region, - unsigned int mask) -{ - CompScreen *s = w->screen; - Bool status; - Bool dontDraw = FALSE; - - TILE_WINDOW (w); - TILE_SCREEN (s); - - if (tw->animationType != NoAnimation) - { - WindowPaintAttrib wAttrib = *attrib; - CompTransform wTransform = *transform; - float progress; - - progress = (float)ts->msResizing / - (float)tileGetAnimationDuration (s->display); - - switch (tileGetAnimateType (s->display)) - { - /* - Drop animation - */ - case AnimateTypeDropFromTop: - matrixRotate (&wTransform, - (progress * 100.0f) - 100.0f, - 0.0f, 0.0f, 1.0f); - mask |= PAINT_WINDOW_TRANSFORMED_MASK; - break; - - /* - Zoom animation - */ - case AnimateTypeZoom: - matrixTranslate (&wTransform, 0, 0, progress - 1.0f); - mask |= PAINT_WINDOW_TRANSFORMED_MASK; - break; - - /* - Slide animation - */ - case AnimateTypeSlide: - if (progress < 0.75f) - wAttrib.opacity /= 2; - else - wAttrib.opacity *= (0.5f + 2 * (progress - 0.75f)); - - if (ts->msResizing > tw->animationNum * ts->oneDuration) - { - /* animation finished */ - tw->animationType = AnimationDone; - } - else if (ts->msResizing > (tw->animationNum - 1) * - ts->oneDuration) - { - int thisDur; /* ms spent animating this window */ - thisDur = ts->msResizing % ts->oneDuration; - - if (tw->animationNum % 2) - matrixTranslate (&wTransform, - s->width - s->width * - (float)thisDur / ts->oneDuration, - 0, 0); - else - matrixTranslate (&wTransform, - -s->width + s->width * - (float)thisDur / ts->oneDuration, - 0, 0); - - mask |= PAINT_WINDOW_TRANSFORMED_MASK; - } - else - dontDraw = TRUE; - break; - /* - Outline animation - */ - case AnimateTypeFilledOutline: - dontDraw = TRUE; - break; - - /* - Fade animation - */ - case AnimateTypeFade: - // first half of the animation, fade out - if (progress < 0.4f) - wAttrib.opacity -= wAttrib.opacity * progress / 0.4f; - else - { - if (progress > 0.6f && tw->alreadyResized) - { - // second half of animation, fade in - wAttrib.opacity *= (progress - 0.6f) / 0.4f; - } - else - { - if (tw->needConfigure) - tileSetNewWindowSize (w); - dontDraw = TRUE; - } - } - break; - - default: - break; - } - - if (dontDraw) - mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; - - UNWRAP (ts, s, paintWindow); - status = (*s->paintWindow) (w, &wAttrib, &wTransform, region, mask); - WRAP (ts, s, paintWindow, tilePaintWindow); - } - else // paint window as always - { - UNWRAP (ts, s, paintWindow); - status = (*s->paintWindow) (w, attrib, transform, region, mask); - WRAP (ts, s, paintWindow, tilePaintWindow); - } - - return status; -} - -static void -tilePreparePaintScreen (CompScreen *s, - int msSinceLastPaint) -{ - TILE_SCREEN (s); - - // add spent time - if (ts->grabIndex) - ts->msResizing += msSinceLastPaint; - - UNWRAP (ts, s, preparePaintScreen); - (*s->preparePaintScreen) (s, msSinceLastPaint); - WRAP (ts, s, preparePaintScreen, tilePreparePaintScreen); -} - -static void -tilePaintScreen (CompScreen *s, - CompOutput *outputs, - int numOutputs, - unsigned int mask) -{ - TILE_SCREEN (s); - - if (ts->grabIndex) - { - outputs = &s->fullscreenOutput; - numOutputs = 1; - } - - UNWRAP (ts, s, paintScreen); - (*s->paintScreen) (s, outputs, numOutputs, mask); - WRAP (ts, s, paintScreen, tilePaintScreen); -} - -static void -tileDonePaintScreen (CompScreen *s) -{ - TILE_SCREEN (s); - - if (ts->grabIndex) - { - if (ts->msResizing > tileGetAnimationDuration (s->display)) - { - CompWindow *w; - for (w = s->windows; w; w = w->next) - { - TILE_WINDOW (w); - tw->animationType = NoAnimation; - } - - ts->msResizing = 0; - - removeScreenGrab (s, ts->grabIndex, NULL); - ts->grabIndex = 0; - } - - damageScreen (s); - } - - UNWRAP (ts, s, donePaintScreen); - (*s->donePaintScreen) (s); - WRAP (ts, s, donePaintScreen, tileDonePaintScreen); -} - -static Bool -tilePaintOutput (CompScreen *s, - const ScreenPaintAttrib *sa, - const CompTransform *transform, - Region region, - CompOutput *output, - unsigned int mask) -{ - Bool status; - - TILE_SCREEN (s); - - if (ts->grabIndex) - mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; - - UNWRAP (ts, s, paintOutput); - status = (*s->paintOutput) (s, sa, transform, region, output, mask); - WRAP (ts, s, paintOutput, tilePaintOutput); - - /* Check if animation is enabled, there is resizing - on screen and only outline should be drawn */ - - if (ts->grabIndex && (output->id == ~0) && - (tileGetAnimateType (s->display) == AnimateTypeFilledOutline)) - { - CompWindow *w; - CompTransform sTransform = *transform; - float animationDuration = tileGetAnimationDuration (s->display); - int x, y, width, height; - - transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform); - glPushMatrix (); - glLoadMatrixf (sTransform.m); - - glLineWidth (4.0f); - - for (w = s->windows; w; w = w->next) - { - TILE_WINDOW (w); - - if (tw->animationType == Animating) - { - /* Coordinate = start + speed * elapsedTime - Coordinate = start + (target - start)/interval * elapsedTime - Draw outline */ - - x = tw->prevCoords.x - w->input.left + - (((float)(w->attrib.x - tw->prevCoords.x)) * - ts->msResizing / animationDuration); - y = tw->prevCoords.y - w->input.top + - (((float)(w->attrib.y - tw->prevCoords.y)) * - ts->msResizing / animationDuration); - width = tw->prevCoords.width + w->input.left + w->input.right + - (((float)(w->attrib.width - tw->prevCoords.width)) * - ts->msResizing / animationDuration); - height = tw->prevCoords.height + - w->input.top + w->input.bottom + - (((float)(w->attrib.height - tw->prevCoords.height)) * - ts->msResizing / animationDuration); - - glColor3us (tw->outlineColor[0] * 0.66, - tw->outlineColor[1] * 0.66, - tw->outlineColor[2] * 0.66); - glRecti (x, y + height, x + width, y); - - glColor3usv (tw->outlineColor); - - glBegin (GL_LINE_LOOP); - glVertex3f (x, y, 0.0f); - glVertex3f (x + width, y, 0.0f); - glVertex3f (x + width, y + height, 0.0f); - glVertex3f (x, y + height, 0.0f); - glEnd (); - - glColor4usv (defaultColor); - } - } - - glPopMatrix (); - glColor4usv (defaultColor); - glLineWidth (1.0f); - } - - return status; -} - -/* Resize notify used when windows are tiled horizontally or vertically */ -static void -tileResizeNotify (CompWindow *w, - int dx, - int dy, - int dwidth, - int dheight) -{ - TILE_SCREEN (w->screen); - TILE_WINDOW (w); - - UNWRAP (ts, w->screen, windowResizeNotify); - (*w->screen->windowResizeNotify) (w, dx, dy, dwidth, dheight); - WRAP (ts, w->screen, windowResizeNotify, tileResizeNotify); - - if (!tw->alreadyResized) - { - tw->alreadyResized = TRUE; - return; - } - - /* Dont do anything if joining is disabled or windows are being resized */ - if (tileGetTileJoin (w->screen->display) && !ts->grabIndex) - { - CompWindow *prev = NULL, *next = NULL, *cw; - Bool windowSeen = FALSE; - - /* determine previous and next tiled window */ - for (cw = w->screen->reverseWindows; cw; cw = cw->prev) - { - if (windowSeen) - { - next = cw; - break; - } - else - { - if (cw != w) - prev = cw; - else - windowSeen = TRUE; - } - } - - switch (ts->tileType) - { - case TileToggleTypeTile: - if (prev) - placeWin (prev, - prev->attrib.x, prev->attrib.y, - w->attrib.x - prev->attrib.x - - w->input.left - prev->input.right, - prev->height); - - if (next) - { - int currentX; - currentX = w->attrib.x + w->width + - w->input.right + next->input.left; - placeWin (next, currentX, next->attrib.y, - next->width + next->attrib.x - currentX, - next->height); - } - break; - - case TileToggleTypeTileHorizontally: - if (prev) - placeWin (prev, - prev->attrib.x, prev->attrib.y, - prev->width, - w->attrib.y - prev->attrib.y - - w->input.top - prev->input.bottom); - - if (next) - { - int currentY; - currentY = w->attrib.y + w->height + - w->input.bottom + next->input.top; - placeWin (next, next->attrib.x, - currentY, next->width, - next->height + next->attrib.y - currentY); - } - break; - case TileToggleTypeLeft: - if (!next && prev && dwidth) /* last window - on the left */ - { - XRectangle workArea; - int currentX; - - workArea = w->screen->workArea; - - for (cw = w->screen->windows; cw; cw = cw->next) - { - TILE_WINDOW(cw); - - if (!tw->isTiled || (cw->id == w->id)) - continue; - - currentX = workArea.x + w->serverX + - w->serverWidth + w->input.right + cw->input.left; - - placeWin (cw, currentX, cw->attrib.y, - workArea.width - currentX - w->input.right, - cw->attrib.height); - } - } - else if (next) /* windows on the right */ - { - XRectangle workArea; - Bool first = TRUE; - - workArea = w->screen->workArea; - - for (cw = w->screen->windows; cw; cw = cw->next) - { - TILE_WINDOW (cw); - - if (!tw->isTiled || (cw->id == w->id)) - continue; - - if (first) - { - placeWin (cw, - workArea.x + cw->input.left, cw->attrib.y, - w->serverX - w->input.left - - cw->input.left - cw->input.right - workArea.x, - cw->attrib.height); - - first = FALSE; - } - else - { - int x = cw->attrib.x; - int y = cw->attrib.y; - int width = cw->attrib.width; - int height = cw->attrib.height; - - if (prev && (cw->id == prev->id)) - height = w->serverY - cw->attrib.y - - w->input.top - cw->input.bottom; - else if (next && (cw->id == next->id)) - y = w->serverY + w->serverHeight + - w->input.bottom + cw->input.top; - - x = w->serverX; - width = workArea.width + workArea.x - - w->serverX - w->input.right; - - placeWin (cw, x, y, width, height); - } - } - } - break; - - default: - break; - } - } -} - -static Bool -tileInitScreen (CompPlugin *p, - CompScreen *s) -{ - TileScreen *ts; - - TILE_DISPLAY (s->display); - - ts = (TileScreen *) calloc (1, sizeof (TileScreen)); - - ts->windowPrivateIndex = allocateWindowPrivateIndex (s); - if (ts->windowPrivateIndex < 0) - { - free (ts); - return FALSE; - } - srand (time (0)); - - s->base.privates[td->screenPrivateIndex].ptr = ts; - - ts->grabIndex = 0; - ts->msResizing = 0; - ts->oneDuration = 0; - - /* Wrap plugin functions */ - WRAP (ts, s, paintOutput, tilePaintOutput); - WRAP (ts, s, preparePaintScreen, tilePreparePaintScreen); - WRAP (ts, s, paintScreen, tilePaintScreen); - WRAP (ts, s, donePaintScreen, tileDonePaintScreen); - WRAP (ts, s, windowResizeNotify, tileResizeNotify); - WRAP (ts, s, paintWindow, tilePaintWindow); - - return TRUE; -} - -static void -tileFiniScreen (CompPlugin *p, - CompScreen *s) -{ - TILE_SCREEN (s); - - freeWindowPrivateIndex (s, ts->windowPrivateIndex); - - /* Restore the original function */ - UNWRAP (ts, s, paintOutput); - UNWRAP (ts, s, preparePaintScreen); - UNWRAP (ts, s, paintScreen); - UNWRAP (ts, s, donePaintScreen); - UNWRAP (ts, s, windowResizeNotify); - UNWRAP (ts, s, paintWindow); - - free (ts); -} - -/* this is resizeConstrainMinMax from resize.c, - thanks to David Reveman/Nigel Cunningham */ -static void -constrainMinMax (CompWindow *w, - int width, - int height, - int *newWidth, - int *newHeight) -{ - const XSizeHints *hints = &w->sizeHints; - int min_width = 0; - int min_height = 0; - int max_width = MAXSHORT; - int max_height = MAXSHORT; - - if ((hints->flags & PBaseSize) && (hints->flags & PMinSize)) - { - min_width = hints->min_width; - min_height = hints->min_height; - } - else if (hints->flags & PBaseSize) - { - min_width = hints->base_width; - min_height = hints->base_height; - } - else if (hints->flags & PMinSize) - { - min_width = hints->min_width; - min_height = hints->min_height; - } - - if (hints->flags & PMaxSize) - { - max_width = hints->max_width; - max_height = hints->max_height; - } -#define CLAMP(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v)) - - /* clamp width and height to min and max values */ - width = CLAMP (width, min_width, max_width); - height = CLAMP (height, min_height, max_height); - -#undef CLAMP - - *newWidth = width; - *newHeight = height; -} - -/* Moves window to [x,y] and resizes to width x height - if no animation or starts animation */ -static Bool -placeWin (CompWindow *w, - int x, - int y, - int width, - int height) -{ - /* window existence check */ - if (!w) - return FALSE; - - /* this checks if the window isnt smaller - than minimum size it has defined */ - constrainMinMax (w, width, height, &width, &height); - - /* check if the window isnt already where its going to be */ - if (x == w->attrib.x && y == w->attrib.y && - width == w->attrib.width && height == w->attrib.height) - return TRUE; - - TILE_WINDOW(w); - - /* set previous coordinates for animation */ - tw->prevCoords.x = w->attrib.x; - tw->prevCoords.y = w->attrib.y; - tw->prevCoords.width = w->attrib.width; - tw->prevCoords.height = w->attrib.height; - - /* set future coordinates for animation */ - tw->newCoords.x = x; - tw->newCoords.y = y; - tw->newCoords.width = width; - tw->newCoords.height = height; - - tw->alreadyResized = FALSE; /* window is not resized now */ - tw->needConfigure = TRUE; - - switch (tileGetAnimateType (w->screen->display)) - { - case AnimateTypeNone: - tileSetNewWindowSize (w); - break; - case AnimateTypeFilledOutline: - case AnimateTypeSlide: - case AnimateTypeZoom: - case AnimateTypeDropFromTop: - tileSetNewWindowSize (w); - /* fall-through */ - case AnimateTypeFade: - tw->animationType = Animating; - break; - default: - break; - } - - return TRUE; -} - -static Bool -tileSetNewWindowSize (CompWindow *w) -{ - XWindowChanges xwc; - unsigned int mask = CWX | CWY | CWWidth | CWHeight; - - TILE_WINDOW (w); - TILE_SCREEN (w->screen); - - xwc.x = tw->newCoords.x; - xwc.y = tw->newCoords.y; - xwc.width = tw->newCoords.width; - xwc.height = tw->newCoords.height; - - if (ts->tileType == -1) - { - if (tw->savedValid) - maximizeWindow (w, tw->savedMaxState); - } - else - maximizeWindow (w, 0); - - if (xwc.width == w->serverWidth) - mask &= ~CWWidth; - - if (xwc.height == w->serverHeight) - mask &= ~CWHeight; - - if (w->mapNum && (mask & (CWWidth | CWHeight))) - sendSyncRequest (w); - - configureXWindow (w, mask, &xwc); - tw->needConfigure = FALSE; - - return TRUE; -} - -/* Heavily inspired by windowIs3D and isSDWindow, - returns TRUE if the window is usable for tiling */ -static Bool -isTileWindow (CompWindow *w) -{ - if (matchEval (tileGetExcludeMatch (w->screen->display), w)) - return FALSE; - - if (w->attrib.override_redirect) - return FALSE; - - if (!((*w->screen->focusWindow) (w))) - return FALSE; - - if (w->wmType & (CompWindowTypeDockMask | CompWindowTypeDesktopMask)) - return FALSE; - - if (w->state & CompWindowStateSkipPagerMask) - return FALSE; - - if (w->minimized || !w->placed) - return FALSE; - - return TRUE; -} - -/* save window coordinates to use for restore */ -static void -saveCoords (CompWindow *w) -{ - TILE_WINDOW (w); - - if (tw->savedValid) - return; - - tw->savedCoords.x = w->serverX; - tw->savedCoords.y = w->serverY; - tw->savedCoords.width = w->serverWidth; - tw->savedCoords.height = w->serverHeight; - - tw->savedMaxState = w->state & MAXIMIZE_STATE; - - tw->savedValid = TRUE; -} - -/* Applies tiling/restoring */ -static Bool -applyTiling (CompScreen *s) -{ - CompWindow *w; - int count = 0; - - TILE_SCREEN (s); - - if (ts->grabIndex) - return FALSE; - - for (w = s->windows; w; w = w->next) - { - if (isTileWindow (w)) - count++; - } - - ts->oneDuration = tileGetAnimationDuration (s->display) / MAX (count, 1); - - if (count > 1) - { - int countX = 0, countY = 0; - int currentX = 0, currentY = 0; - int winWidth = 0, winHeight = 0; - int x = 0, y = 0; - int height = 0, occupancy = 0, delta = 0; - Bool first = TRUE; - int i = 0; - XRectangle workArea; - CompWindowExtents border; - - memset (&border, 0, sizeof (CompWindowExtents)); - /* first get the largest border of the windows on this - screen - some of the windows in our list might be - maximized now and not be maximized later, so - their border information may be inaccurate */ - for (w = s->windows; w; w = w->next) - { - if (w->input.left > border.left) - border.left = w->input.left; - if (w->input.right > border.right) - border.right = w->input.right; - if (w->input.top > border.top) - border.top = w->input.top; - if (w->input.bottom > border.bottom) - border.bottom = w->input.bottom; - } - - workArea = s->workArea; - - switch (ts->tileType) - { - case TileToggleTypeTile: - countX = ceil (sqrt (count)); - countY = ceil ((float)count / countX); - currentX = workArea.x; - currentY = workArea.y; - winWidth = workArea.width / countX; - winHeight = workArea.height / countY; - break; - case TileToggleTypeLeft: - height = workArea.height / (count - 1); - occupancy = tileGetTileLeftOccupancy (s->display); - break; - case TileToggleTypeTileVertically: - winWidth = workArea.width / count; - winHeight = workArea.height; - y = workArea.y; - break; - case TileToggleTypeTileHorizontally: - winWidth = workArea.width; - winHeight = workArea.height / count; - x = workArea.x; - break; - case TileToggleTypeCascade: - delta = tileGetTileDelta (s->display); - currentX = workArea.x; - currentY = workArea.y; - winHeight = workArea.height - delta * (count - 1); - winWidth = workArea.width - delta * (count - 1); - break; - default: - break; - } - - for (w = s->windows; w; w = w->next) - { - if (!isTileWindow (w)) - continue; - - TILE_WINDOW (w); - - if (!tw->savedValid) - saveCoords (w); - - switch (ts->tileType) - { - case TileToggleTypeTile: - placeWin(w, - currentX + border.left, currentY + border.top, - winWidth - (border.left + border.right), - winHeight - (border.top + border.bottom)); - tw->isTiled = TRUE; - break; - case TileToggleTypeLeft: - if (first) - { - x = workArea.x; - y = workArea.y; - winWidth = workArea.width * occupancy / 100; - winHeight = workArea.height; - first = FALSE; - } - else - { - x = workArea.x + (workArea.width * occupancy / 100); - y = workArea.y + (i * height); - winWidth = (workArea.width * (100 - occupancy) / 100); - winHeight = height; - } - - placeWin(w, - x + border.left, y + border.top, - winWidth - (border.left + border.right), - winHeight - (border.top + border.bottom)); - tw->isTiled = TRUE; - break; - case TileToggleTypeTileVertically: - x = workArea.x + (winWidth * i); - placeWin(w, - x + border.left, y + border.top, - winWidth - (border.left + border.right), - winHeight - (border.top + border.bottom)); - tw->isTiled = TRUE; - break; - case TileToggleTypeTileHorizontally: - y = workArea.y + (winHeight * i); - placeWin (w, x + border.left, y + border.top, - winWidth - (border.left + border.right), - winHeight - (border.top + border.bottom)); - tw->isTiled = TRUE; - break; - case TileToggleTypeCascade: - placeWin (w, - currentX + border.left, currentY + border.top, - winWidth - (border.left + border.right), - winHeight - (border.top + border.bottom)); - tw->isTiled = TRUE; - break; - case -1: - if (tw->isTiled) - { - placeWin (w, - tw->savedCoords.x, tw->savedCoords.y, - tw->savedCoords.width, tw->savedCoords.height); - tw->savedValid = FALSE; - tw->isTiled = FALSE; - } - break; - default: - break; - } - - i++; - tw->animationNum = i; - - switch (ts->tileType) - { - case TileToggleTypeTile: - if (!(i % countX)) - { - currentX = workArea.x; - currentY += winHeight; - } - else - currentX += winWidth; - break; - case TileToggleTypeCascade: - currentX += delta; - currentY += delta; - default: - break; - } - } - - if (!ts->grabIndex) - ts->grabIndex = pushScreenGrab (s, s->invisibleCursor, "tile"); - - ts->msResizing = 0; - } - - return TRUE; -} - -static Bool -tileTile (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) - { - TILE_SCREEN (s); - - ts->tileType = TileToggleTypeTile; - applyTiling (s); - } - - return FALSE; -} - -static Bool -tileVertically (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) - { - TILE_SCREEN (s); - - ts->tileType = TileToggleTypeTileVertically; - applyTiling (s); - } - - return FALSE; -} - -static Bool -tileHorizontally (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) - { - TILE_SCREEN (s); - - ts->tileType = TileToggleTypeTileHorizontally; - applyTiling (s); - } - - return FALSE; -} - -static Bool -tileCascade (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) - { - TILE_SCREEN (s); - - ts->tileType = TileToggleTypeCascade; - applyTiling (s); - } - - return FALSE; -} - -static Bool -tileRestore (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) - { - TILE_SCREEN (s); - - ts->tileType = -1; - applyTiling (s); - } - - return FALSE; -} - -static Bool -tileToggle (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) - { - CompWindow *w; - - TILE_SCREEN (s); - - for (w = s->windows; w; w = w->next) - { - TILE_WINDOW (w); - if (tw->isTiled) - break; - } - - if (w) - { - ts->tileType = -1; - applyTiling (s); - } - else - { - ts->tileType = tileGetTileToggleType (d); - applyTiling (s); - } - } - - return FALSE; -} - -static Bool -tileInitDisplay (CompPlugin *p, - CompDisplay *d) -{ - TileDisplay *td; - - if (!checkPluginABI ("core", CORE_ABIVERSION)) - return FALSE; - - td = malloc (sizeof (TileDisplay)); - if (!td) - return FALSE; - - /* Allocate a private index */ - td->screenPrivateIndex = allocateScreenPrivateIndex (d); - - /* Check if its valid */ - if (td->screenPrivateIndex < 0) - { - free (td); - return FALSE; - } - - tileSetTileVerticallyKeyInitiate (d, tileVertically); - tileSetTileHorizontallyKeyInitiate (d, tileHorizontally); - tileSetTileTileKeyInitiate (d, tileTile); - tileSetTileCascadeKeyInitiate (d, tileCascade); - tileSetTileRestoreKeyInitiate (d, tileRestore); - tileSetTileToggleKeyInitiate (d, tileToggle); - - /* Record the display */ - d->base.privates[displayPrivateIndex].ptr = td; - - return TRUE; -} - -static void -tileFiniDisplay (CompPlugin *p, - CompDisplay *d) -{ - TILE_DISPLAY (d); - - /* Free the private index */ - freeScreenPrivateIndex (d, td->screenPrivateIndex); - - free (td); -} - -static Bool -tileInitWindow (CompPlugin *p, - CompWindow *w) -{ - TileWindow *tw; - - TILE_SCREEN (w->screen); - - tw = malloc (sizeof (TileWindow)); - if (!tw) - return FALSE; - - memset (&tw->newCoords, 0, sizeof (XRectangle)); - memset (&tw->prevCoords, 0, sizeof (XRectangle)); - memset (&tw->savedCoords, 0, sizeof (XRectangle)); - - tw->savedValid = FALSE; - tw->animationType = NoAnimation; - tw->savedMaxState = 0; - tw->isTiled = FALSE; - tw->needConfigure = FALSE; - - /* random color, from group.c thanks to the author for doing it */ - tw->outlineColor[0] = rand() % 0xFFFF; - tw->outlineColor[1] = rand() % 0xFFFF; - tw->outlineColor[2] = rand() % 0xFFFF; - - w->base.privates[ts->windowPrivateIndex].ptr = tw; - - return TRUE; -} - -static void -tileFiniWindow (CompPlugin *p, - CompWindow *w) -{ - TILE_WINDOW (w); - - free (tw); -} - -static CompBool -tileInitObject (CompPlugin *p, - CompObject *o) -{ - static InitPluginObjectProc dispTab[] = { - (InitPluginObjectProc) 0, /* InitCore */ - (InitPluginObjectProc) tileInitDisplay, - (InitPluginObjectProc) tileInitScreen, - (InitPluginObjectProc) tileInitWindow - }; - - RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o)); -} - -static void -tileFiniObject (CompPlugin *p, - CompObject *o) -{ - static FiniPluginObjectProc dispTab[] = { - (FiniPluginObjectProc) 0, /* FiniCore */ - (FiniPluginObjectProc) tileFiniDisplay, - (FiniPluginObjectProc) tileFiniScreen, - (FiniPluginObjectProc) tileFiniWindow - }; - - DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o)); -} - -static Bool -tileInit (CompPlugin *p) -{ - displayPrivateIndex = allocateDisplayPrivateIndex (); - - if (displayPrivateIndex < 0) - return FALSE; - - return TRUE; -} - -static void -tileFini (CompPlugin * p) -{ - freeDisplayPrivateIndex (displayPrivateIndex); -} - -CompPluginVTable tileVTable = { - "tile", - 0, - tileInit, - tileFini, - tileInitObject, - tileFiniObject, - 0, - 0 -}; - -CompPluginVTable* -getCompPluginInfo (void) -{ - return &tileVTable; -} diff --git a/tile.cpp b/tile.cpp new file mode 100644 index 0000000..a5835e8 --- /dev/null +++ b/tile.cpp @@ -0,0 +1,1075 @@ +/** + * + * Compiz tile plugin + * + * tile.c + * + * 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. + * + * TODO + * - change vertical and horizontal tiling to similar behavior as Left + * - fix bugs + * - make vertical and horizontal maximization be saved when tiling + * + **/ + +/* TODO: Right now we are tiling immediately with no animation, fix that */ +/* FIX: Should check if window can be resized to amount we want, otherwise + don't include that window */ + +#include "tile.h" + +COMPIZ_PLUGIN_20081216 (tile, TilePluginVTable); + +/* window painting function, draws animation */ +bool +TileWindow::glPaint (const GLWindowPaintAttrib &attrib, + const GLMatrix &transform, + CompRegion ®ion, + unsigned int mask) +{ + bool status; +#if 0 + bool dontDraw = false; + if (tw->animationType != NoAnimation) + { + WindowPaintAttrib wAttrib = *attrib; + CompTransform wTransform = *transform; + float progress; + + progress = (float)ts->msResizing / + (float)tileGetAnimationDuration (s->display); + + switch (tileGetAnimateType (s->display)) + { + /* + Drop animation + */ + case AnimateTypeDropFromTop: + matrixRotate (&wTransform, + (progress * 100.0f) - 100.0f, + 0.0f, 0.0f, 1.0f); + mask |= PAINT_WINDOW_TRANSFORMED_MASK; + break; + + /* + Zoom animation + */ + case AnimateTypeZoom: + matrixTranslate (&wTransform, 0, 0, progress - 1.0f); + mask |= PAINT_WINDOW_TRANSFORMED_MASK; + break; + + /* + Slide animation + */ + case AnimateTypeSlide: + if (progress < 0.75f) + wAttrib.opacity /= 2; + else + wAttrib.opacity *= (0.5f + 2 * (progress - 0.75f)); + + if (ts->msResizing > tw->animationNum * ts->oneDuration) + { + /* animation finished */ + tw->animationType = AnimationDone; + } + else if (ts->msResizing > (tw->animationNum - 1) * + ts->oneDuration) + { + int thisDur; /* ms spent animating this window */ + thisDur = ts->msResizing % ts->oneDuration; + + if (tw->animationNum % 2) + matrixTranslate (&wTransform, + s->width - s->width * + (float)thisDur / ts->oneDuration, + 0, 0); + else + matrixTranslate (&wTransform, + -s->width + s->width * + (float)thisDur / ts->oneDuration, + 0, 0); + + mask |= PAINT_WINDOW_TRANSFORMED_MASK; + } + else + dontDraw = true; + break; + /* + Outline animation + */ + case AnimateTypeFilledOutline: + dontDraw = true; + break; + + /* + Fade animation + */ + case AnimateTypeFade: + // first half of the animation, fade out + if (progress < 0.4f) + wAttrib.opacity -= wAttrib.opacity * progress / 0.4f; + else + { + if (progress > 0.6f && tw->alreadyResized) + { + // second half of animation, fade in + wAttrib.opacity *= (progress - 0.6f) / 0.4f; + } + else + { + if (tw->needConfigure) + tileSetNewWindowSize (w); + dontDraw = true; + } + } + break; + + default: + break; + } + + if (dontDraw) + mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK; + + UNWRAP (ts, s, paintWindow); + status = (*s->paintWindow) (w, &wAttrib, &wTransform, region, mask); + WRAP (ts, s, paintWindow, tilePaintWindow); + } + else // paint window as always +#endif + + status = gWindow->glPaint (attrib, transform, region, mask); + + return status; +} + +void +TileScreen::preparePaint (int msSinceLastPaint) +{ +#if 0 + // add spent time + if (state == In || state == Out) + ts->msResizing += msSinceLastPaint; +#endif + cScreen->preparePaint (msSinceLastPaint); +} +#if 0 +void +TileScreen::glPaintScreen (CompOutput *outputs, + int numOutputs, + unsigned int mask) +{ + if (state == In || state == Out) + { + /* We want to ensure that we are painting the fullscreen output */ + outputs = &screen->fullscreenOutput (); + numOutputs = 1; + } + + gScreen->glPaintScreen (outputs, numOutputs, mask); +} +#endif +void +TileScreen::donePaint () +{ +#if 0 + if (state == In || state == Out) + { + if (msResizing > tileGetAnimationDuration (s->display)) + { + foreach (CompWindow *w, screen->windows ()) + { + TILE_WINDOW (w); + //tw->animationType = NoAnimation; + } + + //ts->msResizing = 0; + + if (state == In) + state = Tiled; + else if (state == Out) + state = Normal; + } + + cScreen->damageScreen (); + } +#endif + cScreen->donePaint (); +} + +bool +TileScreen::glPaintOutput (const GLScreenPaintAttrib &attrib, + const GLMatrix &transform, + CompRegion ®ion, + CompOutput *output, + unsigned int mask) +{ + bool status; + + if (state == In || state == Out) + mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK; + + status = gScreen->glPaintOutput (attrib, transform, region, output, mask); + + /* Check if animation is enabled, there is resizing + on screen and only outline should be drawn */ + +#if 0 + if ((state == In || state == Out) && (output->id () == ~0) && + (optionGetAnimateType () == TileOptions::AnimateTypeFilledOutline)) + { + GLMatrix sTransform = transform; + float animationDuration = optionGetAnimationDuration (); + int x, y, width, height; + + sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); + glPushMatrix (); + glLoadMatrixf (sTransform.getMatrix ()); + + glLineWidth (4.0f); + + foreach (CompWindow *w, screen->windows ()) + { + TILE_WINDOW (w); + if (tw->animationType == Animating) + { + /* Coordinate = start + speed * elapsedTime + Coordinate = start + (target - start)/interval * elapsedTime + Draw outline */ + + x = tw->tiler->previous.x () - w->input ().left + + (((float)(w->x () - tw->previous.x ())) * + ts->msResizing / animationDuration); + y = tw->previous.y () - w->input ().top + + (((float)(w->y () - tw->previous.y ())) * + ts->msResizing / animationDuration); + width = tw->previous.width () + w->input ().left + w->input ().right + + (((float)(w->width () - tw->previous.width ())) * + ts->msResizing / animationDuration); + height = tw->previous.height () + + w->input ().top + w->input ().bottom + + (((float)(w->height () - tw->previous.height ())) * + ts->msResizing / animationDuration); + + glColor3us (tw->outlineColor[0] * 0.66, + tw->outlineColor[1] * 0.66, + tw->outlineColor[2] * 0.66); + glRecti (x, y + height, x + width, y); + + glColor3usv (tw->outlineColor); + + glBegin (GL_LINE_LOOP); + glVertex3f (x, y, 0.0f); + glVertex3f (x + width, y, 0.0f); + glVertex3f (x + width, y + height, 0.0f); + glVertex3f (x, y + height, 0.0f); + glEnd (); + + glColor4usv (defaultColor); + } + } + glPopMatrix (); + glColor4usv (defaultColor); + glLineWidth (1.0f); + } +#endif + + return status; +} + +/* Resize notify used when windows are tiled horizontally or vertically */ +void +TileWindow::resizeNotify (int dx, + int dy, + int dwidth, + int dheight) +{ + window->resizeNotify (dx, dy, dwidth, dheight); + + if (!alreadyResized) + { + alreadyResized = true; + return; + } +#if 0 +//WE WILL MOVE THIS TO A DIFFERENT PLUGIN + /* Dont do anything if joining is disabled or windows are being resized */ + if (tileGetTileJoin (w->screen->display) && !ts->grabIndex) + { + CompWindow *prev = NULL, *next = NULL, *cw; + bool windowSeen = false; + + /* determine previous and next tiled window */ + for (cw = w->screen->reverseWindows; cw; cw = cw->prev) + { + if (windowSeen) + { + next = cw; + break; + } + else + { + if (cw != w) + prev = cw; + else + windowSeen = true; + } + } + + switch (ts->tileType) + { + case TileToggleTypeTile: + if (prev) + placeWin (prev, + prev->attrib.x, prev->attrib.y, + w->attrib.x - prev->attrib.x - + w->input.left - prev->input.right, + prev->height); + + if (next) + { + int currentX; + currentX = w->attrib.x + w->width + + w->input.right + next->input.left; + placeWin (next, currentX, next->attrib.y, + next->width + next->attrib.x - currentX, + next->height); + } + break; + + case TileToggleTypeTileHorizontally: + if (prev) + placeWin (prev, + prev->attrib.x, prev->attrib.y, + prev->width, + w->attrib.y - prev->attrib.y - + w->input.top - prev->input.bottom); + + if (next) + { + int currentY; + currentY = w->attrib.y + w->height + + w->input.bottom + next->input.top; + placeWin (next, next->attrib.x, + currentY, next->width, + next->height + next->attrib.y - currentY); + } + break; + case TileToggleTypeLeft: + if (!next && prev && dwidth) /* last window - on the left */ + { + XRectangle workArea; + int currentX; + + workArea = w->screen->workArea; + + for (cw = w->screen->windows; cw; cw = cw->next) + { + TILE_WINDOW(cw); + + if (!tw->isTiled || (cw->id == w->id)) + continue; + + currentX = workArea.x + w->serverX + + w->serverWidth + w->input.right + cw->input.left; + + placeWin (cw, currentX, cw->attrib.y, + workArea.width - currentX - w->input.right, + cw->attrib.height); + } + } + else if (next) /* windows on the right */ + { + XRectangle workArea; + bool first = true; + + workArea = w->screen->workArea; + + for (cw = w->screen->windows; cw; cw = cw->next) + { + TILE_WINDOW (cw); + + if (!tw->isTiled || (cw->id == w->id)) + continue; + + if (first) + { + placeWin (cw, + workArea.x + cw->input.left, cw->attrib.y, + w->serverX - w->input.left - + cw->input.left - cw->input.right - workArea.x, + cw->attrib.height); + + first = false; + } + else + { + int x = cw->attrib.x; + int y = cw->attrib.y; + int width = cw->attrib.width; + int height = cw->attrib.height; + + if (prev && (cw->id == prev->id)) + height = w->serverY - cw->attrib.y - + w->input.top - cw->input.bottom; + else if (next && (cw->id == next->id)) + y = w->serverY + w->serverHeight + + w->input.bottom + cw->input.top; + + x = w->serverX; + width = workArea.width + workArea.x - + w->serverX - w->input.right; + + placeWin (cw, x, y, width, height); + } + } + } + break; + + default: + break; + } + } +#endif +} + +/* this is resizeConstrainMinMax from resize.c, + thanks to David Reveman/Nigel Cunningham */ +void +TileWindow::constrainMinMax (int width, + int height, + int &newWidth, + int &newHeight) +{ + const XSizeHints *hints = &window->sizeHints (); + int min_width = 0; + int min_height = 0; + int max_width = MAXSHORT; + int max_height = MAXSHORT; + + if ((hints->flags & PBaseSize) && (hints->flags & PMinSize)) + { + min_width = hints->min_width; + min_height = hints->min_height; + } + else if (hints->flags & PBaseSize) + { + min_width = hints->base_width; + min_height = hints->base_height; + } + else if (hints->flags & PMinSize) + { + min_width = hints->min_width; + min_height = hints->min_height; + } + + if (hints->flags & PMaxSize) + { + max_width = hints->max_width; + max_height = hints->max_height; + } +#define CLAMP(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v)) + + /* clamp width and height to min and max values */ + width = CLAMP (width, min_width, max_width); + height = CLAMP (height, min_height, max_height); + +#undef CLAMP + + newWidth = width; + newHeight = height; +} + +/* Moves window to [x,y] and resizes to width x height + if no animation or starts animation */ + +bool +TileWindow::placeWin (int x, + int y, + unsigned int width, + unsigned int height) +{ + /* Workaround for g++ warnings */ + int i_width; + int i_height; + /* this checks if the window isnt smaller + than minimum size it has defined */ + constrainMinMax (i_width, i_height, i_width, i_height); + + width = i_width; + height = i_height; + + /* does the window need to be moved? */ + if (x == window->x () && y == window->y () && + width == window->width () && height == window->height ()) + return true; + + if (!tiler) + return false; + + /* set previous coordinates for animation */ + tiler->previous.setGeometry (window->x (), window->y (), + window->width (), window->height ()); + + /* set future coordinates for animation */ + tiler->current.setGeometry (x, y, width, height); + + alreadyResized = false; /* window is not resized now */ + needConfigure = true; +#if 0 + switch (tileGetAnimateType (w->screen->display)) + { + case AnimateTypeNone: + tileSetNewWindowSize (w); + break; + case AnimateTypeFilledOutline: + case AnimateTypeSlide: + case AnimateTypeZoom: + case AnimateTypeDropFromTop: + tileSetNewWindowSize (w); + /* fall-through */ + case AnimateTypeFade: + tw->animationType = Animating; + break; + default: + break; + } +#endif + return true; +} + +bool +TileWindow::is () +{ + TILE_SCREEN (screen); + + if (ts->optionGetExcludeMatch ().evaluate (window)) + return false; + + if (window->overrideRedirect ()) + return false; + + if (!window->focus ()) + return false; + + if (window->wmType () & (CompWindowTypeDockMask | CompWindowTypeDesktopMask)) + return false; + + if (window->state () & CompWindowStateSkipPagerMask) + return false; + + if (window->minimized () || !window->placed ()) + return false; + + return true; +} + +Tiler::Tiler () : + state (Tiler::NotTiled), + maximized (false), + savedMaxState (0) +{ + TILE_SCREEN (screen); + ts->tilers.push_back(this); +} + +void +Tiler::save (CompWindow *w) +{ + saved.setGeometry (w->serverX (), w->serverY (), + w->serverWidth (), w->serverHeight ()); + + maximized = w->state () & MAXIMIZE_STATE; + + savedMaxState = w->state () & MAXIMIZE_STATE; +} + +bool +Tiler::configure (CompWindow *w, + TileScreen::TileType type) +{ + XWindowChanges xwc; + unsigned int mask = CWX | CWY | CWWidth | CWHeight; + unsigned int xwidth, xheight; + + TILE_WINDOW (w); + + xwc.x = current.x (); + xwc.y = current.y (); + xwc.width = current.width (); + xwc.height = current.height (); + + if (type == TileScreen::Restore) + { + if (maximized) + w->maximize (savedMaxState); // ??? + } + else + w->maximize (0); + + xwidth = xwc.width; + xheight = xwc.height; + + if (xwidth == w->serverWidth ()) + mask &= ~CWWidth; + + if (xheight == w->serverHeight ()) + mask &= ~CWHeight; + + if (w->mapNum () && (mask & (CWWidth | CWHeight))) + w->sendSyncRequest (); + + w->configureXWindow (mask, &xwc); + tw->needConfigure = false; + + return true; +} + +void +TileScreen::restoreTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ + foreach (CompWindow *w, screen->windows ()) + { + TILE_WINDOW (w); + if (tw->tiler) + { + tw->placeWin (tw->tiler->saved.x (), tw->tiler->saved.y (), + tw->tiler->saved.width (), tw->tiler->saved.height ()); + tilers.remove (tw->tiler); + delete tw->tiler; + } + } +} + + +void +TileScreen::squareTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ + int countX = ceil (sqrt (count)); + int countY = ceil ((float)count / countX); + int currentX = workArea.x; + int currentY = workArea.y; + int winWidth = workArea.width / countX; + int winHeight = workArea.height / countY; + int i = 0; + + foreach (CompWindow *w, screen->windows ()) + { + TILE_WINDOW (w); + /* Put the window at the current slot */ + tw->placeWin (currentX + border.left, currentY + border.top, + winWidth - (border.left + border.right), + winHeight - (border.top + border.bottom)); + + /* If we have reached countX ... */ + if (!(i % countX)) + { + /* Reset currentX back to the workArea start + * and move current Y + */ + currentX = workArea.x; + currentY += winHeight; + } + /* Otherwise, add winWidth to currentX */ + else + currentX += winWidth; + } +} + +void +TileScreen::horizontalTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ +} + +void +TileScreen::verticalTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ +} + +/* Adapated from scale.c + * Copyright (c) 2007 Novell Inc. + */ + +void +TileScreen::evenTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ +} + +/* Adapted from maximumize.c + * Copyright (c) 2007 Kristian Lyngstol + */ + +void +TileScreen::expandTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ +} + +/* Adapted from presentwindows.cpp + * Copyright (c) 2007 Rivo Laks + * Copyright (c) 2008 Lucas Murray + */ + +void +TileScreen::organicTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ +} + +void +TileScreen::cascadeTile (CompWindowExtents &border, + XRectangle &workArea, + int count) +{ +} + +bool +TileScreen::applyTiling (CompAction *action, + CompAction::State state, + CompOption::Vector options, + TileScreen::TileType type) +{ + int count = 0; + XRectangle workArea; + CompWindowExtents border; + + workArea = screen->workArea (); + memset (&border, 0, sizeof (CompWindowExtents)); + + foreach (CompWindow *w, screen->windows ()) + { + TILE_WINDOW (w); + /* Set the largest border size as some windows may be maximized */ + if (tw->is ()) + { + if (w->input ().left > border.left) + border.left = w->input ().left; + if (w->input ().right > border.right) + border.right = w->input ().right; + if (w->input ().top > border.top) + border.top = w->input ().top; + if (w->input ().bottom > border.bottom) + border.bottom = w->input ().bottom; + + if (!tw->tiler) + tw->tiler = new Tiler; + + count++; + } + } + + /* TODO: Should probably be replaced by a propper extension manager */ + + switch (type) + { + case Restore: + restoreTile (border, workArea, count); + break; + case Square: + squareTile (border, workArea, count); + break; + case Even: + evenTile (border, workArea, count); + break; + case Horizontal: + horizontalTile (border, workArea, count); + break; + case Vertical: + verticalTile (border, workArea, count); + break; + case Expand: + expandTile (border, workArea, count); + break; + case Organic: + organicTile (border, workArea, count); + break; + case Cascade: + cascadeTile (border, workArea, count); + break; + } + + return true; +} + +#if 0 +/* Applies tiling/restoring */ +static bool +applyTiling (CompScreen *s) +{ + CompWindow *w; + int count = 0; + + TILE_SCREEN (s); + + if (ts->grabIndex) + return false; + + for (w = s->windows; w; w = w->next) + { + if (isTileWindow (w)) + count++; + } + + ts->oneDuration = tileGetAnimationDuration (s->display) / MAX (count, 1); + + if (count > 1) + { + memset (&border, 0, sizeof (CompWindowExtents)); + /* first get the largest border of the windows on this + screen - some of the windows in our list might be + maximized now and not be maximized later, so + their border information may be inaccurate */ + for (w = s->windows; w; w = w->next) + { + if (w->input.left > border.left) + border.left = w->input.left; + if (w->input.right > border.right) + border.right = w->input.right; + if (w->input.top > border.top) + border.top = w->input.top; + if (w->input.bottom > border.bottom) + border.bottom = w->input.bottom; + } + + workArea = s->workArea; + + switch (ts->tileType) + { + case TileToggleTypeTile: + + break; + case TileToggleTypeLeft: + height = workArea.height / (count - 1); + occupancy = tileGetTileLeftOccupancy (s->display); + break; + case TileToggleTypeTileVertically: + winWidth = workArea.width / count; + winHeight = workArea.height; + y = workArea.y; + break; + case TileToggleTypeTileHorizontally: + winWidth = workArea.width; + winHeight = workArea.height / count; + x = workArea.x; + break; + case TileToggleTypeCascade: + delta = tileGetTileDelta (s->display); + currentX = workArea.x; + currentY = workArea.y; + winHeight = workArea.height - delta * (count - 1); + winWidth = workArea.width - delta * (count - 1); + break; + default: + break; + } + + for (w = s->windows; w; w = w->next) + { + if (!isTileWindow (w)) + continue; + + TILE_WINDOW (w); + + if (!tw->savedValid) + saveCoords (w); + + switch (ts->tileType) + { + case TileToggleTypeTile: + placeWin(w, + currentX + border.left, currentY + border.top, + winWidth - (border.left + border.right), + winHeight - (border.top + border.bottom)); + tw->isTiled = true; + break; + case TileToggleTypeLeft: + if (first) + { + x = workArea.x; + y = workArea.y; + winWidth = workArea.width * occupancy / 100; + winHeight = workArea.height; + first = false; + } + else + { + x = workArea.x + (workArea.width * occupancy / 100); + y = workArea.y + (i * height); + winWidth = (workArea.width * (100 - occupancy) / 100); + winHeight = height; + } + + placeWin(w, + x + border.left, y + border.top, + winWidth - (border.left + border.right), + winHeight - (border.top + border.bottom)); + tw->isTiled = true; + break; + case TileToggleTypeTileVertically: + x = workArea.x + (winWidth * i); + placeWin(w, + x + border.left, y + border.top, + winWidth - (border.left + border.right), + winHeight - (border.top + border.bottom)); + tw->isTiled = true; + break; + case TileToggleTypeTileHorizontally: + y = workArea.y + (winHeight * i); + placeWin (w, x + border.left, y + border.top, + winWidth - (border.left + border.right), + winHeight - (border.top + border.bottom)); + tw->isTiled = true; + break; + case TileToggleTypeCascade: + placeWin (w, + currentX + border.left, currentY + border.top, + winWidth - (border.left + border.right), + winHeight - (border.top + border.bottom)); + tw->isTiled = true; + break; + case -1: + if (tw->isTiled) + { + placeWin (w, + tw->savedCoords.x, tw->savedCoords.y, + tw->savedCoords.width, tw->savedCoords.height); + tw->savedValid = false; + tw->isTiled = false;; } + break; + default: + break; + } + + i++; + tw->animationNum = i; + + switch (ts->tileType) + { + case TileToggleTypeTile: + if (!(i % countX)) + { + currentX = workArea.x; + currentY += winHeight; + } + else + currentX += winWidth; + break; + case TileToggleTypeCascade: + currentX += delta; + currentY += delta; + default: + break; + } + } + + if (!ts->grabIndex) + ts->grabIndex = pushScreenGrab (s, s->invisibleCursor, "tile"); + + ts->msResizing = 0; + } + + return true; +} +#endif + +TileScreen::TileScreen (CompScreen *screen) : + PrivateHandler <TileScreen, CompScreen> (screen), + TileOptions (tileVTable->getMetadata ()), + cScreen (CompositeScreen::get (screen)), + gScreen (GLScreen::get (screen)), + state (Normal), + time (0), + nextPosition (0, 0, 0, 0) +{ + ScreenInterface::setHandler (screen); + CompositeScreenInterface::setHandler (cScreen, false); + GLScreenInterface::setHandler (gScreen, false); + +#define tileInitiate(opt, type) \ + optionSet##opt##Initiate (boost::bind (&TileScreen::applyTiling, this, \ + _1, _2, _3, type)) + + tileInitiate (RestoreKey, Restore); + tileInitiate (SquareKey, Square); + tileInitiate (EvenKey, Restore); + tileInitiate (HorizontalKey, Restore); + tileInitiate (VerticalKey, Restore); + tileInitiate (ExpandKey, Restore); + tileInitiate (OrganicKey, Restore); + tileInitiate (CascadeKey, Restore); + + tileInitiate (RestoreEdge, Restore); + tileInitiate (SquareEdge, Square); + tileInitiate (EvenEdge, Restore); + tileInitiate (HorizontalEdge, Restore); + tileInitiate (VerticalEdge, Restore); + tileInitiate (ExpandEdge, Restore); + tileInitiate (OrganicEdge, Restore); + tileInitiate (CascadeEdge, Restore); + +#undef tileInitiate +} + +TileWindow::TileWindow (CompWindow *window) : + PrivateHandler <TileWindow, CompWindow> (window), + window (window), + gWindow (GLWindow::get (window)), + time (0), + alreadyResized (false), + needConfigure (false), + tiler (NULL) +{ + WindowInterface::setHandler (window, false); + GLWindowInterface::setHandler (gWindow, false); + + for (int i = 0; i < 3; i++) + outlineColor[i] = 0; + +} + +TileWindow::~TileWindow () +{ + if (tiler) + { + TILE_SCREEN (screen); + ts->tilers.remove (tiler); + delete tiler; + } +} + +bool +TilePluginVTable::init () +{ + if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) || + !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) || + !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI)) + return false; /* should set 'animate' vars'*/ + + return true; +} @@ -0,0 +1,255 @@ +/** + * + * Compiz tile plugin + * + * tile.c + * + * 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> + * + * Rewritten by: + * Copyright (c) 2008 Sam Spilsbury <smspillaz@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * TODO + * - change vertical and horizontal tiling to similar behavior as Left + * - fix bugs + * - make vertical and horizontal maximization be saved when tiling + * + **/ + +#include <core/core.h> +#include <core/privatehandler.h> + +#include <composite/composite.h> +#include <opengl/opengl.h> + +#include "tile_options.h" + +#include <cmath> + +class Tiler; + +class TileScreen : + public PrivateHandler <TileScreen, CompScreen>, + public TileOptions, + public ScreenInterface, + public CompositeScreenInterface, + public GLScreenInterface +{ + public: + + typedef enum + { + Normal = 0, + In, + Tiled, + Out + } State; + + typedef enum + { + Restore = 0, + Square, + Even, + Horizontal, + Vertical, + Expand, + Organic, + Cascade + } TileType; + + public: + + TileScreen (CompScreen *screen); + + CompositeScreen *cScreen; + GLScreen *gScreen; + + State state; + int time; + + /* Tiling queue */ + + std::list <Tiler *> tilers; + CompRect nextPosition; + TileType type; + + void + preparePaint (int); + + /* finsih */ + + bool + glPaintOutput (const GLScreenPaintAttrib &attrib, + const GLMatrix &transform, + CompRegion ®ion, + CompOutput *output, + unsigned int mask); +#if 0 + bool + glPaintScreen (CompOutput *outputs, + int numOutputs, + unsigned int mask); //for ensuring fullscreen output; +#endif + void + donePaint (); + + /* Tiling modes */ + + void + restoreTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + void + squareTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + void + horizontalTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + void + verticalTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + void + evenTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + void + expandTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + void + organicTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + void + cascadeTile (CompWindowExtents &border, + XRectangle &workArea, + int count); + + /* Actions */ + + bool + applyTiling (CompAction *action, + CompAction::State state, + CompOption::Vector options, + TileType type); +}; + +#define TILE_SCREEN(s) \ + TileScreen *ts = TileScreen::get (s); + +class Tiler +{ + public: + + Tiler (); + + public: + + typedef enum + { + NotTiled = 0, + WaitingForTile, + WaitingForRestore, + Tiled + } State; + + public: + + State state; + + bool maximized; + int savedMaxState; + + CompRect saved; + CompRect previous; + CompRect current; + + bool + configure (CompWindow *, + TileScreen::TileType); + + void + save (CompWindow *); +}; + +class TileWindow : + public PrivateHandler <TileWindow, CompWindow>, + public WindowInterface, + public GLWindowInterface +{ + public: + + TileWindow (CompWindow *window); + ~TileWindow (); + + CompWindow *window; + GLWindow *gWindow; + + bool animate; + + int outlineColor[3]; + int time; + + bool alreadyResized; + bool needConfigure; + + Tiler *tiler; + + void + resizeNotify (int, int, int, int); + + bool + glPaint (const GLWindowPaintAttrib &attrib, + const GLMatrix &transform, + CompRegion ®ion, + unsigned int mask); + + void + constrainMinMax (int width, + int height, + int &newWidth, + int &newHeight); + + bool + placeWin (int x, + int y, + unsigned int width, + unsigned int height); + + bool is (); +}; + +#define TILE_WINDOW(w) \ + TileWindow *tw = TileWindow::get (w); + +class TilePluginVTable : + public CompPlugin::VTableForScreenAndWindow <TileScreen, TileWindow> +{ + public: + + bool init (); + + PLUGIN_OPTION_HELPER (TileScreen); +}; diff --git a/tile.xml.in b/tile.xml.in index 19ea3f4..90d8e31 100644 --- a/tile.xml.in +++ b/tile.xml.in @@ -4,7 +4,7 @@ <_short>Tile</_short> <_long>Tile windows</_long> <category>Window Management</category> - <display> + <options> <group> <_short>Options</_short> <option name="animate_type" type="int"> @@ -99,36 +99,72 @@ </group> <group> <_short>Key Bindings</_short> - <option name="tile_vertically_key" type="key"> - <_short>Tile Windows Vertically</_short> - <_long>Move and resize all visible windows so that they have full height, same width and occupy whole screen.</_long> - </option> - <option name="tile_horizontally_key" type="key"> - <_short>Tile Windows Horizontally</_short> - <_long>Move and resize all visible windows so that they have full width, same height and occupy whole screen.</_long> - </option> - <option name="tile_tile_key" type="key"> - <_short>Tile Windows</_short> - <_long>Move and resize all visible windows both vertically and horizontally, so that the occupy whole screen and are in a grid.</_long> - <default><Super><Shift>a</default> - </option> - <option name="tile_cascade_key" type="key"> - <_short>Cascade Windows</_short> - <_long>Move and resize all visible windows with the delta value set for cascading.</_long> - <default><Super><Shift>s</default> - </option> - <option name="tile_restore_key" type="key"> - <_short>Restore Windows</_short> - <_long>Restore windows to their original position they had before tiling.</_long> - <default><Super><Shift>z</default> - </option> - <option name="tile_toggle_key" type="key"> - <_short>Toggle Tiling</_short> - <_long>Toggle between tile and restore</_long> - <default><Super><Shift>x</default> + <option name="restore_key" type="key"> + <_short>Restore to previous position</_short> + <_long>Restore all windows to an untiled state</_long> + </option> + <option name="square_key" type="key"> + <_short>Tile windows in a square pattern</_short> + <_long>Move and resize all windows so that they appear on screen in a square pattern</_long> + </option> + <option name="even_key" type="key"> + <_short>Tile windows evenly</_short> + <_long>Move and resize all windows so that they are mostly the same size and take up all screen space</_long> + </option> + <option name="horizontal_key" type="key"> + <_short>Tile windows in a horizontal pattern</_short> + <_long>Move and resize all windwos so that they appear on screen in a horizontal pattern</_long> + </option> + <option name="vertical_key" type="key"> + <_short>Tile windows in a vertical pattern</_short> + <_long>Move and resize all windwos so that they appear on screen in a vertical pattern</_long> + </option> + <option name="expand_key" type="key"> + <_short>Expand all windows</_short> + <_long>Move and resize all windows so that they stay in their current position as best as possible and expand to take up screen space</_long> + </option> + <option name="organic_key" type="key"> + <_short>Make visible all windows</_short> + <_long>Move and resize all windows as little as possible to ensure that every one is visible</_long> + </option> + <option name="cascade_key" type="key"> + <_short>Cascade windows</_short> + <_long>Move and resize all windows so they are in a cascading pattern with a specified distance between them</_long> + </option> + <option name="restore_edge" type="edge"> + <_short>Restore to previous position</_short> + <_long>Restore all windows to an untiled state</_long> + </option> + <option name="square_edge" type="edge"> + <_short>Tile windows in a square pattern</_short> + <_long>Move and resize all windows so that they appear on screen in a square pattern</_long> + </option> + <option name="even_edge" type="edge"> + <_short>Tile windows evenly</_short> + <_long>Move and resize all windows so that they are mostly the same size and take up all screen space</_long> + </option> + <option name="horizontal_edge" type="edge"> + <_short>Tile windows in a horizontal pattern</_short> + <_long>Move and resize all windwos so that they appear on screen in a horizontal pattern</_long> + </option> + <option name="vertical_edge" type="edge"> + <_short>Tile windows in a vertical pattern</_short> + <_long>Move and resize all windwos so that they appear on screen in a vertical pattern</_long> + </option> + <option name="expand_edge" type="edge"> + <_short>Expand all windows</_short> + <_long>Move and resize all windows so that they stay in their current position as best as possible and expand to take up screen space</_long> + </option> + <option name="organic_edge" type="edge"> + <_short>Make visible all windows</_short> + <_long>Move and resize all windows as little as possible to ensure that every one is visible</_long> + </option> + <option name="cascade_edge" type="edge"> + <_short>Cascade windows</_short> + <_long>Move and resize all windows so they are in a cascading pattern with a specified distance between them</_long> </option> </group> - </display> + </options> </plugin> </compiz> |