summaryrefslogtreecommitdiff
path: root/tile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tile.cpp')
-rw-r--r--tile.cpp1075
1 files changed, 1075 insertions, 0 deletions
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 &region,
+ 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 &region,
+ 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;
+}