summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoronestone <onestone>2006-10-31 15:26:22 +0000
committeronestone <onestone>2006-10-31 15:26:22 +0000
commit8fe64cafed0113ca7dc4d75f016c893e1f2ddc15 (patch)
tree0591dae43ef8ee3cc57bf4a1185ddbe33c36437d
downloadaquamarine-8fe64cafed0113ca7dc4d75f016c893e1f2ddc15.tar.gz
aquamarine-8fe64cafed0113ca7dc4d75f016c893e1f2ddc15.tar.bz2
Initial import of aquamarine (KDE window decorator)
-rw-r--r--Makefile.am.in11
-rw-r--r--Makefile.cvs16
-rwxr-xr-xautogen.sh4
-rw-r--r--configure.in.in12
-rw-r--r--src/KWinInterface.h17
-rw-r--r--src/Makefile.am20
-rw-r--r--src/aquamarine.cpp189
-rw-r--r--src/decorator.cpp740
-rw-r--r--src/decorator.h155
-rw-r--r--src/options.cpp167
-rw-r--r--src/options.h124
-rw-r--r--src/switcher.cpp336
-rw-r--r--src/switcher.h67
-rw-r--r--src/utils.cpp499
-rw-r--r--src/utils.h111
-rw-r--r--src/window.cpp1653
-rw-r--r--src/window.h248
17 files changed, 4369 insertions, 0 deletions
diff --git a/Makefile.am.in b/Makefile.am.in
new file mode 100644
index 0000000..c262d9a
--- /dev/null
+++ b/Makefile.am.in
@@ -0,0 +1,11 @@
+AUTOMAKE_OPTIONS = foreign 1.5
+DISTCLEANFILES = inst-apps
+
+MAINTAINERCLEANFILES = subdirs configure.in acinclude.m4 SUBDIRS
+include admin/deps.am
+
+include admin/Doxyfile.am
+
+
+
+
diff --git a/Makefile.cvs b/Makefile.cvs
new file mode 100644
index 0000000..b4752bd
--- /dev/null
+++ b/Makefile.cvs
@@ -0,0 +1,16 @@
+
+all:
+ @echo "This Makefile is only for the CVS repository"
+ @echo "This will be deleted before making the distribution"
+ @echo ""
+ @if test ! -d admin; then \
+ echo "Please recheckout this module!" ;\
+ echo "for cvs: use checkout once and after that update again" ;\
+ echo "for cvsup: checkout kde-common from cvsup and" ;\
+ echo " link kde-common/admin to ./admin" ;\
+ exit 1 ;\
+ fi
+ $(MAKE) -f admin/Makefile.common cvs
+
+.SILENT:
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..866bb42
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+make -f Makefile.cvs
+
diff --git a/configure.in.in b/configure.in.in
new file mode 100644
index 0000000..f4fb07d
--- /dev/null
+++ b/configure.in.in
@@ -0,0 +1,12 @@
+#MIN_CONFIG
+KDE_ENABLE_HIDDEN_VISIBILITY
+AC_CHECK_RANDOM
+AC_CHECK_USLEEP
+CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS"
+
+AC_DEFUN([AQUAMARINE_CHECK_KDECORATION],[HAVE_KDECORATION=0
+KDE_CHECK_HEADER(kdecoration.h,HAVE_KDECORATION=1,
+ AC_MSG_ERROR([Unable to find KDecoration. Make sure you have the kdebase development package installed.]))
+])
+
+AQUAMARINE_CHECK_KDECORATION
diff --git a/src/KWinInterface.h b/src/KWinInterface.h
new file mode 100644
index 0000000..aa236e9
--- /dev/null
+++ b/src/KWinInterface.h
@@ -0,0 +1,17 @@
+// taken from KWin
+
+#ifndef KWIN_INTERFACE_H
+#define KWIN_INTERFACE_H
+
+#include <dcopobject.h>
+
+class KWinInterface:virtual public DCOPObject
+{
+ K_DCOP
+
+ k_dcop:
+
+ virtual ASYNC reconfigure () = 0;
+};
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..46c704c
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,20 @@
+INCLUDES = -I$(srcdir)/lib $(all_includes)
+
+bin_PROGRAMS = aquamarine
+
+aquamarine_SOURCES = aquamarine.cpp \
+ utils.cpp \
+ decorator.cpp \
+ window.cpp \
+ switcher.cpp \
+ KWinInterface.skel \
+ options.cpp
+
+aquamarine_LDADD = $(LIB_KDECORE) -lkdecorations
+aquamarine_LDFLAGS = $(all_libraries)
+
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.h *.cpp -o $(podir)/aquamarine.pot
+
diff --git a/src/aquamarine.cpp b/src/aquamarine.cpp
new file mode 100644
index 0000000..44c4069
--- /dev/null
+++ b/src/aquamarine.cpp
@@ -0,0 +1,189 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrender.h>
+
+#include <fixx11h.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include <stdlib.h>
+
+#include "decorator.h"
+#include "utils.h"
+
+static const KCmdLineOptions options[] = {
+ {"replace", "Replace existing window decorator", 0},
+ {"deco <deco>", "Decoration", 0},
+ KCmdLineLastOption
+};
+
+
+int
+main (int argc, char **argv)
+{
+ bool argb_visual = false;
+ char *display = 0;
+ Display *dpy = XOpenDisplay (display);
+ int screen = DefaultScreen (dpy);
+
+ KCmdLineArgs::init (argc, argv, "aquamarine", I18N_NOOP ("Aquamarine"),
+ I18N_NOOP ("KDE Window Decorator for Beryl"), "0.1");
+ KCmdLineArgs::addCmdLineOptions (options);
+
+ Atom wm_name = XInternAtom (dpy, "_NET_WM_NAME", false);
+ char buf[128];
+ sprintf(buf,"WM_S%d",screen);
+ Atom wm_sn = XInternAtom (dpy, buf, false);
+ Atom manager = XInternAtom (dpy, "MANAGER", false);
+ Atom utf8_string = XInternAtom (dpy, "UTF8_STRING", false);
+
+ Bool restart = FALSE;
+ int rv = 1;
+ do
+ {
+
+ if (!dpy)
+ {
+ qWarning ("cannot connect to X server ");
+ exit (1);
+ }
+
+
+ Colormap colormap = 0;
+ Visual *visual = 0;
+ int event_base, error_base;
+
+ if (XRenderQueryExtension (dpy, &event_base, &error_base))
+ {
+ int nvi;
+ XVisualInfo templ;
+ templ.screen = screen;
+ templ.depth = 32;
+ templ.c_class = TrueColor;
+ XVisualInfo *xvi =
+ XGetVisualInfo (dpy,
+ VisualScreenMask | VisualDepthMask |
+ VisualClassMask, &templ, &nvi);
+
+ for (int i = 0; i < nvi; i++)
+ {
+ XRenderPictFormat *format =
+ XRenderFindVisualFormat (dpy, xvi[i].visual);
+ if (format->type == PictTypeDirect && format->direct.alphaMask)
+ {
+ visual = xvi[i].visual;
+ colormap =
+ XCreateColormap (dpy, RootWindow (dpy, screen), visual,
+ AllocNone);
+ argb_visual = true;
+ break;
+ }
+ }
+ }
+
+ Bool berylRunning = false;
+ do
+ {
+ XEvent xev;
+ WId wm = XGetSelectionOwner(dpy,wm_sn);
+ if (wm != None)
+ {
+ Atom actual;
+ int result, format;
+ unsigned long n, left;
+ unsigned char * data;
+
+ result = XGetWindowProperty (dpy, wm, wm_name,
+ 0L, 2L, FALSE, utf8_string, &actual, &format,
+ &n, &left, &data);
+
+ if (result == Success && n && data)
+ {
+ printf("Window Manager \"%s\"\n",data);
+ sprintf(buf,"%s",data);
+ if (strcmp(buf,"beryl") == 0)
+ {
+ berylRunning = true;
+ }
+ }
+
+ if (!berylRunning)
+ {
+ XSelectInput(dpy, wm, StructureNotifyMask);
+ printf("Found not compatible window manager. Waiting...\n");
+ do
+ {
+ XWindowEvent(dpy, wm, StructureNotifyMask, &xev);
+ } while (xev.type != DestroyNotify);
+ }
+ }
+ else
+ {
+ printf("No window manager. Waiting...\n");
+ XSelectInput(dpy, RootWindow(dpy, screen), StructureNotifyMask);
+ Bool foundWM = false;
+ do
+ {
+ XNextEvent(dpy, &xev);
+ if (xev.type == ClientMessage &&
+ xev.xclient.message_type == manager &&
+ (Atom)xev.xclient.data.l[1] == wm_sn)
+ {
+ printf("New Window Manager\n");
+ foundWM = true;
+ }
+ } while (xev.type == ClientMessage &&
+ xev.xclient.message_type == manager &&
+ (Atom)xev.xclient.data.l[1] == wm_sn);
+ }
+ } while (!berylRunning);
+
+ Aquamarine::Decorator *app = new Aquamarine::Decorator(dpy, Qt::HANDLE (visual),
+ Qt::HANDLE (colormap));
+
+ DCOPClient *client = app->dcopClient ();
+ client->registerAs ("kwin", false);
+ client->setDefaultObject ("KWinInterface");
+
+ if (app->isReady ()) {
+ rv = app->exec ();
+ if (rv == 0)
+ restart = app->restart();
+ }
+ delete app;
+ delete KGlobal::_locale; // HACK to fix crash during KApplication restart
+ KGlobal::_locale = 0;
+
+ } while (restart);
+ return rv;
+}
diff --git a/src/decorator.cpp b/src/decorator.cpp
new file mode 100644
index 0000000..488f53a
--- /dev/null
+++ b/src/decorator.cpp
@@ -0,0 +1,740 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <qglobal.h>
+
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kwinmodule.h>
+#include <klocale.h>
+
+#include <qpoint.h>
+
+#include "switcher.h"
+#include "decorator.h"
+#include "options.h"
+#include "utils.h"
+
+#include <stdio.h>
+
+#define GRAVITY_WEST (1 << 0)
+#define GRAVITY_EAST (1 << 1)
+#define GRAVITY_NORTH (1 << 2)
+#define GRAVITY_SOUTH (1 << 3)
+
+#define XX_MASK (1 << 12)
+#define XY_MASK (1 << 13)
+#define YX_MASK (1 << 14)
+#define YY_MASK (1 << 15)
+
+#define CLAMP_HORZ (1 << 0)
+#define CLAMP_VERT (1 << 1)
+
+Aquamarine::PluginManager * Aquamarine::Decorator::m_plugins = 0;
+Aquamarine::Options * Aquamarine::Decorator::m_options = 0;
+QSize
+ Aquamarine::Decorator::m_desktop;
+QPoint
+ Aquamarine::Decorator::m_viewport;
+QSize
+ Aquamarine::Decorator::m_rootSize;
+
+extern Time
+ qt_x_time;
+
+struct _cursor
+ cursors[3][3] = {
+ {C (top_left_corner), C (top_side), C (top_right_corner)},
+ {C (left_side), C (left_ptr), C (right_side)},
+ {C (bottom_left_corner), C (bottom_side), C (bottom_right_corner)}
+};
+
+
+Aquamarine::PluginManager::PluginManager (KConfig * config):
+KDecorationPlugins (config)
+{
+ // taken from KWin
+ defaultPlugin =
+ (QPixmap::defaultDepth () > 8) ? "kwin3_plastik" : "kwin3_quartz";
+}
+
+
+
+Aquamarine::Decorator::Decorator (Display * dpy, Qt::HANDLE visual, Qt::HANDLE colormap):
+DCOPObject ("KWinInterface"),
+KApplication (dpy, visual, colormap),
+m_defDeco (0),
+m_defDecoActive (0),
+m_activeWindow (0),
+m_config (0),
+m_kwinmodule (new KWinModule (this, KWinModule::INFO_ALL)), m_switcher (0)
+{
+ delete KGlobal::_locale;
+ KGlobal::_locale = new KLocale( "kwin" , NULL );
+
+ ready = false;
+ m_restart = false;
+
+ m_plugins = NULL;
+ m_options = NULL;
+
+ Atoms::init ();
+
+ m_activeWM = XGetSelectionOwner(qt_xdisplay(),Atoms::wm_sn);
+ if (m_activeWM == None)
+ return;
+ XSelectInput (qt_xdisplay(), m_activeWM, StructureNotifyMask);
+
+ KCmdLineArgs *
+ args = KCmdLineArgs::parsedArgs ();
+ bool
+ replace = args->isSet ("replace");
+ ready = acquireDmSession (qt_xdisplay (), qt_xscreen (), replace);
+ if (!ready)
+ return;
+
+ set_dm_check_hint (qt_xscreen ());
+
+ m_config = new KConfig ("kwinrc");
+ m_config->setGroup ("Style");
+
+ QString
+ decoName;
+ if (args->isSet ("deco"))
+ decoName = args->getOption ("deco");
+ if (!decoName.startsWith ("kwin3_") && !decoName.isEmpty ())
+ decoName = "kwin3_" + decoName;
+
+ m_options = new Aquamarine::Options (m_config);
+ m_plugins = new PluginManager (m_config);
+ kdDebug () << "loading plugin: " << decoName << endl;
+ bool
+ rv = pluginManager ()->loadPlugin (decoName);
+ kdDebug () << "plugin loaded: " << rv << endl;
+
+ updateDesktopGeometry ();
+
+ m_defDeco =
+ new Aquamarine::Window (qt_xrootwin (), 0,
+ Aquamarine::Window::DecorationDefault);
+ m_defDecoActive =
+ new Aquamarine::Window (qt_xrootwin (), 0,
+ Aquamarine::Window::DecorationDefaultActive);
+
+ connect (m_kwinmodule, SIGNAL (windowAdded (WId)),
+ SLOT (slotWindowAdded (WId)));
+ connect (m_kwinmodule, SIGNAL (windowRemoved (WId)),
+ SLOT (slotWindowRemoved (WId)));
+ connect (m_kwinmodule, SIGNAL (activeWindowChanged (WId)),
+ SLOT (slotActiveWindowChanged (WId)));
+ connect (m_kwinmodule,
+ SIGNAL (windowChanged (WId, const unsigned long *)),
+ SLOT (slotWindowChanged (WId, const unsigned long *)));
+
+ QValueList < WId >::ConstIterator it;
+ for (it = m_kwinmodule->windows ().begin ();
+ it != m_kwinmodule->windows ().end (); ++it)
+ {
+ slotWindowAdded ((*it));
+ }
+
+
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ if (cursors[i][j].shape != XC_left_ptr)
+ cursors[i][j].cursor =
+ XCreateFontCursor (qt_xdisplay (), cursors[i][j].shape);
+ }
+ }
+
+ connect( this, SIGNAL(appearanceChanged()), SLOT(reconfigure()) );
+}
+
+Aquamarine::Decorator::~Decorator ()
+{
+ QMap < WId, Aquamarine::Window * >::ConstIterator it;
+ for (it = m_windows.begin ();
+ it != m_windows.end (); ++it)
+ {
+ delete (*it);
+ }
+ delete
+ m_defDeco;
+ delete
+ m_defDecoActive;
+ delete
+ m_options;
+ delete
+ m_plugins;
+ delete
+ m_config;
+ delete
+ m_switcher;
+ delete
+ m_kwinmodule;
+ if (dm_window != None) XDestroyWindow(qt_xdisplay(),dm_window);
+ dm_window = None;
+}
+
+bool
+Aquamarine::Decorator::x11EventFilter (XEvent * xevent)
+{
+ WId
+ xid = 0;
+
+
+ switch (xevent->type)
+ {
+ case DestroyNotify:
+ if (xevent->xdestroywindow.window == m_activeWM)
+ {
+ m_restart = true;
+ KApplication::exit(0);
+ }
+ break;
+ case SelectionRequest:
+ handleSelectionRequest (xevent);
+ break;
+ case SelectionClear:
+ if (xevent->xselectionclear.selection == Atoms::dm_sn)
+ {
+ m_restart = false;
+ KApplication::exit(0);
+ }
+ break;
+ case ConfigureNotify:
+ {
+ XConfigureEvent *
+ xce = reinterpret_cast < XConfigureEvent * >(xevent);
+ Aquamarine::Window * client = 0;
+ if (m_frames.contains (xce->window))
+ client = m_frames[xce->window];
+ if (!client)
+ break;
+ client->updateFrame (xce->window);
+ }
+ case PropertyNotify:
+ if (xevent->xproperty.atom == Atoms::net_frame_window)
+ {
+ xid = xevent->xproperty.window;
+ slotWindowAdded (xid);
+ }
+ if (xevent->xproperty.atom == Atoms::select_window)
+ {
+ xid = xevent->xproperty.window;
+ if (!m_switcher || m_switcher->xid () != xid)
+ slotWindowAdded (xid);
+ m_switcher->update ();
+
+ }
+ if (xevent->xproperty.atom == Atoms::net_desktop_geometry
+ || xevent->xproperty.atom == Atoms::net_desktop_viewport)
+ {
+ updateDesktopGeometry ();
+ }
+ if (xevent->xproperty.atom == Atoms::opacity)
+ {
+ Aquamarine::Window * client = 0;
+ if (m_windows.contains (xevent->xproperty.window))
+ client = m_windows[xevent->xproperty.window];
+ if (client)
+ client->updateOpacity ();
+ }
+ if (xevent->xproperty.atom == Atoms::brightness)
+ {
+ Aquamarine::Window * client = 0;
+ if (m_windows.contains (xevent->xproperty.window))
+ client = m_windows[xevent->xproperty.window];
+ if (client)
+ client->updateBrightness ();
+ }
+ if (xevent->xproperty.atom == Atoms::saturation)
+ {
+ Aquamarine::Window * client = 0;
+ if (m_windows.contains (xevent->xproperty.window))
+ client = m_windows[xevent->xproperty.window];
+ if (client)
+ client->updateSaturation ();
+ }
+ break;
+ case EnterNotify:
+ {
+ XCrossingEvent *
+ xce = reinterpret_cast < XCrossingEvent * >(xevent);
+ Aquamarine::Window * client = 0;
+ if (m_frames.contains (xce->window))
+ client = m_frames[xce->window];
+ if (!client)
+ break;
+ QWidget *
+ widget = client->decoration ()->widget ();
+ QWidget *
+ child = widget->childAt (xce->x, xce->y, true);
+ if (!child)
+ break;
+
+ QEvent qe (QEvent::Enter);
+ QApplication::sendEvent (child, &qe);
+ client->setActiveChild (child);
+ client->updateCursor (QPoint (xce->x, xce->y));
+ break;
+ }
+ case LeaveNotify:
+ {
+ XCrossingEvent *
+ xce = reinterpret_cast < XCrossingEvent * >(xevent);
+ Aquamarine::Window * client = 0;
+ if (m_frames.contains (xce->window))
+ client = m_frames[xce->window];
+ if (!client)
+ break;
+
+ QEvent qe (QEvent::Leave);
+ QApplication::sendEvent (client->activeChild (), &qe);
+ XUndefineCursor (qt_xdisplay (), client->frameId ());
+ break;
+ }
+ case MotionNotify:
+ {
+ XMotionEvent *
+ xme = reinterpret_cast < XMotionEvent * >(xevent);
+ Aquamarine::Window * client = 0;
+ if (m_frames.contains (xme->window))
+ client = m_frames[xme->window];
+ if (!client)
+ break;
+ QWidget *
+ widget = client->decoration ()->widget ();
+ QWidget *
+ child = widget->childAt (xme->x, xme->y, true);
+ if (!child)
+ break;
+ if (child != client->activeChild ())
+ {
+ QEvent qee (QEvent::Enter);
+ QEvent qle (QEvent::Leave);
+ if (client->activeChild ())
+ QApplication::sendEvent (client->activeChild (), &qle);
+ QApplication::sendEvent (child, &qee);
+ client->setActiveChild (child);
+ }
+ QPoint qp (xme->x, xme->y);
+ if (widget != child)
+ qp -= QPoint (child->pos ().x (), child->pos ().y ());
+ QMouseEvent qme (QEvent::MouseMove, qp,
+ Qt::NoButton, Qt::NoButton);
+ QApplication::sendEvent (child, &qme);
+
+ client->updateCursor (QPoint (xme->x, xme->y));
+
+ break;
+ }
+ case ButtonPress:
+ case ButtonRelease:
+ {
+ XButtonEvent *
+ xbe = reinterpret_cast < XButtonEvent * >(xevent);
+ Aquamarine::Window * client = 0;
+ if (m_frames.contains (xbe->window))
+ client = m_frames[xbe->window];
+ if (!client)
+ break;
+
+ QWidget *
+ widget = client->decoration ()->widget ();
+ QWidget *
+ child = widget->childAt (xbe->x, xbe->y, true);
+ if (!child)
+ break;
+
+ XButtonEvent *
+ xbe2 = new XButtonEvent;
+ memcpy (xbe2, xbe, sizeof (XButtonEvent));
+ xbe2->window = child->winId ();
+ if (widget != child)
+ {
+ xbe2->x = xbe->x - child->pos ().x ();
+ xbe2->y = xbe->y - child->pos ().y ();
+ }
+ QApplication::x11ProcessEvent ((XEvent *) xbe2);
+ return true;
+ }
+ default:
+ break;
+ }
+ return KApplication::x11EventFilter (xevent);
+}
+
+WId
+Aquamarine::Decorator::fetchFrame (WId window)
+{
+ Atom
+ type;
+ int
+ format;
+ unsigned long
+ nitems;
+ unsigned long
+ bytes_after;
+ WId *
+ w;
+ WId **ww = &w;
+ int
+ err,
+ result;
+
+ Aquamarine::trapXError ();
+
+ type = None;
+ result = XGetWindowProperty (qt_xdisplay (),
+ window,
+ Atoms::net_frame_window,
+ 0, LONG_MAX,
+ False, XA_WINDOW, &type, &format, &nitems,
+ &bytes_after, (unsigned char **)ww);
+ err = Aquamarine::popXError ();
+
+ if (err || result != Success)
+ return 0;
+
+ if (type != XA_WINDOW)
+ {
+ XFree (w);
+ return 0;
+ }
+
+ WId
+ rv = *w;
+ XFree (w);
+
+ if (validWindow(rv))
+ return rv;
+ else
+ return 0;
+}
+
+void
+Aquamarine::Decorator::reconfigure ()
+{
+ kdDebug () << k_funcinfo << endl;
+
+ m_config->reparseConfiguration ();
+ unsigned long
+ changed = m_options->updateSettings ();
+
+ if (m_plugins->reset (changed))
+ {
+ for (QMap < WId, Aquamarine::Window * >::ConstIterator it =
+ m_windows.constBegin (); it != m_windows.constEnd (); ++it)
+ it.data ()->reloadDecoration ();
+ m_defDeco->reloadDecoration ();
+ m_defDecoActive->reloadDecoration ();
+ m_plugins->destroyPreviousPlugin ();
+ }
+}
+
+void
+Aquamarine::Decorator::slotWindowAdded (WId id)
+{
+ kdDebug () << k_funcinfo << endl;
+ if (!validWindow(id)) return;
+ Aquamarine::trapXError ();
+ XSelectInput (qt_xdisplay (), id, defaultMask);
+ if (Aquamarine::popXError ())
+ return;
+ if (Aquamarine::readWindowProperty (id, Atoms::select_window, NULL))
+ {
+ if (!m_switcher)
+ m_switcher = new Switcher (id);
+ if (m_switcher->xid () != id)
+ {
+ delete
+ m_switcher;
+ m_switcher = new Switcher (id);
+ }
+ return;
+ }
+ WId
+ frame = fetchFrame (id);
+ Aquamarine::Window * client = 0;
+ for (QMap < WId, Aquamarine::Window * >::ConstIterator it =
+ m_windows.constBegin (); it != m_windows.constEnd (); ++it)
+ {
+ if (it.data ()->winId () == id)
+ {
+ return;
+ }
+ }
+ if (frame)
+ {
+ if (!m_windows.contains (id))
+ {
+ client = new Aquamarine::Window (id, frame);
+ connect( this, SIGNAL(desktopGeometryChanged()), client, SLOT(slotDesktopGeometryChanged()) );
+ if (m_kwinmodule->activeWindow () == id)
+ {
+ if (m_activeWindow)
+ m_activeWindow->setActive (false);
+ m_activeWindow = client;
+ client->setActive(true);
+ }
+ m_windows.insert (id, client);
+ m_frames.insert (frame, client);
+ }
+ else
+ {
+ client = m_windows[id];
+ m_frames.remove (client->frameId ());
+ m_frames.insert (frame, client);
+ client->updateFrame (frame);
+ }
+ }
+ else
+ {
+ if (m_windows.contains (id))
+ {
+ client = m_windows[id];
+ }
+ if (client)
+ {
+ m_windows.remove (client->windowId ());
+ m_frames.remove (client->frameId ());
+ delete
+ client;
+ }
+ }
+}
+
+void
+Aquamarine::Decorator::slotWindowRemoved (WId id)
+{
+ kdDebug () << k_funcinfo << endl;
+ Aquamarine::Window * window = 0;
+ if (m_windows.contains (id))
+ {
+ window = m_windows[id];
+ }
+ else if (m_frames.contains (id))
+ {
+ window = m_frames[id];
+ }
+ if (window)
+ {
+ m_windows.remove (window->windowId ());
+ m_frames.remove (window->frameId ());
+ if (m_activeWindow == window)
+ m_activeWindow = 0;
+ delete
+ window;
+ }
+ if (m_switcher && m_switcher->xid () == id)
+ {
+ delete
+ m_switcher;
+ m_switcher = NULL;
+ }
+}
+
+void
+Aquamarine::Decorator::slotActiveWindowChanged (WId id)
+{
+ kdDebug () << k_funcinfo << endl;
+
+ Aquamarine::Window * newActiveWindow = 0;
+ if (m_windows.contains (id))
+ newActiveWindow = m_windows[id];
+
+ if (newActiveWindow && newActiveWindow != m_activeWindow)
+ {
+ if (m_activeWindow)
+ {
+ Aquamarine::trapXError ();
+ XWindowAttributes
+ attr;
+ if (XGetWindowAttributes
+ (qt_xdisplay (), m_activeWindow->windowId (), &attr)
+ && !Aquamarine::popXError ())
+ m_activeWindow->setActive (false);
+ }
+ newActiveWindow->setActive (true);
+ }
+ m_activeWindow = newActiveWindow;
+}
+
+void
+Aquamarine::Decorator::slotWindowChanged (WId id,
+ const unsigned long *properties)
+{
+ Aquamarine::Window * client = 0;
+ if (m_windows.contains (id))
+ client = m_windows[id];
+
+ if (properties[0] & NET::WMName)
+ {
+ if (client)
+ client->updateName ();
+ }
+ if (properties[0] & NET::WMState)
+ {
+ if (client)
+ client->updateState ();
+ }
+ if (properties[0] & NET::WMIcon)
+ {
+ if (client)
+ client->updateIcons ();
+ }
+ if (properties[0] & NET::WMGeometry)
+ {
+ if (m_switcher && m_switcher->xid () == id)
+ m_switcher->updateGeometry ();
+ if (client)
+ client->updateWindowGeometry ();
+ }
+}
+
+void
+Aquamarine::Decorator::sendClientMessage (WId w, Atom a, Atom protocol,
+ long data1, long data2, long data3)
+{
+ XEvent
+ ev;
+ long
+ mask;
+
+ memset (&ev, 0, sizeof (ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = w;
+ ev.xclient.message_type = a;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = protocol;
+ ev.xclient.data.l[1] = qt_x_time;
+ ev.xclient.data.l[2] = data1;
+ ev.xclient.data.l[3] = data2;
+ ev.xclient.data.l[4] = data3;
+ mask = 0L;
+ if (w == qt_xrootwin ())
+ mask = SubstructureRedirectMask;
+ XSendEvent (qt_xdisplay (), w, False, mask, &ev);
+}
+
+void
+Aquamarine::Decorator::updateDesktopGeometry ()
+{
+ int
+ x,
+ y;
+ unsigned int
+ width,
+ height,
+ border,
+ depth;
+ ::Window root;
+ XGetGeometry (qt_xdisplay (), qt_xrootwin (), &root, &x, &y, &width,
+ &height, &border, &depth);
+ m_rootSize = QSize (width, height);
+
+ int
+ num_val;
+ void *
+ values =
+ readXProperty (qt_xrootwin (), Atoms::net_desktop_geometry,
+ XA_CARDINAL, &num_val);
+
+ if (values)
+ {
+ unsigned long *
+ val = (unsigned long *)values;
+ m_desktop = QSize (val[0], val[1]);
+ XFree (val);
+ }
+ else
+ {
+ m_desktop = QSize (m_rootSize.width (), m_rootSize.height ());
+ }
+ values =
+ readXProperty (qt_xrootwin (), Atoms::net_desktop_viewport,
+ XA_CARDINAL, &num_val);
+
+ if (values)
+ {
+ unsigned long *
+ val = (unsigned long *)values;
+ m_viewport = QPoint (val[0], val[1]);
+ XFree (val);
+ }
+ else
+ {
+ m_viewport = QPoint (0, 0);
+ }
+
+ emit desktopGeometryChanged();
+}
+
+int
+Aquamarine::Decorator::onViewport (QPoint pos)
+{
+ return (((pos.y () +
+ m_viewport.y ()) / m_rootSize.height ()) * (m_desktop.width () /
+ m_rootSize.
+ width ())) +
+ ((pos.x () + m_viewport.x ()) / m_rootSize.width ()) + 1;
+}
+
+QSize
+Aquamarine::Decorator::viewports ()
+{
+ return QSize ((m_desktop.width () / m_rootSize.width ()),
+ (m_desktop.height () / m_rootSize.height ()));
+}
+
+void
+Aquamarine::Decorator::moveToViewport (WId id, int vp)
+{
+ int
+ x,
+ y;
+ unsigned int
+ width,
+ height,
+ border,
+ depth;
+ ::Window root;
+ XGetGeometry (qt_xdisplay (), id, &root, &x, &y, &width, &height, &border,
+ &depth);
+ if (vp <= 0) vp+= (m_desktop.width () / m_rootSize.width ()) * (m_desktop.height () / m_rootSize.height ());
+ vp = ((vp - 1) % ((m_desktop.width () / m_rootSize.width ()) * (m_desktop.height () / m_rootSize.height ()))) + 1;
+ int
+ offsetX = m_rootSize.width () * ((vp - 1) % viewports ().width ());
+ int
+ offsetY = m_rootSize.height () * ((vp - 1) / viewports ().width ());
+ XMoveWindow (qt_xdisplay (), id, x + offsetX - m_viewport.x (),
+ y + offsetY - m_viewport.y ());
+}
diff --git a/src/decorator.h b/src/decorator.h
new file mode 100644
index 0000000..1e9186b
--- /dev/null
+++ b/src/decorator.h
@@ -0,0 +1,155 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AQUAMARINE_DECORATOR_H
+#define AQUAMARINE_DECORATOR_H
+
+#include <kapplication.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/cursorfont.h>
+
+#include <fixx11h.h>
+#include <kconfig.h>
+#include <kdecoration_plugins_p.h>
+#include <kdecoration_p.h>
+
+#include "window.h"
+#include "KWinInterface.h"
+
+#define C(name) { 0, XC_ ## name }
+
+struct _cursor
+{
+ Cursor cursor;
+ unsigned int shape;
+};
+
+class KConfig;
+class KWinModule;
+
+static const long defaultMask = StructureNotifyMask | PropertyChangeMask;
+
+namespace Aquamarine
+{
+
+ class Options;
+ class Switcher;
+
+ class PluginManager:public KDecorationPlugins
+ {
+ public:
+ PluginManager (KConfig * config);
+ virtual bool provides (Requirement)
+ {
+ return false;
+ }
+ };
+
+
+ class Decorator:public KApplication, public KWinInterface
+ {
+ Q_OBJECT public:
+ Decorator (Display * dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap =
+ 0);
+ ~Decorator ();
+
+ bool isReady ()
+ {
+ return ready;
+ }
+ bool x11EventFilter (XEvent *);
+
+ static PluginManager *pluginManager ()
+ {
+ return m_plugins;
+ }
+ static Aquamarine::Options * options ()
+ {
+ return m_options;
+ }
+
+ static void sendClientMessage (WId w, Atom a, Atom protocol,
+ long data1 = 0, long data2 =
+ 0, long data3 = 0);
+
+ static int onViewport (QPoint pos);
+ static QSize viewports ();
+ static void moveToViewport (WId id, int vp);
+
+ bool restart () const
+ {
+ return m_restart;
+ }
+
+ public slots:
+ void reconfigure ();
+
+ signals:
+ void desktopGeometryChanged();
+
+ private:
+ WId fetchFrame (WId window);
+ void updateDesktopGeometry ();
+
+ private slots:
+ void slotWindowAdded (WId id);
+ void slotWindowRemoved (WId id);
+ void slotActiveWindowChanged (WId id);
+ void slotWindowChanged (WId id, const unsigned long *properties);
+
+ private:
+
+ bool ready;
+
+ Aquamarine::Window * m_defDeco;
+ Aquamarine::Window * m_defDecoActive;
+
+ QMap < WId, Aquamarine::Window * >m_windows;
+ QMap < WId, Aquamarine::Window * >m_frames;
+ Aquamarine::Window * m_activeWindow;
+
+ KConfig *m_config;
+
+ static PluginManager *m_plugins;
+ static Aquamarine::Options * m_options;
+
+ KWinModule *m_kwinmodule;
+
+ Switcher *m_switcher;
+
+ static QSize m_desktop;
+ static QPoint m_viewport;
+ static QSize m_rootSize;
+
+ WId m_activeWM;
+ bool m_restart;
+ };
+
+}
+
+#endif
diff --git a/src/options.cpp b/src/options.cpp
new file mode 100644
index 0000000..5818809
--- /dev/null
+++ b/src/options.cpp
@@ -0,0 +1,167 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "options.h"
+
+#include <kconfig.h>
+#include <kdecoration_p.h>
+
+Aquamarine::Options::Options (KConfig * config):
+KDecorationOptions (), m_config (config)
+{
+ d = new KDecorationOptionsPrivate;
+ updateSettings ();
+}
+
+unsigned long
+Aquamarine::Options::updateSettings ()
+{
+ unsigned long changed = 0;
+ changed |= d->updateKWinSettings (m_config);
+
+ m_config->setGroup( "Windows" );
+ OpTitlebarDblClick =
+ windowOperation (m_config->
+ readEntry ("TitlebarDoubleClickCommand", "Shade"),
+ true);
+ d->OpMaxButtonLeftClick =
+ windowOperation (m_config->
+ readEntry ("MaximizeButtonLeftClickCommand",
+ "Maximize"), true);
+ d->OpMaxButtonMiddleClick =
+ windowOperation (m_config->
+ readEntry ("MaximizeButtonMiddleClickCommand",
+ "Maximize (vertical only)"), true);
+ d->OpMaxButtonRightClick =
+ windowOperation (m_config->
+ readEntry ("MaximizeButtonRightClickCommand",
+ "Maximize (horizontal only)"), true);
+
+ m_config->setGroup( "MouseBindings");
+ CmdActiveTitlebar1 = mouseCommand(m_config->readEntry("CommandActiveTitlebar1","Raise"), true );
+ CmdActiveTitlebar2 = mouseCommand(m_config->readEntry("CommandActiveTitlebar2","Lower"), true );
+ CmdActiveTitlebar3 = mouseCommand(m_config->readEntry("CommandActiveTitlebar3","Operations menu"), true );
+ CmdInactiveTitlebar1 = mouseCommand(m_config->readEntry("CommandInactiveTitlebar1","Activate and raise"), true );
+ CmdInactiveTitlebar2 = mouseCommand(m_config->readEntry("CommandInactiveTitlebar2","Activate and lower"), true );
+ CmdInactiveTitlebar3 = mouseCommand(m_config->readEntry("CommandInactiveTitlebar3","Operations menu"), true );
+
+ CmdTitlebarWheel = mouseWheelCommand(m_config->readEntry("CommandTitlebarWheel","Nothing"));
+
+ return changed;
+}
+
+// restricted should be true for operations that the user may not be able to repeat
+// if the window is moved out of the workspace (e.g. if the user moves a window
+// by the titlebar, and moves it too high beneath Kicker at the top edge, they
+// may not be able to move it back, unless they know about Alt+LMB)
+KDecorationDefines::WindowOperation
+Aquamarine::Options::windowOperation (const QString & name, bool restricted)
+{
+ if (name == "Move")
+ return restricted ? Aquamarine::Options::MoveOp :
+ Aquamarine::Options::UnrestrictedMoveOp;
+ else if (name == "Resize")
+ return restricted ? Aquamarine::Options::ResizeOp :
+ Aquamarine::Options::UnrestrictedResizeOp;
+ else if (name == "Maximize")
+ return Aquamarine::Options::MaximizeOp;
+ else if (name == "Minimize")
+ return Aquamarine::Options::MinimizeOp;
+ else if (name == "Close")
+ return Aquamarine::Options::CloseOp;
+ else if (name == "OnAllDesktops")
+ return Aquamarine::Options::OnAllDesktopsOp;
+ else if (name == "Shade")
+ return Aquamarine::Options::ShadeOp;
+ else if (name == "Operations")
+ return Aquamarine::Options::OperationsOp;
+ else if (name == "Maximize (vertical only)")
+ return Aquamarine::Options::VMaximizeOp;
+ else if (name == "Maximize (horizontal only)")
+ return Aquamarine::Options::HMaximizeOp;
+ else if (name == "Lower")
+ return Aquamarine::Options::LowerOp;
+ return Aquamarine::Options::NoOp;
+}
+
+Aquamarine::Options::MouseCommand
+Aquamarine::Options::mouseCommand(const QString &name, bool restricted )
+{
+ QString lowerName = name.lower();
+ if (lowerName == "raise") return MouseRaise;
+ if (lowerName == "lower") return MouseLower;
+ if (lowerName == "operations menu") return MouseOperationsMenu;
+ if (lowerName == "toggle raise and lower") return MouseToggleRaiseAndLower;
+ if (lowerName == "activate and raise") return MouseActivateAndRaise;
+ if (lowerName == "activate and lower") return MouseActivateAndLower;
+ if (lowerName == "activate") return MouseActivate;
+ if (lowerName == "activate, raise and pass click") return MouseActivateRaiseAndPassClick;
+ if (lowerName == "activate and pass click") return MouseActivateAndPassClick;
+ if (lowerName == "activate, raise and move")
+ return restricted ? MouseActivateRaiseAndMove : MouseActivateRaiseAndUnrestrictedMove;
+ if (lowerName == "move") return restricted ? MouseMove : MouseUnrestrictedMove;
+ if (lowerName == "resize") return restricted ? MouseResize : MouseUnrestrictedResize;
+ if (lowerName == "shade") return MouseShade;
+ if (lowerName == "minimize") return MouseMinimize;
+ if (lowerName == "nothing") return MouseNothing;
+ return MouseNothing;
+}
+
+Aquamarine::Options::MouseWheelCommand
+Aquamarine::Options::mouseWheelCommand(const QString &name)
+{
+ QString lowerName = name.lower();
+ if (lowerName == "raise/lower") return MouseWheelRaiseLower;
+ if (lowerName == "shade/unshade") return MouseWheelShadeUnshade;
+ if (lowerName == "maximize/restore") return MouseWheelMaximizeRestore;
+ if (lowerName == "above/below") return MouseWheelAboveBelow;
+ if (lowerName == "previous/next desktop") return MouseWheelPreviousNextDesktop;
+ if (lowerName == "change opacity") return MouseWheelChangeOpacity;
+ return MouseWheelNothing;
+}
+
+Aquamarine::Options::MouseCommand
+Aquamarine::Options::wheelToMouseCommand(MouseWheelCommand com, int delta)
+{
+ switch( com )
+ {
+ case MouseWheelRaiseLower:
+ return delta > 0 ? MouseRaise : MouseLower;
+ case MouseWheelShadeUnshade:
+ return delta > 0 ? MouseSetShade : MouseUnsetShade;
+ case MouseWheelMaximizeRestore:
+ return delta > 0 ? MouseMaximize : MouseRestore;
+ case MouseWheelAboveBelow:
+ return delta > 0 ? MouseAbove : MouseBelow;
+ case MouseWheelPreviousNextDesktop:
+ return delta > 0 ? MousePreviousDesktop : MouseNextDesktop;
+ case MouseWheelChangeOpacity:
+ return delta > 0 ? MouseOpacityMore : MouseOpacityLess;
+ default:
+ return MouseNothing;
+ }
+}
+
diff --git a/src/options.h b/src/options.h
new file mode 100644
index 0000000..c6d37e6
--- /dev/null
+++ b/src/options.h
@@ -0,0 +1,124 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AQUAMARINE_OPTIONS_H
+#define AQUAMARINE_OPTIONS_H
+
+#include <kdecoration.h>
+
+class KConfig;
+
+namespace Aquamarine
+{
+
+ class Options : public KDecorationOptions
+ {
+ public:
+ enum MouseCommand
+ {
+ MouseRaise, MouseLower, MouseOperationsMenu, MouseToggleRaiseAndLower,
+ MouseActivateAndRaise, MouseActivateAndLower, MouseActivate,
+ MouseActivateRaiseAndPassClick, MouseActivateAndPassClick,
+ MouseMove, MouseUnrestrictedMove,
+ MouseActivateRaiseAndMove, MouseActivateRaiseAndUnrestrictedMove,
+ MouseResize, MouseUnrestrictedResize,
+ MouseShade, MouseSetShade, MouseUnsetShade,
+ MouseMaximize, MouseRestore, MouseMinimize,
+ MouseNextDesktop, MousePreviousDesktop,
+ MouseAbove, MouseBelow,
+ MouseOpacityMore, MouseOpacityLess,
+ MouseNothing
+ };
+ enum MouseWheelCommand
+ {
+ MouseWheelRaiseLower, MouseWheelShadeUnshade, MouseWheelMaximizeRestore,
+ MouseWheelAboveBelow, MouseWheelPreviousNextDesktop,
+ MouseWheelChangeOpacity,
+ MouseWheelNothing
+ };
+
+
+ Options (KConfig * config);
+ virtual unsigned long updateSettings ();
+
+ WindowOperation operationTitlebarDblClick ()
+ {
+ return OpTitlebarDblClick;
+ }
+
+ MouseCommand commandActiveTitlebar1()
+ {
+ return CmdActiveTitlebar1;
+ }
+ MouseCommand commandActiveTitlebar2()
+ {
+ return CmdActiveTitlebar2;
+ }
+ MouseCommand commandActiveTitlebar3()
+ {
+ return CmdActiveTitlebar3;
+ }
+ MouseCommand commandInactiveTitlebar1()
+ {
+ return CmdInactiveTitlebar1;
+ }
+ MouseCommand commandInactiveTitlebar2()
+ {
+ return CmdInactiveTitlebar2;
+ }
+ MouseCommand commandInactiveTitlebar3()
+ {
+ return CmdInactiveTitlebar3;
+ }
+
+ MouseCommand operationTitlebarMouseWheel( int delta )
+ {
+ return wheelToMouseCommand( CmdTitlebarWheel, delta );
+ }
+
+ private:
+ static KDecorationDefines::
+ WindowOperation windowOperation (const QString & name, bool restricted);
+ MouseCommand mouseCommand(const QString &name, bool restricted);
+ MouseWheelCommand mouseWheelCommand(const QString &name);
+ MouseCommand wheelToMouseCommand( MouseWheelCommand com, int delta );
+
+ private:
+ KDecorationDefines::WindowOperation OpTitlebarDblClick;
+ MouseCommand CmdActiveTitlebar1;
+ MouseCommand CmdActiveTitlebar2;
+ MouseCommand CmdActiveTitlebar3;
+ MouseCommand CmdInactiveTitlebar1;
+ MouseCommand CmdInactiveTitlebar2;
+ MouseCommand CmdInactiveTitlebar3;
+ MouseWheelCommand CmdTitlebarWheel;
+
+ KConfig *m_config;
+ };
+
+}
+
+#endif
diff --git a/src/switcher.cpp b/src/switcher.cpp
new file mode 100644
index 0000000..43a745b
--- /dev/null
+++ b/src/switcher.cpp
@@ -0,0 +1,336 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "switcher.h"
+#include "decorator.h"
+#include "options.h"
+#include "utils.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/shape.h>
+
+#include <fixx11h.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kdecoration.h>
+#include <kwin.h>
+
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qevent.h>
+#include <qpainter.h>
+#include <qobjectlist.h>
+#include <qwidget.h>
+#include <qstring.h>
+#include <qtimer.h>
+#include <qcursor.h>
+
+#define GRAVITY_WEST (1 << 0)
+#define GRAVITY_EAST (1 << 1)
+#define GRAVITY_NORTH (1 << 2)
+#define GRAVITY_SOUTH (1 << 3)
+
+#define XX_MASK (1 << 12)
+#define XY_MASK (1 << 13)
+#define YX_MASK (1 << 14)
+#define YY_MASK (1 << 15)
+
+#define CLAMP_HORZ (1 << 0)
+#define CLAMP_VERT (1 << 1)
+
+extern Atom net_window_decor;
+
+extern Atom select_window_atom;
+
+#define TOP 10
+#define BOTTOM 50
+#define LEFT 10
+#define RIGHT 10
+
+#define BACKGROUND 0xd7bfbfbf
+
+Aquamarine::Switcher::Switcher (WId wid):
+m_wid (wid)
+{
+ updateGeometry ();
+}
+
+Aquamarine::Switcher::~Switcher ()
+{
+
+}
+
+void
+Aquamarine::Switcher::updateGeometry ()
+{
+ int
+ x,
+ y;
+ unsigned int
+ width,
+ height,
+ border,
+ depth;
+ ::Window root;
+ XGetGeometry (qt_xdisplay (), m_wid, &root, &x, &y, &width, &height,
+ &border, &depth);
+ m_geometry = QRect (x, y, width, height);
+ m_qpixmap = QPixmap (width + LEFT + RIGHT, height + TOP + BOTTOM);
+
+
+ Aquamarine::readWindowProperty (m_wid, Atoms::select_window,
+ (long *)&m_selected);
+ m_sName = KWin::readNameProperty (m_selected, XA_WM_NAME);
+
+
+ XSetWindowBackground (qt_xdisplay (), m_wid, BACKGROUND);
+ XClearWindow (qt_xdisplay (), m_wid);
+ XSync (qt_xdisplay (), FALSE);
+
+ QPainter
+ p (&m_qpixmap);
+
+ QBrush
+ b1 (QColor (0, BACKGROUND));
+
+ p.setPen (Qt::black);
+ p.setBrush (b1);
+ p.drawRoundRect (0, 0, m_qpixmap.width (), m_qpixmap.height (),
+ (8 * m_qpixmap.height ()) / m_qpixmap.width (), 8);
+
+ QFont
+ font (Aquamarine::Decorator::options ()->font (true));
+ p.setFont (font);
+ QFontMetrics
+ fm = p.fontMetrics ();
+ while (fm.width (m_sName) > m_geometry.width ())
+ {
+ m_sName.truncate (m_sName.length () - 6);
+ m_sName += "...";
+ }
+
+ p.drawText ((m_qpixmap.width () - fm.width (m_sName)) / 2,
+ TOP + m_geometry.height () + 5 + fm.ascent (), m_sName);
+
+ updateWindowProperties ();
+}
+
+void
+Aquamarine::Switcher::update ()
+{
+ Aquamarine::readWindowProperty (m_wid, Atoms::select_window,
+ (long *)&m_selected);
+ m_sName = KWin::readNameProperty (m_selected, XA_WM_NAME);
+
+ QPainter
+ p (&m_qpixmap);
+
+ QBrush
+ b1 (QColor (0, BACKGROUND));
+ p.setPen (Qt::NoPen);
+ p.setBrush (b1);
+ p.drawRect (LEFT, TOP + m_geometry.height (), m_geometry.width (), 30);
+
+ QFont
+ font (Aquamarine::Decorator::options ()->font (true));
+ p.setFont (font);
+ QFontMetrics
+ fm = p.fontMetrics ();
+ while (fm.width (m_sName) > m_geometry.width ())
+ {
+ m_sName.truncate (m_sName.length () - 6);
+ m_sName += "...";
+ }
+
+ p.drawText ((m_qpixmap.width () - fm.width (m_sName)) / 2,
+ TOP + m_geometry.height () + 5 + fm.ascent (), m_sName);
+
+ updateWindowProperties ();
+}
+
+void
+Aquamarine::Switcher::updateWindowProperties ()
+{
+
+ Pixmap
+ m_pixmap = m_qpixmap.handle ();
+
+ int
+ w_w = m_geometry.width ();
+ int
+ w_h = m_geometry.height ();
+
+ long
+ mdata[256];
+
+ long *
+ data = mdata;
+
+ *data++ = 0;
+ memcpy (data++, &m_pixmap, sizeof (m_pixmap));
+
+ *data++ = LEFT;
+ *data++ = RIGHT;
+ *data++ = TOP;
+ *data++ = BOTTOM;
+
+ *data++ = LEFT;
+ *data++ = RIGHT;
+ *data++ = TOP;
+ *data++ = BOTTOM;
+
+ *data++ = 0;
+ *data++ = 0;
+
+ //TOP
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = -LEFT;
+ *data++ = -TOP;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = LEFT;
+ *data++ = TOP;
+ *data++ = 0;
+ *data++ = 0;
+
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = -TOP;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = w_w;
+ *data++ = TOP;
+ *data++ = LEFT;
+ *data++ = 0;
+
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 0) |
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = -TOP;
+ *data++ = RIGHT;
+ *data++ = 0;
+ *data++ = RIGHT;
+ *data++ = TOP;
+ *data++ = LEFT + w_w;
+ *data++ = 0;
+
+
+ //BOTTOM
+
+ *data++ =
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = -LEFT;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = BOTTOM;
+ *data++ = LEFT;
+ *data++ = BOTTOM;
+ *data++ = 0;
+ *data++ = w_h + TOP;
+
+ *data++ =
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = BOTTOM;
+ *data++ = w_w;
+ *data++ = BOTTOM;
+ *data++ = LEFT;
+ *data++ = w_h + TOP;
+
+ *data++ =
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = RIGHT;
+ *data++ = BOTTOM;
+ *data++ = RIGHT;
+ *data++ = BOTTOM;
+ *data++ = LEFT + w_w;
+ *data++ = w_h + TOP;
+
+ //LEFT
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = -LEFT;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = LEFT;
+ *data++ = w_h;
+ *data++ = 0;
+ *data++ = TOP;
+
+ //RIGHT
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = RIGHT;
+ *data++ = 0;
+ *data++ = RIGHT;
+ *data++ = w_h;
+ *data++ = w_w + LEFT;
+ *data++ = TOP;
+
+ XChangeProperty (qt_xdisplay (), m_wid,
+ Atoms::net_window_decor,
+ XA_INTEGER,
+ 32, PropModeReplace, (unsigned char *)mdata,
+ 12 + (8 * 9));
+ XSync (qt_xdisplay (), FALSE);
+}
diff --git a/src/switcher.h b/src/switcher.h
new file mode 100644
index 0000000..01a7a0e
--- /dev/null
+++ b/src/switcher.h
@@ -0,0 +1,67 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AQUAMARINE_SWITCHER_H
+#define AQUAMARINE_SWITCHER_H
+
+#include <qpixmap.h>
+#include <qwidget.h>
+#include <qstring.h>
+
+namespace Aquamarine
+{
+
+ class Switcher
+ {
+
+ public:
+ Switcher (WId wid);
+ ~Switcher ();
+
+ void update ();
+ void updateGeometry ();
+
+ WId xid () const
+ {
+ return m_wid;
+ }
+
+ private:
+ void updateWindowProperties ();
+
+ private:
+
+ WId m_wid;
+ WId m_selected;
+ QString m_sName;
+
+ QPixmap m_qpixmap;
+ QRect m_geometry;
+ };
+
+}
+
+#endif
diff --git a/src/utils.cpp b/src/utils.cpp
new file mode 100644
index 0000000..819321b
--- /dev/null
+++ b/src/utils.cpp
@@ -0,0 +1,499 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "utils.h"
+
+#include <qt.h>
+
+#include <X11/Xlib.h>
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xmd.h>
+
+#include <stdlib.h>
+
+static char program_name[] = "aquamarine";
+
+static int trapped_error_code = 0;
+Time dm_sn_timestamp;
+
+namespace Aquamarine
+{
+ WId dm_window = None;
+
+ namespace Atoms
+ {
+
+ Atom select_window;
+
+ Atom manager;
+ Atom targets;
+ Atom multiple;
+ Atom timestamp;
+ Atom version;
+ Atom atom_pair;
+
+ Atom opacity;
+ Atom saturation;
+ Atom brightness;
+
+ Atom utf8_string;
+
+ Atom dm_name;
+ Atom dm_sn;
+
+ Atom net_frame_window;
+ Atom net_window_decor;
+ Atom net_wm_moveresize;
+
+ Atom wm_delete_window;
+ Atom wm_take_focus;
+ Atom net_wm_context_help;
+ Atom net_wm_ping;
+ Atom net_wm_take_activity;
+ Atom wm_protocols;
+
+ Atom net_desktop_viewport;
+ Atom net_desktop_geometry;
+
+ Atom wm_name;
+ Atom wm_sn;
+
+ }
+}
+
+static int (*old_error_handler) (Display * d, XErrorEvent * e);
+static int
+xErrorHandler (Display *, XErrorEvent * error)
+{
+ trapped_error_code = error->error_code;
+ return 0;
+}
+
+void
+Aquamarine::trapXError (void)
+{
+ trapped_error_code = 0;
+ old_error_handler = XSetErrorHandler (xErrorHandler);
+}
+
+int
+Aquamarine::popXError (void)
+{
+ XSetErrorHandler (old_error_handler);
+ return trapped_error_code;
+}
+
+void *
+Aquamarine::readXProperty (WId window, Atom property, Atom type, int *items)
+{
+ long offset = 0, length = 2048l;
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_remaining;
+ unsigned char *data = 0l;
+
+ Aquamarine::trapXError ();
+ int result =
+ XGetWindowProperty (qt_xdisplay (), window, property, offset, length,
+ false, type,
+ &actual_type, &actual_format, &nitems,
+ &bytes_remaining, &data);
+
+ if (Aquamarine::popXError ())
+ return NULL;
+ if (result == Success && actual_type == type
+ && actual_format == 32 && nitems > 0)
+ {
+ if (items)
+ *items = nitems;
+
+ return reinterpret_cast < void *>(data);
+ }
+
+ if (data)
+ XFree (data);
+
+ if (items)
+ *items = 0;
+
+ return NULL;
+}
+
+bool
+Aquamarine::readWindowProperty (long window, long property, long *value)
+{
+ void *data = readXProperty (window, property, XA_WINDOW, NULL);
+
+ if (data)
+ {
+ if (value)
+ *value = *reinterpret_cast < int *>(data);
+ XFree (data);
+
+ return true;
+ }
+
+ return false;
+}
+
+unsigned short
+Aquamarine::readWindowPropertyDefault (WId id, Atom property,
+ unsigned short defaultValue)
+{
+ Atom actual;
+ int result, format;
+ unsigned long n, left;
+ unsigned char *data;
+
+ result = XGetWindowProperty (qt_xdisplay (), id, property,
+ 0L, 1L, FALSE, XA_CARDINAL, &actual, &format,
+ &n, &left, &data);
+
+ if (result == Success && n && data)
+ {
+ CARD32 value;
+
+ memcpy (&value, data, sizeof (CARD32));
+
+ XFree (data);
+
+ return value >> 16;
+ }
+
+ return defaultValue;
+}
+
+void
+Aquamarine::setWindowProperty (WId id, Atom property, unsigned short value)
+{
+ CARD32 value32;
+
+ value32 = value << 16 | value;
+
+ XChangeProperty (qt_xdisplay (), id, property,
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *)&value32, 1);
+}
+
+
+
+bool
+Aquamarine::acquireDmSession (Display * xdisplay, int screen, bool replace)
+{
+ XEvent event;
+ XSetWindowAttributes attr;
+ Window current_dm_sn_owner, new_dm_sn_owner;
+ char buf[128];
+
+ sprintf (buf, "DM_S%d", screen);
+ Atoms::dm_sn = XInternAtom (xdisplay, buf, 0);
+
+ current_dm_sn_owner = XGetSelectionOwner (xdisplay, Atoms::dm_sn);
+
+ if (current_dm_sn_owner != dm_window)
+ {
+ if (!replace)
+ {
+ fprintf (stderr,
+ "%s: Screen %d on display \"%s\" already "
+ "has a decoration manager; try using the "
+ "--replace option to replace the current "
+ "decoration manager.\n",
+ program_name, screen, DisplayString (xdisplay));
+
+ return false;
+ }
+
+ XSelectInput (xdisplay, current_dm_sn_owner, StructureNotifyMask);
+ }
+
+ if (current_dm_sn_owner == dm_window && current_dm_sn_owner != None)
+ {
+ return true;
+ }
+
+ attr.override_redirect = true;
+ attr.event_mask = PropertyChangeMask;
+
+ new_dm_sn_owner =
+ XCreateWindow (xdisplay, XRootWindow (xdisplay, screen),
+ -100, -100, 1, 1, 0,
+ CopyFromParent, CopyFromParent,
+ CopyFromParent,
+ CWOverrideRedirect | CWEventMask, &attr);
+
+ XChangeProperty (xdisplay,
+ new_dm_sn_owner,
+ Atoms::dm_name,
+ Atoms::utf8_string, 8,
+ PropModeReplace, (unsigned char *)"gwd", strlen ("gwd"));
+
+ XWindowEvent (xdisplay, new_dm_sn_owner, PropertyChangeMask, &event);
+
+ dm_sn_timestamp = event.xproperty.time;
+
+ XSetSelectionOwner (xdisplay, Atoms::dm_sn, new_dm_sn_owner,
+ dm_sn_timestamp);
+
+ if (XGetSelectionOwner (xdisplay, Atoms::dm_sn) != new_dm_sn_owner)
+ {
+ fprintf (stderr,
+ "%s: Could not acquire decoration manager "
+ "selection on screen %d display \"%s\"\n",
+ program_name, screen, DisplayString (xdisplay));
+
+ XDestroyWindow (xdisplay, new_dm_sn_owner);
+
+ return false;
+ }
+
+ /* Send client message indicating that we are now the DM */
+ event.xclient.type = ClientMessage;
+ event.xclient.window = XRootWindow (xdisplay, screen);
+ event.xclient.message_type = Atoms::manager;
+ event.xclient.format = 32;
+ event.xclient.data.l[0] = dm_sn_timestamp;
+ event.xclient.data.l[1] = Atoms::dm_name;
+ event.xclient.data.l[2] = 0;
+ event.xclient.data.l[3] = 0;
+ event.xclient.data.l[4] = 0;
+
+ XSendEvent (xdisplay, XRootWindow (xdisplay, screen), false,
+ StructureNotifyMask, &event);
+
+ /* Wait for old decoration manager to go away */
+ if (current_dm_sn_owner != None)
+ {
+ do
+ {
+ XWindowEvent (xdisplay, current_dm_sn_owner,
+ StructureNotifyMask, &event);
+ } while (event.type != DestroyNotify);
+ }
+
+ dm_window = new_dm_sn_owner;
+
+ return true;
+}
+
+void
+Aquamarine::set_dm_check_hint (int screen)
+{
+ XSetWindowAttributes attrs;
+ unsigned long data[1];
+ Window xroot;
+ Display *xdisplay = qt_xdisplay ();
+ Atom atom;
+
+ attrs.override_redirect = true;
+ attrs.event_mask = PropertyChangeMask;
+
+ xroot = RootWindow (xdisplay, screen);
+
+ data[0] = XCreateWindow (xdisplay,
+ xroot,
+ -100, -100, 1, 1,
+ 0,
+ CopyFromParent,
+ CopyFromParent,
+ (Visual *) CopyFromParent,
+ CWOverrideRedirect | CWEventMask, &attrs);
+
+ atom = XInternAtom (xdisplay, "_NET_SUPPORTING_DM_CHECK", FALSE);
+
+ XChangeProperty (xdisplay, xroot,
+ atom,
+ XA_WINDOW,
+ 32, PropModeReplace, (unsigned char *)data, 1);
+}
+
+/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
+bool
+Aquamarine::convertProperty (WId w, Atom target, Atom property)
+{
+
+#define N_TARGETS 4
+
+ Atom conversion_targets[N_TARGETS];
+ long icccm_version[] = { 2, 0 };
+
+ conversion_targets[0] = Atoms::targets;
+ conversion_targets[1] = Atoms::multiple;
+ conversion_targets[2] = Atoms::timestamp;
+ conversion_targets[3] = Atoms::version;
+
+ if (target == Atoms::targets)
+ XChangeProperty (qt_xdisplay (), w, property,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *)conversion_targets, N_TARGETS);
+ else if (target == Atoms::timestamp)
+ XChangeProperty (qt_xdisplay (), w, property,
+ XA_INTEGER, 32, PropModeReplace,
+ (unsigned char *)&dm_sn_timestamp, 1);
+ else if (target == Atoms::version)
+ XChangeProperty (qt_xdisplay (), w, property,
+ XA_INTEGER, 32, PropModeReplace,
+ (unsigned char *)icccm_version, 2);
+ else
+ return FALSE;
+
+ /* Be sure the PropertyNotify has arrived so we
+ * can send SelectionNotify
+ */
+ XSync (qt_xdisplay (), FALSE);
+
+ return TRUE;
+}
+
+void
+Aquamarine::handleSelectionRequest (XEvent * event)
+{
+ XSelectionEvent reply;
+
+ reply.type = SelectionNotify;
+ reply.display = qt_xdisplay ();
+ reply.requestor = event->xselectionrequest.requestor;
+ reply.selection = event->xselectionrequest.selection;
+ reply.target = event->xselectionrequest.target;
+ reply.property = None;
+ reply.time = event->xselectionrequest.time;
+
+ if (event->xselectionrequest.target == Atoms::multiple)
+ {
+ if (event->xselectionrequest.property != None)
+ {
+ Atom type, *adata;
+ int i, format;
+ unsigned long num, rest;
+ unsigned char *data;
+
+ if (XGetWindowProperty (qt_xdisplay (),
+ event->xselectionrequest.requestor,
+ event->xselectionrequest.property,
+ 0, 256, FALSE,
+ Atoms::atom_pair,
+ &type, &format, &num, &rest,
+ &data) != Success)
+ return;
+
+ /* FIXME: to be 100% correct, should deal with rest > 0,
+ * but since we have 4 possible targets, we will hardly ever
+ * meet multiple requests with a length > 8
+ */
+ adata = (Atom *) data;
+ i = 0;
+ while (i < (int)num)
+ {
+ if (!convertProperty (event->xselectionrequest.requestor,
+ adata[i], adata[i + 1]))
+ adata[i + 1] = None;
+
+ i += 2;
+ }
+
+ XChangeProperty (qt_xdisplay (),
+ event->xselectionrequest.requestor,
+ event->xselectionrequest.property,
+ Atoms::atom_pair,
+ 32, PropModeReplace, data, num);
+ }
+ }
+ else
+ {
+ if (event->xselectionrequest.property == None)
+ event->xselectionrequest.property =
+ event->xselectionrequest.target;
+
+ if (convertProperty (event->xselectionrequest.requestor,
+ event->xselectionrequest.target,
+ event->xselectionrequest.property))
+ reply.property = event->xselectionrequest.property;
+ }
+
+ XSendEvent (qt_xdisplay (),
+ event->xselectionrequest.requestor,
+ FALSE, 0L, (XEvent *) & reply);
+}
+
+bool
+Aquamarine::validWindow (WId id)
+{
+ Aquamarine::trapXError ();
+ XWindowAttributes
+ attr;
+ if (XGetWindowAttributes (qt_xdisplay (), id, &attr)
+ && !Aquamarine::popXError ())
+ return true;
+ return false;
+}
+
+void
+Aquamarine::Atoms::init ()
+{
+ Display *
+ xdisplay = qt_xdisplay ();
+
+ net_frame_window = XInternAtom (xdisplay, "_NET_FRAME_WINDOW", false);
+ net_window_decor = XInternAtom (xdisplay, "_NET_WINDOW_DECOR", false);
+ net_wm_moveresize = XInternAtom (xdisplay, "_NET_WM_MOVERESIZE", false);
+
+ select_window = XInternAtom (xdisplay, "_SWITCH_SELECT_WINDOW", false);
+
+ manager = XInternAtom (xdisplay, "MANAGER", false);
+ targets = XInternAtom (xdisplay, "TARGETS", false);
+ multiple = XInternAtom (xdisplay, "MULTIPLE", false);
+ timestamp = XInternAtom (xdisplay, "TIMESTAMP", false);
+ version = XInternAtom (xdisplay, "VERSION", false);
+ atom_pair = XInternAtom (xdisplay, "ATOM_PAIR", false);
+
+ utf8_string = XInternAtom (xdisplay, "UTF8_STRING", false);
+
+ dm_name = XInternAtom (xdisplay, "_NET_DM_NAME", false);
+
+ wm_delete_window = XInternAtom (xdisplay, "WM_DELETE_WINDOW", false);
+ wm_take_focus = XInternAtom (xdisplay, "WM_TAKE_FOCUS", false);
+ net_wm_context_help =
+ XInternAtom (xdisplay, "_NET_WM_CONTEXT_HELP", false);
+ net_wm_ping = XInternAtom (xdisplay, "_NET_WM_PING", false);
+ net_wm_take_activity =
+ XInternAtom (xdisplay, "_NET_WM_TAKE_ACTIVITY", false);
+ wm_protocols = XInternAtom (xdisplay, "WM_PROTOCOLS", false);
+
+ net_desktop_viewport =
+ XInternAtom (xdisplay, "_NET_DESKTOP_VIEWPORT", false);
+ net_desktop_geometry =
+ XInternAtom (xdisplay, "_NET_DESKTOP_GEOMETRY", false);
+
+ opacity = XInternAtom (xdisplay, "_NET_WM_WINDOW_OPACITY", false);
+ brightness = XInternAtom (xdisplay, "_NET_WM_WINDOW_BRIGHTNESS", false);
+ saturation = XInternAtom (xdisplay, "_NET_WM_WINDOW_SATURATION", false);
+
+ wm_name = XInternAtom (xdisplay, "_NET_WM_NAME", false);
+ char buf[128];
+ sprintf(buf,"WM_S%d",qt_xscreen());
+ wm_sn = XInternAtom (xdisplay, buf, false);
+}
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 0000000..8974253
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,111 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#ifndef AQUAMARINE_UTILS_H
+#define AQUAMARINE_UTILS_H
+
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+#include <qwidget.h>
+
+namespace Aquamarine
+{
+ namespace Atoms
+ {
+ extern Atom restack_window;
+ extern Atom select_window;
+ extern Atom mwm_hints;
+
+ extern Atom toolkit_action;
+ extern Atom toolkit_action_main_menu;
+ extern Atom toolkit_action_run_dialog;
+ extern Atom toolkit_action_window_menu;
+ extern Atom toolkit_action_force_quit_dialog;
+
+ extern Atom panel_action;
+ extern Atom panel_action_main_menu;
+ extern Atom panel_action_run_dialog;
+
+ extern Atom manager;
+ extern Atom targets;
+ extern Atom multiple;
+ extern Atom timestamp;
+ extern Atom version;
+ extern Atom atom_pair;
+
+ extern Atom opacity;
+ extern Atom saturation;
+ extern Atom brightness;
+
+ extern Atom utf8_string;
+
+ extern Atom dm_name;
+ extern Atom dm_sn;
+
+ extern Atom net_frame_window;
+ extern Atom net_window_decor;
+ extern Atom net_window_decor_sync;
+ extern Atom net_wm_moveresize;
+ extern Atom net_active_window;
+
+ extern Atom wm_delete_window;
+ extern Atom wm_take_focus;
+ extern Atom net_wm_context_help;
+ extern Atom net_wm_ping;
+ extern Atom net_wm_take_activity;
+ extern Atom wm_protocols;
+
+ extern Atom net_desktop_viewport;
+ extern Atom net_desktop_geometry;
+
+ extern Atom wm_name;
+ extern Atom wm_sn;
+
+ void init ();
+ }
+
+ extern WId dm_window;
+
+ void trapXError (void);
+ int popXError (void);
+ bool eventFilter (void *message, long *result);
+ void *readXProperty (WId window, Atom property, Atom type, int *items);
+ bool readWindowProperty (long wId, long property, long *value);
+ bool acquireDmSession (Display * xdisplay, int screen, bool replace);
+ void set_dm_check_hint (int screen);
+ bool convertProperty (WId w, Atom target, Atom property);
+ void handleSelectionRequest (XEvent * event);
+
+ unsigned short readWindowPropertyDefault (WId id, Atom property,
+ unsigned short defaultValue);
+ void setWindowProperty (WId id, Atom property, unsigned short value);
+
+ bool validWindow (WId id);
+}
+
+#endif
diff --git a/src/window.cpp b/src/window.cpp
new file mode 100644
index 0000000..2b731c5
--- /dev/null
+++ b/src/window.cpp
@@ -0,0 +1,1653 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "window.h"
+#include "decorator.h"
+#include "options.h"
+#include "utils.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/shape.h>
+
+#include <fixx11h.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdecoration.h>
+#include <kwin.h>
+#include <klocale.h>
+
+
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qevent.h>
+#include <qpainter.h>
+#include <qobjectlist.h>
+#include <qwidget.h>
+#include <qstring.h>
+#include <qtimer.h>
+#include <qcursor.h>
+#include <qpopupmenu.h>
+
+#define GRAVITY_WEST (1 << 0)
+#define GRAVITY_EAST (1 << 1)
+#define GRAVITY_NORTH (1 << 2)
+#define GRAVITY_SOUTH (1 << 3)
+
+#define XX_MASK (1 << 12)
+#define XY_MASK (1 << 13)
+#define YX_MASK (1 << 14)
+#define YY_MASK (1 << 15)
+
+#define CLAMP_HORZ (1 << 0)
+#define CLAMP_VERT (1 << 1)
+
+#define WM_MOVERESIZE_SIZE_TOPLEFT 0
+#define WM_MOVERESIZE_SIZE_TOP 1
+#define WM_MOVERESIZE_SIZE_TOPRIGHT 2
+#define WM_MOVERESIZE_SIZE_RIGHT 3
+#define WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
+#define WM_MOVERESIZE_SIZE_BOTTOM 5
+#define WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
+#define WM_MOVERESIZE_SIZE_LEFT 7
+#define WM_MOVERESIZE_MOVE 8
+#define WM_MOVERESIZE_SIZE_KEYBOARD 9
+#define WM_MOVERESIZE_MOVE_KEYBOARD 10
+
+extern Atom net_window_decor;
+extern Atom net_wm_moveresize;
+
+extern Atom wm_protocols;
+extern Atom wm_delete_window;
+extern Atom wm_take_focus;
+extern Atom net_wm_context_help;
+extern Atom net_wm_ping;
+extern Atom net_wm_take_activity;
+
+extern struct _cursor cursors[3][3];
+
+Aquamarine::Window::Window (WId wid, WId frame, DecorationType type):
+m_wid (wid),
+m_active (false),
+m_deco (0),
+m_fakeMaximized (false),
+m_shapeSet (false),
+m_grabChildPending (false),
+m_grabChildInProgress (false),
+m_updateWindowPending (false),
+m_grabAllChildren (false),
+m_type (type),
+m_popup (0),
+m_advanced_popup (0),
+m_viewport_menu (0),
+m_appearance_menu (0),
+m_brightness_menu (0), m_saturation_menu (0), m_opacity_menu (0)
+{
+ if (m_type == DecorationNormal)
+ {
+ KWin::WindowInfo wInf = KWin::windowInfo (m_wid, NET::WMState, 0);
+ m_state = wInf.state ();
+
+ m_name = KWin::readNameProperty (m_wid, XA_WM_NAME);
+
+ m_icons =
+ QIconSet (KWin::icon (m_wid, 16, 16, TRUE),
+ KWin::icon (m_wid, 32, 32, TRUE));
+
+ m_opacity = readWindowPropertyDefault (m_wid, Atoms::opacity, 0xffff);
+ m_brightness =
+ readWindowPropertyDefault (m_wid, Atoms::brightness, 0xffff);
+ m_saturation =
+ readWindowPropertyDefault (m_wid, Atoms::saturation, 0xffff);
+
+
+ updateFrame (frame);
+
+ int
+ x,
+ y;
+ unsigned int
+ width,
+ height,
+ border,
+ depth;
+ ::Window root;
+ XGetGeometry (qt_xdisplay (), m_wid, &root, &x, &y, &width, &height,
+ &border, &depth);
+ m_geometry = QRect (x, y, width, height);
+
+ setWState (Qt::WState_Visible);
+ installEventFilter (this);
+
+ getWindowProtocols ();
+ createDecoration ();
+ }
+ else
+ {
+
+ m_icons =
+ QIconSet (KGlobal::iconLoader ()->
+ loadIcon ("xapp", KIcon::NoGroup, 16),
+ KGlobal::iconLoader ()->loadIcon ("xapp",
+ KIcon::NoGroup, 32));
+
+ m_name = QString ("");
+
+ m_geometry = QRect (50, 50, 200, 100);
+
+ setWState (Qt::WState_Visible);
+ installEventFilter (this);
+ createDecoration ();
+ if (m_type == DecorationDefaultActive)
+ m_active = true;
+ }
+
+ m_activeChild = m_deco->widget ();
+}
+
+Aquamarine::Window::~Window ()
+{
+ delete
+ m_deco;
+ delete
+ m_popup;
+
+ Atom
+ my_atom = Atoms::net_window_decor;
+ if (m_type == DecorationDefault)
+ my_atom =
+ XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_NORMAL", FALSE);
+ else if (m_type == DecorationDefaultActive)
+ my_atom =
+ XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_ACTIVE", FALSE);
+
+ Aquamarine::trapXError ();
+ XWindowAttributes
+ attr;
+ if (XGetWindowAttributes (qt_xdisplay (), m_wid, &attr)
+ && !Aquamarine::popXError ())
+ {
+ XDeleteProperty (qt_xdisplay (), m_wid, my_atom);
+ }
+ Aquamarine::popXError ();
+
+
+}
+
+
+
+bool
+Aquamarine::Window::isActive () const
+{
+ return m_active;
+}
+
+bool
+Aquamarine::Window::isCloseable () const
+{
+ return true;
+}
+
+bool
+Aquamarine::Window::isMaximizable () const
+{
+ return true;
+}
+
+KDecoration::MaximizeMode Aquamarine::Window::maximizeMode () const
+{
+ if (m_type != DecorationNormal)
+ return MaximizeRestore;
+ if (m_fakeMaximized)
+ return MaximizeVertical | MaximizeHorizontal;
+
+ MaximizeMode cur = ((m_state & NET::MaxVert)
+ ? MaximizeVertical : MaximizeRestore) |
+ ((m_state & NET::MaxHoriz) ? MaximizeHorizontal : MaximizeRestore);
+ return cur;
+}
+
+bool
+Aquamarine::Window::isMinimizable () const
+{
+ return true;
+}
+
+bool
+Aquamarine::Window::providesContextHelp () const
+{
+ if (m_type != DecorationNormal)
+ return false;
+
+ return m_supportContextHelp;
+}
+
+int
+Aquamarine::Window::desktop () const
+{
+ return (m_state & NET::Sticky) ? NET::OnAllDesktops : 1;
+}
+
+bool
+Aquamarine::Window::isModal () const
+{
+ return m_state & NET::Modal;
+}
+
+bool
+Aquamarine::Window::isShadeable () const
+{
+ return true;
+}
+
+bool
+Aquamarine::Window::isShade () const
+{
+ if (m_type != DecorationNormal)
+ return false;
+
+ return (m_state & NET::Shaded);
+}
+
+bool
+Aquamarine::Window::isSetShade () const
+{
+ return isShade ();
+}
+
+bool
+Aquamarine::Window::keepAbove () const
+{
+ if (m_type != DecorationNormal)
+ return false;
+
+ return (m_state & NET::KeepAbove);
+}
+
+bool
+Aquamarine::Window::keepBelow () const
+{
+ if (m_type != DecorationNormal)
+ return false;
+
+ return (m_state & NET::KeepBelow);
+}
+
+bool
+Aquamarine::Window::isMovable () const
+{
+ return true;
+}
+
+NET::WindowType Aquamarine::Window::windowType (unsigned long) const
+{
+ return NET::Normal;
+}
+
+bool
+Aquamarine::Window::isResizable () const
+{
+ return true;
+}
+
+QIconSet
+Aquamarine::Window::icon () const
+{
+ return m_icons;
+}
+
+QString
+Aquamarine::Window::caption () const
+{
+ return m_name;
+}
+
+void
+Aquamarine::Window::showWindowMenu (QPoint pos)
+{
+ kdDebug () << k_funcinfo << pos << endl;
+
+ // create menu if we don't have it already
+ if (!m_popup)
+ {
+ m_popup = new QPopupMenu (this);
+ m_popup->setCheckable (true);
+ m_popup->setFont (KGlobalSettings::menuFont ());
+
+ m_advanced_popup = new QPopupMenu (m_popup);
+ m_advanced_popup->setCheckable (true);
+ m_advanced_popup->setFont (KGlobalSettings::menuFont ());
+ connect (m_advanced_popup, SIGNAL (activated (int)),
+ SLOT (slotPopupActivated (int)));
+
+ m_advanced_popup->insertItem (SmallIconSet ("up"),
+ i18n ("Keep &Above Others"),
+ Options::KeepAboveOp);
+ m_advanced_popup->insertItem (SmallIconSet ("down"),
+ i18n ("Keep &Below Others"),
+ Options::KeepBelowOp);
+ m_advanced_popup->insertItem (SmallIconSet ("window_fullscreen"),
+ i18n ("&Fullscreen"),
+ Options::FullScreenOp);
+
+ m_popup->insertItem (i18n ("Ad&vanced"), m_advanced_popup);
+
+ m_viewport_menu = new QPopupMenu (m_popup);
+ m_viewport_menu->setCheckable (true);
+ m_viewport_menu->setFont (KGlobalSettings::menuFont ());
+ connect (m_viewport_menu, SIGNAL (activated (int)),
+ SLOT (slotChangeViewport (int)));
+
+ m_viewport_menu->insertItem (i18n ("On all Viewports"), 0);
+ m_viewport_menu->insertSeparator ();
+ for (int i = 1;
+ i <=
+ Decorator::viewports ().height () *
+ Decorator::viewports ().width (); ++i)
+ m_viewport_menu->insertItem (i18n ("Move to Viewport %1").arg (i),
+ i);
+
+ m_popup->insertItem (i18n ("To Viewport"), m_viewport_menu);
+
+ m_popup->insertItem (SmallIconSet ("move"), i18n ("&Move"),
+ Options::MoveOp);
+ m_popup->insertItem (i18n ("Re&size"), Options::ResizeOp);
+
+ m_popup->insertItem (i18n ("Mi&nimize"), Options::MinimizeOp);
+ m_popup->insertItem (i18n ("Ma&ximize"), Options::MaximizeOp);
+ m_popup->insertItem (i18n ("Sh&ade"), Options::ShadeOp);
+
+
+ m_appearance_menu = new QPopupMenu (m_popup);
+ m_appearance_menu->setFont (KGlobalSettings::menuFont ());
+
+ m_opacity_menu = new QPopupMenu (m_appearance_menu);
+ m_opacity_menu->setFont (KGlobalSettings::menuFont ());
+ m_opacity_menu->insertItem ("25%", ChangeOpacity25);
+ m_opacity_menu->insertItem ("50%", ChangeOpacity50);
+ m_opacity_menu->insertItem ("75%", ChangeOpacity75);
+ m_opacity_menu->insertItem ("100%", ChangeOpacity100);
+
+ m_brightness_menu = new QPopupMenu (m_appearance_menu);
+ m_brightness_menu->setFont (KGlobalSettings::menuFont ());
+ m_brightness_menu->insertItem ("25%", ChangeBrightness25);
+ m_brightness_menu->insertItem ("50%", ChangeBrightness50);
+ m_brightness_menu->insertItem ("75%", ChangeBrightness75);
+ m_brightness_menu->insertItem ("100%", ChangeBrightness100);
+
+ m_saturation_menu = new QPopupMenu (m_appearance_menu);
+ m_saturation_menu->setFont (KGlobalSettings::menuFont ());
+ m_saturation_menu->insertItem ("25%", ChangeSaturation25);
+ m_saturation_menu->insertItem ("50%", ChangeSaturation50);
+ m_saturation_menu->insertItem ("75%", ChangeSaturation75);
+ m_saturation_menu->insertItem ("100%", ChangeSaturation100);
+
+ m_appearance_menu->insertItem (i18n ("Opacity"), m_opacity_menu);
+ m_appearance_menu->insertItem (i18n ("Brightness"),
+ m_brightness_menu);
+ m_appearance_menu->insertItem (i18n ("Saturation"),
+ m_saturation_menu);
+ m_appearance_menu->insertSeparator ();
+ m_appearance_menu->insertItem (i18n ("Reset settings"), ResetValues);
+
+ m_popup->insertItem (i18n ("Appearance"), m_appearance_menu);
+
+ connect (m_appearance_menu, SIGNAL (activated (int)),
+ SLOT (slotAppearanceChange (int)));
+ connect (m_opacity_menu, SIGNAL (activated (int)),
+ SLOT (slotAppearanceChange (int)));
+ connect (m_brightness_menu, SIGNAL (activated (int)),
+ SLOT (slotAppearanceChange (int)));
+ connect (m_saturation_menu, SIGNAL (activated (int)),
+ SLOT (slotAppearanceChange (int)));
+
+
+ m_popup->insertSeparator ();
+ m_popup->insertItem (SmallIconSet ("fileclose"), i18n ("&Close"),
+ Options::CloseOp);
+ m_popup->insertSeparator ();
+
+ connect (m_popup, SIGNAL (aboutToShow ()),
+ SLOT (slotPopupAboutToShow ()));
+ connect (m_popup, SIGNAL (activated (int)),
+ SLOT (slotPopupActivated (int)));
+ }
+ m_popup->exec (pos);
+}
+
+void
+Aquamarine::Window::showWindowMenu (const QRect & pos)
+{
+ showWindowMenu (pos.bottomLeft ());
+}
+
+void
+Aquamarine::Window::processMousePressEvent (QMouseEvent * qme)
+{
+ Options::MouseCommand com = Options::MouseNothing;
+ bool active = isActive();
+ if ( !m_supportTakeFocus )
+ active = TRUE;
+
+ switch (qme->button ())
+ {
+ case Qt::LeftButton:
+ com = active ? Decorator::options()->commandActiveTitlebar1() : Decorator::options()->commandInactiveTitlebar1();
+ break;
+ case Qt::MidButton:
+ com = active ? Decorator::options()->commandActiveTitlebar2() : Decorator::options()->commandInactiveTitlebar2();
+ break;
+ case Qt::RightButton:
+ com = active ? Decorator::options()->commandActiveTitlebar3() : Decorator::options()->commandInactiveTitlebar3();
+ break;
+ default:
+ break;
+ }
+ if( qme->button () == Qt::LeftButton
+ && com != Options::MouseOperationsMenu // actions where it's not possible to get the matching
+ && com != Options::MouseMinimize ) // mouse release event
+ {
+ moveWindow (qme);
+ }
+
+
+ performMouseCommand( com, qme);
+}
+
+void
+Aquamarine::Window::performWindowOperation (WindowOperation wo)
+{
+ kdDebug () << k_funcinfo << wo << endl;
+ switch (wo)
+ {
+ case KDecoration::MaximizeOp:
+ maximize (maximizeMode () == KDecoration::MaximizeFull
+ ? KDecoration::MaximizeRestore : KDecoration::MaximizeFull);
+ break;
+ case KDecoration::HMaximizeOp:
+ maximize (maximizeMode () ^ KDecoration::MaximizeHorizontal);
+ break;
+ case KDecoration::VMaximizeOp:
+ maximize (maximizeMode () ^ KDecoration::MaximizeVertical);
+ break;
+ case KDecoration::MinimizeOp:
+ minimize ();
+ break;
+ case KDecoration::ShadeOp:
+ setShade (!isShade ());
+ break;
+ case KDecoration::CloseOp:
+ closeWindow ();
+ break;
+ case KDecoration::KeepAboveOp:
+ setKeepAbove (!keepAbove ());
+ break;
+ case KDecoration::KeepBelowOp:
+ setKeepBelow (!keepBelow ());
+ break;
+ case KDecoration::FullScreenOp:
+ if (m_state & NET::FullScreen)
+ {
+ KWin::clearState (m_wid, NET::FullScreen);
+ }
+ else
+ KWin::setState (m_wid, NET::FullScreen);
+ break;
+ case KDecoration::MoveOp:
+ {
+ // FIXME: not supported in beryl
+ XEvent
+ ev;
+ ev.xclient.type = ClientMessage;
+ ev.xclient.display = qt_xdisplay ();
+
+ ev.xclient.serial = 0;
+ ev.xclient.send_event = TRUE;
+
+ ev.xclient.window = m_wid;
+ ev.xclient.message_type = Atoms::net_wm_moveresize;
+ ev.xclient.format = 32;
+
+ ev.xclient.data.l[0] = m_geometry.x () + (m_geometry.width () / 2);
+ ev.xclient.data.l[1] = m_geometry.y () + (m_geometry.height () / 2);
+ ev.xclient.data.l[2] = WM_MOVERESIZE_MOVE_KEYBOARD;
+ ev.xclient.data.l[3] = 1;
+ ev.xclient.data.l[4] = 1;
+
+ XUngrabPointer (qt_xdisplay (), CurrentTime);
+ XUngrabKeyboard (qt_xdisplay (), CurrentTime);
+
+ XSendEvent (qt_xdisplay (), qt_xrootwin (), FALSE,
+ SubstructureRedirectMask | SubstructureNotifyMask, &ev);
+
+ XSync (qt_xdisplay (), FALSE);
+ }
+ break;
+ case KDecoration::ResizeOp:
+ {
+ XEvent
+ ev;
+ ev.xclient.type = ClientMessage;
+ ev.xclient.display = qt_xdisplay ();
+
+ ev.xclient.serial = 0;
+ ev.xclient.send_event = TRUE;
+
+ ev.xclient.window = m_wid;
+ ev.xclient.message_type = Atoms::net_wm_moveresize;
+ ev.xclient.format = 32;
+
+ ev.xclient.data.l[0] = m_geometry.x () + (m_geometry.width () / 2);
+ ev.xclient.data.l[1] = m_geometry.y () + (m_geometry.height () / 2);
+ ev.xclient.data.l[2] = WM_MOVERESIZE_SIZE_KEYBOARD;
+ ev.xclient.data.l[3] = 1;
+ ev.xclient.data.l[4] = 1;
+
+ XUngrabPointer (qt_xdisplay (), CurrentTime);
+ XUngrabKeyboard (qt_xdisplay (), CurrentTime);
+
+ XSendEvent (qt_xdisplay (), qt_xrootwin (), FALSE,
+ SubstructureRedirectMask | SubstructureNotifyMask, &ev);
+
+ XSync (qt_xdisplay (), FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+Aquamarine::Window::setMask (const QRegion & reg, int)
+{
+ if (m_type != DecorationNormal)
+ return;
+
+ kdDebug () << k_funcinfo << endl;
+ m_shape = QRegion (reg);
+ m_shapeSet = true;
+ int
+ top,
+ bottom,
+ left,
+ right;
+ m_deco->borders (left, right, top, bottom);
+
+ m_clip =
+ QRegion (0, 0, m_geometry.width () + left + right,
+ m_geometry.height () + top + bottom);
+ m_clip -= QRegion (left, top, m_geometry.width (), m_geometry.height ());
+ m_clip -= reg;
+
+ XShapeCombineRegion (qt_xdisplay (), m_frame, ShapeInput, 0, 0,
+ reg.handle (), ShapeSet);
+}
+
+bool
+Aquamarine::Window::isPreview () const
+{
+ return false;
+}
+
+QRect
+Aquamarine::Window::geometry () const
+{
+ if (m_deco)
+ {
+ int
+ top,
+ bottom,
+ left,
+ right;
+ m_deco->borders (left, right, top, bottom);
+ return QRect (0, 0, m_geometry.width () + left + right,
+ m_geometry.height () + top + bottom);
+ }
+ return m_geometry;
+}
+
+QRect
+Aquamarine::Window::iconGeometry () const
+{
+ return QRect ();
+}
+
+QRegion
+Aquamarine::Window::unobscuredRegion (const QRegion & r) const
+{
+ return r;
+}
+
+QWidget *
+Aquamarine::Window::workspaceWidget () const
+{
+ return 0;
+}
+
+WId
+Aquamarine::Window::windowId () const
+{
+ return m_wid;
+}
+
+void
+Aquamarine::Window::closeWindow ()
+{
+ kdDebug () << k_funcinfo << endl;
+ if (!isCloseable ())
+ return;
+ if (m_supportDeleteWindow)
+ {
+ Aquamarine::Decorator::sendClientMessage (m_wid, Atoms::wm_protocols,
+ Atoms::wm_delete_window);
+ }
+ else
+ {
+ XKillClient (qt_xdisplay (), m_wid);
+ }
+}
+
+void
+Aquamarine::Window::maximize (MaximizeMode mode)
+{
+ kdDebug () << k_funcinfo << endl;
+
+ KWin::setState (m_wid,
+ ((mode & MaximizeVertical) ? NET::
+ MaxVert : 0) | ((mode & MaximizeHorizontal) ? NET::
+ MaxHoriz : 0));
+ KWin::clearState (m_wid,
+ ((mode & MaximizeVertical) ? 0 : NET::
+ MaxVert) | ((mode & MaximizeHorizontal) ? 0 : NET::
+ MaxHoriz));
+}
+
+void
+Aquamarine::Window::minimize ()
+{
+ kdDebug () << k_funcinfo << endl;
+ KWin::iconifyWindow (m_wid, false);
+}
+
+void
+Aquamarine::Window::showContextHelp ()
+{
+ kdDebug () << k_funcinfo << endl;
+ if (m_supportContextHelp)
+ {
+ Aquamarine::Decorator::sendClientMessage (m_wid, Atoms::wm_protocols,
+ Atoms::net_wm_context_help);
+ }
+}
+
+void
+Aquamarine::Window::titlebarDblClickOperation ()
+{
+ kdDebug () << k_funcinfo << endl;
+ performWindowOperation (Aquamarine::Decorator::options ()->
+ operationTitlebarDblClick ());
+}
+
+void
+Aquamarine::Window::setDesktop (int desktop)
+{
+ kdDebug () << k_funcinfo << endl;
+ if (desktop == NET::OnAllDesktops)
+ {
+ KWin::setState (m_wid, NET::Sticky);
+ }
+ else
+ {
+ KWin::clearState (m_wid, NET::Sticky);
+ }
+}
+
+void
+Aquamarine::Window::setKeepBelow (bool set)
+{
+ if (set)
+ {
+ KWin::clearState (m_wid, NET::KeepAbove);
+ KWin::setState (m_wid, NET::KeepBelow);
+ }
+ else
+ KWin::clearState (m_wid, NET::KeepBelow);
+}
+
+void
+Aquamarine::Window::setKeepAbove (bool set)
+{
+ if (set)
+ {
+ KWin::clearState (m_wid, NET::KeepBelow);
+ KWin::setState (m_wid, NET::KeepAbove);
+ }
+ else
+ KWin::clearState (m_wid, NET::KeepAbove);
+}
+
+void
+Aquamarine::Window::setShade (bool set)
+{
+ kdDebug () << k_funcinfo << endl;
+ if (set)
+ KWin::setState (m_wid, NET::Shaded);
+ else
+ KWin::clearState (m_wid, NET::Shaded);
+ m_deco->shadeChange ();
+}
+
+void
+Aquamarine::Window::titlebarMouseWheelOperation (int delta)
+{
+ kdDebug () << k_funcinfo << endl;
+ performMouseCommand( Decorator::options()->operationTitlebarMouseWheel( delta ), 0);
+}
+
+
+int
+Aquamarine::Window::currentDesktop () const
+{
+ return 1;
+}
+
+QWidget *
+Aquamarine::Window::initialParentWidget () const
+{
+ return const_cast < Window * >(this);
+}
+
+Qt::WFlags Aquamarine::Window::initialWFlags () const
+{
+ return 0;
+}
+
+void
+Aquamarine::Window::helperShowHide (bool)
+{
+}
+
+void
+Aquamarine::Window::grabXServer (bool)
+{
+}
+
+
+bool
+Aquamarine::Window::eventFilter (QObject * watched, QEvent * event)
+{
+ if (event->type () == QEvent::ChildInserted)
+ {
+ QChildEvent * ce = static_cast < QChildEvent * >(event);
+ if (ce->child () != m_popup)
+ {
+ ce->child ()->installEventFilter (this);
+ // the child might already have childs
+ // TODO: make this recursive
+ const QObjectList * list = ce->child ()->children ();
+ if (list)
+ {
+ QObjectListIt
+ it (*list);
+ QObject *
+ grandchild;
+ while ((grandchild = it.current ()) != 0)
+ {
+ ++it;
+ if (grandchild->isWidgetType ())
+ grandchild->installEventFilter (this);
+ }
+ }
+ }
+ }
+ if (event->type () == QEvent::Paint && !m_grabChildInProgress)
+ {
+ if (watched != m_deco->widget ())
+ {
+ if (!m_pendingChildren.contains(watched))
+ m_pendingChildren.append (watched);
+ if (!m_grabChildPending)
+ {
+ m_grabChildPending = true;
+ QTimer::singleShot (0, this, SLOT(grabChildWidgets()));
+ }
+ }
+ else
+ {
+ QRect rect = static_cast < QPaintEvent * >(event)->rect ();
+ m_grabAllChildren = true;
+ if (!m_grabChildPending)
+ {
+ m_grabChildPending = true;
+ QTimer::singleShot (0, this, SLOT (grabChildWidgets ()));
+ }
+ if (!m_updateWindowPending)
+ {
+ m_updateWindowPending = true;
+ QTimer::singleShot (0, this,
+ SLOT (updateWindowProperties ()));
+ }
+ }
+ }
+
+ return QWidget::eventFilter (watched, event);
+}
+
+
+
+void
+Aquamarine::Window::createDecoration ()
+{
+ if (m_deco)
+ return;
+ KDecoration *
+ deco = Decorator::pluginManager ()->createDecoration (this);
+ deco->init ();
+ m_deco = deco;
+
+ resizeDecoration ( true );
+
+ if (m_type == DecorationNormal)
+ XSelectInput (qt_xdisplay (), m_frame,
+ defaultMask | ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | EnterWindowMask | LeaveWindowMask);
+}
+
+void
+Aquamarine::Window::resizeDecoration ( bool force )
+{
+ int
+ top,
+ bottom,
+ left,
+ right;
+ m_deco->borders (left, right, top, bottom);
+ move (m_geometry.x() - left, m_geometry.y() - top);
+ if (!force && m_qpixmap.width () == (m_geometry.width () + left + right)
+ && m_qpixmap.height () == (m_geometry.height () + top + bottom))
+ return;
+
+ if (m_pending_pixmap.isNull ())
+ m_pending_pixmap =
+ QPixmap (m_geometry.width () + left + right,
+ m_geometry.height () + top + bottom);
+ else
+ m_pending_pixmap.resize (m_geometry.width () + left + right,
+ m_geometry.height () + top + bottom);
+ resize (m_geometry.width () + left + right,
+ m_geometry.height () + top + bottom);
+ QPainter::redirect (m_deco->widget (), &m_pending_pixmap);
+ m_deco->
+ resize (QSize
+ (m_geometry.width () + left + right,
+ m_geometry.height () + top + bottom));
+ m_deco->widget ()->setShown (true);
+
+ QPaintEvent *
+ e = new QPaintEvent (m_deco->widget ()->rect (), false);
+ QApplication::postEvent (m_deco->widget (), e);
+}
+
+void
+Aquamarine::Window::updateWindowProperties ()
+{
+ Atom
+ my_atom = Atoms::net_window_decor;
+ if (m_type == DecorationDefault)
+ my_atom =
+ XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_NORMAL", FALSE);
+ else if (m_type == DecorationDefaultActive)
+ my_atom =
+ XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_ACTIVE", FALSE);
+
+ m_updateWindowPending = false;
+ QPixmap
+ delete_me_later;
+ if (!m_pending_pixmap.isNull ())
+ {
+ delete_me_later = m_qpixmap;
+ m_qpixmap = m_pending_pixmap;
+ m_pending_pixmap = QPixmap ();
+ QPainter::redirect (m_deco->widget (), &m_qpixmap);
+ }
+ Pixmap
+ m_pixmap = m_qpixmap.handle ();
+
+ int
+ top,
+ bottom,
+ left,
+ right;
+ int
+ mtop,
+ mbottom,
+ mleft,
+ mright;
+
+ m_fakeMaximized = true;
+ m_deco->borders (mleft, mright, mtop, mbottom);
+ m_fakeMaximized = false;
+ m_deco->borders (left, right, top, bottom);
+
+
+ int
+ w_w = m_geometry.width ();
+ int
+ w_h = m_geometry.height ();
+
+ long
+ mdata[256];
+
+ long *
+ data = mdata;
+
+ *data++ = 0;
+ memcpy (data++, &m_pixmap, sizeof (m_pixmap));
+
+ *data++ = left;
+ *data++ = right;
+ *data++ = top;
+ *data++ = bottom;
+
+ *data++ = mleft;
+ *data++ = mright;
+ *data++ = mtop;
+ *data++ = mbottom;
+
+ *data++ = 0;
+ *data++ = 0;
+
+ //TOP
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = -left;
+ *data++ = -top;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = left;
+ *data++ = top;
+ *data++ = 0;
+ *data++ = 0;
+
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = -top;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = w_w;
+ *data++ = top;
+ *data++ = left;
+ *data++ = 0;
+
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 0) |
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = -top;
+ *data++ = right;
+ *data++ = 0;
+ *data++ = right;
+ *data++ = top;
+ *data++ = left + w_w;
+ *data++ = 0;
+
+
+ //BOTTOM
+ *data++ =
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = -left;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = bottom;
+ *data++ = left;
+ *data++ = bottom;
+ *data++ = 0;
+ *data++ = w_h + top;
+
+ *data++ =
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = bottom;
+ *data++ = w_w;
+ *data++ = bottom;
+ *data++ = left;
+ *data++ = w_h + top;
+
+ *data++ =
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = right;
+ *data++ = bottom;
+ *data++ = right;
+ *data++ = bottom;
+ *data++ = left + w_w;
+ *data++ = w_h + top;
+
+ //LEFT
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_WEST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = -left;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = left;
+ *data++ = w_h;
+ *data++ = 0;
+ *data++ = top;
+
+ //RIGHT
+ *data++ =
+ ((GRAVITY_NORTH | GRAVITY_EAST) << 0) |
+ ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) |
+ (0 << 8) | ((CLAMP_HORZ | CLAMP_VERT) << 10) | (XX_MASK) | (YY_MASK);
+
+ *data++ = 0;
+ *data++ = 0;
+ *data++ = right;
+ *data++ = 0;
+ *data++ = right;
+ *data++ = w_h;
+ *data++ = w_w + left;
+ *data++ = top;
+
+ Aquamarine::trapXError ();
+ XChangeProperty (qt_xdisplay (), m_wid,
+ my_atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (unsigned char *)mdata,
+ 12 + (8 * 9));
+ Aquamarine::popXError ();
+ XSync (qt_xdisplay (), FALSE);
+}
+
+void
+Aquamarine::Window::grabChildWidgets ()
+{
+ m_grabChildPending = false;
+ if (!m_deco)
+ return;
+
+ QPixmap * activePixmap;
+
+ m_grabChildInProgress = true;
+ QPainter * p = 0;
+ if (!m_pending_pixmap.isNull ())
+ {
+ p = new QPainter (&m_pending_pixmap);
+ activePixmap = &m_pending_pixmap;
+ }
+ else
+ {
+ p = new QPainter (&m_qpixmap);
+ activePixmap = &m_qpixmap;
+ }
+
+ QRegion childs;
+
+ const QObjectList * children = m_deco->widget ()->children ();
+ if (children)
+ {
+ QObjectListIt it (*children);
+ QObject * child;
+ while ((child = it.current ()) != 0)
+ {
+ ++it;
+ if (child->isWidgetType () && (m_grabAllChildren || m_pendingChildren.contains(child)))
+ {
+ QWidget * wid = static_cast < QWidget * >(child);
+ childs += wid->rect ();
+ QPixmap pix = QPixmap::grabWidget (wid);
+ p->drawPixmap (wid->pos (), pix);
+ }
+ }
+ }
+ delete p;
+ QRegion clip = QRegion(m_clip);
+ if (!m_grabAllChildren)
+ clip &= childs;
+ m_grabAllChildren = false;
+ m_pendingChildren.clear();
+ m_grabChildInProgress = false;
+
+ if (m_shapeSet)
+ {
+ Pixmap
+ pix = activePixmap->handle ();
+ XGCValues
+ gcv;
+ gcv.foreground = 0x00000000;
+ gcv.plane_mask = 0xffffffff;
+ GC
+ gc = XCreateGC (qt_xdisplay (), pix, GCForeground, &gcv);
+
+ QMemArray < QRect > rects = clip.rects ();
+ QMemArray < QRect >::ConstIterator it;
+ for (it = rects.begin (); it != rects.end (); ++it)
+ {
+ XFillRectangle (qt_xdisplay (), pix, gc, it->x (), it->y (),
+ it->width (), it->height ());
+ }
+
+ XFreeGC (qt_xdisplay (), gc);
+ }
+}
+
+void
+Aquamarine::Window::setActive (bool active)
+{
+ m_active = active;
+ m_deco->activeChange ();
+ resizeDecoration ();
+}
+
+void
+Aquamarine::Window::updateFrame (WId frame)
+{
+ m_frame = frame;
+ XSelectInput (qt_xdisplay (), m_frame,
+ defaultMask | ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | EnterWindowMask | LeaveWindowMask);
+ if (m_shapeSet)
+ XShapeCombineRegion (qt_xdisplay (), m_frame, ShapeInput, 0, 0,
+ m_shape.handle (), ShapeSet);
+}
+
+void
+Aquamarine::Window::updateWindowGeometry ()
+{
+ int
+ x,
+ y;
+ unsigned int
+ width,
+ height,
+ border,
+ depth;
+ ::Window root;
+ XGetGeometry (qt_xdisplay (), m_wid, &root, &x, &y, &width, &height,
+ &border, &depth);
+ m_geometry = QRect (x, y, width, height);
+ resizeDecoration ();
+}
+
+void
+Aquamarine::Window::reloadDecoration ()
+{
+ delete m_deco;
+ m_deco = 0;
+ createDecoration ();
+}
+
+void
+Aquamarine::Window::updateCursor (QPoint pos)
+{
+ switch (m_deco->mousePosition (pos))
+ {
+ case PositionCenter:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[1][1].cursor);
+ break;
+ case PositionLeft:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[1][0].cursor);
+ break;
+ case PositionRight:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[1][2].cursor);
+ break;
+ case PositionTop:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[0][1].cursor);
+ break;
+ case PositionBottom:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[2][1].cursor);
+ break;
+ case PositionTopLeft:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[0][0].cursor);
+ break;
+ case PositionTopRight:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[0][2].cursor);
+ break;
+ case PositionBottomLeft:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[2][0].cursor);
+ break;
+ case PositionBottomRight:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[2][2].cursor);
+ break;
+ default:
+ XDefineCursor (qt_xdisplay (), m_frame, cursors[1][1].cursor);
+ break;
+ }
+}
+
+void
+Aquamarine::Window::getWindowProtocols ()
+{
+ Atom *
+ p;
+ int
+ i,
+ n;
+
+ m_supportDeleteWindow = false;
+ m_supportTakeFocus = false;
+ m_supportTakeActivity = false;
+ m_supportContextHelp = false;
+ m_supportPing = false;
+
+ if (XGetWMProtocols (qt_xdisplay (), m_wid, &p, &n))
+ {
+ for (i = 0; i < n; i++)
+ if (p[i] == Atoms::wm_delete_window)
+ m_supportDeleteWindow = true;
+ else if (p[i] == Atoms::wm_take_focus)
+ m_supportTakeFocus = true;
+ else if (p[i] == Atoms::net_wm_take_activity)
+ m_supportTakeActivity = true;
+ else if (p[i] == Atoms::net_wm_context_help)
+ m_supportContextHelp = true;
+ else if (p[i] == Atoms::net_wm_ping)
+ m_supportPing = true;
+ if (n > 0)
+ XFree (p);
+ }
+}
+
+void
+Aquamarine::Window::slotPopupActivated (int id)
+{
+ WindowOperation
+ op = static_cast < WindowOperation > (id);
+ performWindowOperation (op);
+}
+
+void
+Aquamarine::Window::slotPopupAboutToShow ()
+{
+ m_popup->setItemEnabled (Options::ResizeOp, isResizable ());
+ m_popup->setItemEnabled (Options::MoveOp, isMovable ());
+
+ m_popup->setItemEnabled (Options::MaximizeOp, isMaximizable ());
+ m_popup->setItemChecked (Options::MaximizeOp,
+ maximizeMode () == MaximizeFull);
+
+ m_popup->setItemChecked (Options::ShadeOp, isShade ());
+ m_popup->setItemEnabled (Options::ShadeOp, isShadeable ());
+
+ m_advanced_popup->setItemChecked (Options::KeepAboveOp, keepAbove ());
+ m_advanced_popup->setItemChecked (Options::KeepBelowOp, keepBelow ());
+ m_advanced_popup->setItemChecked (Options::FullScreenOp, m_state & NET::FullScreen);
+
+ m_popup->setItemEnabled (Options::MinimizeOp, isMinimizable ());
+ m_popup->setItemEnabled (Options::CloseOp, isCloseable ());
+
+
+ m_opacity_menu->setItemEnabled (ChangeOpacity25, m_opacity != 0x3fff);
+ m_opacity_menu->setItemEnabled (ChangeOpacity50, m_opacity != 0x7fff);
+ m_opacity_menu->setItemEnabled (ChangeOpacity75, m_opacity != 0xbfff);
+ m_opacity_menu->setItemEnabled (ChangeOpacity100, m_opacity != 0xffff);
+
+ m_brightness_menu->setItemEnabled (ChangeBrightness25,
+ m_brightness != 0x3fff);
+ m_brightness_menu->setItemEnabled (ChangeBrightness50,
+ m_brightness != 0x7fff);
+ m_brightness_menu->setItemEnabled (ChangeBrightness75,
+ m_brightness != 0xbfff);
+ m_brightness_menu->setItemEnabled (ChangeBrightness100,
+ m_brightness != 0xffff);
+
+ m_saturation_menu->setItemEnabled (ChangeSaturation25,
+ m_saturation != 0x3fff);
+ m_saturation_menu->setItemEnabled (ChangeSaturation50,
+ m_saturation != 0x7fff);
+ m_saturation_menu->setItemEnabled (ChangeSaturation75,
+ m_saturation != 0xbfff);
+ m_saturation_menu->setItemEnabled (ChangeSaturation100,
+ m_saturation != 0xffff);
+
+ m_appearance_menu->setItemEnabled (ResetValues, m_opacity != 0xffff
+ || m_brightness != 0xffff
+ || m_saturation != 0xffff);
+
+ m_viewport_menu->setItemChecked (0, desktop () == NET::OnAllDesktops);
+ for (int i = 1;
+ i <=
+ Decorator::viewports ().width () * Decorator::viewports ().height ();
+ ++i)
+ {
+ if (Decorator::
+ onViewport (QPoint (m_geometry.x (), m_geometry.y ())) == i)
+ {
+ m_viewport_menu->setItemEnabled (i, false);
+ }
+ else
+ {
+ m_viewport_menu->setItemEnabled (i, true);
+ }
+ }
+}
+
+void
+Aquamarine::Window::updateState ()
+{
+ KWin::WindowInfo wInf = KWin::windowInfo (m_wid, NET::WMState, 0);
+ unsigned long
+ newState = wInf.state ();
+ unsigned long
+ stateChange = m_state ^ newState;
+ m_state = newState;
+
+ if (stateChange & NET::Max)
+ {
+ m_deco->maximizeChange ();
+ resizeDecoration (true);
+ }
+ if (stateChange & NET::KeepAbove && !(m_state & NET::KeepAbove))
+ m_deco->emitKeepAboveChanged (m_state & NET::KeepAbove);
+ if (stateChange & NET::KeepBelow && !(m_state & NET::KeepBelow))
+ m_deco->emitKeepBelowChanged (m_state & NET::KeepBelow);
+ if (stateChange & NET::KeepAbove && m_state & NET::KeepAbove)
+ m_deco->emitKeepAboveChanged (m_state & NET::KeepAbove);
+ if (stateChange & NET::KeepBelow && m_state & NET::KeepBelow)
+ m_deco->emitKeepBelowChanged (m_state & NET::KeepBelow);
+ if (stateChange & NET::Shaded)
+ m_deco->shadeChange ();
+ if (stateChange & NET::Sticky)
+ m_deco->desktopChange ();
+}
+
+void
+Aquamarine::Window::updateName ()
+{
+ m_name = KWin::readNameProperty (m_wid, XA_WM_NAME);
+ m_deco->captionChange ();
+}
+
+void
+Aquamarine::Window::updateIcons ()
+{
+ kdDebug () << k_funcinfo << endl;
+ m_icons =
+ QIconSet (KWin::icon (m_wid, 16, 16, TRUE),
+ KWin::icon (m_wid, 32, 32, TRUE));
+ m_deco->iconChange ();
+}
+
+void
+Aquamarine::Window::slotChangeViewport (int id)
+{
+ if (id == 0)
+ setDesktop ((desktop () ==
+ NET::OnAllDesktops) ? 1 : NET::OnAllDesktops);
+ else
+ Decorator::moveToViewport (m_wid, id);
+}
+
+void
+Aquamarine::Window::slotAppearanceChange (int id)
+{
+ switch (id)
+ {
+ case ResetValues:
+ setWindowProperty (m_wid, Atoms::opacity, 0xffff);
+ setWindowProperty (m_wid, Atoms::brightness, 0xffff);
+ setWindowProperty (m_wid, Atoms::saturation, 0xffff);
+ break;
+ case ChangeOpacity25:
+ setWindowProperty (m_wid, Atoms::opacity, 0x3fff);
+ break;
+ case ChangeOpacity50:
+ setWindowProperty (m_wid, Atoms::opacity, 0x7fff);
+ break;
+ case ChangeOpacity75:
+ setWindowProperty (m_wid, Atoms::opacity, 0xbfff);
+ break;
+ case ChangeOpacity100:
+ setWindowProperty (m_wid, Atoms::opacity, 0xffff);
+ break;
+ case ChangeBrightness25:
+ setWindowProperty (m_wid, Atoms::brightness, 0x3fff);
+ break;
+ case ChangeBrightness50:
+ setWindowProperty (m_wid, Atoms::brightness, 0x7fff);
+ break;
+ case ChangeBrightness75:
+ setWindowProperty (m_wid, Atoms::brightness, 0xbfff);
+ break;
+ case ChangeBrightness100:
+ setWindowProperty (m_wid, Atoms::brightness, 0xffff);
+ break;
+ case ChangeSaturation25:
+ setWindowProperty (m_wid, Atoms::saturation, 0x3fff);
+ break;
+ case ChangeSaturation50:
+ setWindowProperty (m_wid, Atoms::saturation, 0x7fff);
+ break;
+ case ChangeSaturation75:
+ setWindowProperty (m_wid, Atoms::saturation, 0xbfff);
+ break;
+ case ChangeSaturation100:
+ setWindowProperty (m_wid, Atoms::saturation, 0xffff);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+Aquamarine::Window::moveWindow (QMouseEvent * qme)
+{
+ if (!qme)
+ return;
+ int
+ direction = WM_MOVERESIZE_MOVE;
+ switch (m_deco->mousePosition (qme->pos ()))
+ {
+
+ case PositionCenter:
+ direction = WM_MOVERESIZE_MOVE;
+ break;
+ case PositionLeft:
+ direction = WM_MOVERESIZE_SIZE_LEFT;
+ break;
+ case PositionRight:
+ direction = WM_MOVERESIZE_SIZE_RIGHT;
+ break;
+ case PositionTop:
+ direction = WM_MOVERESIZE_SIZE_TOP;
+ break;
+ case PositionBottom:
+ direction = WM_MOVERESIZE_SIZE_BOTTOM;
+ break;
+ case PositionTopLeft:
+ direction = WM_MOVERESIZE_SIZE_TOPLEFT;
+ break;
+ case PositionTopRight:
+ direction = WM_MOVERESIZE_SIZE_TOPRIGHT;
+ break;
+ case PositionBottomLeft:
+ direction = WM_MOVERESIZE_SIZE_BOTTOMLEFT;
+ break;
+ case PositionBottomRight:
+ direction = WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
+ break;
+ default:
+ direction = WM_MOVERESIZE_MOVE;
+ break;
+ }
+
+ XEvent
+ ev;
+ ev.xclient.type = ClientMessage;
+ ev.xclient.display = qt_xdisplay ();
+
+ ev.xclient.serial = 0;
+ ev.xclient.send_event = TRUE;
+
+ ev.xclient.window = m_wid;
+ ev.xclient.message_type = Atoms::net_wm_moveresize;
+ ev.xclient.format = 32;
+
+ ev.xclient.data.l[0] = qme->globalX ();
+ ev.xclient.data.l[1] = qme->globalY ();
+ ev.xclient.data.l[2] = direction;
+ ev.xclient.data.l[3] = qme->button ();
+ ev.xclient.data.l[4] = 1;
+
+ XUngrabPointer (qt_xdisplay (), CurrentTime);
+ XUngrabKeyboard (qt_xdisplay (), CurrentTime);
+
+ XSendEvent (qt_xdisplay (), RootWindow (qt_xdisplay (), qt_xscreen ()),
+ FALSE, SubstructureRedirectMask | SubstructureNotifyMask,
+ &ev);
+
+ XSync (qt_xdisplay (), FALSE);
+}
+
+void Aquamarine::Window::slotDesktopGeometryChanged()
+{
+ // force menu regeneration
+ delete m_popup;
+ m_popup = 0;
+}
+
+
+void Aquamarine::Window::performMouseCommand(Options::MouseCommand command, QMouseEvent *qme)
+{
+ switch (command)
+ {
+ case Options::MouseRaise:
+ KWin::raiseWindow (m_wid);
+ break;
+ case Options::MouseLower:
+ KWin::lowerWindow (m_wid);
+ break;
+ case Options::MouseShade :
+ setShade (!isShade ());
+ break;
+ case Options::MouseSetShade:
+ setShade (true);
+ break;
+ case Options::MouseUnsetShade:
+ setShade (false);
+ break;
+ case Options::MouseOperationsMenu:
+ {
+ QPoint mp(0,0);
+ if (qme)
+ mp = QPoint(qme->globalX (), qme->globalY ());
+ showWindowMenu (mp);
+ break;
+ }
+ case Options::MouseMaximize:
+ maximize( KDecoration::MaximizeFull );
+ break;
+ case Options::MouseRestore:
+ maximize( KDecoration::MaximizeRestore );
+ break;
+ case Options::MouseMinimize:
+ minimize();
+ break;
+ case Options::MouseAbove:
+ {
+ if( keepBelow())
+ setKeepBelow( false );
+ else
+ setKeepAbove( true );
+ break;
+ }
+ case Options::MouseBelow:
+ {
+ if( keepAbove())
+ setKeepAbove( false );
+ else
+ setKeepBelow( true );
+ break;
+ }
+ case Options::MousePreviousDesktop:
+ {
+ int vp = Decorator::onViewport (m_geometry.topLeft ());
+ Decorator::moveToViewport (m_wid, vp-1);
+ break;
+ }
+ case Options::MouseNextDesktop:
+ {
+ int vp = Decorator::onViewport (m_geometry.topLeft ());
+ Decorator::moveToViewport (m_wid, vp+1);
+ break;
+ }
+ case Options::MouseOpacityMore:
+ if (m_opacity < 0xFFFF)
+ {
+ if (m_opacity < 0xF333)
+ setWindowProperty (m_wid, Atoms::opacity, m_opacity + 0xCCC);
+ else
+ setWindowProperty (m_wid, Atoms::opacity, 0xFFFF);
+ }
+ break;
+ case Options::MouseOpacityLess:
+ if (m_opacity > 0)
+ setWindowProperty (m_wid, Atoms::opacity, (m_opacity > 0xCCC)? m_opacity - 0xCCC : 0);
+ break;
+ case Options::MouseActivateRaiseAndMove:
+ case Options::MouseActivateRaiseAndUnrestrictedMove:
+ case Options::MouseMove:
+ case Options::MouseUnrestrictedMove:
+ case Options::MouseResize:
+ case Options::MouseUnrestrictedResize:
+ moveWindow (qme);
+ break;
+ case Options::MouseNothing:
+ default:
+ break;
+ }
+}
+
diff --git a/src/window.h b/src/window.h
new file mode 100644
index 0000000..252d425
--- /dev/null
+++ b/src/window.h
@@ -0,0 +1,248 @@
+/*
+ * Aquamarine the KDE window decorator
+ *
+ * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org>
+ * Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+ *
+ * Uses code of:
+ * Emerald window decorator (www.beryl-project.org)
+ * KWin window manager (www.kde.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AQUAMARINE_WINDOW_H
+#define AQUAMARINE_WINDOW_H
+
+#include <kdecoration_p.h>
+
+#include <qpixmap.h>
+#include <qwidget.h>
+
+#include "utils.h"
+#include "options.h"
+
+class KDecoration;
+class QPopupMenu;
+
+namespace Aquamarine
+{
+
+ class Window:public QWidget, public KDecorationBridge
+ {
+ Q_OBJECT public:
+
+ enum DecorationType
+ {
+ DecorationNormal,
+ DecorationDefault,
+ DecorationDefaultActive
+ };
+
+ public:
+ Window (WId wid, WId frame, DecorationType type =
+ DecorationNormal);
+ ~Window ();
+
+ // KDecorationBridge methods
+ virtual bool isActive () const;
+ virtual bool isCloseable () const;
+ virtual bool isMaximizable () const;
+ virtual MaximizeMode maximizeMode () const;
+ virtual bool isMinimizable () const;
+ virtual bool providesContextHelp () const;
+ virtual int desktop () const;
+ virtual bool isModal () const;
+ virtual bool isShadeable () const;
+ virtual bool isShade () const;
+ virtual bool isSetShade () const;
+ virtual bool keepAbove () const;
+ virtual bool keepBelow () const;
+ virtual bool isMovable () const;
+ virtual bool isResizable () const;
+ virtual NET::
+ WindowType windowType (unsigned long supported_types) const;
+ virtual QIconSet icon () const;
+ virtual QString caption () const;
+ virtual void processMousePressEvent (QMouseEvent *);
+ virtual void showWindowMenu (const QRect &);
+ virtual void showWindowMenu (QPoint);
+ virtual void performWindowOperation (WindowOperation);
+ virtual void setMask (const QRegion &, int);
+ virtual bool isPreview () const;
+ virtual QRect geometry () const;
+ virtual QRect iconGeometry () const;
+ virtual QRegion unobscuredRegion (const QRegion & r) const;
+ virtual QWidget *workspaceWidget () const;
+ virtual WId windowId () const;
+ virtual void closeWindow ();
+ virtual void maximize (MaximizeMode mode);
+ virtual void minimize ();
+ virtual void showContextHelp ();
+ virtual void setDesktop (int desktop);
+ virtual void titlebarDblClickOperation ();
+ virtual void titlebarMouseWheelOperation (int delta);
+ virtual void setShade (bool set);
+ virtual void setKeepAbove (bool);
+ virtual void setKeepBelow (bool);
+
+ virtual int currentDesktop () const;
+ virtual QWidget *initialParentWidget () const;
+ virtual Qt::WFlags initialWFlags () const;
+ virtual void helperShowHide (bool);
+ virtual void grabXServer (bool grab);
+
+
+ void setActive (bool active);
+ void updateFrame (WId frame);
+ void updateWindowGeometry ();
+
+ void updateCursor (QPoint pos);
+
+ WId frameId () const
+ {
+ return m_frame;
+ }
+ KDecoration *decoration () const
+ {
+ return m_deco;
+ }
+ QWidget *activeChild () const
+ {
+ return m_activeChild;
+ }
+ void setActiveChild (QWidget * child)
+ {
+ m_activeChild = child;
+ }
+
+ void moveWindow (QMouseEvent * qme);
+
+ void reloadDecoration ();
+
+ void updateState ();
+ void updateName ();
+ void updateIcons ();
+
+ void updateOpacity ()
+ {
+ m_opacity =
+ readWindowPropertyDefault (m_wid, Atoms::opacity, 0xffff);
+ }
+ void updateBrightness ()
+ {
+ m_brightness =
+ readWindowPropertyDefault (m_wid, Atoms::brightness, 0xffff);
+ }
+ void updateSaturation ()
+ {
+ m_saturation =
+ readWindowPropertyDefault (m_wid, Atoms::saturation, 0xffff);
+ }
+
+ protected:
+ virtual bool eventFilter (QObject * watched, QEvent * event);
+
+ private:
+ enum WindowAppearance
+ {
+ ResetValues,
+ ChangeOpacity25,
+ ChangeOpacity50,
+ ChangeOpacity75,
+ ChangeOpacity100,
+ ChangeBrightness25,
+ ChangeBrightness50,
+ ChangeBrightness75,
+ ChangeBrightness100,
+ ChangeSaturation25,
+ ChangeSaturation50,
+ ChangeSaturation75,
+ ChangeSaturation100
+ };
+
+ private:
+ void createDecoration ();
+ void resizeDecoration ( bool force = false );
+ void getWindowProtocols ();
+ void performMouseCommand( Options::MouseCommand, QMouseEvent *qme );
+
+ private slots:
+ void grabChildWidgets ();
+ void updateWindowProperties ();
+ void slotPopupActivated (int id);
+ void slotPopupAboutToShow ();
+ void slotChangeViewport (int id);
+ void slotAppearanceChange (int id);
+ void slotDesktopGeometryChanged ();
+
+ private:
+ WId m_wid;
+ WId m_frame;
+
+ // window properties
+ QRect m_geometry;
+ bool m_active;
+ QString m_name;
+ QIconSet m_icons;
+
+ unsigned short m_opacity;
+ unsigned short m_brightness;
+ unsigned short m_saturation;
+
+ // decoration stuff
+ KDecoration *m_deco;
+ QPixmap m_qpixmap;
+ QPixmap m_pending_pixmap;
+ bool m_fakeMaximized;
+
+ // shape stuff
+ bool m_shapeSet;
+ QRegion m_shape;
+ QRegion m_clip;
+
+ // event handling stuff
+ QWidget *m_activeChild;
+ bool m_grabChildPending;
+ bool m_grabChildInProgress;
+ bool m_updateWindowPending;
+ bool m_grabAllChildren;
+ QValueList<QObject*> m_pendingChildren;
+
+ // window handling
+ bool m_supportDeleteWindow;
+ bool m_supportTakeFocus;
+ bool m_supportTakeActivity;
+ bool m_supportContextHelp;
+ bool m_supportPing;
+
+ DecorationType m_type;
+
+ // window menu
+ QPopupMenu *m_popup;
+ QPopupMenu *m_advanced_popup;
+ QPopupMenu *m_viewport_menu;
+ QPopupMenu *m_appearance_menu;
+ QPopupMenu *m_brightness_menu;
+ QPopupMenu *m_saturation_menu;
+ QPopupMenu *m_opacity_menu;
+
+ unsigned long m_state;
+ };
+
+}
+
+#endif