diff options
author | onestone <onestone> | 2006-10-31 15:26:22 +0000 |
---|---|---|
committer | onestone <onestone> | 2006-10-31 15:26:22 +0000 |
commit | 8fe64cafed0113ca7dc4d75f016c893e1f2ddc15 (patch) | |
tree | 0591dae43ef8ee3cc57bf4a1185ddbe33c36437d /src | |
download | aquamarine-8fe64cafed0113ca7dc4d75f016c893e1f2ddc15.tar.gz aquamarine-8fe64cafed0113ca7dc4d75f016c893e1f2ddc15.tar.bz2 |
Initial import of aquamarine (KDE window decorator)
Diffstat (limited to 'src')
-rw-r--r-- | src/KWinInterface.h | 17 | ||||
-rw-r--r-- | src/Makefile.am | 20 | ||||
-rw-r--r-- | src/aquamarine.cpp | 189 | ||||
-rw-r--r-- | src/decorator.cpp | 740 | ||||
-rw-r--r-- | src/decorator.h | 155 | ||||
-rw-r--r-- | src/options.cpp | 167 | ||||
-rw-r--r-- | src/options.h | 124 | ||||
-rw-r--r-- | src/switcher.cpp | 336 | ||||
-rw-r--r-- | src/switcher.h | 67 | ||||
-rw-r--r-- | src/utils.cpp | 499 | ||||
-rw-r--r-- | src/utils.h | 111 | ||||
-rw-r--r-- | src/window.cpp | 1653 | ||||
-rw-r--r-- | src/window.h | 248 |
13 files changed, 4326 insertions, 0 deletions
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 |