summaryrefslogtreecommitdiff
path: root/plugins/switcher
diff options
context:
space:
mode:
authorDennis Kasprzyk <onestone@compiz-fusion.org>2009-03-15 06:09:18 +0100
committerDennis kasprzyk <onestone@compiz-fusion.org>2009-03-15 06:09:18 +0100
commit163f6b6f3c3b7764987cbdf8e03cc355edeaa499 (patch)
tree4278afde195343dcb8277b0bb0b6efc926ce8907 /plugins/switcher
parent28e45c55c11e20206d3bc9056aea8fc7f1b7a0e7 (diff)
downloadcompiz-with-glib-mainloop-163f6b6f3c3b7764987cbdf8e03cc355edeaa499.tar.gz
compiz-with-glib-mainloop-163f6b6f3c3b7764987cbdf8e03cc355edeaa499.tar.bz2
New generalized build system.
Diffstat (limited to 'plugins/switcher')
-rw-r--r--plugins/switcher/CMakeLists.txt5
-rw-r--r--plugins/switcher/src/switcher.cpp1635
-rw-r--r--plugins/switcher/src/switcher.h238
-rw-r--r--plugins/switcher/switcher.xml.in156
4 files changed, 2034 insertions, 0 deletions
diff --git a/plugins/switcher/CMakeLists.txt b/plugins/switcher/CMakeLists.txt
new file mode 100644
index 0000000..a5908e1
--- /dev/null
+++ b/plugins/switcher/CMakeLists.txt
@@ -0,0 +1,5 @@
+find_package (Compiz REQUIRED)
+
+include (CompizPlugin)
+
+compiz_plugin(switcher PLUGINDEPS composite opengl) \ No newline at end of file
diff --git a/plugins/switcher/src/switcher.cpp b/plugins/switcher/src/switcher.cpp
new file mode 100644
index 0000000..a13c47f
--- /dev/null
+++ b/plugins/switcher/src/switcher.cpp
@@ -0,0 +1,1635 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include "switcher.h"
+
+COMPIZ_PLUGIN_20081216 (switcher, SwitchPluginVTable)
+
+static float _boxVertices[] =
+{
+ -(WIDTH >> 1), 0,
+ -(WIDTH >> 1), BOX_WIDTH,
+ (WIDTH >> 1), BOX_WIDTH,
+ (WIDTH >> 1), 0,
+
+ -(WIDTH >> 1), BOX_WIDTH,
+ -(WIDTH >> 1), HEIGHT - BOX_WIDTH,
+ -(WIDTH >> 1) + BOX_WIDTH, HEIGHT - BOX_WIDTH,
+ -(WIDTH >> 1) + BOX_WIDTH, 0,
+
+ (WIDTH >> 1) - BOX_WIDTH, BOX_WIDTH,
+ (WIDTH >> 1) - BOX_WIDTH, HEIGHT - BOX_WIDTH,
+ (WIDTH >> 1), HEIGHT - BOX_WIDTH,
+ (WIDTH >> 1), 0,
+
+ -(WIDTH >> 1), HEIGHT - BOX_WIDTH,
+ -(WIDTH >> 1), HEIGHT,
+ (WIDTH >> 1), HEIGHT,
+ (WIDTH >> 1), HEIGHT - BOX_WIDTH
+};
+
+
+void
+SwitchScreen::setSelectedWindowHint ()
+{
+ XChangeProperty (screen->dpy (), popupWindow, selectWinAtom,
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &selectedWindow, 1);
+}
+
+bool
+SwitchWindow::isSwitchWin ()
+{
+ if (!window->isViewable ())
+ {
+ if (sScreen->opt[SWITCH_OPTION_MINIMIZED].value ().b ())
+ {
+ if (!window->minimized () && !window->inShowDesktopMode () &&
+ !window->shaded ())
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (!window->isFocussable ())
+ return false;
+
+ if (window->overrideRedirect ())
+ return false;
+
+ if (sScreen->selection == Panels)
+ {
+ if (!(window->type () &
+ (CompWindowTypeDockMask | CompWindowTypeDesktopMask)))
+ return false;
+ }
+ else
+ {
+ CompMatch *match;
+
+ if (window->wmType () &
+ (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
+ return false;
+
+ if (window->state () & CompWindowStateSkipTaskbarMask)
+ return false;
+
+ match = &sScreen->opt[SWITCH_OPTION_WINDOW_MATCH].value ().match ();
+ if (!match->evaluate (window))
+ return false;
+
+ }
+
+ if (sScreen->selection == CurrentViewport)
+ {
+ if (!window->mapNum () || !window->isViewable ())
+ {
+ CompWindow::Geometry &sg = window->serverGeometry ();
+ if (sg.x () + sg.width () <= 0 ||
+ sg.y () + sg.height () <= 0 ||
+ sg.x () >= screen->width () ||
+ sg.y () >= screen->height ())
+ return false;
+ }
+ else
+ {
+ if (!window->focus ())
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void
+SwitchScreen::activateEvent (bool activating)
+{
+ CompOption::Vector o (0);
+
+ o.push_back (CompOption ("root", CompOption::TypeInt));
+ o.push_back (CompOption ("active", CompOption::TypeBool));
+
+ o[0].value ().set ((int) screen->root ());
+ o[1].value ().set (activating);
+
+ screen->handleCompizEvent ("switcher", "activate", o);
+}
+
+
+static bool
+compareWindows (CompWindow *w1,
+ CompWindow *w2)
+{
+
+ if (w1->mapNum () && !w2->mapNum ())
+ return true;
+
+ if (w2->mapNum () && !w1->mapNum ())
+ return false;
+
+ return w2->activeNum () < w1->activeNum ();
+}
+
+
+void
+SwitchScreen::updateWindowList (int count)
+{
+ int x, y;
+
+ if (count > 1)
+ {
+ count -= (count + 1) & 1;
+ if (count < 3)
+ count = 3;
+ }
+
+ pos = ((count >> 1) - windows.size ()) * WIDTH;
+ move = 0;
+
+ selectedWindow = windows.front ()->id ();
+
+ x = screen->currentOutputDev ().x1 () +
+ screen->currentOutputDev ().width () / 2;
+ y = screen->currentOutputDev ().y1 () +
+ screen->currentOutputDev ().height () / 2;
+
+ if (popupWindow)
+ {
+ CompWindow *w = screen->findWindow (popupWindow);
+
+ if (w)
+ w->resize (x - WINDOW_WIDTH (count) / 2,
+ y - WINDOW_HEIGHT / 2,
+ WINDOW_WIDTH (count),
+ WINDOW_HEIGHT);
+ else
+ XMoveResizeWindow (screen->dpy (), popupWindow,
+ x - WINDOW_WIDTH (count) / 2,
+ y - WINDOW_HEIGHT / 2,
+ WINDOW_WIDTH (count),
+ WINDOW_HEIGHT);
+ }
+}
+
+void
+SwitchScreen::createWindowList (int count)
+{
+
+ windows.clear ();
+
+ foreach (CompWindow *w, screen->windows ())
+ {
+ if (SwitchWindow::get (w)->isSwitchWin ())
+ {
+ SWITCH_WINDOW (w);
+ windows.push_back (w);
+
+ sw->cWindow->damageRectSetEnabled (sw, true);
+ }
+ }
+
+ windows.sort (compareWindows);
+
+ if (windows.size () == 2)
+ {
+ windows.push_back (windows.front ());
+ windows.push_back ((*++windows.begin ()));
+ }
+
+ updateWindowList (count);
+}
+
+void
+SwitchScreen::switchToWindow (bool toNext)
+{
+ CompWindow *w = NULL;
+ CompWindowList::iterator it;
+
+ if (!grabIndex)
+ return;
+
+ for (it = windows.begin (); it != windows.end (); it++)
+ {
+ if ((*it)->id () == selectedWindow)
+ break;
+ }
+
+ if (it == windows.end ())
+ return;
+
+ if (toNext)
+ {
+ it++;
+ if (it == windows.end ())
+ w = windows.front ();
+ else
+ w = *it;
+ }
+ else
+ {
+ if (it == windows.begin ())
+ w = windows.back ();
+ else
+ w = *--it;
+ }
+
+ if (w)
+ {
+ Window old = selectedWindow;
+
+ if (selection == AllViewports &&
+ opt[SWITCH_OPTION_AUTO_ROTATE].value ().b ())
+ {
+ XEvent xev;
+ CompPoint pnt = w->defaultViewport ();
+
+ xev.xclient.type = ClientMessage;
+ xev.xclient.display = screen->dpy ();
+ xev.xclient.format = 32;
+
+ xev.xclient.message_type = Atoms::desktopViewport;
+ xev.xclient.window = screen->root ();
+
+ xev.xclient.data.l[0] = pnt.x () * screen->width ();
+ xev.xclient.data.l[1] = pnt.y () * screen->height ();
+ xev.xclient.data.l[2] = 0;
+ xev.xclient.data.l[3] = 0;
+ xev.xclient.data.l[4] = 0;
+
+ XSendEvent (screen->dpy (), screen->root (), FALSE,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+ }
+
+ lastActiveNum = w->activeNum ();
+ selectedWindow = w->id ();
+
+ if (!zoomedWindow)
+ zoomedWindow = selectedWindow;
+
+ if (old != w->id ())
+ {
+ if (toNext)
+ move -= WIDTH;
+ else
+ move += WIDTH;
+
+ moreAdjust = true;
+ }
+
+ if (popupWindow)
+ {
+ CompWindow *popup;
+
+ popup = screen->findWindow (popupWindow);
+ if (popup)
+ CompositeWindow::get (popup)->addDamage ();
+
+ setSelectedWindowHint ();
+ }
+
+ CompositeWindow::get (w)->addDamage ();
+
+ if (old)
+ {
+ w = screen->findWindow (old);
+ if (w)
+ CompositeWindow::get (w)->addDamage ();
+ }
+ }
+}
+
+int
+SwitchScreen::countWindows ()
+{
+ int count = 0;
+
+ foreach (CompWindow *w, screen->windows ())
+ if (SwitchWindow::get (w)->isSwitchWin ())
+ {
+ count++;
+ if (count == 5)
+ break;
+ }
+
+ if (count == 5 && screen->width () <= WINDOW_WIDTH (5))
+ count = 3;
+
+ return count;
+}
+
+static Visual *
+findArgbVisual (Display *dpy, int scr)
+{
+ XVisualInfo *xvi;
+ XVisualInfo temp;
+ int nvi;
+ int i;
+ XRenderPictFormat *format;
+ Visual *visual;
+
+ temp.screen = scr;
+ temp.depth = 32;
+ temp.c_class = TrueColor;
+
+ xvi = XGetVisualInfo (dpy,
+ VisualScreenMask |
+ VisualDepthMask |
+ VisualClassMask,
+ &temp,
+ &nvi);
+ if (!xvi)
+ return 0;
+
+ visual = 0;
+ for (i = 0; i < nvi; i++)
+ {
+ format = XRenderFindVisualFormat (dpy, xvi[i].visual);
+ if (format->type == PictTypeDirect && format->direct.alphaMask)
+ {
+ visual = xvi[i].visual;
+ break;
+ }
+ }
+
+ XFree (xvi);
+
+ return visual;
+}
+
+
+void
+SwitchScreen::initiate (SwitchWindowSelection selection,
+ bool showPopup)
+{
+ int count;
+
+ if (screen->otherGrabExist ("switcher", "scale", "cube", 0))
+ return;
+
+ this->selection = selection;
+ selectedWindow = None;
+
+ count = countWindows ();
+ if (count < 1)
+ return;
+
+ if (!popupWindow && showPopup)
+ {
+ Display *dpy = screen->dpy ();
+ XSizeHints xsh;
+ XWMHints xwmh;
+ Atom state[4];
+ int nState = 0;
+ XSetWindowAttributes attr;
+ Visual *visual;
+
+ visual = findArgbVisual (dpy, screen->screenNum ());
+ if (!visual)
+ return;
+
+ if (count > 1)
+ {
+ count -= (count + 1) & 1;
+ if (count < 3)
+ count = 3;
+ }
+
+ xsh.flags = PSize | PPosition | PWinGravity;
+ xsh.width = WINDOW_WIDTH (count);
+ xsh.height = WINDOW_HEIGHT;
+ xsh.win_gravity = StaticGravity;
+
+ xwmh.flags = InputHint;
+ xwmh.input = 0;
+
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap (dpy, screen->root (), visual,
+ AllocNone);
+
+ popupWindow =
+ XCreateWindow (dpy, screen->root (),
+ screen->width () / 2 - xsh.width / 2,
+ screen->height () / 2 - xsh.height / 2,
+ xsh.width, xsh.height, 0,
+ 32, InputOutput, visual,
+ CWBackPixel | CWBorderPixel | CWColormap, &attr);
+
+ XSetWMProperties (dpy, popupWindow, NULL, NULL,
+ programArgv, programArgc,
+ &xsh, &xwmh, NULL);
+
+ state[nState++] = Atoms::winStateAbove;
+ state[nState++] = Atoms::winStateSticky;
+ state[nState++] = Atoms::winStateSkipTaskbar;
+ state[nState++] = Atoms::winStateSkipPager;
+
+ XChangeProperty (dpy, popupWindow,
+ Atoms::winState,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) state, nState);
+
+ XChangeProperty (dpy, popupWindow,
+ Atoms::winType,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) &Atoms::winTypeUtil, 1);
+
+ screen->setWindowProp (popupWindow, Atoms::winDesktop, 0xffffffff);
+
+ setSelectedWindowHint ();
+ }
+
+ if (!grabIndex)
+ grabIndex = screen->pushGrab (screen->invisibleCursor (), "switcher");
+
+ if (grabIndex)
+ {
+ if (!switching)
+ {
+ lastActiveNum = screen->activeNum ();
+
+ createWindowList (count);
+
+ sTranslate = zoom;
+
+ if (popupWindow && showPopup)
+ {
+ CompWindow *w;
+
+
+ w = screen->findWindow (popupWindow);
+ if (w && (w->state () & CompWindowStateHiddenMask))
+ {
+ w->unminimize ();
+ }
+ else
+ {
+ XMapWindow (screen->dpy (), popupWindow);
+ }
+ setSelectedWindowHint ();
+ }
+
+ activateEvent (true);
+ }
+
+ cScreen->damageScreen ();
+
+ switching = true;
+ moreAdjust = true;
+
+ screen->handleEventSetEnabled (this, true);
+ cScreen->preparePaintSetEnabled (this, true);
+ cScreen->donePaintSetEnabled (this, true);
+ gScreen->glPaintOutputSetEnabled (this, true);
+
+ foreach (CompWindow *w, screen->windows ())
+ {
+ SWITCH_WINDOW (w);
+
+ sw->gWindow->glPaintSetEnabled (sw, true);
+ }
+ }
+}
+
+
+static bool
+switchTerminate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = CompOption::getIntOptionNamed (options, "root");
+
+ if (action)
+ action->setState (action->state () & ~(CompAction::StateTermKey |
+ CompAction::StateTermButton));
+
+ if (xid && xid != screen->root ())
+ return false;
+
+ SWITCH_SCREEN (screen);
+
+
+ if (ss->grabIndex)
+ {
+ CompWindow *w;
+
+ if (ss->popupWindow)
+ {
+ w = screen->findWindow (ss->popupWindow);
+ if (w && w->managed () && w->mapNum ())
+ {
+ w->minimize ();
+ }
+ else
+ {
+ XUnmapWindow (screen->dpy (), ss->popupWindow);
+ }
+ }
+
+ ss->switching = false;
+
+ if (state & CompAction::StateCancel)
+ {
+ ss->selectedWindow = None;
+ ss->zoomedWindow = None;
+ }
+
+ if (state && ss->selectedWindow)
+ {
+ w = screen->findWindow (ss->selectedWindow);
+ if (w)
+ screen->sendWindowActivationRequest (w->id ());
+ }
+
+ screen->removeGrab (ss->grabIndex, 0);
+ ss->grabIndex = NULL;
+
+ if (!ss->popupWindow)
+ screen->handleEventSetEnabled (ss, false);
+
+ if (!ss->zooming)
+ {
+ ss->selectedWindow = None;
+ ss->zoomedWindow = None;
+
+ ss->activateEvent (false);
+ }
+ else
+ {
+ ss->moreAdjust = true;
+ }
+
+ ss->selectedWindow = None;
+ ss->setSelectedWindowHint ();
+
+ ss->lastActiveNum = 0;
+
+ ss->cScreen->damageScreen ();
+ }
+
+
+ return false;
+}
+
+static bool
+switchInitiateCommon (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options,
+ SwitchWindowSelection selection,
+ bool showPopup,
+ bool nextWindow)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = CompOption::getIntOptionNamed (options, "root");
+
+ if (xid != screen->root ())
+ return false;
+
+ SWITCH_SCREEN (screen);
+
+ if (!ss->switching)
+ {
+ ss->initiate (selection, showPopup);
+
+ if (state & CompAction::StateInitKey)
+ action->setState (action->state () | CompAction::StateTermKey);
+
+ if (state & CompAction::StateInitEdge)
+ action->setState (action->state () | CompAction::StateTermEdge);
+ else if (state & CompAction::StateInitButton)
+ action->setState (action->state () | CompAction::StateTermButton);
+ }
+
+ ss->switchToWindow (nextWindow);
+
+ return false;
+}
+
+#define SWITCHBIND(a,b,c) boost::bind (switchInitiateCommon, _1, _2, _3, a, b, c)
+
+static const CompMetadata::OptionInfo switchOptionInfo[] = {
+ { "next_button", "button", 0,
+ SWITCHBIND (CurrentViewport, true, true), switchTerminate },
+ { "next_key", "key", 0,
+ SWITCHBIND (CurrentViewport, true, true), switchTerminate },
+ { "prev_button", "button", 0,
+ SWITCHBIND (CurrentViewport, true, false), switchTerminate },
+ { "prev_key", "key", 0,
+ SWITCHBIND (CurrentViewport, true, false), switchTerminate },
+ { "next_all_button", "button", 0,
+ SWITCHBIND (AllViewports, true, true), switchTerminate },
+ { "next_all_key", "key", 0,
+ SWITCHBIND (AllViewports, true, true), switchTerminate },
+ { "prev_all_button", "button", 0,
+ SWITCHBIND (AllViewports, true, false), switchTerminate },
+ { "prev_all_key", "key", 0,
+ SWITCHBIND (AllViewports, true, false), switchTerminate },
+ { "next_no_popup_button", "button", 0,
+ SWITCHBIND (CurrentViewport, false, true), switchTerminate },
+ { "next_no_popup_key", "key", 0,
+ SWITCHBIND (CurrentViewport, false, true), switchTerminate },
+ { "prev_no_popup_button", "button", 0,
+ SWITCHBIND (CurrentViewport, false, false), switchTerminate },
+ { "prev_no_popup_key", "key", 0,
+ SWITCHBIND (CurrentViewport, false, false), switchTerminate },
+ { "next_panel_button", "button", 0,
+ SWITCHBIND (Panels, false, true), switchTerminate },
+ { "next_panel_key", "key", 0,
+ SWITCHBIND (Panels, false, true), switchTerminate },
+ { "prev_panel_button", "button", 0,
+ SWITCHBIND (Panels, false, false), switchTerminate },
+ { "prev_panel_key", "key", 0,
+ SWITCHBIND (Panels, false, false), switchTerminate },
+ { "speed", "float", "<min>0.1</min>", 0, 0 },
+ { "timestep", "float", "<min>0.1</min>", 0, 0 },
+ { "window_match", "match", 0, 0, 0 },
+ { "mipmap", "bool", 0, 0, 0 },
+ { "saturation", "int", "<min>0</min><max>100</max>", 0, 0 },
+ { "brightness", "int", "<min>0</min><max>100</max>", 0, 0 },
+ { "opacity", "int", "<min>0</min><max>100</max>", 0, 0 },
+ { "bring_to_front", "bool", 0, 0, 0 },
+ { "zoom", "float", "<min>0</min>", 0, 0 },
+ { "icon", "bool", 0, 0, 0 },
+ { "minimized", "bool", 0, 0, 0 },
+ { "auto_rotate", "bool", 0, 0, 0 }
+};
+
+#undef SWITCHBIND
+
+void
+SwitchScreen::windowRemove (Window id)
+{
+ CompWindow *w;
+
+ w = screen->findWindow (id);
+ if (w)
+ {
+ bool inList = false;
+ int count, j, i = 0;
+ Window selected, old;
+
+ SWITCH_WINDOW (w);
+
+ if (!sw->isSwitchWin ())
+ return;
+
+ sw->cWindow->damageRectSetEnabled (sw, false);
+ sw->gWindow->glPaintSetEnabled (sw, false);
+
+ old = selected = selectedWindow;
+
+ CompWindowList::iterator it = windows.begin ();
+ while (it != windows.end ())
+ {
+ if (*it == w)
+ {
+ inList = true;
+
+ if (w->id () == selected)
+ {
+ it++;
+ if (it == windows.end ())
+ selected = windows.front ()->id ();
+ else
+ selected = (*it)->id ();
+ it--;
+ }
+
+ CompWindowList::iterator del = it;
+ it++;
+ windows.erase (del);
+ }
+ else
+ it++;
+ }
+
+ if (!inList)
+ return;
+
+ count = windows.size ();
+
+ if (windows.size () == 2)
+ {
+ if (windows.front () == windows.back ())
+ {
+ windows.pop_back ();
+ count = 1;
+ }
+ else
+ {
+ windows.push_back (windows.front ());
+ windows.push_back ((*++windows.begin ()));
+ }
+ }
+
+ if (windows.size () == 0)
+ {
+ CompOption::Vector o (0);
+
+ o.push_back (CompOption ("root", CompOption::TypeInt));
+
+ o[0].value ().set ((int) screen->root ());
+
+ switchTerminate (NULL, 0, o);
+ return;
+ }
+
+ if (!grabIndex)
+ return;
+
+ updateWindowList (count);
+
+ foreach (CompWindow *w, windows)
+ {
+ selectedWindow = w->id ();
+
+ if (selectedWindow == selected)
+ break;
+
+ pos -= WIDTH;
+ if (pos < -windows.size () * WIDTH)
+ pos += windows.size () * WIDTH;
+ }
+
+ if (popupWindow)
+ {
+ CompWindow *popup;
+
+ popup = screen->findWindow (popupWindow);
+ if (popup)
+ CompositeWindow::get (popup)->addDamage ();
+
+ setSelectedWindowHint ();
+ }
+
+ if (old != selectedWindow)
+ {
+ CompositeWindow::get (w)->addDamage ();
+
+ w = screen->findWindow (old);
+ if (w)
+ CompositeWindow::get (w)->addDamage ();
+
+ moreAdjust = true;
+ }
+ }
+}
+
+void
+SwitchScreen::updateForegroundColor ()
+{
+ Atom actual;
+ int result, format;
+ unsigned long n, left;
+ unsigned char *propData;
+
+ if (!popupWindow)
+ return;
+
+
+ result = XGetWindowProperty (screen->dpy (), popupWindow,
+ selectFgColorAtom, 0L, 4L, FALSE,
+ XA_INTEGER, &actual, &format,
+ &n, &left, &propData);
+
+ if (result == Success && n && propData)
+ {
+ if (n == 3 || n == 4)
+ {
+ long *data = (long *) propData;
+
+ fgColor[0] = MIN (0xffff, data[0]);
+ fgColor[1] = MIN (0xffff, data[1]);
+ fgColor[2] = MIN (0xffff, data[2]);
+
+ if (n == 4)
+ fgColor[3] = MIN (0xffff, data[3]);
+ }
+
+ XFree (propData);
+ }
+ else
+ {
+ fgColor[0] = 0;
+ fgColor[1] = 0;
+ fgColor[2] = 0;
+ fgColor[3] = 0xffff;
+ }
+}
+
+
+
+void
+SwitchScreen::handleEvent (XEvent *event)
+{
+ CompWindow *w;
+
+ screen->handleEvent (event);
+
+ switch (event->type) {
+ case UnmapNotify:
+ windowRemove (event->xunmap.window);
+ break;
+ case DestroyNotify:
+ windowRemove (event->xdestroywindow.window);
+ break;
+ case PropertyNotify:
+ if (event->xproperty.atom == selectFgColorAtom)
+ {
+ if (event->xproperty.window == popupWindow)
+ updateForegroundColor ();
+ }
+
+ default:
+ break;
+ }
+}
+
+bool
+SwitchScreen::adjustVelocity ()
+{
+ float dx, adjust, amount;
+
+ dx = move;
+
+ adjust = dx * 0.15f;
+ amount = fabs (dx) * 1.5f;
+ if (amount < 0.2f)
+ amount = 0.2f;
+ else if (amount > 2.0f)
+ amount = 2.0f;
+
+ mVelocity = (amount * mVelocity + adjust) / (amount + 1.0f);
+
+ if (zooming)
+ {
+ float dt, ds;
+
+ if (switching)
+ dt = zoom - translate;
+ else
+ dt = 0.0f - translate;
+
+ adjust = dt * 0.15f;
+ amount = fabs (dt) * 1.5f;
+ if (amount < 0.2f)
+ amount = 0.2f;
+ else if (amount > 2.0f)
+ amount = 2.0f;
+
+ tVelocity = (amount * tVelocity + adjust) / (amount + 1.0f);
+
+ if (selectedWindow == zoomedWindow)
+ ds = zoom - sTranslate;
+ else
+ ds = 0.0f - sTranslate;
+
+ adjust = ds * 0.5f;
+ amount = fabs (ds) * 5.0f;
+ if (amount < 1.0f)
+ amount = 1.0f;
+ else if (amount > 6.0f)
+ amount = 6.0f;
+
+ sVelocity = (amount * sVelocity + adjust) / (amount + 1.0f);
+
+ if (selectedWindow == zoomedWindow)
+ {
+ if (fabs (dx) < 0.1f && fabs (mVelocity) < 0.2f &&
+ fabs (dt) < 0.001f && fabs (tVelocity) < 0.001f &&
+ fabs (ds) < 0.001f && fabs (sVelocity) < 0.001f)
+ {
+ mVelocity = tVelocity = sVelocity = 0.0f;
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (fabs (dx) < 0.1f && fabs (mVelocity) < 0.2f)
+ {
+ mVelocity = 0.0f;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void
+SwitchScreen::preparePaint (int msSinceLastPaint)
+{
+ if (moreAdjust)
+ {
+ int steps, m;
+ float amount, chunk;
+
+ amount = msSinceLastPaint * 0.05f *
+ opt[SWITCH_OPTION_SPEED].value ().f ();
+ steps = amount /
+ (0.5f * opt[SWITCH_OPTION_TIMESTEP].value ().f ());
+ if (!steps) steps = 1;
+ chunk = amount / (float) steps;
+
+ while (steps--)
+ {
+ moreAdjust = adjustVelocity ();
+ if (!moreAdjust)
+ {
+ pos += move;
+ move = 0;
+
+ if (zooming)
+ {
+ if (switching)
+ {
+ translate = zoom;
+ sTranslate = zoom;
+ }
+ else
+ {
+ translate = 0.0f;
+ sTranslate = zoom;
+
+ selectedWindow = None;
+ zoomedWindow = None;
+
+ if (grabIndex)
+ {
+ screen->removeGrab (grabIndex, 0);
+ grabIndex = 0;
+ }
+
+ activateEvent (false);
+ }
+ }
+ break;
+ }
+
+ m = mVelocity * chunk;
+ if (!m)
+ {
+ if (mVelocity)
+ m = (move > 0) ? 1 : -1;
+ }
+
+ move -= m;
+ pos += m;
+ if (pos < -windows.size () * WIDTH)
+ pos += windows.size () * WIDTH;
+ else if (pos > 0)
+ pos -= windows.size () * WIDTH;
+
+ translate += tVelocity * chunk;
+ sTranslate += sVelocity * chunk;
+
+ if (selectedWindow != zoomedWindow)
+ {
+ if (sTranslate < 0.01f)
+ zoomedWindow = selectedWindow;
+ }
+ }
+ }
+
+ cScreen->preparePaint (msSinceLastPaint);
+}
+
+bool
+SwitchScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
+ const GLMatrix &transform,
+ const CompRegion &region,
+ CompOutput *output,
+ unsigned int mask)
+{
+ bool status;
+
+ zoomMask = ZOOMED_WINDOW_MASK | NORMAL_WINDOW_MASK;
+
+ if (grabIndex || (zooming && translate > 0.001f))
+ {
+ GLMatrix sTransform (transform);
+ CompWindow *zoomed;
+ CompWindow *switcher;
+ Window zoomedAbove = None;
+
+ if (zooming)
+ {
+ mask &= ~PAINT_SCREEN_REGION_MASK;
+ mask |= PAINT_SCREEN_TRANSFORMED_MASK | PAINT_SCREEN_CLEAR_MASK;
+
+ sTransform.translate (0.0f, 0.0f, -translate);
+
+ zoomMask = NORMAL_WINDOW_MASK;
+ }
+
+ if (opt[SWITCH_OPTION_BRINGTOFRONT].value ().b ())
+ {
+ zoomed = screen->findWindow (zoomedWindow);
+ if (zoomed)
+ {
+ CompWindow *w;
+
+ for (w = zoomed->prev; w && w->id () <= 1; w = w->prev);
+ zoomedAbove = (w) ? w->id () : None;
+
+ screen->unhookWindow (zoomed);
+ screen->insertWindow (zoomed,
+ screen->windows ().back ()->id ());
+ }
+ }
+ else
+ {
+ zoomed = NULL;
+ }
+
+ ignoreSwitcher = true;
+
+ status = gScreen->glPaintOutput (sAttrib, sTransform, region, output,
+ mask);
+
+ if (zooming)
+ {
+ float zTranslate;
+
+ mask &= ~PAINT_SCREEN_CLEAR_MASK;
+ mask |= PAINT_SCREEN_NO_BACKGROUND_MASK;
+
+ zoomMask = ZOOMED_WINDOW_MASK;
+
+ zTranslate = MIN (sTranslate, translate);
+ sTransform.translate (0.0f, 0.0f, zTranslate);
+
+ status = gScreen->glPaintOutput (sAttrib, sTransform, region,
+ output, mask);
+ }
+
+ if (zoomed)
+ {
+ screen->unhookWindow (zoomed);
+ screen->insertWindow (zoomed, zoomedAbove);
+ }
+
+ ignoreSwitcher = false;
+
+ switcher = screen->findWindow (popupWindow);
+
+ if (switcher)
+ {
+ SWITCH_WINDOW (switcher);
+
+ sTransform = transform;
+
+ sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
+
+ glPushMatrix ();
+ glLoadMatrixf (sTransform.getMatrix ());
+
+ if (!switcher->destroyed () &&
+ switcher->isViewable () &&
+ sw->cWindow->damaged ())
+ {
+ sw->gWindow->glPaint (sw->gWindow->paintAttrib (),
+ sTransform, infiniteRegion, 0);
+ }
+
+ glPopMatrix ();
+ }
+ }
+ else
+ {
+ status = gScreen->glPaintOutput (sAttrib, transform, region, output,
+ mask);
+ }
+
+ return status;
+}
+
+void
+SwitchScreen::donePaint ()
+{
+ if ((grabIndex || zooming) && moreAdjust)
+ {
+ if (zooming)
+ {
+ cScreen->damageScreen ();
+ }
+ else
+ {
+ CompWindow *w;
+
+ w = screen->findWindow (popupWindow);
+ if (w)
+ CompositeWindow::get (w)->addDamage ();
+ }
+ }
+ else if (!grabIndex && !(zooming && translate > 0.001f) && !moreAdjust)
+ {
+ cScreen->preparePaintSetEnabled (this, false);
+ cScreen->donePaintSetEnabled (this, false);
+ gScreen->glPaintOutputSetEnabled (this, false);
+
+ foreach (CompWindow *w, screen->windows ())
+ {
+ SWITCH_WINDOW (w);
+ sw->cWindow->damageRectSetEnabled (sw, false);
+ sw->gWindow->glPaintSetEnabled (sw, false);
+ }
+ }
+
+ cScreen->donePaint ();
+}
+
+
+void
+SwitchWindow::paintThumb (const GLWindowPaintAttrib &attrib,
+ const GLMatrix &transform,
+ unsigned int mask,
+ int x,
+ int y,
+ int x1,
+ int x2)
+{
+ GLWindowPaintAttrib sAttrib (attrib);
+ int wx, wy;
+ float width, height;
+ GLTexture *icon = NULL;
+ CompWindow::Geometry &g = window->geometry ();
+
+ mask |= PAINT_WINDOW_TRANSFORMED_MASK;
+
+ if (window->mapNum ())
+ {
+ if (gWindow->textures ().empty ())
+ gWindow->bind ();
+ }
+
+ if (!gWindow->textures ().empty ())
+ {
+ GLMatrix wTransform (transform);
+ int ww, wh;
+ int addWindowGeometryIndex =
+ gWindow->glAddGeometryGetCurrentIndex ();
+
+ width = WIDTH - (SPACE << 1);
+ height = HEIGHT - (SPACE << 1);
+
+ ww = g.width () + window->input ().left +
+ window->input ().right;
+ wh = g.height () + window->input ().top +
+ window->input ().bottom;
+
+ if (ww > width)
+ sAttrib.xScale = width / ww;
+ else
+ sAttrib.xScale = 1.0f;
+
+ if (wh > height)
+ sAttrib.yScale = height / wh;
+ else
+ sAttrib.yScale = 1.0f;
+
+ if (sAttrib.xScale < sAttrib.yScale)
+ sAttrib.yScale = sAttrib.xScale;
+ else
+ sAttrib.xScale = sAttrib.yScale;
+
+ width = ww * sAttrib.xScale;
+ height = wh * sAttrib.yScale;
+
+ wx = x + SPACE + ((WIDTH - (SPACE << 1)) - width) / 2;
+ wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
+
+ sAttrib.xTranslate = wx - g.x () +
+ window->input ().left * sAttrib.xScale;
+ sAttrib.yTranslate = wy - g.y () +
+ window->input ().top * sAttrib.yScale;
+
+ GLFragment::Attrib fragment (sAttrib);
+
+ if (window->alpha () || fragment.getOpacity () != OPAQUE)
+ mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+
+ wTransform.translate (g.x (), g.y (), 0.0f);
+ wTransform.scale (sAttrib.xScale, sAttrib.yScale, 1.0f);
+ wTransform.translate (sAttrib.xTranslate / sAttrib.xScale - g.x (),
+ sAttrib.yTranslate / sAttrib.yScale - g.y (),
+ 0.0f);
+
+ glPushMatrix ();
+ glLoadMatrixf (wTransform.getMatrix ());
+
+ /* XXX: replacing the addWindowGeometry function like this is
+ very ugly but necessary until the vertex stage has been made
+ fully pluggable. */
+ gWindow->glAddGeometrySetCurrentIndex (MAXSHORT);
+ gWindow->glDraw (wTransform, fragment, infiniteRegion, mask);
+ gWindow->glAddGeometrySetCurrentIndex (addWindowGeometryIndex);
+
+ glPopMatrix ();
+
+ if (sScreen->opt[SWITCH_OPTION_ICON].value ().b ())
+ {
+ icon = gWindow->getIcon (ICON_SIZE, ICON_SIZE);
+ if (icon)
+ {
+ sAttrib.xScale = sAttrib.yScale = 1.0f;
+
+ wx = x + WIDTH - icon->width () - SPACE;
+ wy = y + HEIGHT - icon->height () - SPACE;
+ }
+ }
+ }
+ else
+ {
+ width = WIDTH - (WIDTH >> 2);
+ height = HEIGHT - (HEIGHT >> 2);
+
+ icon = gWindow->getIcon (ICON_SIZE, ICON_SIZE);
+ if (!icon)
+ icon = gScreen->defaultIcon ();
+
+ if (icon)
+ {
+ int iw, ih;
+
+ iw = width - SPACE;
+ ih = height - SPACE;
+
+ if (icon->width () < (iw >> 1))
+ sAttrib.xScale = (iw / icon->width ());
+ else
+ sAttrib.xScale = 1.0f;
+
+ if (icon->height () < (ih >> 1))
+ sAttrib.yScale = (ih / icon->height ());
+ else
+ sAttrib.yScale = 1.0f;
+
+ if (sAttrib.xScale < sAttrib.yScale)
+ sAttrib.yScale = sAttrib.xScale;
+ else
+ sAttrib.xScale = sAttrib.yScale;
+
+ width = icon->width () * sAttrib.xScale;
+ height = icon->height () * sAttrib.yScale;
+
+ wx = x + SPACE + ((WIDTH - (SPACE << 1)) - width) / 2;
+ wy = y + SPACE + ((HEIGHT - (SPACE << 1)) - height) / 2;
+ }
+ }
+
+ if (icon)
+ {
+ CompRegion iconReg (g.x (), g.y (), icon->width (),
+ icon->height ());
+ GLTexture::MatrixList matrix (1);
+ int addWindowGeometryIndex =
+ gWindow->glAddGeometryGetCurrentIndex ();
+
+ mask |= PAINT_WINDOW_BLEND_MASK;
+
+ matrix[0] = icon->matrix ();
+ matrix[0].x0 -= (g.x () * matrix[0].xx);
+ matrix[0].y0 -= (g.y () * matrix[0].yy);
+
+ sAttrib.xTranslate = wx - g.x ();
+ sAttrib.yTranslate = wy - g.y ();
+
+ gWindow->geometry ().reset ();
+
+ gWindow->glAddGeometrySetCurrentIndex (MAXSHORT);
+ gWindow->glAddGeometry (matrix, iconReg, infiniteRegion);
+ gWindow->glAddGeometrySetCurrentIndex (addWindowGeometryIndex);
+
+ if (gWindow->geometry ().vCount)
+ {
+ GLFragment::Attrib fragment (sAttrib);
+ GLMatrix wTransform (transform);
+
+ wTransform.translate (g.x (), g.y (), 0.0f);
+ wTransform.scale (sAttrib.xScale, sAttrib.yScale, 1.0f);
+ wTransform.translate (sAttrib.xTranslate / sAttrib.xScale - g.x (),
+ sAttrib.yTranslate / sAttrib.yScale - g.y (),
+ 0.0f);
+
+ glPushMatrix ();
+ glLoadMatrixf (wTransform.getMatrix ());
+
+ gWindow->glDrawTexture (icon, fragment, mask);
+
+ glPopMatrix ();
+ }
+ }
+}
+
+bool
+SwitchWindow::glPaint (const GLWindowPaintAttrib &attrib,
+ const GLMatrix &transform,
+ const CompRegion &region,
+ unsigned int mask)
+{
+ int zoomType = NORMAL_WINDOW_MASK;
+ bool status;
+
+ if (window->id () == sScreen->popupWindow)
+ {
+ GLenum filter;
+ int x, y, x1, x2, cx, i;
+ unsigned short color[4];
+
+ CompWindow::Geometry &g = window->geometry ();
+
+ if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
+ sScreen->ignoreSwitcher)
+ return false;
+
+ status = gWindow->glPaint (attrib, transform, region, mask);
+
+ if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK) && region.isEmpty ())
+ return true;
+
+ x1 = g.x () + SPACE;
+ x2 = g.x () + g.width () - SPACE;
+
+ x = x1 + sScreen->pos;
+ y = g.y () + SPACE;
+
+ filter = gScreen->textureFilter ();
+
+ if (sScreen->opt[SWITCH_OPTION_MIPMAP].value ().b ())
+ gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR);
+
+ glPushAttrib (GL_SCISSOR_BIT);
+
+ glEnable (GL_SCISSOR_TEST);
+ glScissor (x1, 0, x2 - x1, screen->height ());
+
+ foreach (CompWindow *w, sScreen->windows)
+ {
+ if (x + WIDTH > x1)
+ SwitchWindow::get (w)->paintThumb (
+ gWindow->lastPaintAttrib (), transform,
+ mask, x, y, x1, x2);
+ x += WIDTH;
+ }
+
+ foreach (CompWindow *w, sScreen->windows)
+ {
+ if (x > x2)
+ break;
+
+ SwitchWindow::get (w)->paintThumb (
+ gWindow->lastPaintAttrib (), transform,
+ mask, x, y, x1, x2);
+ x += WIDTH;
+ }
+
+ glPopAttrib ();
+
+ gScreen->setTextureFilter (filter);
+
+ cx = g.x () + (g.width () >> 1);
+
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glEnable (GL_BLEND);
+ for (i = 0; i < 4; i++)
+ color[i] = (unsigned int)sScreen->fgColor[i] *
+ gWindow->lastPaintAttrib ().opacity /
+ 0xffff;
+ glColor4usv (color);
+ glPushMatrix ();
+ glTranslatef (cx, y, 0.0f);
+ glVertexPointer (2, GL_FLOAT, 0, _boxVertices);
+ glDrawArrays (GL_QUADS, 0, 16);
+ glPopMatrix ();
+ glColor4usv (defaultColor);
+ glDisable (GL_BLEND);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ }
+ else if (window->id () == sScreen->selectedWindow)
+ {
+ if (sScreen->opt[SWITCH_OPTION_BRINGTOFRONT].value ().b () &&
+ sScreen->selectedWindow == sScreen->zoomedWindow)
+ zoomType = ZOOMED_WINDOW_MASK;
+
+ if (!(sScreen->zoomMask & zoomType))
+ return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
+ false : true;
+
+ status = gWindow->glPaint (attrib, transform, region, mask);
+ }
+ else if (sScreen->switching)
+ {
+ GLWindowPaintAttrib sAttrib (attrib);
+ GLuint value;
+
+ value = sScreen->opt[SWITCH_OPTION_SATURATION].value ().i ();
+ if (value != 100)
+ sAttrib.saturation = sAttrib.saturation * value / 100;
+
+ value = sScreen->opt[SWITCH_OPTION_BRIGHTNESS].value ().i ();
+ if (value != 100)
+ sAttrib.brightness = sAttrib.brightness * value / 100;
+
+ if (window->wmType () & ~(CompWindowTypeDockMask |
+ CompWindowTypeDesktopMask))
+ {
+ value = sScreen->opt[SWITCH_OPTION_OPACITY].value ().i ();
+ if (value != 100)
+ sAttrib.opacity = sAttrib.opacity * value / 100;
+ }
+
+ if (sScreen->opt[SWITCH_OPTION_BRINGTOFRONT].value ().b () &&
+ window->id () == sScreen->zoomedWindow)
+ zoomType = ZOOMED_WINDOW_MASK;
+
+ if (!(sScreen->zoomMask & zoomType))
+ return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
+ false : true;
+
+ status = gWindow->glPaint (sAttrib, transform, region, mask);
+ }
+ else
+ {
+ if (!(sScreen->zoomMask & zoomType))
+ return (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) ?
+ false : true;
+
+ status = gWindow->glPaint (attrib, transform, region, mask);
+ }
+
+ return status;
+}
+
+bool
+SwitchWindow::damageRect (bool initial, const CompRect &rect)
+{
+ bool status;
+
+ if (sScreen->grabIndex)
+ {
+ CompWindow *popup;
+ int i;
+
+ foreach (CompWindow *w, sScreen->windows)
+ {
+ if (window == w)
+ {
+ popup = screen->findWindow (sScreen->popupWindow);
+ if (popup)
+ CompositeWindow::get (popup)->addDamage ();
+
+ break;
+ }
+ }
+ }
+
+ cWindow->damageRect (initial, rect);
+
+ return status;
+}
+
+CompOption::Vector &
+SwitchScreen::getOptions ()
+{
+ return opt;
+}
+
+bool
+SwitchScreen::setOption (const char *name,
+ CompOption::Value &value)
+{
+ CompOption *o;
+ unsigned int index;
+
+ o = CompOption::findOption (opt, name, &index);
+ if (!o)
+ return false;
+
+ switch (index) {
+ case SWITCH_OPTION_ZOOM:
+ if (o->set (value))
+ {
+ if (o->value ().f () < 0.05f)
+ {
+ zooming = false;
+ zoom = 0.0f;
+ }
+ else
+ {
+ zooming = true;
+ zoom = o->value ().f () / 30.0f;
+ }
+
+ return true;
+ }
+ break;
+ default:
+ return CompOption::setOption (*o, value);
+ }
+
+ return false;
+}
+
+SwitchScreen::SwitchScreen (CompScreen *screen) :
+ PrivateHandler<SwitchScreen,CompScreen> (screen),
+ cScreen (CompositeScreen::get (screen)),
+ gScreen (GLScreen::get (screen)),
+ opt(SWITCH_OPTION_NUM),
+ popupWindow (None),
+ selectedWindow (None),
+ zoomedWindow (None),
+ lastActiveNum (0),
+ grabIndex (NULL),
+ switching (false),
+ zoomMask (~0),
+ moreAdjust (false),
+ mVelocity (0.0),
+ tVelocity (0.0),
+ sVelocity (0.0),
+ windows (),
+ pos (0),
+ move (0),
+ translate (0.0),
+ sTranslate (0.0),
+ selection (CurrentViewport),
+ ignoreSwitcher (false)
+{
+ if (!switcherVTable->getMetadata ()->initOptions (switchOptionInfo,
+ SWITCH_OPTION_NUM, opt))
+ {
+ setFailed ();
+ return;
+ }
+
+ zoom = opt[SWITCH_OPTION_ZOOM].value ().f () / 30.0f;
+
+ zooming = (opt[SWITCH_OPTION_ZOOM].value ().f () > 0.05f);
+
+ fgColor[0] = 0;
+ fgColor[1] = 0;
+ fgColor[2] = 0;
+ fgColor[3] = 0xffff;
+
+ selectWinAtom =
+ XInternAtom (screen->dpy (), DECOR_SWITCH_WINDOW_ATOM_NAME, 0);
+ selectFgColorAtom =
+ XInternAtom (screen->dpy (), DECOR_SWITCH_FOREGROUND_COLOR_ATOM_NAME, 0);
+
+
+ ScreenInterface::setHandler (screen, false);
+ CompositeScreenInterface::setHandler (cScreen, false);
+ GLScreenInterface::setHandler (gScreen, false);
+}
+
+SwitchScreen::~SwitchScreen ()
+{
+ if (popupWindow)
+ XDestroyWindow (screen->dpy (), popupWindow);
+}
+
+bool
+SwitchPluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
+ !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
+ return false;
+
+ getMetadata ()->addFromOptionInfo (switchOptionInfo, SWITCH_OPTION_NUM);
+ getMetadata ()->addFromFile (name ());
+
+ return true;
+}
+
diff --git a/plugins/switcher/src/switcher.h b/plugins/switcher/src/switcher.h
new file mode 100644
index 0000000..f2c5a81
--- /dev/null
+++ b/plugins/switcher/src/switcher.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <decoration.h>
+#include <core/core.h>
+#include <core/privatehandler.h>
+#include <core/atoms.h>
+
+#include <composite/composite.h>
+#include <opengl/opengl.h>
+
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrender.h>
+
+#define ZOOMED_WINDOW_MASK (1 << 0)
+#define NORMAL_WINDOW_MASK (1 << 1)
+
+#define SWITCH_OPTION_NEXT_BUTTON 0
+#define SWITCH_OPTION_NEXT_KEY 1
+#define SWITCH_OPTION_PREV_BUTTON 2
+#define SWITCH_OPTION_PREV_KEY 3
+#define SWITCH_OPTION_NEXT_ALL_BUTTON 4
+#define SWITCH_OPTION_NEXT_ALL_KEY 5
+#define SWITCH_OPTION_PREV_ALL_BUTTON 6
+#define SWITCH_OPTION_PREV_ALL_KEY 7
+#define SWITCH_OPTION_NEXT_NO_POPUP_BUTTON 8
+#define SWITCH_OPTION_NEXT_NO_POPUP_KEY 9
+#define SWITCH_OPTION_PREV_NO_POPUP_BUTTON 10
+#define SWITCH_OPTION_PREV_NO_POPUP_KEY 11
+#define SWITCH_OPTION_NEXT_PANEL_BUTTON 12
+#define SWITCH_OPTION_NEXT_PANEL_KEY 13
+#define SWITCH_OPTION_PREV_PANEL_BUTTON 14
+#define SWITCH_OPTION_PREV_PANEL_KEY 15
+#define SWITCH_OPTION_SPEED 16
+#define SWITCH_OPTION_TIMESTEP 17
+#define SWITCH_OPTION_WINDOW_MATCH 18
+#define SWITCH_OPTION_MIPMAP 19
+#define SWITCH_OPTION_SATURATION 20
+#define SWITCH_OPTION_BRIGHTNESS 21
+#define SWITCH_OPTION_OPACITY 22
+#define SWITCH_OPTION_BRINGTOFRONT 23
+#define SWITCH_OPTION_ZOOM 24
+#define SWITCH_OPTION_ICON 25
+#define SWITCH_OPTION_MINIMIZED 26
+#define SWITCH_OPTION_AUTO_ROTATE 27
+#define SWITCH_OPTION_NUM 28
+
+enum SwitchWindowSelection{
+ CurrentViewport = 0,
+ AllViewports,
+ Panels
+};
+
+class SwitchScreen :
+ public ScreenInterface,
+ public CompositeScreenInterface,
+ public GLScreenInterface,
+ public PrivateHandler<SwitchScreen,CompScreen>
+{
+ public:
+
+ SwitchScreen (CompScreen *screen);
+ ~SwitchScreen ();
+
+ CompOption::Vector & getOptions ();
+ bool setOption (const char *name, CompOption::Value &value);
+
+ void handleEvent (XEvent *);
+
+ void preparePaint (int);
+ void donePaint ();
+
+ bool glPaintOutput (const GLScreenPaintAttrib &,
+ const GLMatrix &, const CompRegion &,
+ CompOutput *, unsigned int);
+
+ void setSelectedWindowHint ();
+ void activateEvent (bool activating);
+ void updateWindowList (int count);
+ void createWindowList (int count);
+ void switchToWindow (bool toNext);
+ int countWindows ();
+ void initiate (SwitchWindowSelection selection,
+ bool showPopup);
+ void windowRemove (Window id);
+ void updateForegroundColor ();
+
+ bool adjustVelocity ();
+
+ CompositeScreen *cScreen;
+ GLScreen *gScreen;
+
+ CompOption::Vector opt;
+
+ Atom selectWinAtom;
+ Atom selectFgColorAtom;
+
+ Window popupWindow;
+
+ Window selectedWindow;
+ Window zoomedWindow;
+ unsigned int lastActiveNum;
+
+ float zoom;
+
+ CompScreen::GrabHandle grabIndex;
+
+ Bool switching;
+ Bool zooming;
+ int zoomMask;
+
+ bool moreAdjust;
+
+ GLfloat mVelocity;
+ GLfloat tVelocity;
+ GLfloat sVelocity;
+
+ CompWindowList windows;
+
+ int pos;
+ int move;
+
+ float translate;
+ float sTranslate;
+
+ SwitchWindowSelection selection;
+
+ unsigned int fgColor[4];
+
+ bool ignoreSwitcher;
+};
+
+class SwitchWindow :
+ public CompositeWindowInterface,
+ public GLWindowInterface,
+ public PrivateHandler<SwitchWindow,CompWindow>
+{
+ public:
+ SwitchWindow (CompWindow *window) :
+ PrivateHandler<SwitchWindow,CompWindow> (window),
+ window (window),
+ gWindow (GLWindow::get (window)),
+ cWindow (CompositeWindow::get (window)),
+ sScreen (SwitchScreen::get (screen)),
+ gScreen (GLScreen::get (screen))
+ {
+ GLWindowInterface::setHandler (gWindow, false);
+ CompositeWindowInterface::setHandler (cWindow, false);
+
+ if (sScreen->popupWindow && sScreen->popupWindow == window->id ())
+ gWindow->glPaintSetEnabled (this, true);
+ }
+
+ bool glPaint (const GLWindowPaintAttrib &, const GLMatrix &,
+ const CompRegion &, unsigned int);
+
+ bool damageRect (bool, const CompRect &);
+
+ bool isSwitchWin ();
+
+ void paintThumb (const GLWindowPaintAttrib &, const GLMatrix &,
+ unsigned int, int, int, int, int);
+
+ CompWindow *window;
+ GLWindow *gWindow;
+ CompositeWindow *cWindow;
+ SwitchScreen *sScreen;
+ GLScreen *gScreen;
+};
+
+#define MwmHintsDecorations (1L << 1)
+
+typedef struct {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+} MwmHints;
+
+#define WIDTH 212
+#define HEIGHT 192
+#define SPACE 10
+
+#define SWITCH_ZOOM 0.1f
+
+#define BOX_WIDTH 3
+
+#define ICON_SIZE 64
+
+#define WINDOW_WIDTH(count) (WIDTH * (count) + (SPACE << 1))
+#define WINDOW_HEIGHT (HEIGHT + (SPACE << 1))
+
+#define SWITCH_SCREEN(s) \
+ SwitchScreen *ss = SwitchScreen::get (s)
+
+#define SWITCH_WINDOW(w) \
+ SwitchWindow *sw = SwitchWindow::get (w)
+
+class SwitchPluginVTable :
+ public CompPlugin::VTableForScreenAndWindow<SwitchScreen, SwitchWindow>
+{
+ public:
+
+ bool init ();
+
+ PLUGIN_OPTION_HELPER (SwitchScreen);
+
+};
+
+
diff --git a/plugins/switcher/switcher.xml.in b/plugins/switcher/switcher.xml.in
new file mode 100644
index 0000000..dda448a
--- /dev/null
+++ b/plugins/switcher/switcher.xml.in
@@ -0,0 +1,156 @@
+<compiz>
+ <plugin name="switcher">
+ <_short>Application Switcher</_short>
+ <_long>Application Switcher</_long>
+ <deps>
+ <requirement>
+ <plugin>opengl</plugin>
+ </requirement>
+ </deps>
+ <options>
+ <option name="next_button" type="button">
+ <_short>Next window</_short>
+ <_long>Popup switcher if not visible and select next window</_long>
+ </option>
+ <option name="next_key" type="key">
+ <_short>Next window</_short>
+ <_long>Popup switcher if not visible and select next window</_long>
+ <default>&lt;Alt&gt;Tab</default>
+ </option>
+ <option name="prev_button" type="button">
+ <_short>Prev window</_short>
+ <_long>Popup switcher if not visible and select previous window</_long>
+ </option>
+ <option name="prev_key" type="key">
+ <_short>Prev window</_short>
+ <_long>Popup switcher if not visible and select previous window</_long>
+ <default>&lt;Shift&gt;&lt;Alt&gt;Tab</default>
+ </option>
+ <option name="next_all_button" type="button">
+ <_short>Next window (All windows)</_short>
+ <_long>Popup switcher if not visible and select next window out of all windows</_long>
+ </option>
+ <option name="next_all_key" type="key">
+ <_short>Next window (All windows)</_short>
+ <_long>Popup switcher if not visible and select next window out of all windows</_long>
+ <default>&lt;Control&gt;&lt;Alt&gt;Tab</default>
+ </option>
+ <option name="prev_all_button" type="button">
+ <_short>Prev window (All windows)</_short>
+ <_long>Popup switcher if not visible and select previous window out of all windows</_long>
+ </option>
+ <option name="prev_all_key" type="key">
+ <_short>Prev window (All windows)</_short>
+ <_long>Popup switcher if not visible and select previous window out of all windows</_long>
+ <default>&lt;Shift&gt;&lt;Control&gt;&lt;Alt&gt;Tab</default>
+ </option>
+ <option name="next_no_popup_button" type="button">
+ <_short>Next window (No popup)</_short>
+ <_long>Select next window without showing the popup window.</_long>
+ </option>
+ <option name="next_no_popup_key" type="key">
+ <_short>Next window (No popup)</_short>
+ <_long>Select next window without showing the popup window.</_long>
+ </option>
+ <option name="prev_no_popup_button" type="button">
+ <_short>Prev window (No popup)</_short>
+ <_long>Select previous window without showing the popup window.</_long>
+ </option>
+ <option name="prev_no_popup_key" type="key">
+ <_short>Prev window (No popup)</_short>
+ <_long>Select previous window without showing the popup window.</_long>
+ </option>
+ <option name="next_panel_button" type="button">
+ <_short>Next Panel</_short>
+ <_long>Select next panel type window.</_long>
+ </option>
+ <option name="next_panel_key" type="key">
+ <_short>Next Panel</_short>
+ <_long>Select next panel type window.</_long>
+ </option>
+ <option name="prev_panel_button" type="button">
+ <_short>Prev Panel</_short>
+ <_long>Select previous panel type window.</_long>
+ </option>
+ <option name="prev_panel_key" type="key">
+ <_short>Prev Panel</_short>
+ <_long>Select previous panel type window.</_long>
+ </option>
+ <option name="speed" type="float">
+ <_short>Speed</_short>
+ <_long>Switcher speed</_long>
+ <default>1.5</default>
+ <min>0.1</min>
+ <max>50</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="timestep" type="float">
+ <_short>Timestep</_short>
+ <_long>Switcher timestep</_long>
+ <default>1.2</default>
+ <min>0.1</min>
+ <max>50</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="window_match" type="match">
+ <_short>Switcher windows</_short>
+ <_long>Windows that should be shown in switcher</_long>
+ <default>Toolbar | Utility | Dialog | Normal | Unknown</default>
+ </option>
+ <option name="mipmap" type="bool">
+ <_short>Mipmap</_short>
+ <_long>Generate mipmaps when possible for higher quality scaling</_long>
+ <default>true</default>
+ </option>
+ <option name="saturation" type="int">
+ <_short>Saturation</_short>
+ <_long>Amount of saturation in percent</_long>
+ <default>100</default>
+ <min>0</min>
+ <max>100</max>
+ </option>
+ <option name="brightness" type="int">
+ <_short>Brightness</_short>
+ <_long>Amount of brightness in percent</_long>
+ <default>65</default>
+ <min>0</min>
+ <max>100</max>
+ </option>
+ <option name="opacity" type="int">
+ <_short>Opacity</_short>
+ <_long>Amount of opacity in percent</_long>
+ <default>40</default>
+ <min>0</min>
+ <max>100</max>
+ </option>
+ <option name="bring_to_front" type="bool">
+ <_short>Bring To Front</_short>
+ <_long>Bring selected window to front</_long>
+ <default>true</default>
+ </option>
+ <option name="zoom" type="float">
+ <_short>Zoom</_short>
+ <_long>Distance desktop should be zoom out while switching windows</_long>
+ <default>1</default>
+ <min>0</min>
+ <max>5</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="icon" type="bool">
+ <_short>Icon</_short>
+ <_long>Show icon next to thumbnail</_long>
+ <default>true</default>
+ </option>
+ <option name="minimized" type="bool">
+ <_short>Minimized</_short>
+ <_long>Show minimized windows</_long>
+ <default>true</default>
+ </option>
+ <option name="auto_rotate" type="bool">
+ <_short>Auto Rotate</_short>
+ <_long>Rotate to the selected window while switching</_long>
+ <default>false</default>
+ </option>
+ </options>
+ </plugin>
+</compiz>