summaryrefslogtreecommitdiff
path: root/plugins/compiztoolbox
diff options
context:
space:
mode:
authorErkin Bahceci <erkinbah@gmail.com>2009-07-23 19:53:05 -0500
committerErkin Bahceci <erkinbah@gmail.com>2009-07-23 19:53:05 -0500
commit930c9a1fe05c4598baf93250e9ec8bd8dd9df7ce (patch)
tree97ba64ed7c6d9c82bd010273a2fd6d8843f0d82d /plugins/compiztoolbox
parent3cfa58a22f12820e41f93e6176d923b340e8654c (diff)
downloadcompiz-with-glib-mainloop-930c9a1fe05c4598baf93250e9ec8bd8dd9df7ce.tar.gz
compiz-with-glib-mainloop-930c9a1fe05c4598baf93250e9ec8bd8dd9df7ce.tar.bz2
Refactor switcher, move parts into toolbox library plugin.
Diffstat (limited to 'plugins/compiztoolbox')
-rw-r--r--plugins/compiztoolbox/CMakeLists.txt5
-rw-r--r--plugins/compiztoolbox/compiz-compiztoolbox.pc.in12
-rw-r--r--plugins/compiztoolbox/include/compiztoolbox/compiztoolbox.h140
-rw-r--r--plugins/compiztoolbox/src/compiztoolbox.cpp557
4 files changed, 714 insertions, 0 deletions
diff --git a/plugins/compiztoolbox/CMakeLists.txt b/plugins/compiztoolbox/CMakeLists.txt
new file mode 100644
index 0000000..d6a1f89
--- /dev/null
+++ b/plugins/compiztoolbox/CMakeLists.txt
@@ -0,0 +1,5 @@
+find_package (Compiz REQUIRED)
+
+include (CompizPlugin)
+
+compiz_plugin(compiztoolbox PLUGINDEPS composite opengl)
diff --git a/plugins/compiztoolbox/compiz-compiztoolbox.pc.in b/plugins/compiztoolbox/compiz-compiztoolbox.pc.in
new file mode 100644
index 0000000..dd22975
--- /dev/null
+++ b/plugins/compiztoolbox/compiz-compiztoolbox.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: compiz-compiztoolbox
+Description: Toolbox library plugin for compiz
+Version: @VERSION@
+
+Requires:
+Libs:
+Cflags: @COMPIZ_CFLAGS@
diff --git a/plugins/compiztoolbox/include/compiztoolbox/compiztoolbox.h b/plugins/compiztoolbox/include/compiztoolbox/compiztoolbox.h
new file mode 100644
index 0000000..cea3fe8
--- /dev/null
+++ b/plugins/compiztoolbox/include/compiztoolbox/compiztoolbox.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright © 2007 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>
+ */
+
+#ifndef _COMPIZ_COMPIZTOOLBOX_H
+#define _COMPIZ_COMPIZTOOLBOX_H
+
+#include <decoration.h>
+#include <core/core.h>
+#include <core/atoms.h>
+
+#include <composite/composite.h>
+#include <opengl/opengl.h>
+
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrender.h>
+
+
+typedef enum {
+ CurrentViewport = 0,
+ AllViewports,
+ Panels,
+ Group
+} SwitchWindowSelection;
+
+
+class BaseSwitchScreen
+{
+ public:
+ BaseSwitchScreen (CompScreen *screen);
+ virtual ~BaseSwitchScreen () {}
+
+ void handleEvent (XEvent *);
+ void setSelectedWindowHint ();
+ void activateEvent (bool activating);
+ void updateForegroundColor ();
+
+ CompWindow *switchToWindow (bool toNext, bool autoChangeVPOption);
+ static bool compareWindows (CompWindow *w1, CompWindow *w2);
+ static Visual *findArgbVisual (Display *dpy, int scr);
+
+ virtual bool shouldShowIcon () { return false; }
+ virtual void windowRemove (Window id) {}
+ virtual void doWindowDamage (CompWindow *w);
+ virtual void handleSelectionChange (bool toNext, int nextIdx) {}
+ virtual void getMinimizedAndMatch (bool &minimizedOption,
+ CompMatch *&matchOption);
+
+ CompositeScreen *cScreen;
+ GLScreen *gScreen;
+
+ Atom selectWinAtom;
+ Atom selectFgColorAtom;
+
+ CompWindowList windows;
+
+ Window popupWindow;
+ Window selectedWindow;
+ unsigned int lastActiveNum;
+
+ CompScreen::GrabHandle grabIndex;
+
+ bool moreAdjust;
+
+ SwitchWindowSelection selection;
+
+ unsigned int fgColor[4];
+
+ bool ignoreSwitcher;
+};
+
+class BaseSwitchWindow
+{
+ public:
+ BaseSwitchWindow (BaseSwitchScreen *, CompWindow *);
+
+ void paintThumb (const GLWindowPaintAttrib &attrib,
+ const GLMatrix &transform,
+ unsigned int mask,
+ int x,
+ int y,
+ int width1,
+ int height1,
+ int width2,
+ int height2);
+ virtual void updateIconTexturedWindow (GLWindowPaintAttrib &sAttrib,
+ int &wx,
+ int &wy,
+ int x,
+ int y,
+ GLTexture *icon) {}
+ virtual void updateIconNontexturedWindow (GLWindowPaintAttrib &sAttrib,
+ int &wx,
+ int &wy,
+ float &width,
+ float &height,
+ int x,
+ int y,
+ GLTexture *icon) {}
+ virtual void updateIconPos (int &wx,
+ int &wy,
+ int x,
+ int y,
+ float width,
+ float height) {}
+ bool damageRect (bool, const CompRect &);
+ bool isSwitchWin ();
+
+ BaseSwitchScreen *baseScreen;
+ GLWindow *gWindow;
+ CompositeWindow *cWindow;
+ GLScreen *gScreen;
+ CompWindow *window;
+};
+
+#define ICON_SIZE 64
+#define MAX_ICON_SIZE 256
+
+#endif
diff --git a/plugins/compiztoolbox/src/compiztoolbox.cpp b/plugins/compiztoolbox/src/compiztoolbox.cpp
new file mode 100644
index 0000000..d12a523
--- /dev/null
+++ b/plugins/compiztoolbox/src/compiztoolbox.cpp
@@ -0,0 +1,557 @@
+/*
+ * 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 <core/core.h>
+
+#include <compiztoolbox/compiztoolbox.h>
+
+
+void
+BaseSwitchScreen::setSelectedWindowHint ()
+{
+ XChangeProperty (::screen->dpy (), popupWindow, selectWinAtom,
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &selectedWindow, 1);
+}
+
+void
+BaseSwitchScreen::getMinimizedAndMatch (bool &minimizedOption,
+ CompMatch *&matchOption)
+{
+ minimizedOption = false;
+ matchOption = NULL;
+}
+
+bool
+BaseSwitchWindow::isSwitchWin ()
+{
+ bool minimizedOption;
+ CompMatch *matchOption;
+ baseScreen->getMinimizedAndMatch (minimizedOption, matchOption);
+
+ if (!window->isViewable () || !window->isMapped ())
+ {
+ if (minimizedOption)
+ {
+ if (!window->minimized () && !window->inShowDesktopMode () &&
+ !window->shaded ())
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (!window->isFocussable ())
+ return false;
+
+ if (window->overrideRedirect ())
+ return false;
+
+ if (baseScreen->selection == Panels)
+ {
+ if (!(window->type () &
+ (CompWindowTypeDockMask | CompWindowTypeDesktopMask)))
+ return false;
+ }
+ else
+ {
+ if (window->wmType () &
+ (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
+ return false;
+
+ if (window->state () & CompWindowStateSkipTaskbarMask)
+ return false;
+
+ if (matchOption && !matchOption->evaluate (window))
+ return false;
+
+ }
+
+ if (baseScreen->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 () >= (int) ::screen->width () ||
+ sg.y () >= (int) ::screen->height ())
+ return false;
+ }
+ else
+ {
+ if (!window->focus ())
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void
+BaseSwitchScreen::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);
+}
+
+bool
+BaseSwitchScreen::compareWindows (CompWindow *w1,
+ CompWindow *w2)
+{
+ if (w1->mapNum () && !w2->mapNum ())
+ return true;
+
+ if (w2->mapNum () && !w1->mapNum ())
+ return false;
+
+ return w2->activeNum () < w1->activeNum ();
+}
+
+CompWindow *
+BaseSwitchScreen::switchToWindow (bool toNext,
+ bool autoChangeVPOption)
+{
+ CompWindow *w = NULL;
+ CompWindowList::iterator it;
+
+ int cur = 0;
+ int nextIdx = 0;
+
+ if (!grabIndex)
+ return NULL;
+
+ for (it = windows.begin (); it != windows.end (); it++, cur++)
+ {
+ if ((*it)->id () == selectedWindow)
+ break;
+ }
+
+ if (it == windows.end ())
+ return NULL;
+
+ if (toNext)
+ {
+ it++;
+ if (it == windows.end ())
+ w = windows.front ();
+ else
+ w = *it;
+ nextIdx = (cur + 1) % windows.size ();
+ }
+ else
+ {
+ if (it == windows.begin ())
+ w = windows.back ();
+ else
+ w = *--it;
+ nextIdx = (cur + windows.size () - 1) % windows.size ();
+ }
+
+ if (w)
+ {
+ Window old = selectedWindow;
+
+ if (selection == AllViewports && autoChangeVPOption)
+ {
+ 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 (old != w->id ())
+ handleSelectionChange (toNext, nextIdx);
+
+ if (popupWindow)
+ {
+ CompWindow *popup;
+
+ popup = ::screen->findWindow (popupWindow);
+ if (popup)
+ CompositeWindow::get (popup)->addDamage ();
+
+ setSelectedWindowHint ();
+ }
+
+ doWindowDamage (w);
+
+ if (old)
+ {
+ w = ::screen->findWindow (old);
+ if (w)
+ doWindowDamage (w);
+ }
+ }
+
+ return w;
+}
+
+void
+BaseSwitchScreen::doWindowDamage (CompWindow *w)
+{
+ CompositeWindow::get (w)->addDamage ();
+}
+
+Visual *
+BaseSwitchScreen::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
+BaseSwitchWindow::paintThumb (const GLWindowPaintAttrib &attrib,
+ const GLMatrix &transform,
+ unsigned int mask,
+ int x,
+ int y,
+ int width1,
+ int height1,
+ int width2,
+ int height2)
+{
+ 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 = width1;
+ height = height1;
+
+ ww = window->inputRect ().width ();
+ wh = window->inputRect ().height ();
+
+ 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;
+
+ updateIconPos (wx, wy, x, y, width, height);
+
+ 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 (baseScreen->shouldShowIcon ())
+ {
+ icon = gWindow->getIcon (MAX_ICON_SIZE, MAX_ICON_SIZE);
+ if (icon)
+ updateIconTexturedWindow (sAttrib, wx, wy, x, y, icon);
+ }
+ }
+ else
+ {
+ width = width2;
+ height = height2;
+
+ /* try to get a matching icon first */
+ icon = gWindow->getIcon (width, height);
+ /* if none found, try a large one */
+ if (!icon)
+ icon = gWindow->getIcon (MAX_ICON_SIZE, MAX_ICON_SIZE);
+ if (!icon)
+ icon = gScreen->defaultIcon ();
+
+ if (icon)
+ updateIconNontexturedWindow (sAttrib, wx, wy,
+ width, height, x, y, icon);
+ }
+
+ 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
+BaseSwitchWindow::damageRect (bool initial, const CompRect &rect)
+{
+ if (baseScreen->grabIndex)
+ {
+ CompWindow *popup;
+
+ popup = ::screen->findWindow (baseScreen->popupWindow);
+ if (popup)
+ {
+ foreach (CompWindow *w, baseScreen->windows)
+ {
+ if (window == w)
+ {
+ CompositeWindow::get (popup)->addDamage ();
+ break;
+ }
+ }
+ }
+ }
+
+ return cWindow->damageRect (initial, rect);
+}
+
+void
+BaseSwitchScreen::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
+BaseSwitchScreen::handleEvent (XEvent *event)
+{
+ ::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 ();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+BaseSwitchScreen::BaseSwitchScreen (CompScreen *screen) :
+ cScreen (CompositeScreen::get (screen)),
+ gScreen (GLScreen::get (screen)),
+ windows (),
+ popupWindow (None),
+ selectedWindow (None),
+ lastActiveNum (0),
+ grabIndex (NULL),
+ moreAdjust (false),
+ selection (CurrentViewport),
+ ignoreSwitcher (false)
+{
+ selectWinAtom =
+ XInternAtom (::screen->dpy (), DECOR_SWITCH_WINDOW_ATOM_NAME, 0);
+ selectFgColorAtom =
+ XInternAtom (::screen->dpy (), DECOR_SWITCH_FOREGROUND_COLOR_ATOM_NAME, 0);
+
+ fgColor[0] = 0;
+ fgColor[1] = 0;
+ fgColor[2] = 0;
+ fgColor[3] = 0xffff;
+}
+
+BaseSwitchWindow::BaseSwitchWindow (BaseSwitchScreen *ss, CompWindow *w) :
+ baseScreen (ss),
+ gWindow (GLWindow::get (w)),
+ cWindow (CompositeWindow::get (w)),
+ gScreen (GLScreen::get (::screen)),
+ window (w)
+{
+}
+