diff options
author | onestone <onestone> | 2007-01-09 15:01:39 +0000 |
---|---|---|
committer | onestone <onestone> | 2007-01-09 15:01:39 +0000 |
commit | 4648e9757d531d51af93cff047243a24a28bf0e6 (patch) | |
tree | 10e32743fe8d668a3252f5a56d79c6194a41ffe2 /src | |
parent | 7d589a6d6bf49f1dcc5bc2f2181dfecba797f412 (diff) | |
download | aquamarine-4648e9757d531d51af93cff047243a24a28bf0e6.tar.gz aquamarine-4648e9757d531d51af93cff047243a24a28bf0e6.tar.bz2 |
aquamarine: ported compiz kwd changes back to aquamarine. (libdeco.* will be removed after libberyldecoration has been updated)
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/aquamarine.cpp | 44 | ||||
-rw-r--r-- | src/decorator.cpp | 1542 | ||||
-rw-r--r-- | src/decorator.h | 249 | ||||
-rw-r--r-- | src/defaultDeco.cpp | 704 | ||||
-rw-r--r-- | src/defaultDeco.h | 127 | ||||
-rw-r--r-- | src/defaultShadow.cpp | 459 | ||||
-rw-r--r-- | src/defaultShadow.h | 66 | ||||
-rw-r--r-- | src/libdeco.c | 2620 | ||||
-rw-r--r-- | src/libdeco.h | 393 | ||||
-rw-r--r-- | src/options.cpp | 168 | ||||
-rw-r--r-- | src/options.h | 174 | ||||
-rw-r--r-- | src/switcher.cpp | 349 | ||||
-rw-r--r-- | src/switcher.h | 68 | ||||
-rw-r--r-- | src/utils.cpp | 532 | ||||
-rw-r--r-- | src/utils.h | 100 | ||||
-rw-r--r-- | src/window.cpp | 3217 | ||||
-rw-r--r-- | src/window.h | 479 |
18 files changed, 6352 insertions, 4947 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index bcfb211..e77ad04 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,15 +8,15 @@ aquamarine_SOURCES = aquamarine.cpp \ utils.cpp \ decorator.cpp \ window.cpp \ - switcher.cpp \ KWinInterface.skel \ options.cpp \ - defaultDeco.cpp \ - defaultShadow.cpp \ - settings.kcfgc + settings.kcfgc \ + libdeco.c +#aquamarine_LDADD = $(LIB_KDECORE) -lkdecorations $(BERYLSETTINGS_LIBS) $(XCOMPOSITE_LIBS) $(DECOLIB_LIBS) aquamarine_LDADD = $(LIB_KDECORE) -lkdecorations $(BERYLSETTINGS_LIBS) $(XCOMPOSITE_LIBS) aquamarine_LDFLAGS = $(all_libraries) +#KDE_CXXFLAGS = $(BERYLSETTINGS_CFLAGS) $(XCOMPOSITE_CFLAGS) $(DECOLIB_CFLAGS) KDE_CXXFLAGS = $(BERYLSETTINGS_CFLAGS) $(XCOMPOSITE_CFLAGS) METASOURCES = AUTO diff --git a/src/aquamarine.cpp b/src/aquamarine.cpp index bcc96e3..2920dc1 100644 --- a/src/aquamarine.cpp +++ b/src/aquamarine.cpp @@ -3,10 +3,9 @@ * * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> * Copyright (c) 2006 Volker Krause <vkrause@kde.org> + * Copyright (c) 2006 David Reveman <davidr@novell.com> * * Uses code of: - * Emerald window decorator (www.beryl-project.org) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) * KWin window manager (www.kde.org) * * This program is free software; you can redistribute it and/or modify @@ -56,7 +55,6 @@ static const KCmdLineOptions options[] = { int main (int argc, char **argv) { - bool argb_visual = false; char *display = 0; Display *dpy = XOpenDisplay (display); int screen = DefaultScreen (dpy); @@ -83,39 +81,6 @@ main (int argc, char **argv) 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 wmRunning = false; do { @@ -173,12 +138,7 @@ main (int argc, char **argv) } } while (!wmRunning); - Aquamarine::Decorator *app = new Aquamarine::Decorator(dpy, Qt::HANDLE (visual), - Qt::HANDLE (colormap)); - - DCOPClient *client = app->dcopClient (); - client->registerAs ("kwin", false); - client->setDefaultObject ("KWinInterface"); + Aquamarine::Decorator *app = new Aquamarine::Decorator(); if (app->isReady ()) { rv = app->exec (); diff --git a/src/decorator.cpp b/src/decorator.cpp index 535684e..7986190 100644 --- a/src/decorator.cpp +++ b/src/decorator.cpp @@ -1,29 +1,28 @@ /* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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. - * - */ +* Aquamarine the KDE window decorator +* +* Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> +* Copyright (c) 2006 Volker Krause <vkrause@kde.org> +* Copyright (c) 2006 David Reveman <davidr@novell.com> +* +* Uses code of: +* 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> @@ -34,11 +33,14 @@ #include <kglobal.h> #include <kwinmodule.h> #include <klocale.h> +#include <kcommondecoration.h> #include <kwin.h> - +#include <qwidgetlist.h> #include <qpoint.h> -#include "switcher.h" +#include <X11/Xlib.h> +#include <X11/extensions/Xcomposite.h> + #include "decorator.h" #include "options.h" #include "utils.h" @@ -46,755 +48,949 @@ #include <stdio.h> -#ifdef HAVE_BERYL_SETTINGS +decor_context_t Aquamarine::Decorator::mDefaultContext; +decor_shadow_t *Aquamarine::Decorator::mNoBorderShadow = 0; +decor_shadow_t *Aquamarine::Decorator::mDefaultShadow = 0; +Aquamarine::PluginManager *Aquamarine::Decorator::mPlugins = 0; +Aquamarine::Options *Aquamarine::Decorator::mOptions = 0; +NETRootInfo *Aquamarine::Decorator::mRootInfo; +WId Aquamarine::Decorator::mActiveId; +decor_shadow_options_t Aquamarine::Decorator::mShadowOptions; + +QSize Aquamarine::Decorator::mDesktop; +QPoint Aquamarine::Decorator::mViewport; +QSize Aquamarine::Decorator::mRootSize; -extern "C" { -#include <beryl-settings.h> -} -#endif - -#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)} +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::PluginManager::PluginManager (KConfig * config): -KDecorationPlugins (config) +Aquamarine::Decorator::Decorator (void) : DCOPObject ("KWinInterface"), + KApplication (), + mConfig (0), + mKWinModule (new KWinModule (this, KWinModule::INFO_ALL)), + mCompositeWindow (0) { - // taken from KWin - defaultPlugin = - (QPixmap::defaultDepth () > 8) ? "kwin3_plastik" : "kwin3_quartz"; + KGlobal::locale()->insertCatalogue("kdelibs"); + KGlobal::locale()->setActiveCatalogue("aquamarine"); + + mReady = false; + mRestart = false; + + int event, error; + + DCOPClient *client; + int i, j; + + mRootInfo = new NETRootInfo (qt_xdisplay (), 0); + + mActiveId = 0; + + Atoms::init (); + + if (!XDamageQueryExtension (qt_xdisplay (), &event, &error)) + { + fprintf (stderr, "Damage extension is missing on display \"%s\"\n", + DisplayString (qt_xdisplay ())); + return; + } + + mActiveWM = XGetSelectionOwner(qt_xdisplay(),Atoms::wmSn); + if (mActiveWM == None) + return; + XSelectInput (qt_xdisplay(), mActiveWM, StructureNotifyMask); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs (); + + Time timestamp; + int status = decor_acquire_dm_session (qt_xdisplay (), 0, "Aquamarine", + args->isSet ("replace"),×tamp); + + if (status != DECOR_ACQUIRE_STATUS_SUCCESS) + { + if (status == DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING) + { + fprintf (stderr, + "Could not acquire decoration manager " + "selection on screen %d display \"%s\"\n", + 0, DisplayString (qt_xdisplay ())); + } + else if (status == DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING) + { + fprintf (stderr, + "Screen %d on display \"%s\" already " + "has a decoration manager; try using the " + "--replace option to replace the current " + "decoration manager.\n", + 0, DisplayString (qt_xdisplay ())); + } + return; + } + + decor_set_dm_check_hint (qt_xdisplay (), 0); + + mConfig = new KConfig ("kwinrc"); + mConfig->setGroup ("Style"); + + mOptions = new Aquamarine::Options (mConfig); + mPlugins = new PluginManager (mConfig); + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if (cursors[i][j].shape != XC_left_ptr) + cursors[i][j].cursor = + XCreateFontCursor (qt_xdisplay (), cursors[i][j].shape); + } + } + + client = dcopClient (); + client->registerAs ("kwin", false); + client->setDefaultObject ("KWinInterface"); + + mShadowOptions.shadow_radius = (Settings::drawShadows())? + Settings::shadowRadius():0; + mShadowOptions.shadow_opacity = Settings::shadowOpacity() / 100.0; + mShadowOptions.shadow_offset_x = Settings::shadowOffsetX(); + mShadowOptions.shadow_offset_y = Settings::shadowOffsetY(); + mShadowOptions.shadow_color[0] = Settings::shadowColor().red() * 0x101; + mShadowOptions.shadow_color[1] = Settings::shadowColor().green() * 0x101; + mShadowOptions.shadow_color[2] = Settings::shadowColor().blue() * 0x101; + mShadowOptions.shadow_color[3] = 0xffff; + + mCompositeWindow = new QWidget (0, "AquamarineCompositeWidget", + Qt::WType_TopLevel | Qt::WStyle_NoBorder | + Qt::WX11BypassWM); + + mCompositeWindow->setGeometry (QRect (-ROOT_OFF_X, -ROOT_OFF_Y, 1, 1)); + mCompositeWindow->show (); + + XCompositeRedirectSubwindows (qt_xdisplay (), mCompositeWindow->winId (), + CompositeRedirectManual); + + if (!enableDecorations (timestamp, event)) + { + fprintf (stderr, "Could not enable decorations on display \"%s\"\n", + DisplayString (qt_xdisplay ())); + return; + } + + updateDesktopGeometry (); + + mReady = true; } +Aquamarine::Decorator::~Decorator (void) +{ + QMap <WId, Aquamarine::Window *>::ConstIterator it; + + for (it = mClients.begin (); it != mClients.end (); it++) + delete (*it); + + if (mDecorNormal) + delete mDecorNormal; + if (mDecorActive) + delete mDecorActive; -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) + /* XXX: mCompositeWindow is not deleted, some plugins seem to rely on + it not being deleted... not sure what to do about this. */ + + delete mOptions; + delete mPlugins; + delete mConfig; + delete mKWinModule; + delete mRootInfo; +} + +bool Aquamarine::Decorator::enableDecorations (Time timestamp, int damageEvent) { -// delete KGlobal::_locale; -// KGlobal::_locale = new KLocale( "kwin" , NULL ); -// KGlobal::locale()->insertCatalogue("aquamarine"); - KGlobal::locale()->insertCatalogue("kdelibs"); - KGlobal::locale()->setActiveCatalogue("aquamarine"); + QValueList <WId>::ConstIterator it; + + mDmSnTimestamp = timestamp; + mDamageEvent = damageEvent; + + if (!pluginManager ()->loadPlugin ("")) + return false; + + updateShadow (); - 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"); - - connect (this, SIGNAL (settingsChanged (int)), - SLOT (slotSettingsChanged (int))); - - 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::DefaultDecoration (false); - m_defDecoActive = new Aquamarine::DefaultDecoration (true); - m_defShadow = (Settings::drawShadows())? new Aquamarine::DefaultShadow () : NULL; - - 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()) ); + mDecorNormal = new Aquamarine::Window (mCompositeWindow, qt_xrootwin (), + 0, Window::Default); + mDecorActive = new Aquamarine::Window (mCompositeWindow, qt_xrootwin (), + 0, Window::DefaultActive); + + connect (mKWinModule, SIGNAL (windowAdded (WId)), + SLOT (handleWindowAdded (WId))); + connect (mKWinModule, SIGNAL (windowRemoved (WId)), + SLOT (handleWindowRemoved (WId))); + connect (mKWinModule, SIGNAL (activeWindowChanged (WId)), + SLOT (handleActiveWindowChanged (WId))); + connect (mKWinModule, SIGNAL (windowChanged (WId, const unsigned long *)), + SLOT (handleWindowChanged (WId, const unsigned long *))); + + connect (&mIdleTimer, SIGNAL (timeout ()), SLOT (processDamage ())); + + mActiveId = mKWinModule->activeWindow (); + + it = mKWinModule->windows ().begin (); + for (; it != mKWinModule->windows ().end (); it++) + handleWindowAdded ((*it)); + + connect (this, SIGNAL (appearanceChanged ()), SLOT (reconfigure ())); (void) QApplication::desktop (); // trigger creation of desktop widget // select for client messages XSelectInput (qt_xdisplay(), qt_xrootwin (), - StructureNotifyMask | PropertyChangeMask); + StructureNotifyMask | PropertyChangeMask); + + return true; +} + +void Aquamarine::Decorator::updateDefaultShadow (Aquamarine::Window *w) +{ + bool uniqueHorzShape, uniqueVertShape; + + if (mDefaultShadow) + { + decor_shadow_destroy (qt_xdisplay (), mDefaultShadow); + mDefaultShadow = NULL; + } + + w->getShapeInfo (&uniqueHorzShape, &uniqueVertShape); + + /* only return shadow if decoration doesn't use a unique shape */ + if (uniqueHorzShape || uniqueVertShape) + return; + + mDefaultContext = *w->context (); + mDefaultShadow = w->shadow (); + + if (mDefaultShadow) + decor_shadow_reference (mDefaultShadow); +} + +void Aquamarine::Decorator::updateAllShadowOptions (void) +{ + mShadowOptions.shadow_radius = (Settings::drawShadows())? + Settings::shadowRadius():0; + mShadowOptions.shadow_opacity = Settings::shadowOpacity() / 100.0; + mShadowOptions.shadow_offset_x = Settings::shadowOffsetX(); + mShadowOptions.shadow_offset_y = Settings::shadowOffsetY(); + mShadowOptions.shadow_color[0] = Settings::shadowColor().red() * 0x101; + mShadowOptions.shadow_color[1] = Settings::shadowColor().green() * 0x101; + mShadowOptions.shadow_color[2] = Settings::shadowColor().blue() * 0x101; } -Aquamarine::Decorator::~Decorator () +void Aquamarine::Decorator::updateShadow (void) { - 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_defShadow; - 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; + Display *xdisplay = qt_xdisplay (); + Screen *xscreen = ScreenOfDisplay (xdisplay, qt_xscreen ()); + decor_context_t context; + + if (mDefaultShadow) + { + decor_shadow_destroy (xdisplay, mDefaultShadow); + mDefaultShadow = NULL; + } + + if (mNoBorderShadow) + decor_shadow_destroy (xdisplay, mNoBorderShadow); + + mNoBorderShadow = decor_shadow_create (xdisplay, + xscreen, + 1, 1, + 0, + 0, + 0, + 0, + 0, 0, 0, 0, + &mShadowOptions, + &context, + decor_draw_simple, + 0); + + if (mNoBorderShadow) + { + decor_extents_t extents = { 0, 0, 0, 0 }; + long data[256]; + decor_quad_t quads[N_QUADS_MAX]; + int nQuad; + decor_layout_t layout; + + decor_get_default_layout (&context, 1, 1, &layout); + + nQuad = decor_set_lSrStSbS_window_quads (quads, &context, &layout); + + decor_quads_to_property (data, mNoBorderShadow->pixmap, + &extents, &extents, + 0, 0, quads, nQuad); + + Aquamarine::trapXError (); + XChangeProperty (qt_xdisplay (), qt_xrootwin (), + Atoms::netWindowDecorBare, + XA_INTEGER, + 32, PropModeReplace, (unsigned char *) data, + BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad); + Aquamarine::popXError (); + } } -bool -Aquamarine::Decorator::x11EventFilter (XEvent * xevent) +void Aquamarine::Decorator::processDamage (void) { - WId - xid = 0; + QMap <WId, Aquamarine::Window *>::ConstIterator it; + mDecorNormal->processDamage (); + mDecorActive->processDamage (); - switch (xevent->type) - { + for (it = mClients.constBegin (); it != mClients.constEnd (); it++) + it.data ()->processDamage (); +} + +bool Aquamarine::Decorator::x11EventFilter (XEvent *xevent) +{ + Aquamarine::Window *client; + int status; + + switch (xevent->type) { case MapNotify: { - Aquamarine::Window * client = 0; - if (m_frames.contains (xevent->xmap.window)) - client = m_frames[xevent->xmap.window]; - if (!client) - break; - client->setMapping(true); + XMapEvent *xme = reinterpret_cast <XMapEvent *> (xevent); + + if (mWindows.contains (xme->window)) + client = mWindows[xme->window]; + else if (mDecorNormal->winId () == xme->window) + client = mDecorNormal; + else if (mDecorActive->winId () == xme->window) + client = mDecorActive; + else + break; + + if (client->handleMap ()) + { + if (!mIdleTimer.isActive ()) + mIdleTimer.start (0, TRUE); + } break; } - case UnmapNotify: + case ConfigureNotify: { - Aquamarine::Window * client = 0; - if (m_frames.contains (xevent->xunmap.window)) - client = m_frames[xevent->xunmap.window]; - if (!client) - break; - client->setMapping(false); + XConfigureEvent *xce = reinterpret_cast <XConfigureEvent *> (xevent); + + if (mFrames.contains (xce->window)) + mFrames[xce->window]->updateFrame (xce->window); + + if (mWindows.contains (xce->window)) + client = mWindows[xce->window]; + else if (mDecorNormal->winId () == xce->window) + client = mDecorNormal; + else if (mDecorActive->winId () == xce->window) + client = mDecorActive; + else + break; + + if (client->handleConfigure ()) + { + if (!mIdleTimer.isActive ()) + mIdleTimer.start (0, TRUE); + } break; } - 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; - 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; - 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) + case DestroyNotify: + if (xevent->xdestroywindow.window == mActiveWM) { - QMap < WId, Aquamarine::Window * >::ConstIterator it; - for (it = m_windows.begin (); - it != m_windows.end (); ++it) - { - if ((*it)->decoration()->widget()->handle() == xme->window) - client = (*it); - } + mRestart = true; + KApplication::exit(0); } - if (!client) - break; - client->updateCursor (QPoint (xme->x, xme->y)); - break; - } - case ClientMessage: - if (xevent->xclient.message_type == Atoms::toolkitActionAtom) - { - long action; - - action = xevent->xclient.data.l[0]; - if ((Atom)action == Atoms::toolkitActionWindowMenuAtom) + break; + case SelectionRequest: + decor_handle_selection_request (qt_xdisplay (), xevent, mDmSnTimestamp); + break; + case SelectionClear: + status = decor_handle_selection_clear (qt_xdisplay (), + xevent, 0); + if (status == DECOR_SELECTION_GIVE_UP) + KApplication::exit (0); + break; + case PropertyNotify: + if (xevent->xproperty.atom == Atoms::netFrameWindow) { - if (m_windows.contains (xevent->xclient.window)) + handleWindowAdded (xevent->xproperty.window); + } + else if (xevent->xproperty.atom == Atoms::switchSelectWindow) { - QPoint pos; - - Aquamarine::Window * client = m_windows[xevent->xclient.window]; - - if (xevent->xclient.data.l[2]) + if (!mClients.contains (xevent->xproperty.window)) { - pos = QPoint (xevent->xclient.data.l[3], - xevent->xclient.data.l[4]); + handleWindowAdded (xevent->xproperty.window); } else { - pos = client->geometry ().topLeft (); - } + WId id; - client->showWindowMenu (pos); + if (Aquamarine::readWindowProperty (xevent->xproperty.window, + Atoms::switchSelectWindow, + (long *) &id)) + mClients[xevent->xproperty.window]->updateSelected (id); + } } + else if (xevent->xproperty.atom == Atoms::netWmWindowOpacity) + { + if (mClients.contains (xevent->xproperty.window)) + mClients[xevent->xproperty.window]->updateOpacity (); } - else if ((Atom)action == Atoms::toolkitActionMainMenuAtom) + else if (xevent->xproperty.atom == Atoms::netWmWindowBrightness) { - dcopClient ()->send ("kicker", - "kicker", - "showKMenu()", - QByteArray ()); + if (mClients.contains (xevent->xproperty.window)) + mClients[xevent->xproperty.window]->updateBrightness (); } - else if ((Atom)action == Atoms::toolkitActionRunDialogAtom) + else if (xevent->xproperty.atom == Atoms::netWmWindowSaturation) { - dcopClient ()->send ("kdesktop", - "KDesktopIface", - "popupExecuteCommand()", - QByteArray ()); + if (mClients.contains (xevent->xproperty.window)) + mClients[xevent->xproperty.window]->updateSaturation (); } - else if ((Atom)action == Atoms::toolkitActionForceQuitDialogAtom) + else if (xevent->xproperty.atom == Atoms::netDesktopGeometry + || xevent->xproperty.atom == Atoms::netDesktopViewport) { - if (m_windows.contains (xevent->xclient.window)) + updateDesktopGeometry (); + } + break; + case EnterNotify: + { + XCrossingEvent *xce = reinterpret_cast <XCrossingEvent *> (xevent); + QWidget *widget, *child; + + if (!mFrames.contains (xce->window)) + break; + + client = mFrames[xce->window]; + + widget = client->decoration ()->widget (); + child = widget->childAt (xce->x, xce->y, true); + if (child) { - Time timestamp = xevent->xclient.data.l[1]; + QEvent qe (QEvent::Enter); - Aquamarine::Window * client = m_windows[xevent->xclient.window]; + QApplication::sendEvent (child, &qe); - if (xevent->xclient.data.l[2]) - client->showKillProcessDialog (timestamp); - else - client->hideKillProcessDialog (); + client->setActiveChild (child); + client->updateCursor (QPoint (xce->x, xce->y)); } + break; + } + case LeaveNotify: + { + XCrossingEvent *xce = reinterpret_cast <XCrossingEvent *> (xevent); + + if (mFrames.contains (xce->window)) + { + QEvent qe (QEvent::Leave); + + client = mFrames[xce->window]; + + QApplication::sendEvent (client->activeChild (), &qe); + + XUndefineCursor (qt_xdisplay (), client->frameId ()); } + break; } + case MotionNotify: + { + XMotionEvent *xme = reinterpret_cast < XMotionEvent * >(xevent); + QWidget *widget, *child; + + if (!mFrames.contains (xme->window)) + break; + + client = mFrames[xme->window]; + + widget = client->decoration ()->widget (); + child = widget->childAt (xme->x, xme->y, true); + if (child) + { + QPoint qp (xme->x, xme->y); + + 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); + } + + 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); + QWidget *widget, *child; + + if (!mFrames.contains (xbe->window)) + break; + + client = mFrames[xbe->window]; + + widget = client->decoration ()->widget (); + child = widget->childAt (xbe->x, xbe->y, true); + + if (child) + { + XButtonEvent xbe2 = *xbe; + + 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; + } + break; + } + case ClientMessage: + if (xevent->xclient.message_type == Atoms::toolkitActionAtom) + { + unsigned long action; + + action = xevent->xclient.data.l[0]; + if (action == Atoms::toolkitActionWindowMenuAtom) + { + if (mClients.contains (xevent->xclient.window)) + { + QPoint pos; + + client = mClients[xevent->xclient.window]; + + if (xevent->xclient.data.l[2]) + { + pos = QPoint (xevent->xclient.data.l[3], + xevent->xclient.data.l[4]); + } + else + { + pos = client->clientGeometry ().topLeft (); + } + + client->showWindowMenu (pos); + } + } + else if (action == Atoms::toolkitActionMainMenuAtom) + { + dcopClient ()->send ("kicker", + "kicker", + "showKMenu()", + QByteArray ()); + } + else if (action == Atoms::toolkitActionRunDialogAtom) + { + dcopClient ()->send ("kdesktop", + "KDesktopIface", + "popupExecuteCommand()", + QByteArray ()); + } + else if (action == Atoms::toolkitActionForceQuitDialogAtom) + { + if (mClients.contains (xevent->xclient.window)) + { + Time timestamp = xevent->xclient.data.l[1]; + + client = mClients[xevent->xclient.window]; + + if (xevent->xclient.data.l[2]) + client->showKillProcessDialog (timestamp); + else + client->hideKillProcessDialog (); + } + } + } + break; + default: + if (xevent->type == mDamageEvent + XDamageNotify) + { + XDamageNotifyEvent *xde = + reinterpret_cast <XDamageNotifyEvent *>(xevent); + + if (mWindows.contains (xde->drawable)) + client = mWindows[xde->drawable]; + else if (mDecorNormal->winId () == xde->drawable) + client = mDecorNormal; + else if (mDecorActive->winId () == xde->drawable) + client = mDecorActive; + else + break; + + client->addDamageRect (xde->area.x, + xde->area.y, + xde->area.width, + xde->area.height); + + if (client->pixmapId ()) + { + if (!mIdleTimer.isActive ()) + mIdleTimer.start (0, TRUE); + } + + return true; + } break; - 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; + return KApplication::x11EventFilter (xevent); } void -Aquamarine::Decorator::reconfigure () +Aquamarine::Decorator::reconfigure (void) { - kdDebug () << k_funcinfo << endl; + unsigned long changed; Settings::self()->config()->reparseConfiguration(); Settings::self()->readConfig(); - m_config->reparseConfiguration (); - unsigned long changed = m_options->updateSettings (); + updateAllShadowOptions(); - for (QMap < WId, Aquamarine::Window * >::ConstIterator it = - m_windows.constBegin (); it != m_windows.constEnd (); ++it) - it.data ()->updateConfig (); + mConfig->reparseConfiguration (); + changed = mOptions->updateSettings (); - if (m_defShadow) - delete m_defShadow; - m_defShadow = (Settings::drawShadows())? new Aquamarine::DefaultShadow () : NULL; + updateShadow (); -#ifdef HAVE_BERYL_SETTINGS - beryl_settings_send_reload_signal(); -#endif + if (mPlugins->reset (changed)) + { + QMap < WId, Aquamarine::Window * >::ConstIterator it; - 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 (); - } -} + mDecorNormal->reloadDecoration (); + mDecorActive->reloadDecoration (); -void -Aquamarine::Decorator::slotSettingsChanged (int) -{ - kdDebug () << k_funcinfo << endl; -#ifdef HAVE_BERYL_SETTINGS - beryl_settings_send_reload_signal(); -#endif + for (it = mClients.constBegin (); it != mClients.constEnd (); it++) + it.data ()->reloadDecoration (); + + mPlugins->destroyPreviousPlugin (); + } + else + { + QMap < WId, Aquamarine::Window * >::ConstIterator it; + + mDecorNormal->updateShadow (); + mDecorActive->updateShadow (); + + for (it = mClients.constBegin (); it != mClients.constEnd (); it++) + it.data ()->updateShadow (); + } } void -Aquamarine::Decorator::slotWindowAdded (WId id) +Aquamarine::Decorator::handleWindowAdded (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; - } - } - - KWin::WindowInfo wInfo = KWin::windowInfo (id, NET::WMWindowType, 0); - - switch (wInfo.windowType (~0)) { - case NET::Normal: - case NET::Dialog: - case NET::Toolbar: - case NET::Menu: - case NET::Utility: - case NET::Splash: - /* decorate these window types */ - break; - default: - return; + QMap <WId, Aquamarine::Window *>::ConstIterator it; + Aquamarine::Window *client = 0; + WId select, frame = 0; + Aquamarine::Window::Type type; + unsigned int width, height, border, depth; + int x, y; + XID root; + QWidgetList *widgets; + + /* avoid adding any of our own top level windows */ + widgets = QApplication::topLevelWidgets (); + if (widgets) + { + for (QWidgetListIt it (*widgets); it.current (); ++it) + { + if (it.current ()->winId () == id) + { + delete widgets; + return; + } + } + + delete widgets; } + Aquamarine::trapXError (); + XGetGeometry (qt_xdisplay (), id, &root, &x, &y, &width, &height, + &border, &depth); + if (Aquamarine::popXError ()) + return; + + Aquamarine::readWindowProperty (id, Atoms::netFrameWindow, (long *) &frame); + if (Aquamarine::readWindowProperty (id, Atoms::switchSelectWindow, + (long *) &select)) + { + type = Aquamarine::Window::Switcher; + } + else + { + KWin::WindowInfo wInfo = KWin::windowInfo (id, NET::WMWindowType, 0); + + switch (wInfo.windowType (~0)) { + case NET::Normal: + case NET::Dialog: + case NET::Toolbar: + case NET::Menu: + case NET::Utility: + case NET::Splash: + case NET::Unknown: + /* decorate these window types */ + break; + default: + return; + } + + type = Aquamarine::Window::Normal; + } + + Aquamarine::trapXError (); + XSelectInput (qt_xdisplay (), id, StructureNotifyMask | PropertyChangeMask); + Aquamarine::popXError (); + 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; - } - } + { + if (!mClients.contains (id)) + { + client = new Aquamarine::Window (mCompositeWindow, id, frame, type, + x, y, + width + border * 2, + height + border * 2); + connect( this, SIGNAL(desktopGeometryChanged()), client, + SLOT(handleDesktopGeometryChanged()) ); + + mClients.insert (id, client); + mWindows.insert (client->winId (), client); + mFrames.insert (frame, client); + } + else + { + client = mClients[id]; + mFrames.remove (client->frameId ()); + mFrames.insert (frame, client); + + client->updateFrame (frame); + } + } + else if (type == Aquamarine::Window::Switcher) + { + if (!mClients.contains (id)) + { + client = new Aquamarine::Window (mCompositeWindow, id, 0, type, + x, y, + width + border * 2, + height + border * 2); + mClients.insert (id, client); + mWindows.insert (client->winId (), client); + } + } + else + { + if (mClients.contains (id)) + client = mClients[id]; + + if (client) + { + mClients.remove (client->windowId ()); + mWindows.remove (client->winId ()); + mFrames.remove (client->frameId ()); + + delete client; + } + } } void -Aquamarine::Decorator::slotWindowRemoved (WId id) +Aquamarine::Decorator::handleWindowRemoved (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; - } + Aquamarine::Window *window = 0; + + if (mClients.contains (id)) + window = mClients[id]; + else if (mFrames.contains (id)) + window = mFrames[id]; + + if (window) + { + mClients.remove (window->windowId ()); + mWindows.remove (window->winId ()); + mFrames.remove (window->frameId ()); + + delete window; + } } void -Aquamarine::Decorator::slotActiveWindowChanged (WId id) +Aquamarine::Decorator::handleActiveWindowChanged (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; + if (id != mActiveId) + { + Aquamarine::Window *newActiveWindow = 0; + Aquamarine::Window *oldActiveWindow = 0; + + if (mClients.contains (id)) + newActiveWindow = mClients[id]; + + if (mClients.contains (mActiveId)) + oldActiveWindow = mClients[mActiveId]; + + mActiveId = id; + + if (oldActiveWindow) + oldActiveWindow->handleActiveChange (); + + if (newActiveWindow) + newActiveWindow->handleActiveChange (); + } } void -Aquamarine::Decorator::slotWindowChanged (WId id, - const unsigned long *properties) +Aquamarine::Decorator::handleWindowChanged (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 (); - } + Aquamarine::Window *client; + + if (!mClients.contains (id)) + return; + + client = mClients[id]; + + if (properties[0] & NET::WMName) + client->updateName (); + if (properties[0] & NET::WMState) + client->updateState (); + if (properties[0] & NET::WMIcon) + client->updateIcons (); + if (properties[0] & NET::WMGeometry) + client->updateWindowGeometry (); } void -Aquamarine::Decorator::sendClientMessage (WId w, Atom a, Atom protocol, - long data1, long data2, long data3) +Aquamarine::Decorator::sendClientMessage (WId eventWid, + WId wid, + Atom atom, + Atom value, + 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); + XEvent ev; + long mask = 0; + + memset (&ev, 0, sizeof (ev)); + + ev.xclient.type = ClientMessage; + ev.xclient.window = wid; + ev.xclient.message_type = atom; + ev.xclient.format = 32; + + ev.xclient.data.l[0] = value; + 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; + + if (eventWid == qt_xrootwin ()) + mask = SubstructureRedirectMask | SubstructureNotifyMask; + + Aquamarine::trapXError (); + XSendEvent (qt_xdisplay (), eventWid, false, mask, &ev); + Aquamarine::popXError (); } -void -Aquamarine::Decorator::updateDesktopGeometry () +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 x, y; + unsigned int width, height, border, depth; + ::Window root; + XGetGeometry (qt_xdisplay (), qt_xrootwin (), &root, &x, &y, &width, + &height, &border, &depth); + mRootSize = QSize (width, height); + + int num_val; + void *values = readXProperty (qt_xrootwin (), Atoms::netDesktopGeometry, + XA_CARDINAL, &num_val); + + if (values) + { + unsigned long * + val = (unsigned long *)values; + mDesktop = QSize (val[0], val[1]); + XFree (val); + } + else + { + mDesktop = QSize (mRootSize.width (), mRootSize.height ()); + } + values = readXProperty (qt_xrootwin (), Atoms::netDesktopViewport, + XA_CARDINAL, &num_val); + + if (values) + { + unsigned long *val = (unsigned long *)values; + mViewport = QPoint (val[0], val[1]); + XFree (val); + } + else + { + mViewport = QPoint (0, 0); + } + + emit desktopGeometryChanged(); } -int -Aquamarine::Decorator::onViewport (QPoint pos) + +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; + return (((pos.y () + + mViewport.y ()) / mRootSize.height ()) * (mDesktop.width () / + mRootSize. + width ())) + + ((pos.x () + mViewport.x ()) / mRootSize.width ()) + 1; } -QSize -Aquamarine::Decorator::viewports () +QSize Aquamarine::Decorator::viewports () { - return QSize ((m_desktop.width () / m_rootSize.width ()), - (m_desktop.height () / m_rootSize.height ())); + return QSize ((mDesktop.width () / mRootSize.width ()), + (mDesktop.height () / mRootSize.height ())); } -void -Aquamarine::Decorator::moveToViewport (WId id, int vp) +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 ()); + 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+= (mDesktop.width () / mRootSize.width ()) * (mDesktop.height () / mRootSize.height ()); + vp = ((vp - 1) % ((mDesktop.width () / mRootSize.width ()) * (mDesktop.height () / mRootSize.height ()))) + 1; + int offsetX = mRootSize.width () * ((vp - 1) % viewports ().width ()); + int offsetY = mRootSize.height () * ((vp - 1) / viewports ().width ()); + XMoveWindow (qt_xdisplay (), id, x + offsetX - mViewport.x (), + y + offsetY - mViewport.y ()); } diff --git a/src/decorator.h b/src/decorator.h index a3a3c76..646c773 100644 --- a/src/decorator.h +++ b/src/decorator.h @@ -3,10 +3,9 @@ * * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> * Copyright (c) 2006 Volker Krause <vkrause@kde.org> + * Copyright (c) 2006 David Reveman <davidr@novell.com> * * Uses code of: - * Emerald window decorator (www.beryl-project.org) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) * KWin window manager (www.kde.org) * * This program is free software; you can redistribute it and/or modify @@ -25,12 +24,8 @@ * */ -#ifndef AQUAMARINE_DECORATOR_H -#define AQUAMARINE_DECORATOR_H - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif +#ifndef _DECORATOR_H +#define _DECORATOR_H #include <kapplication.h> @@ -38,132 +33,166 @@ #include <X11/Xatom.h> #include <X11/cursorfont.h> +#include <qtimer.h> + #include <fixx11h.h> #include <kconfig.h> #include <kdecoration_plugins_p.h> #include <kdecoration_p.h> +#include <netwm.h> + +//#include <beryl-decoration.h> +#include "libdeco.h" #include "window.h" -#include "defaultDeco.h" -#include "defaultShadow.h" #include "KWinInterface.h" -#define C(name) { 0, XC_ ## name } +#define ROOT_OFF_X 8192 +#define ROOT_OFF_Y 8192 -#define DECOR_INTERFACE_VERSION 20061011 +#define C(name) { 0, XC_ ## name } -struct _cursor -{ - Cursor cursor; +struct _cursor { + Cursor cursor; unsigned int shape; }; +extern struct _cursor cursors[3][3]; + 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); - void slotSettingsChanged (int category); - - private: - - bool ready; - - Aquamarine::DefaultDecoration * m_defDeco; - Aquamarine::DefaultDecoration * m_defDecoActive; - Aquamarine::DefaultShadow * m_defShadow; - - 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; + class PluginManager: public KDecorationPlugins + { + public: + PluginManager (KConfig *config); + virtual bool provides (Requirement) + { + return false; + } + }; - static QSize m_desktop; - static QPoint m_viewport; - static QSize m_rootSize; - WId m_activeWM; - bool m_restart; + class Decorator: public KApplication, public KWinInterface + { + Q_OBJECT public: + + Decorator (void); + ~Decorator (void); + + static NETRootInfo *rootInfo (void) + { + return mRootInfo; + } + static PluginManager *pluginManager (void) + { + return mPlugins; + } + static Aquamarine::Options *options (void) + { + return mOptions; + } + static WId activeId (void) + { + return mActiveId; + } + static decor_shadow_options_t *shadowOptions (void) + { + return &mShadowOptions; + } + static decor_shadow_t *defaultWindowShadow (decor_context_t *context) + { + if (!mDefaultShadow) + return NULL; + + *context = mDefaultContext; + return mDefaultShadow; + } + static void sendClientMessage (WId eventWid, + WId wid, + Atom atom, + Atom value, + long data1 = 0, + long data2 = 0, + long data3 = 0); + static void updateDefaultShadow (Aquamarine::Window *w); + + bool enableDecorations (Time timestamp, int damageEvent); + bool x11EventFilter (XEvent *xevent); + + static int onViewport (QPoint pos); + static QSize viewports (); + static void moveToViewport (WId id, int vp); + + bool isReady () + { + return mReady; + } + + bool restart () const + { + return mRestart; + } + + public slots: + + void reconfigure (void); + + signals: + void desktopGeometryChanged(); + + private: + + WId fetchFrame (WId window); + void updateShadow (void); + void updateAllShadowOptions (void); + void updateDesktopGeometry (); + + private slots: + + void handleWindowAdded (WId id); + void handleWindowRemoved (WId id); + void handleActiveWindowChanged (WId id); + void handleWindowChanged (WId id, + const unsigned long *properties); + void processDamage (void); + + private: + + static PluginManager *mPlugins; + static Aquamarine::Options *mOptions; + static decor_context_t mDefaultContext; + static decor_shadow_t *mDefaultShadow; + static decor_shadow_t *mNoBorderShadow; + static decor_shadow_options_t mShadowOptions; + static NETRootInfo *mRootInfo; + static WId mActiveId; + + Aquamarine::Window *mDecorNormal; + Aquamarine::Window *mDecorActive; + QMap <WId, Aquamarine::Window *>mClients; + QMap <WId, Aquamarine::Window *>mFrames; + QMap <WId, Aquamarine::Window *>mWindows; + KConfig *mConfig; + Time mDmSnTimestamp; + int mDamageEvent; + QTimer mIdleTimer; + KWinModule *mKWinModule; + QWidget *mCompositeWindow; + + static QSize mDesktop; + static QPoint mViewport; + static QSize mRootSize; + + WId mActiveWM; + bool mRestart; + bool mReady; }; - } #endif diff --git a/src/defaultDeco.cpp b/src/defaultDeco.cpp deleted file mode 100644 index 3f8bad5..0000000 --- a/src/defaultDeco.cpp +++ /dev/null @@ -1,704 +0,0 @@ -/* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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 "defaultDeco.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::DefaultDecoration::DefaultDecoration (bool active): -m_active (active), -m_deco (0) -{ - - - 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); - - createDecoration (); -} - -Aquamarine::DefaultDecoration::~DefaultDecoration () -{ - delete - m_deco; - - Atom my_atom = XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_NORMAL", FALSE); - if (m_active) - my_atom = XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_ACTIVE", FALSE); - - Aquamarine::trapXError (); - XDeleteProperty (qt_xdisplay (), qt_xrootwin (), my_atom); - Aquamarine::popXError (); -} - - - -bool -Aquamarine::DefaultDecoration::isActive () const -{ - return m_active; -} - -bool -Aquamarine::DefaultDecoration::isCloseable () const -{ - return false; -} - -bool -Aquamarine::DefaultDecoration::isMaximizable () const -{ - return false; -} - -KDecoration::MaximizeMode Aquamarine::DefaultDecoration::maximizeMode () const -{ - return MaximizeRestore; -} - -bool -Aquamarine::DefaultDecoration::isMinimizable () const -{ - return false; -} - -bool -Aquamarine::DefaultDecoration::providesContextHelp () const -{ - return false; -} - -int -Aquamarine::DefaultDecoration::desktop () const -{ - return 1; -} - -bool -Aquamarine::DefaultDecoration::isModal () const -{ - return false; -} - -bool -Aquamarine::DefaultDecoration::isShadeable () const -{ - return false; -} - -bool -Aquamarine::DefaultDecoration::isShade () const -{ - return false; -} - -bool -Aquamarine::DefaultDecoration::isSetShade () const -{ - return isShade (); -} - -bool -Aquamarine::DefaultDecoration::keepAbove () const -{ - return false; -} - -bool -Aquamarine::DefaultDecoration::keepBelow () const -{ - return false; -} - -bool -Aquamarine::DefaultDecoration::isMovable () const -{ - return false; -} - -NET::WindowType Aquamarine::DefaultDecoration::windowType (unsigned long) const -{ - return NET::Normal; -} - -bool -Aquamarine::DefaultDecoration::isResizable () const -{ - return false; -} - -QIconSet -Aquamarine::DefaultDecoration::icon () const -{ - return m_icons; -} - -QString -Aquamarine::DefaultDecoration::caption () const -{ - return m_name; -} - -void -Aquamarine::DefaultDecoration::showWindowMenu (QPoint) -{ -} - -void -Aquamarine::DefaultDecoration::showWindowMenu (const QRect &) -{ -} - -void -Aquamarine::DefaultDecoration::processMousePressEvent (QMouseEvent *) -{ -} - -void -Aquamarine::DefaultDecoration::performWindowOperation (WindowOperation) -{ -} - -void -Aquamarine::DefaultDecoration::setMask (const QRegion &, int) -{ -} - -bool -Aquamarine::DefaultDecoration::isPreview () const -{ - return false; -} - -QRect -Aquamarine::DefaultDecoration::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::DefaultDecoration::iconGeometry () const -{ - return QRect (); -} - -QRegion -Aquamarine::DefaultDecoration::unobscuredRegion (const QRegion & r) const -{ - return r; -} - -QWidget * -Aquamarine::DefaultDecoration::workspaceWidget () const -{ - return 0; -} - -WId -Aquamarine::DefaultDecoration::windowId () const -{ - return qt_xrootwin(); -} - -void -Aquamarine::DefaultDecoration::closeWindow () -{ -} - -void -Aquamarine::DefaultDecoration::maximize (MaximizeMode) -{ -} - -void -Aquamarine::DefaultDecoration::minimize () -{ -} - -void -Aquamarine::DefaultDecoration::showContextHelp () -{ -} - -void -Aquamarine::DefaultDecoration::titlebarDblClickOperation () -{ -} - -void -Aquamarine::DefaultDecoration::setDesktop (int) -{ -} - -void -Aquamarine::DefaultDecoration::setKeepBelow (bool) -{ -} - -void -Aquamarine::DefaultDecoration::setKeepAbove (bool) -{ -} - -void -Aquamarine::DefaultDecoration::setShade (bool) -{ -} - -void -Aquamarine::DefaultDecoration::titlebarMouseWheelOperation (int) -{ -} - -int -Aquamarine::DefaultDecoration::currentDesktop () const -{ - return 1; -} - -QWidget * -Aquamarine::DefaultDecoration::initialParentWidget () const -{ - return const_cast < DefaultDecoration * >(this); -} - -Qt::WFlags Aquamarine::DefaultDecoration::initialWFlags () const -{ - return 0; -} - -void -Aquamarine::DefaultDecoration::helperShowHide (bool) -{ -} - -void -Aquamarine::DefaultDecoration::grabXServer (bool) -{ -} - -void -Aquamarine::DefaultDecoration::createDecoration () -{ - if (m_deco) - return; - KDecoration * - deco = Decorator::pluginManager ()->createDecoration (this); - deco->init (); - m_deco = deco; - - resizeDecoration ( true ); - grabChildWidgets (); - updateWindowProperties (); -} - -void -Aquamarine::DefaultDecoration::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_qpixmap.isNull ()) - m_qpixmap = - QPixmap (m_geometry.width () + left + right, - m_geometry.height () + top + bottom); - else - m_qpixmap.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_qpixmap); - m_deco-> - resize (QSize - (m_geometry.width () + left + right, - m_geometry.height () + top + bottom)); - m_deco->widget ()->setShown (true); - -} - -void -Aquamarine::DefaultDecoration::updateWindowProperties () -{ - Atom my_atom = XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_NORMAL", FALSE); - if (m_active) - my_atom = XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_ACTIVE", FALSE); - - Pixmap m_pixmap = m_qpixmap.handle (); - - int top, bottom, left, right; - 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++ = left; - *data++ = right; - *data++ = top; - *data++ = bottom; - - *data++ = 0; - *data++ = 0; - - // TOP LEFT - *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; - - // TOP RIGHT - *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 LEFT - *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; - - // BOTTOM RIGHT - *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; - - // TOP CENTER - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_NORTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 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_WEST) << 0) | - ((GRAVITY_NORTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_HORZ << 10) | (YY_MASK); - - *data++ = w_w; - *data++ = -top; - *data++ = 0; - *data++ = 0; - *data++ = SHRT_MAX; - *data++ = top; - *data++ = left + w_w; - *data++ = 0; - - // BOTTOM CENTER - *data++ = - ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 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_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_HORZ << 10) | (YY_MASK); - - *data++ = w_w; - *data++ = 0; - *data++ = 0; - *data++ = bottom; - *data++ = SHRT_MAX; - *data++ = bottom; - *data++ = left + w_w; - *data++ = w_h + top; - - //LEFT - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = -left; - *data++ = 0; - *data++ = 0; - *data++ = 0; - *data++ = left; - *data++ = w_h; - *data++ = 0; - *data++ = top; - - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) | - (0 << 8) | (CLAMP_VERT << 10) | (XX_MASK); - - *data++ = -left; - *data++ = w_h; - *data++ = 0; - *data++ = 0; - *data++ = left; - *data++ = SHRT_MAX; - *data++ = 0; - *data++ = top + w_h; - - //RIGHT - *data++ = - ((GRAVITY_NORTH | GRAVITY_EAST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = 0; - *data++ = right; - *data++ = 0; - *data++ = right; - *data++ = w_h; - *data++ = w_w + left; - *data++ = top; - - *data++ = - ((GRAVITY_NORTH | GRAVITY_EAST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_VERT << 10) | (XX_MASK); - - *data++ = 0; - *data++ = w_h; - *data++ = right; - *data++ = 0; - *data++ = right; - *data++ = SHRT_MAX; - *data++ = w_w + left; - *data++ = top + w_h; - - Aquamarine::trapXError (); - XChangeProperty (qt_xdisplay (), qt_xrootwin(), - my_atom, - XA_INTEGER, - 32, PropModeReplace, (unsigned char *)mdata, - 12 + (12 * 9)); - Aquamarine::popXError (); - XSync (qt_xdisplay (), FALSE); -} - -void -Aquamarine::DefaultDecoration::grabChildWidgets () -{ - if (!m_deco) - return; - - QPaintEvent * - e = new QPaintEvent (m_deco->widget ()->rect (), false); - QApplication::sendEvent (m_deco->widget (), e); - - QPainter * p = 0; - - p = new QPainter (&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 ()) - { - QWidget * wid = static_cast < QWidget * >(child); - childs += wid->rect (); - QPixmap pix = QPixmap::grabWidget (wid); - p->drawPixmap (wid->pos (), pix); - } - } - } - delete p; -} - -void -Aquamarine::DefaultDecoration::reloadDecoration () -{ - delete m_deco; - m_deco = 0; - createDecoration (); -} diff --git a/src/defaultDeco.h b/src/defaultDeco.h deleted file mode 100644 index 8b97429..0000000 --- a/src/defaultDeco.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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_DEFAULT_H -#define AQUAMARINE_DEFAULT_H - -#include <kdecoration_p.h> - -#include <qpixmap.h> -#include <qwidget.h> - -#include "utils.h" -#include "options.h" - -class KDecoration; -class QPopupMenu; - -namespace Aquamarine -{ - - class DefaultDecoration:public QWidget, public KDecorationBridge - { - Q_OBJECT public: - - public: - DefaultDecoration (bool active); - ~DefaultDecoration (); - - // 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 reloadDecoration (); - - private: - void createDecoration (); - void resizeDecoration ( bool force = false ); - - private slots: - void grabChildWidgets (); - void updateWindowProperties (); - - private: - - // window properties - QRect m_geometry; - bool m_active; - QString m_name; - QIconSet m_icons; - - // decoration stuff - KDecoration *m_deco; - QPixmap m_qpixmap; - - }; - -} - -#endif diff --git a/src/defaultShadow.cpp b/src/defaultShadow.cpp deleted file mode 100644 index d44b437..0000000 --- a/src/defaultShadow.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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 "defaultShadow.h" -#include "decorator.h" -#include "utils.h" -#include "settings.h" - -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xrender.h> - -#include <math.h> - -#include <fixx11h.h> - -#include <kglobal.h> - -#define BERYL_ADVANCED_DECORATION_VERSION 10121980 - -#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::DefaultShadow::DefaultShadow () -{ - - double op = Settings::shadowOpacity() / 100.0; - op *= 0xffff; - - m_sradius = Settings::shadowRadius(); - QColor color = Settings::shadowColor(); - m_scolor[0] = short((color.red() / 256.0) * 0xffff); - m_scolor[1] = short((color.green() / 256.0) * 0xffff); - m_scolor[2] = short((color.blue() / 256.0) * 0xffff); - m_scolor[3] = short(op); - - // shifted shadows do not work now - /* - int offX = Settings::shadowOffsetX(); - int offY = Settings::shadowOffsetY(); - offX = KMAX(-m_sradius,KMIN(m_sradius,offX)); - offY = KMAX(-m_sradius,KMIN(m_sradius,offY)); - */ - int offX = 0; - int offY = 0; - - m_soffset.setCoords(-m_sradius + offX,-m_sradius + offY, - m_sradius + offX,m_sradius + offY); - - m_qpixmap = QPixmap(20 + m_soffset.width(),20 + m_soffset.height()); - - renderShadow(); - updateWindowProperties(); - -} - -Aquamarine::DefaultShadow::~DefaultShadow () -{ - Aquamarine::trapXError (); - XDeleteProperty (qt_xdisplay (), qt_xrootwin (), - XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_BARE", FALSE)); - Aquamarine::popXError (); -} - - - - -void -Aquamarine::DefaultShadow::updateWindowProperties () -{ - - Pixmap pix = m_qpixmap.handle(); - - int otop = -m_soffset.top(); - int obottom = m_soffset.bottom(); - int oleft = -m_soffset.left(); - int oright = m_soffset.right(); - - int num = 8; - - long mdata[256]; - - long *data = mdata; - - *data++ = BERYL_ADVANCED_DECORATION_VERSION; - - memcpy (data++, &pix, sizeof (pix)); - - *data++ = 0; - *data++ = 0; - *data++ = 0; - *data++ = 0; - - *data++ = 0; - *data++ = 0; - *data++ = 0; - *data++ = 0; - - *data++ = 0; - *data++ = 0; - - *data++ = 0; - *data++ = (unsigned short)((Settings::activeOpacity() / 100.0) * 0xffff); - *data++ = (unsigned short)((Settings::activeOpacity() / 100.0) * 0xffff); - - // TOP LEFT - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_NORTH | GRAVITY_WEST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = -oleft; - *data++ = -otop; - *data++ = 0; - *data++ = 0; - *data++ = oleft; - *data++ = otop; - *data++ = 0; - *data++ = 0; - - // TOP RIGHT - *data++ = - ((GRAVITY_NORTH | GRAVITY_EAST) << 0) | - ((GRAVITY_NORTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = -otop; - *data++ = oright; - *data++ = 0; - *data++ = oright; - *data++ = otop; - *data++ = oleft + 20; - *data++ = 0; - - // BOTTOM LEFT - *data++ = - ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = -oleft; - *data++ = 0; - *data++ = 0; - *data++ = obottom; - *data++ = oleft; - *data++ = obottom; - *data++ = 0; - *data++ = 20 + otop; - - // BOTTOM RIGHT - *data++ = - ((GRAVITY_SOUTH | GRAVITY_EAST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = 0; - *data++ = oright; - *data++ = obottom; - *data++ = oright; - *data++ = obottom; - *data++ = oleft + 20; - *data++ = 20 + otop; - - // TOP CENTER - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_NORTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_HORZ << 10) | (YY_MASK); - - *data++ = 0; - *data++ = -otop; - *data++ = 0; - *data++ = 0; - *data++ = SHRT_MAX; - *data++ = otop; - *data++ = oleft; - *data++ = 0; - - // BOTTOM CENTER - - *data++ = - ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_HORZ << 10) | (YY_MASK); - - *data++ = 0; - *data++ = 0; - *data++ = 0; - *data++ = obottom; - *data++ = SHRT_MAX; - *data++ = obottom; - *data++ = oleft; - *data++ = 20 + otop; - - //LEFT - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) | - (0 << 8) | (CLAMP_VERT << 10) | (XX_MASK); - - *data++ = -oleft; - *data++ = 0; - *data++ = 0; - *data++ = 0; - *data++ = oleft; - *data++ = SHRT_MAX; - *data++ = 0; - *data++ = otop; - - //RIGHT - - *data++ = - ((GRAVITY_NORTH | GRAVITY_EAST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_VERT << 10) | (XX_MASK); - - *data++ = 0; - *data++ = 0; - *data++ = oright; - *data++ = 0; - *data++ = oright; - *data++ = SHRT_MAX; - *data++ = 20 + oleft; - *data++ = otop; - - Aquamarine::trapXError (); - XChangeProperty (qt_xdisplay (), qt_xrootwin (), - XInternAtom (qt_xdisplay (), "_NET_WINDOW_DECOR_BARE", FALSE), - XA_INTEGER, - 32, PropModeReplace, (unsigned char *)mdata, - 15 + (num * 9)); - Aquamarine::popXError (); - XSync (qt_xdisplay (), FALSE); -} - - -#if INT_MAX != LONG_MAX -/* XRenderSetPictureFilter used to be broken on LP64. This - * works with either the broken or fixed version. - */ -static void -XRenderSetPictureFilter_wrapper (Display *dpy, - Picture picture, - char *filter, - XFixed *params, - int nparams) -{ - Aquamarine::trapXError (); - XRenderSetPictureFilter (dpy, picture, filter, params, nparams); - XSync (dpy, False); - if (Aquamarine::popXError ()) - { - long *long_params = new long[nparams]; - int i; - - for (i = 0; i < nparams; i++) - long_params[i] = params[i]; - - XRenderSetPictureFilter (dpy, picture, filter, - (XFixed *) long_params, nparams); - delete long_params; - } -} - -#define XRenderSetPictureFilter XRenderSetPictureFilter_wrapper -#endif - -#define SIGMA(r) ((r) / 2.0) -#define ALPHA(r) (r) - -void Aquamarine::DefaultShadow::renderShadow () -{ - - - QPixmap qRegPix(20, 20, 32); - QPixmap qTmpPix(20 + m_soffset.width(), 20, 32); - qRegPix.fill( QColor(0, ((m_scolor[3] >> 8) << 24) + 0xffffff)); - - XFixed *params; - int n_params = 0; - int size; - - params = createGaussianKernel (&size); - - n_params = size + 2; - size = size / 2; - - params[0] = (n_params - 2) << 16; - params[1] = 1 << 16; - - XRenderPictFormat *format; - format = XRenderFindStandardFormat (qt_xdisplay(), PictStandardARGB32); - - char *filter = NULL; - XFilters* filters = XRenderQueryFilters (qt_xdisplay(), qRegPix.handle()); - if (filters) - { - int i; - - for (i = 0; i < filters->nfilter; i++) - { - if (strcmp (filters->filter[i], FilterConvolution) == 0) - { - filter = (char *) FilterConvolution; - break; - } - } - - XFree (filters); - } - if (!filter) - return; - - static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; - - Picture fill = XRenderCreateSolidFill (qt_xdisplay(), &white); - Picture src = XRenderCreatePicture(qt_xdisplay(), qRegPix.handle(), format, 0, NULL); - Picture tmp = XRenderCreatePicture(qt_xdisplay(), qTmpPix.handle(), format, 0, NULL); - Picture dst = XRenderCreatePicture(qt_xdisplay(), m_qpixmap.handle(), format, 0, NULL); - - setPictureTransform(src,size,0); - XRenderSetPictureFilter (qt_xdisplay(), src, filter, params, n_params); - XRenderComposite (qt_xdisplay(), PictOpSrc, fill, src, tmp, 0, 0, 0, 0, 0, 0, 20 + m_soffset.width(), 20); - - XRenderFreePicture (qt_xdisplay(), fill); - - params[0] = 1 << 16; - params[1] = (n_params - 2) << 16; - - XRenderFreePicture (qt_xdisplay(), src); - XRenderColor color = { m_scolor[0], m_scolor[1], m_scolor[2], 0xffff }; - - src = XRenderCreateSolidFill (qt_xdisplay(), &color); - - setPictureTransform(tmp,0,size); - XRenderSetPictureFilter (qt_xdisplay(), tmp, filter, params, n_params); - - XRenderComposite (qt_xdisplay(), PictOpSrc, src, tmp, dst, 0, 0, 0, 0, 0, 0, 20 + m_soffset.width(), 20 + m_soffset.height()); - - XRenderFreePicture (qt_xdisplay(), src); - XRenderFreePicture (qt_xdisplay(), tmp); - XRenderFreePicture (qt_xdisplay(), dst); - - delete params; -} - -XFixed *Aquamarine::DefaultShadow::createGaussianKernel (int *r_size) -{ - double sigma = m_sradius / 2.0; - double alpha = m_sradius; - double radius = m_sradius; - - XFixed *params; - double *amp, scale, x_scale, fx, sum; - int size, half_size, x, i, n; - - scale = 1.0f / (2.0f * M_PI * sigma * sigma); - half_size = int(alpha + 0.5f); - - if (half_size == 0) - half_size = 1; - - size = half_size * 2 + 1; - x_scale = 2.0f * radius / size; - - if (size < 3) - return NULL; - - n = size; - - amp = new double[n]; - if (!amp) - return NULL; - - n += 2; - - params = new XFixed[n]; - if (!params) - return NULL; - - i = 0; - sum = 0.0f; - - for (x = 0; x < size; x++) - { - fx = x_scale * (x - half_size); - - amp[i] = scale * exp ((-1.0f * (fx * fx)) / (2.0f * sigma * sigma)); - - sum += amp[i]; - - i++; - } - - /* normalize */ - if (sum != 0.0) - sum = 1.0 / sum; - - params[0] = params[1] = 0; - - for (i = 2; i < n; i++) - params[i] = XDoubleToFixed (amp[i - 2] * sum); - - delete amp; - - *r_size = size; - - return params; -} - -void Aquamarine::DefaultShadow::setPictureTransform (Picture p, int dx, int dy) -{ - XTransform transform = { - { - { 1 << 16, 0, -dx << 16 }, - { 0, 1 << 16, -dy << 16 }, - { 0, 0, 1 << 16 }, - } - }; - - XRenderSetPictureTransform (qt_xdisplay(), p, &transform); -} - diff --git a/src/defaultShadow.h b/src/defaultShadow.h deleted file mode 100644 index 45b7d80..0000000 --- a/src/defaultShadow.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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_SHADOW_H -#define AQUAMARINE_SHADOW_H - -#include <qpixmap.h> - -#include <X11/extensions/Xrender.h> - -#include "utils.h" -#include "options.h" - -namespace Aquamarine -{ - - class DefaultShadow - { - - public: - DefaultShadow (); - ~DefaultShadow (); - - private: - void renderShadow (); - void updateWindowProperties (); - XFixed *createGaussianKernel (int *r_size); - void setPictureTransform (Picture p, int dx, int dy); - - private: - - QPixmap m_qpixmap; - - // shadow - QRect m_soffset; - int m_sradius; - short m_scolor[4]; - }; - -} - -#endif diff --git a/src/libdeco.c b/src/libdeco.c new file mode 100644 index 0000000..a5d96e3 --- /dev/null +++ b/src/libdeco.c @@ -0,0 +1,2620 @@ +/* + * Copyright © 2006 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include "libdeco.h" + +#include <X11/Xatom.h> +#include <X11/Xregion.h> + +int +decor_version (void) +{ + return DECOR_INTERFACE_VERSION; +} + +/* + decoration property + ------------------- + + data[0] = version + + data[1] = pixmap + + data[2] = input left + data[3] = input right + data[4] = input top + data[5] = input bottom + + data[6] = input left when maximized + data[7] = input right when maximized + data[8] = input top when maximized + data[9] = input bottom when maximized + + data[10] = min width + data[11] = min height + + flags + + 1st to 4nd bit p1 gravity, 5rd to 8th bit p2 gravity, + 9rd and 10th bit alignment, 11rd and 12th bit clamp, + 13th bit XX, 14th bit XY, 15th bit YX, 16th bit YY. + + data[11 + n * 9 + 1] = flags + data[11 + n * 9 + 2] = p1 x + data[11 + n * 9 + 3] = p1 y + data[11 + n * 9 + 4] = p2 x + data[11 + n * 9 + 5] = p2 y + data[11 + n * 9 + 6] = widthMax + data[11 + n * 9 + 7] = heightMax + data[11 + n * 9 + 8] = x0 + data[11 + n * 9 + 9] = y0 + */ +void +decor_quads_to_property (long *data, + Pixmap pixmap, + decor_extents_t *input, + decor_extents_t *max_input, + int min_width, + int min_height, + decor_quad_t *quad, + int nQuad) +{ + *data++ = DECOR_INTERFACE_VERSION; + + memcpy (data++, &pixmap, sizeof (Pixmap)); + + *data++ = input->left; + *data++ = input->right; + *data++ = input->top; + *data++ = input->bottom; + + *data++ = max_input->left; + *data++ = max_input->right; + *data++ = max_input->top; + *data++ = max_input->bottom; + + *data++ = min_width; + *data++ = min_height; + + while (nQuad--) + { + *data++ = + (quad->p1.gravity << 0) | + (quad->p2.gravity << 4) | + (quad->align << 8) | + (quad->clamp << 10) | + (quad->m.xx ? XX_MASK : 0) | + (quad->m.xy ? XY_MASK : 0) | + (quad->m.yx ? YX_MASK : 0) | + (quad->m.yy ? YY_MASK : 0); + + *data++ = quad->p1.x; + *data++ = quad->p1.y; + *data++ = quad->p2.x; + *data++ = quad->p2.y; + *data++ = quad->max_width; + *data++ = quad->max_height; + *data++ = quad->m.x0; + *data++ = quad->m.y0; + + quad++; + } +} + +int +decor_property_get_version (long *data) +{ + return (int) *data; +} + +int +decor_property_to_quads (long *data, + int size, + Pixmap *pixmap, + decor_extents_t *input, + decor_extents_t *max_input, + int *min_width, + int *min_height, + decor_quad_t *quad) +{ + int i, n, flags; + + if (size < BASE_PROP_SIZE + QUAD_PROP_SIZE) + return 0; + + if (decor_property_get_version (data) != decor_version ()) + return 0; + + data++; + + memcpy (pixmap, data++, sizeof (Pixmap)); + + input->left = *data++; + input->right = *data++; + input->top = *data++; + input->bottom = *data++; + + max_input->left = *data++; + max_input->right = *data++; + max_input->top = *data++; + max_input->bottom = *data++; + + *min_width = *data++; + *min_height = *data++; + + n = (size - BASE_PROP_SIZE) / QUAD_PROP_SIZE; + + for (i = 0; i < n; i++) + { + flags = *data++; + + quad->p1.gravity = (flags >> 0) & 0xf; + quad->p2.gravity = (flags >> 4) & 0xf; + + quad->align = (flags >> 8) & 0x3; + quad->clamp = (flags >> 10) & 0x3; + + quad->m.xx = (flags & XX_MASK) ? 1.0f : 0.0f; + quad->m.xy = (flags & XY_MASK) ? 1.0f : 0.0f; + quad->m.yx = (flags & YX_MASK) ? 1.0f : 0.0f; + quad->m.yy = (flags & YY_MASK) ? 1.0f : 0.0f; + + quad->p1.x = *data++; + quad->p1.y = *data++; + quad->p2.x = *data++; + quad->p2.y = *data++; + + quad->max_width = *data++; + quad->max_height = *data++; + + quad->m.x0 = *data++; + quad->m.y0 = *data++; + + quad++; + } + + return n; +} + +int +decor_set_vert_quad_row (decor_quad_t *q, + int top, + int top_corner, + int bottom, + int bottom_corner, + int left, + int right, + int gravity, + int height, + int splitY, + int splitGravity, + double x0, + double y0, + int rotation) +{ + int nQuad = 0; + + q->p1.x = left; + q->p1.y = -top; + q->p1.gravity = gravity | GRAVITY_NORTH; + q->p2.x = right; + q->p2.y = splitY; + q->p2.gravity = gravity | splitGravity; + q->max_width = SHRT_MAX; + q->max_height = top + top_corner; + q->align = ALIGN_TOP; + q->clamp = CLAMP_VERT; + q->m.x0 = x0; + q->m.y0 = y0; + + if (rotation) + { + q->m.xx = 0.0; + q->m.xy = 1.0; + q->m.yx = 1.0; + q->m.yy = 0.0; + } + else + { + q->m.xx = 1.0; + q->m.xy = 0.0; + q->m.yx = 0.0; + q->m.yy = 1.0; + } + + q++; nQuad++; + + q->p1.x = left; + q->p1.y = top_corner; + q->p1.gravity = gravity | GRAVITY_NORTH; + q->p2.x = right; + q->p2.y = -bottom_corner; + q->p2.gravity = gravity | GRAVITY_SOUTH; + q->max_width = SHRT_MAX; + q->max_height = SHRT_MAX; + q->align = 0; + q->clamp = CLAMP_VERT; + + if (rotation) + { + q->m.xx = 0.0; + q->m.xy = 0.0; + q->m.yx = 1.0; + q->m.yy = 0.0; + q->m.x0 = x0 + top + top_corner; + q->m.y0 = y0; + } + else + { + q->m.xx = 1.0; + q->m.xy = 0.0; + q->m.yx = 0.0; + q->m.yy = 0.0; + q->m.x0 = x0; + q->m.y0 = y0 + top + top_corner; + } + + q++; nQuad++; + + q->p1.x = left; + q->p1.y = splitY; + q->p1.gravity = gravity | splitGravity; + q->p2.x = right; + q->p2.y = bottom; + q->p2.gravity = gravity | GRAVITY_SOUTH; + q->max_width = SHRT_MAX; + q->max_height = bottom_corner + bottom; + q->align = ALIGN_BOTTOM; + q->clamp = CLAMP_VERT; + + if (rotation) + { + q->m.xx = 0.0; + q->m.xy = 1.0; + q->m.yx = 1.0; + q->m.yy = 0.0; + q->m.x0 = x0 + height; + q->m.y0 = y0; + } + else + { + q->m.xx = 1.0; + q->m.xy = 0.0; + q->m.yx = 0.0; + q->m.yy = 1.0; + q->m.x0 = x0; + q->m.y0 = y0 + height; + } + + nQuad++; + + return nQuad; +} + +int +decor_set_horz_quad_line (decor_quad_t *q, + int left, + int left_corner, + int right, + int right_corner, + int top, + int bottom, + int gravity, + int width, + int splitX, + int splitGravity, + double x0, + double y0) +{ + int nQuad = 0; + + q->p1.x = -left; + q->p1.y = top; + q->p1.gravity = gravity | GRAVITY_WEST; + q->p2.x = splitX; + q->p2.y = bottom; + q->p2.gravity = gravity | splitGravity; + q->max_width = left + left_corner; + q->max_height = SHRT_MAX; + q->align = ALIGN_LEFT; + q->clamp = 0; + q->m.xx = 1.0; + q->m.xy = 0.0; + q->m.yx = 0.0; + q->m.yy = 1.0; + q->m.x0 = x0; + q->m.y0 = y0; + + q++; nQuad++; + + q->p1.x = left_corner; + q->p1.y = top; + q->p1.gravity = gravity | GRAVITY_WEST; + q->p2.x = -right_corner; + q->p2.y = bottom; + q->p2.gravity = gravity | GRAVITY_EAST; + q->max_width = SHRT_MAX; + q->max_height = SHRT_MAX; + q->align = 0; + q->clamp = 0; + q->m.xx = 0.0; + q->m.xy = 0.0; + q->m.yx = 0.0; + q->m.yy = 1.0; + q->m.x0 = x0 + left + left_corner; + q->m.y0 = y0; + + q++; nQuad++; + + q->p1.x = splitX; + q->p1.y = top; + q->p1.gravity = gravity | splitGravity; + q->p2.x = right; + q->p2.y = bottom; + q->p2.gravity = gravity | GRAVITY_EAST; + q->max_width = right_corner + right; + q->max_height = SHRT_MAX; + q->align = ALIGN_RIGHT; + q->clamp = 0; + q->m.xx = 1.0; + q->m.xy = 0.0; + q->m.yx = 0.0; + q->m.yy = 1.0; + q->m.x0 = x0 + width; + q->m.y0 = y0; + + nQuad++; + + return nQuad; +} + +int +decor_set_lSrS_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l) +{ + int lh, rh, splitY, n, nQuad = 0; + + splitY = (c->top_corner_space - c->bottom_corner_space) / 2; + + if (l->rotation) + { + lh = l->left.x2 - l->left.x1; + rh = l->right.x2 - l->right.x1; + } + else + { + lh = l->left.y2 - l->left.y1; + rh = l->right.y2 - l->right.y1; + } + + /* left quads */ + n = decor_set_vert_quad_row (q, + 0, + c->top_corner_space, + 0, + c->bottom_corner_space, + -c->left_space, + 0, + GRAVITY_WEST, + lh, + splitY, + 0, + l->left.x1, + l->left.y1, + l->rotation); + + q += n; nQuad += n; + + /* right quads */ + n = decor_set_vert_quad_row (q, + 0, + c->top_corner_space, + 0, + c->bottom_corner_space, + 0, + c->right_space, + GRAVITY_EAST, + rh, + splitY, + 0, + l->right.x1, + l->right.y1, + l->rotation); + + nQuad += n; + + return nQuad; +} + +int +decor_set_lSrStSbS_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l) +{ + int splitX, n, nQuad = 0; + + splitX = (c->left_corner_space - c->right_corner_space) / 2; + + /* top quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + c->left_corner_space, + c->right_space, + c->right_corner_space, + -c->top_space, + 0, + GRAVITY_NORTH, + l->top.x2 - l->top.x1, + splitX, + 0, + l->top.x1, + l->top.y1); + + q += n; nQuad += n; + + n = decor_set_lSrS_window_quads (q, c, l); + + q += n; nQuad += n; + + /* bottom quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + c->left_corner_space, + c->right_space, + c->right_corner_space, + 0, + c->bottom_space, + GRAVITY_SOUTH, + l->bottom.x2 - l->bottom.x1, + splitX, + 0, + l->bottom.x1, + l->bottom.y1); + + nQuad += n; + + return nQuad; +} + +int +decor_set_lSrStXbS_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l, + int top_stretch_offset) +{ + int splitX, n, nQuad = 0; + int top_left, top_right; + + splitX = (c->left_corner_space - c->right_corner_space) / 2; + + top_left = top_stretch_offset; + top_right = l->top.x2 - l->top.x1 - + c->left_space - c->right_space - top_left - 1; + + /* top quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + top_left, + c->right_space, + top_right, + -c->top_space, + 0, + GRAVITY_NORTH, + l->top.x2 - l->top.x1, + -top_right, + GRAVITY_EAST, + l->top.x1, + l->top.y1); + + q += n; nQuad += n; + + n = decor_set_lSrS_window_quads (q, c, l); + + q += n; nQuad += n; + + /* bottom quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + c->left_corner_space, + c->right_space, + c->right_corner_space, + 0, + c->bottom_space, + GRAVITY_SOUTH, + l->bottom.x2 - l->bottom.x1, + splitX, + 0, + l->bottom.x1, + l->bottom.y1); + + nQuad += n; + + return nQuad; +} + +int +decor_set_lSrStSbX_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l, + int bottom_stretch_offset) +{ + int splitX, n, nQuad = 0; + int bottom_left, bottom_right; + + splitX = (c->left_corner_space - c->right_corner_space) / 2; + + bottom_left = bottom_stretch_offset; + bottom_right = l->bottom.x2 - l->bottom.x1 - + c->left_space - c->right_space - bottom_left - 1; + + /* top quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + c->left_corner_space, + c->right_space, + c->right_corner_space, + -c->top_space, + 0, + GRAVITY_NORTH, + l->top.x2 - l->top.x1, + splitX, + 0, + l->top.x1, + l->top.y1); + + q += n; nQuad += n; + + n = decor_set_lSrS_window_quads (q, c, l); + + q += n; nQuad += n; + + /* bottom quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + bottom_left, + c->right_space, + bottom_right, + 0, + c->bottom_space, + GRAVITY_SOUTH, + l->bottom.x2 - l->bottom.x1, + -bottom_right, + GRAVITY_EAST, + l->bottom.x1, + l->bottom.y1); + + nQuad += n; + + return nQuad; +} + +int +decor_set_lXrXtXbX_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l, + int left_stretch_offset, + int right_stretch_offset, + int top_stretch_offset, + int bottom_stretch_offset) +{ + int lh, rh, n, nQuad = 0; + int left_top, left_bottom; + int right_top, right_bottom; + int top_left, top_right; + int bottom_left, bottom_right; + + top_left = top_stretch_offset; + top_right = l->top.x2 - l->top.x1 - + c->left_space - c->right_space - top_left - 1; + + bottom_left = bottom_stretch_offset; + bottom_right = l->bottom.x2 - l->bottom.x1 - + c->left_space - c->right_space - bottom_left - 1; + + if (l->rotation) + { + lh = l->left.x2 - l->left.x1; + rh = l->right.x2 - l->right.x1; + } + else + { + lh = l->left.y2 - l->left.y1; + rh = l->right.y2 - l->right.y1; + } + + left_top = left_stretch_offset; + left_bottom = lh - left_top - 1; + + right_top = right_stretch_offset; + right_bottom = rh - right_top - 1; + + + /* top quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + top_left, + c->right_space, + top_right, + -c->top_space, + 0, + GRAVITY_NORTH, + l->top.x2 - l->top.x1, + -top_right, + GRAVITY_EAST, + l->top.x1, + l->top.y1); + + q += n; nQuad += n; + + /* left quads */ + n = decor_set_vert_quad_row (q, + 0, + left_top, + 0, + left_bottom, + -c->left_space, + 0, + GRAVITY_WEST, + lh, + -left_bottom, + GRAVITY_SOUTH, + l->left.x1, + l->left.y1, + l->rotation); + + q += n; nQuad += n; + + /* right quads */ + n = decor_set_vert_quad_row (q, + 0, + right_top, + 0, + right_bottom, + 0, + c->right_space, + GRAVITY_EAST, + rh, + -right_bottom, + GRAVITY_SOUTH, + l->right.x1, + l->right.y1, + l->rotation); + + q += n; nQuad += n; + + /* bottom quads */ + n = decor_set_horz_quad_line (q, + c->left_space, + bottom_left, + c->right_space, + bottom_right, + 0, + c->bottom_space, + GRAVITY_SOUTH, + l->bottom.x2 - l->bottom.x1, + -bottom_right, + GRAVITY_EAST, + l->bottom.x1, + l->bottom.y1); + + nQuad += n; + + return nQuad; +} + +#if INT_MAX != LONG_MAX + +static int errors; + +static int +error_handler (Display *xdisplay, + XErrorEvent *event) +{ + errors++; + return 0; +} + +/* XRenderSetPictureFilter used to be broken on LP64. This + * works with either the broken or fixed version. + */ +static void +XRenderSetPictureFilter_wrapper (Display *dpy, + Picture picture, + char *filter, + XFixed *params, + int nparams) +{ + int (*old) (Display *, XErrorEvent *); + + errors = 0; + + old = XSetErrorHandler (error_handler); + + XRenderSetPictureFilter (dpy, picture, filter, params, nparams); + XSync (dpy, False); + + XSetErrorHandler (old); + + if (errors) + { + long *long_params = malloc (sizeof (long) * nparams); + int i; + + for (i = 0; i < nparams; i++) + long_params[i] = params[i]; + + XRenderSetPictureFilter (dpy, picture, filter, + (XFixed *) long_params, nparams); + free (long_params); + } +} + +#define XRenderSetPictureFilter XRenderSetPictureFilter_wrapper +#endif + +static void +set_picture_transform (Display *xdisplay, + Picture p, + int dx, + int dy) +{ + XTransform transform = { + { + { 1 << 16, 0, -dx << 16 }, + { 0, 1 << 16, -dy << 16 }, + { 0, 0, 1 << 16 }, + } + }; + + XRenderSetPictureTransform (xdisplay, p, &transform); +} + +static void +set_picture_clip (Display *xdisplay, + Picture p, + int width, + int height, + int clipX1, + int clipY1, + int clipX2, + int clipY2) +{ + XRectangle clip[4]; + + clip[0].x = 0; + clip[0].y = 0; + clip[0].width = width; + clip[0].height = clipY1; + + clip[1].x = 0; + clip[1].y = clipY2; + clip[1].width = width; + clip[1].height = height - clipY2; + + clip[2].x = 0; + clip[2].y = clipY1; + clip[2].width = clipX1; + clip[2].height = clipY2 - clipY1; + + clip[3].x = clipX2; + clip[3].y = clipY1; + clip[3].width = width - clipX2; + clip[3].height = clipY2 - clipY1; + + XRenderSetPictureClipRectangles (xdisplay, p, 0, 0, clip, 4); +} + +static void +set_no_picture_clip (Display *xdisplay, + Picture p) +{ + XRectangle clip; + + clip.x = 0; + clip.y = 0; + clip.width = SHRT_MAX; + clip.height = SHRT_MAX; + + XRenderSetPictureClipRectangles (xdisplay, p, 0, 0, &clip, 1); +} + +static XFixed * +create_gaussian_kernel (double radius, + double sigma, + double alpha, + int *r_size) +{ + XFixed *params; + double *amp, scale, x_scale, fx, sum; + int size, half_size, x, i, n; + + scale = 1.0f / (2.0f * M_PI * sigma * sigma); + half_size = alpha + 0.5f; + + if (half_size == 0) + half_size = 1; + + size = half_size * 2 + 1; + x_scale = 2.0f * radius / size; + + if (size < 3) + return NULL; + + n = size; + + amp = malloc (sizeof (double) * n); + if (!amp) + return NULL; + + n += 2; + + params = malloc (sizeof (XFixed) * n); + if (!params) + { + free (amp); + return NULL; + } + + i = 0; + sum = 0.0f; + + for (x = 0; x < size; x++) + { + fx = x_scale * (x - half_size); + + amp[i] = scale * exp ((-1.0f * (fx * fx)) / (2.0f * sigma * sigma)); + + sum += amp[i]; + + i++; + } + + /* normalize */ + if (sum != 0.0) + sum = 1.0 / sum; + + params[0] = params[1] = 0; + + for (i = 2; i < n; i++) + params[i] = XDoubleToFixed (amp[i - 2] * sum); + + free (amp); + + *r_size = size; + + return params; +} + +#define SIGMA(r) ((r) / 2.0) +#define ALPHA(r) (r) + +decor_shadow_t * +decor_shadow_create (Display *xdisplay, + Screen *screen, + int width, + int height, + int left, + int right, + int top, + int bottom, + int solid_left, + int solid_right, + int solid_top, + int solid_bottom, + decor_shadow_options_t *opt, + decor_context_t *c, + decor_draw_func_t draw, + void *closure) +{ + static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; + XRenderPictFormat *format; + Pixmap pixmap; + Picture src, dst, tmp; + XFixed opacity, *params; + XFilters *filters; + char *filter = NULL; + int size, n_params = 0; + XRenderColor color; + int shadow_offset_x; + int shadow_offset_y; + Pixmap d_pixmap; + int d_width; + int d_height; + Window xroot = screen->root; + decor_shadow_t *shadow; + int clipX1, clipY1, clipX2, clipY2; + + shadow = malloc (sizeof (decor_shadow_t)); + if (!shadow) + return NULL; + + shadow->ref_count = 1; + + shadow->pixmap = 0; + shadow->picture = 0; + shadow->width = 0; + shadow->height = 0; + + shadow_offset_x = opt->shadow_offset_x; + shadow_offset_y = opt->shadow_offset_y; + + /* compute a gaussian convolution kernel */ + params = create_gaussian_kernel (opt->shadow_radius, + SIGMA (opt->shadow_radius), + ALPHA (opt->shadow_radius), + &size); + if (!params) + shadow_offset_x = shadow_offset_y = size = 0; + + if (opt->shadow_radius <= 0.0 && + shadow_offset_x == 0 && + shadow_offset_y == 0) + size = 0; + + n_params = size + 2; + size = size / 2; + + c->extents.left = left; + c->extents.right = right; + c->extents.top = top; + c->extents.bottom = bottom; + + c->left_space = left + size - shadow_offset_x; + c->right_space = right + size + shadow_offset_x; + c->top_space = top + size - shadow_offset_y; + c->bottom_space = bottom + size + shadow_offset_y; + + c->left_space = MAX (left, c->left_space); + c->right_space = MAX (right, c->right_space); + c->top_space = MAX (top, c->top_space); + c->bottom_space = MAX (bottom, c->bottom_space); + + c->left_corner_space = MAX (1, size - solid_left + shadow_offset_x); + c->right_corner_space = MAX (1, size - solid_right - shadow_offset_x); + c->top_corner_space = MAX (1, size - solid_top + shadow_offset_y); + c->bottom_corner_space = MAX (1, size - solid_bottom - shadow_offset_y); + + width = MAX (width, c->left_corner_space + c->right_corner_space); + height = MAX (height, c->top_corner_space + c->bottom_corner_space); + + width = MAX (1, width); + height = MAX (1, height); + + d_width = c->left_space + width + c->right_space; + d_height = c->top_space + height + c->bottom_space; + + /* all pixmaps are ARGB32 */ + format = XRenderFindStandardFormat (xdisplay, PictStandardARGB32); + + /* no shadow */ + if (size <= 0) + { + if (params) + free (params); + + return shadow; + } + + pixmap = XCreatePixmap (xdisplay, xroot, d_width, d_height, 32); + if (!pixmap) + { + free (params); + return shadow; + } + + /* query server for convolution filter */ + filters = XRenderQueryFilters (xdisplay, pixmap); + if (filters) + { + int i; + + for (i = 0; i < filters->nfilter; i++) + { + if (strcmp (filters->filter[i], FilterConvolution) == 0) + { + filter = (char *) FilterConvolution; + break; + } + } + + XFree (filters); + } + + if (!filter) + { + XFreePixmap (xdisplay, pixmap); + free (params); + + return shadow; + } + + /* create pixmap for temporary decorations */ + d_pixmap = XCreatePixmap (xdisplay, xroot, d_width, d_height, 32); + if (!d_pixmap) + { + XFreePixmap (xdisplay, pixmap); + free (params); + + return shadow; + } + + src = XRenderCreateSolidFill (xdisplay, &white); + dst = XRenderCreatePicture (xdisplay, d_pixmap, format, 0, NULL); + tmp = XRenderCreatePicture (xdisplay, pixmap, format, 0, NULL); + + /* draw decoration */ + (*draw) (xdisplay, d_pixmap, dst, d_width, d_height, c, closure); + + /* first pass */ + params[0] = (n_params - 2) << 16; + params[1] = 1 << 16; + + clipX1 = c->left_space + size; + clipY1 = c->top_space + size; + clipX2 = d_width - c->right_space - size; + clipY2 = d_height - c->bottom_space - size; + + if (clipX1 < clipX2 && clipY1 < clipY2) + set_picture_clip (xdisplay, tmp, d_width, d_height, + clipX1, clipY1, clipX2, clipY2); + + set_picture_transform (xdisplay, dst, shadow_offset_x, 0); + XRenderSetPictureFilter (xdisplay, dst, filter, params, n_params); + XRenderComposite (xdisplay, + PictOpSrc, + src, + dst, + tmp, + 0, 0, + 0, 0, + 0, 0, + d_width, d_height); + + set_no_picture_clip (xdisplay, tmp); + + XRenderFreePicture (xdisplay, src); + + /* second pass */ + params[0] = 1 << 16; + params[1] = (n_params - 2) << 16; + + opacity = XDoubleToFixed (opt->shadow_opacity); + if (opacity < (1 << 16)) + { + /* apply opacity as shadow color if less than 1.0 */ + color.red = (opt->shadow_color[0] * opacity) >> 16; + color.green = (opt->shadow_color[1] * opacity) >> 16; + color.blue = (opt->shadow_color[2] * opacity) >> 16; + color.alpha = opacity; + + opacity = 1 << 16; + } + else + { + /* shadow color */ + color.red = opt->shadow_color[0]; + color.green = opt->shadow_color[1]; + color.blue = opt->shadow_color[2]; + color.alpha = 0xffff; + } + + src = XRenderCreateSolidFill (xdisplay, &color); + + clipX1 = c->left_space; + clipY1 = c->top_space; + clipX2 = d_width - c->right_space; + clipY2 = d_height - c->bottom_space; + + if (clipX1 < clipX2 && clipY1 < clipY2) + set_picture_clip (xdisplay, dst, d_width, d_height, + clipX1, clipY1, clipX2, clipY2); + + set_picture_transform (xdisplay, tmp, 0, shadow_offset_y); + XRenderSetPictureFilter (xdisplay, tmp, filter, params, n_params); + XRenderComposite (xdisplay, + PictOpSrc, + src, + tmp, + dst, + 0, 0, + 0, 0, + 0, 0, + d_width, d_height); + + set_no_picture_clip (xdisplay, dst); + + XRenderFreePicture (xdisplay, src); + + if (opacity != (1 << 16)) + { + XFixed p[3]; + + p[0] = 1 << 16; + p[1] = 1 << 16; + p[2] = opacity; + + if (clipX1 < clipX2 && clipY1 < clipY2) + set_picture_clip (xdisplay, tmp, d_width, d_height, + clipX1, clipY1, clipX2, clipY2); + + /* apply opacity */ + set_picture_transform (xdisplay, dst, 0, 0); + XRenderSetPictureFilter (xdisplay, dst, filter, p, 3); + XRenderComposite (xdisplay, + PictOpSrc, + dst, + None, + tmp, + 0, 0, + 0, 0, + 0, 0, + d_width, d_height); + + XFreePixmap (xdisplay, d_pixmap); + shadow->pixmap = pixmap; + } + else + { + XFreePixmap (xdisplay, pixmap); + shadow->pixmap = d_pixmap; + } + + XRenderFreePicture (xdisplay, tmp); + XRenderFreePicture (xdisplay, dst); + + shadow->picture = XRenderCreatePicture (xdisplay, shadow->pixmap, + format, 0, NULL); + + shadow->width = d_width; + shadow->height = d_height; + + free (params); + + return shadow; +} + +void +decor_shadow_destroy (Display *xdisplay, + decor_shadow_t *shadow) +{ + shadow->ref_count--; + if (shadow->ref_count) + return; + + if (shadow->picture) + XRenderFreePicture (xdisplay, shadow->picture); + + if (shadow->pixmap) + XFreePixmap (xdisplay, shadow->pixmap); + + free (shadow); +} + +void +decor_shadow_reference (decor_shadow_t *shadow) +{ + shadow->ref_count++; +} + +void +decor_draw_simple (Display *xdisplay, + Pixmap pixmap, + Picture picture, + int width, + int height, + decor_context_t *c, + void *closure) +{ + static XRenderColor clear = { 0x0000, 0x0000, 0x0000, 0x0000 }; + static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; + + XRenderFillRectangle (xdisplay, PictOpSrc, picture, &clear, + 0, + 0, + width, + height); + XRenderFillRectangle (xdisplay, PictOpSrc, picture, &white, + c->left_space - c->extents.left, + c->top_space - c->extents.top, + width - c->left_space - c->right_space + + c->extents.left + c->extents.right, + height - c->top_space - c->bottom_space + + c->extents.top + c->extents.bottom); +} + +void +decor_get_default_layout (decor_context_t *c, + int width, + int height, + decor_layout_t *layout) +{ + width = MAX (width, c->left_corner_space + c->right_corner_space); + height = MAX (height, c->top_corner_space + c->bottom_corner_space); + + width += c->left_space + c->right_space; + + layout->top.x1 = 0; + layout->top.y1 = 0; + layout->top.x2 = width; + layout->top.y2 = c->top_space; + layout->top.pad = 0; + + layout->left.x1 = 0; + layout->left.y1 = c->top_space; + layout->left.x2 = c->left_space; + layout->left.y2 = c->top_space + height; + layout->left.pad = 0; + + layout->right.x1 = width - c->right_space; + layout->right.y1 = c->top_space; + layout->right.x2 = width; + layout->right.y2 = c->top_space + height; + layout->right.pad = 0; + + layout->bottom.x1 = 0; + layout->bottom.y1 = height + c->top_space; + layout->bottom.x2 = width; + layout->bottom.y2 = height + c->top_space + c->bottom_space; + layout->bottom.pad = 0; + + layout->width = width; + layout->height = height + c->top_space + c->bottom_space; + + layout->rotation = 0; +} + +void +decor_get_best_layout (decor_context_t *c, + int width, + int height, + decor_layout_t *layout) +{ + int y; + + /* use default layout when no left and right extents */ + if (c->extents.left == 0 && c->extents.right == 0) + { + decor_get_default_layout (c, width, 1, layout); + return; + } + + width = MAX (width, c->left_corner_space + c->right_corner_space); + height = MAX (height, c->top_corner_space + c->bottom_corner_space); + + width += c->left_space + c->right_space; + + if (width >= (height + 2)) + { + int max; + + layout->width = width; + + layout->top.x1 = 0; + layout->top.y1 = 0; + layout->top.x2 = width; + layout->top.y2 = c->top_space; + + y = c->top_space; + + max = MAX (c->left_space, c->right_space); + if (max < height) + { + layout->rotation = 1; + + y += 2; + + layout->top.pad = PAD_BOTTOM; + layout->bottom.pad = PAD_TOP; + layout->left.pad = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT; + layout->right.pad = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT; + + layout->left.x1 = 1; + layout->left.y1 = y; + layout->left.x2 = 1 + height; + layout->left.y2 = y + c->left_space; + + if ((height + 2) <= (width / 2)) + { + layout->right.x1 = height + 3; + layout->right.y1 = y; + layout->right.x2 = height + 3 + height; + layout->right.y2 = y + c->right_space; + + y += max + 2; + } + else + { + y += c->left_space + 2; + + layout->right.x1 = 1; + layout->right.y1 = y; + layout->right.x2 = 1 + height; + layout->right.y2 = y + c->right_space; + + y += c->right_space + 2; + } + } + else + { + layout->top.pad = 0; + layout->bottom.pad = 0; + layout->left.pad = 0; + layout->right.pad = 0; + + layout->left.x1 = 0; + layout->left.y1 = y; + layout->left.x2 = c->left_space; + layout->left.y2 = y + height; + + layout->right.x1 = width - c->right_space; + layout->right.y1 = y; + layout->right.x2 = width; + layout->right.y2 = y + height; + + y += height; + } + + layout->bottom.x1 = 0; + layout->bottom.y1 = y; + layout->bottom.x2 = width; + layout->bottom.y2 = y + c->bottom_space; + + y += c->bottom_space; + } + else + { + layout->rotation = 1; + + layout->left.pad = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT; + layout->right.pad = PAD_TOP | PAD_BOTTOM | PAD_LEFT | PAD_RIGHT; + + layout->top.x1 = 0; + layout->top.y1 = 0; + layout->top.x2 = width; + layout->top.y2 = c->top_space; + + if (((width * 2) + 3) <= (height + 2)) + { + layout->width = height + 2; + + layout->top.pad = PAD_BOTTOM | PAD_RIGHT; + layout->bottom.pad = PAD_TOP | PAD_BOTTOM | PAD_RIGHT | PAD_LEFT; + + layout->bottom.x1 = width + 2; + layout->bottom.y1 = 1; + layout->bottom.x2 = width + 2 + width; + layout->bottom.y2 = 1 + c->bottom_space; + + y = MAX (c->top_space, 1 + c->bottom_space) + 2; + + layout->left.x1 = 1; + layout->left.y1 = y; + layout->left.x2 = 1 + height; + layout->left.y2 = y + c->left_space; + + y += c->left_space + 2; + + layout->right.x1 = 1; + layout->right.y1 = y; + layout->right.x2 = 1 + height; + layout->right.y2 = y + c->right_space; + + y += c->right_space; + } + else + { + layout->width = height + 2; + + layout->top.pad = PAD_BOTTOM | PAD_RIGHT; + layout->bottom.pad = PAD_TOP | PAD_RIGHT; + + y = c->top_space + 2; + + layout->left.x1 = 1; + layout->left.y1 = y; + layout->left.x2 = 1 + height; + layout->left.y2 = y + c->left_space; + + y += c->left_space + 2; + + layout->right.x1 = 1; + layout->right.y1 = y; + layout->right.x2 = 1 + height; + layout->right.y2 = y + c->right_space; + + y += c->right_space + 2; + + layout->bottom.x1 = 0; + layout->bottom.y1 = y; + layout->bottom.x2 = width; + layout->bottom.y2 = y + c->bottom_space; + + y += c->bottom_space; + } + } + + layout->height = y; +} + +static XTransform xident = { + { + { 1 << 16, 0, 0 }, + { 0, 1 << 16, 0 }, + { 0, 0, 1 << 16 }, + } +}; + +void +decor_fill_picture_extents_with_shadow (Display *xdisplay, + decor_shadow_t *shadow, + decor_context_t *context, + Picture picture, + decor_layout_t *layout) +{ + int w, h, x2, y2, left, right, top, bottom, width, height; + + if (!shadow->picture) + return; + + width = layout->top.x2 - layout->top.x1; + if (layout->rotation) + height = layout->left.x2 - layout->left.x1; + else + height = layout->left.y2 - layout->left.y1; + + height += context->top_space + context->bottom_space; + + left = context->left_space + context->left_corner_space; + right = context->right_space + context->right_corner_space; + top = context->top_space + context->top_corner_space; + bottom = context->bottom_space + context->bottom_corner_space; + + if (width - left - right < 0) + { + left = width / 2; + right = width - left; + } + + if (height - top - bottom < 0) + { + top = height / 2; + bottom = height - top; + } + + w = width - left - right; + h = height - top - bottom; + + x2 = width - right; + y2 = height - bottom; + + /* top left */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, 0, + 0, 0, + layout->top.x1, layout->top.y1, + left, context->top_space); + + /* top right */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + shadow->width - right, 0, + 0, 0, + layout->top.x2 - right, layout->top.y1, + right, context->top_space); + + /* bottom left */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, shadow->height - context->bottom_space, + 0, 0, + layout->bottom.x1, layout->bottom.y1, + left, context->bottom_space); + + /* bottom right */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + shadow->width - right, + shadow->height - context->bottom_space, + 0, 0, + layout->bottom.x2 - right, layout->bottom.y1, + right, context->bottom_space); + + if (w > 0) + { + int sw = shadow->width - left - right; + int sx = left; + + if (sw != w) + { + XTransform t = { + { + { (sw << 16) / w, 0, left << 16 }, + { 0, 1 << 16, 0 }, + { 0, 0, 1 << 16 }, + } + }; + + sx = 0; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + } + + /* top */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + sx, 0, + 0, 0, + layout->top.x1 + left, layout->top.y1, + w, context->top_space); + + /* bottom */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + sx, shadow->height - context->bottom_space, + 0, 0, + layout->bottom.x1 + left, layout->bottom.y1, + w, context->bottom_space); + + if (sw != w) + XRenderSetPictureTransform (xdisplay, shadow->picture, &xident); + } + + if (layout->rotation) + { + XTransform t = { + { + { 0, 1 << 16, 0 }, + { 1 << 16, 0, 0 }, + { 0, 0, 1 << 16 } + } + }; + + t.matrix[1][2] = context->top_space << 16; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + + /* left top */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, 0, + 0, 0, + layout->left.x1, + layout->left.y1, + top - context->top_space, context->left_space); + + t.matrix[0][2] = (shadow->width - context->right_space) << 16; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + + /* right top */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, 0, + 0, 0, + layout->right.x1, + layout->right.y1, + top - context->top_space, context->right_space); + + XRenderSetPictureTransform (xdisplay, shadow->picture, &xident); + } + else + { + /* left top */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, context->top_space, + 0, 0, + layout->left.x1, layout->left.y1, + context->left_space, top - context->top_space); + + /* right top */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + shadow->width - context->right_space, + context->top_space, + 0, 0, + layout->right.x1, layout->right.y1, + context->right_space, top - context->top_space); + } + + if (layout->rotation) + { + XTransform t = { + { + { 0, 1 << 16, 0 }, + { 1 << 16, 0, 0 }, + { 0, 0, 1 << 16 } + } + }; + + t.matrix[1][2] = (shadow->height - bottom) << 16; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + + /* left bottom */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, 0, + 0, 0, + layout->left.x2 - (bottom - context->bottom_space), + layout->left.y1, + bottom - context->bottom_space, context->left_space); + + t.matrix[0][2] = (shadow->width - context->right_space) << 16; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + + /* right bottom */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, 0, + 0, 0, + layout->right.x2 - (bottom - context->bottom_space), + layout->right.y1, + bottom - context->bottom_space, context->right_space); + + XRenderSetPictureTransform (xdisplay, shadow->picture, &xident); + } + else + { + /* left bottom */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, shadow->height - bottom, + 0, 0, + layout->left.x1, + layout->left.y2 - (bottom - context->bottom_space), + context->left_space, bottom - context->bottom_space); + + /* right bottom */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + shadow->width - context->right_space, + shadow->height - bottom, + 0, 0, + layout->right.x1, + layout->right.y2 - (bottom - context->bottom_space), + context->right_space, bottom - context->bottom_space); + } + + if (h > 0) + { + int sh = shadow->height - top - bottom; + + if (layout->rotation) + { + XTransform t = { + { + { 0, 1 << 16, 0 }, + { (sh << 16) / h, 0, 0 }, + { 0, 0, 1 << 16 } + } + }; + + t.matrix[1][2] = top << 16; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + + /* left */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, 0, + 0, 0, + layout->left.x1 + (top - context->top_space), + layout->left.y1, + h, context->left_space); + + t.matrix[0][2] = (shadow->width - context->right_space) << 16; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + + /* right */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, 0, + 0, 0, + layout->right.x1 + (top - context->top_space), + layout->right.y1, + h, context->right_space); + + XRenderSetPictureTransform (xdisplay, shadow->picture, &xident); + + } + else + { + int sy = top; + + if (sh != h) + { + XTransform t = { + { + { 1 << 16, 0, 0 }, + { 0, (sh << 16) / h, top << 16 }, + { 0, 0, 1 << 16 }, + } + }; + + sy = 0; + + XRenderSetPictureTransform (xdisplay, shadow->picture, &t); + } + + /* left */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + 0, sy, + 0, 0, + layout->left.x1, + layout->left.y1 + (top - context->top_space), + context->left_space, h); + + /* right */ + XRenderComposite (xdisplay, PictOpSrc, shadow->picture, 0, picture, + shadow->width - context->right_space, sy, + 0, 0, + layout->right.x2 - context->right_space, + layout->right.y1 + (top - context->top_space), + context->right_space, h); + + if (sh != h) + XRenderSetPictureTransform (xdisplay, shadow->picture, &xident); + } + } +} + +static void +_decor_pad_border_picture (Display *xdisplay, + Picture dst, + decor_box_t *box) +{ + int x1, y1, x2, y2; + + x1 = box->x1; + y1 = box->y1; + x2 = box->x2; + y2 = box->y2; + + if (box->pad & PAD_TOP) + { + XRenderComposite (xdisplay, PictOpSrc, dst, None, dst, + x1, y1, + 0, 0, + x1, y1 - 1, + x2 - x1, 1); + + y1--; + } + + if (box->pad & PAD_BOTTOM) + { + XRenderComposite (xdisplay, PictOpSrc, dst, None, dst, + x1, y2 - 1, + 0, 0, + x1, y2, + x2 - x1, 1); + + y2++; + } + + if (box->pad & PAD_LEFT) + { + XRenderComposite (xdisplay, PictOpSrc, dst, None, dst, + x1, y1, + 0, 0, + x1 - 1, y1, + 1, y2 - y1); + } + + if (box->pad & PAD_RIGHT) + { + XRenderComposite (xdisplay, PictOpSrc, dst, None, dst, + x2 - 1, y1, + 0, 0, + x2, y1, + 1, y2 - y1); + } +} + +#ifndef HAVE_XRENDER_0_9_3 +/* XRenderCreateLinearGradient and XRenderCreateRadialGradient used to be + * broken. Flushing Xlib's output buffer before calling one of these + * functions will avoid this specific issue. + */ +static Picture +XRenderCreateLinearGradient_wrapper (Display *xdisplay, + const XLinearGradient *gradient, + const XFixed *stops, + const XRenderColor *colors, + int nStops) +{ + XFlush (xdisplay); + + return XRenderCreateLinearGradient (xdisplay, gradient, + stops, colors, nStops); +} + +static Picture +XRenderCreateRadialGradient_wrapper (Display *xdisplay, + const XRadialGradient *gradient, + const XFixed *stops, + const XRenderColor *colors, + int nStops) +{ + XFlush (xdisplay); + + return XRenderCreateRadialGradient (xdisplay, gradient, + stops, colors, nStops); +} + +#define XRenderCreateLinearGradient XRenderCreateLinearGradient_wrapper +#define XRenderCreateRadialGradient XRenderCreateRadialGradient_wrapper +#endif + +static void +_decor_blend_horz_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha, + int x1, + int y1, + int x2, + int y2, + int dy, + int direction) +{ + XRenderColor color[3] = { + { 0xffff, 0xffff, 0xffff, 0xffff }, + { alpha, alpha, alpha, alpha } + }; + int op = PictOpSrc; + int left, right; + + left = context->extents.left; + right = context->extents.right; + + XOffsetRegion (region, x1, y1); + XRenderSetPictureClipRegion (xdisplay, dst, region); + XOffsetRegion (region, -x1, -y1); + + if (alpha != 0xffff) + { + op = PictOpIn; + + if (shade_alpha) + { + static XFixed stop[2] = { 0, 1 << 16 }; + XTransform transform = { + { + { 1 << 16, 0, 0 }, + { 0, 1 << 16, 0 }, + { 0, 0, 1 << 16 } + } + }; + Picture grad; + XLinearGradient linear; + XRadialGradient radial; + XRenderPictureAttributes attrib; + + attrib.repeat = RepeatPad; + + radial.inner.x = 0; + radial.inner.y = 0; + radial.inner.radius = 0; + radial.outer.x = 0; + radial.outer.y = 0; + + /* left */ + radial.outer.radius = left << 16; + + grad = XRenderCreateRadialGradient (xdisplay, + &radial, + stop, + color, + 2); + + transform.matrix[1][1] = (left << 16) / dy; + transform.matrix[0][2] = -left << 16; + + if (direction < 0) + transform.matrix[1][2] = -left << 16; + + XRenderSetPictureTransform (xdisplay, grad, &transform); + XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib); + + XRenderComposite (xdisplay, PictOpSrc, grad, None, dst, + 0, 0, + 0, 0, + x1, y1, + left, dy); + + XRenderFreePicture (xdisplay, grad); + + /* middle */ + linear.p1.x = 0; + linear.p2.x = 0; + + if (direction > 0) + { + linear.p1.y = 0; + linear.p2.y = dy << 16; + } + else + { + linear.p1.y = dy << 16; + linear.p2.y = 0; + } + + grad = XRenderCreateLinearGradient (xdisplay, + &linear, + stop, + color, + 2); + + XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib); + + XRenderComposite (xdisplay, PictOpSrc, grad, None, dst, + 0, 0, + 0, 0, + x1 + left, y1, + (x2 - x1) - left - right, dy); + + XRenderFreePicture (xdisplay, grad); + + /* right */ + radial.outer.radius = right << 16; + + grad = XRenderCreateRadialGradient (xdisplay, + &radial, + stop, + color, + 2); + + transform.matrix[1][1] = (right << 16) / dy; + transform.matrix[0][2] = 1 << 16; + + if (direction < 0) + transform.matrix[1][2] = -right << 16; + + XRenderSetPictureTransform (xdisplay, grad, &transform); + XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib); + + XRenderComposite (xdisplay, PictOpSrc, grad, None, dst, + 0, 0, + 0, 0, + x2 - right, y1, + right, dy); + + XRenderFreePicture (xdisplay, grad); + } + else + { + XRenderFillRectangle (xdisplay, PictOpSrc, dst, &color[1], + x1, y1, x2 - x1, y2 - y1); + } + } + + XRenderComposite (xdisplay, op, src, None, dst, + xSrc, ySrc, + 0, 0, + x1, y1, + x2 - x1, y2 - y1); + + set_no_picture_clip (xdisplay, dst); +} + +void +decor_blend_top_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha) +{ + int left, right, top; + int x1, y1, x2, y2; + + left = context->extents.left; + right = context->extents.right; + top = context->extents.top; + + x1 = layout->top.x1 + context->left_space - left; + y1 = layout->top.y1 + context->top_space - top; + x2 = layout->top.x2 - context->right_space + right; + y2 = layout->top.y2; + + _decor_blend_horz_border_picture (xdisplay, + context, + src, + xSrc, + ySrc, + dst, + layout, + region, + alpha, + shade_alpha, + x1, + y1, + x2, + y2, + top, + -1); + + _decor_pad_border_picture (xdisplay, dst, &layout->top); +} + +void +decor_blend_bottom_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha) +{ + int left, right, bottom; + int x1, y1, x2, y2; + + left = context->extents.left; + right = context->extents.right; + bottom = context->extents.bottom; + + x1 = layout->bottom.x1 + context->left_space - left; + y1 = layout->bottom.y1; + x2 = layout->bottom.x2 - context->right_space + right; + y2 = layout->bottom.y1 + bottom; + + _decor_blend_horz_border_picture (xdisplay, + context, + src, + xSrc, + ySrc, + dst, + layout, + region, + alpha, + shade_alpha, + x1, + y1, + x2, + y2, + bottom, + 1); + + _decor_pad_border_picture (xdisplay, dst, &layout->bottom); +} + +static void +_decor_blend_vert_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha, + int x1, + int y1, + int x2, + int y2, + int direction) +{ + XRenderColor color[3] = { + { 0xffff, 0xffff, 0xffff, 0xffff }, + { alpha, alpha, alpha, alpha } + }; + int op = PictOpSrc; + + if (layout->rotation) + { + Region rotated_region; + XRectangle rect; + BoxPtr pBox = region->rects; + int nBox = region->numRects; + + rotated_region = XCreateRegion (); + + while (nBox--) + { + rect.x = x1 + pBox->y1; + rect.y = y1 + pBox->x1; + rect.width = pBox->y2 - pBox->y1; + rect.height = pBox->x2 - pBox->x1; + + XUnionRectWithRegion (&rect, rotated_region, rotated_region); + + pBox++; + } + + XRenderSetPictureClipRegion (xdisplay, dst, rotated_region); + XDestroyRegion (rotated_region); + } + else + { + XOffsetRegion (region, x1, y1); + XRenderSetPictureClipRegion (xdisplay, dst, region); + XOffsetRegion (region, -x1, -y1); + } + + if (alpha != 0xffff) + { + op = PictOpIn; + + if (shade_alpha) + { + static XFixed stop[2] = { 0, 1 << 16 }; + Picture grad; + XLinearGradient linear; + XRenderPictureAttributes attrib; + + attrib.repeat = RepeatPad; + + if (layout->rotation) + { + linear.p1.x = 0; + linear.p2.x = 0; + + if (direction < 0) + { + linear.p1.y = 0; + linear.p2.y = (y2 - y1) << 16; + } + else + { + linear.p1.y = (y2 - y1) << 16; + linear.p2.y = 0 << 16; + } + } + else + { + linear.p1.y = 0; + linear.p2.y = 0; + + if (direction < 0) + { + linear.p1.x = 0; + linear.p2.x = (x2 - x1) << 16; + } + else + { + linear.p1.x = (x2 - x1) << 16; + linear.p2.x = 0; + } + } + + grad = XRenderCreateLinearGradient (xdisplay, + &linear, + stop, + color, + 2); + + XRenderChangePicture (xdisplay, grad, CPRepeat, &attrib); + + XRenderComposite (xdisplay, PictOpSrc, grad, None, dst, + 0, 0, + 0, 0, + x1, y1, + x2 - x1, y2 - y1); + + XRenderFreePicture (xdisplay, grad); + } + else + { + XRenderFillRectangle (xdisplay, PictOpSrc, dst, &color[1], + x1, y1, x2 - x1, y2 - y1); + } + } + + if (layout->rotation) + { + XTransform t = { + { + { 0, 1 << 16, 0 }, + { 1 << 16, 0, 0 }, + { 0, 0, 1 << 16 } + } + }; + + t.matrix[0][2] = xSrc << 16; + t.matrix[1][2] = ySrc << 16; + + XRenderSetPictureTransform (xdisplay, src, &t); + + XRenderComposite (xdisplay, op, src, None, dst, + 0, 0, + 0, 0, + x1, y1, x2 - x1, y2 - y1); + + XRenderSetPictureTransform (xdisplay, src, &xident); + } + else + { + XRenderComposite (xdisplay, op, src, None, dst, + xSrc, ySrc, + 0, 0, + x1, y1, x2 - x1, y2 - y1); + } + + set_no_picture_clip (xdisplay, dst); +} + +void +decor_blend_left_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha) +{ + int x1, y1, x2, y2; + + x1 = layout->left.x1; + y1 = layout->left.y1; + x2 = layout->left.x2; + y2 = layout->left.y2; + + if (layout->rotation) + y1 += context->left_space - context->extents.left; + else + x1 += context->left_space - context->extents.left; + + _decor_blend_vert_border_picture (xdisplay, + context, + src, + xSrc, + ySrc, + dst, + layout, + region, + alpha, + shade_alpha, + x1, + y1, + x2, + y2, + 1); + + _decor_pad_border_picture (xdisplay, dst, &layout->left); +} + +void +decor_blend_right_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha) +{ + int x1, y1, x2, y2; + + x1 = layout->right.x1; + y1 = layout->right.y1; + x2 = layout->right.x2; + y2 = layout->right.y2; + + if (layout->rotation) + y2 -= context->right_space - context->extents.right; + else + x2 -= context->right_space - context->extents.right; + + _decor_blend_vert_border_picture (xdisplay, + context, + src, + xSrc, + ySrc, + dst, + layout, + region, + alpha, + shade_alpha, + x1, + y1, + x2, + y2, + -1); + + _decor_pad_border_picture (xdisplay, dst, &layout->right); +} + +int +decor_acquire_dm_session (Display *xdisplay, + int screen, + char *name, + int replace_current_dm, + Time *timestamp) +{ + XEvent event; + XSetWindowAttributes attr; + Window current_dm_sn_owner, new_dm_sn_owner; + Atom dm_sn_atom; + Atom manager_atom; + Atom dm_name_atom; + Atom utf8_string_atom; + Time dm_sn_timestamp; + char buf[128]; + + manager_atom = XInternAtom (xdisplay, "MANAGER", FALSE); + dm_name_atom = XInternAtom (xdisplay, "_NET_DM_NAME", 0); + + utf8_string_atom = XInternAtom (xdisplay, "UTF8_STRING", 0); + + sprintf (buf, "DM_S%d", screen); + dm_sn_atom = XInternAtom (xdisplay, buf, 0); + + current_dm_sn_owner = XGetSelectionOwner (xdisplay, dm_sn_atom); + + if (current_dm_sn_owner != None) + { + if (!replace_current_dm) + return DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING; + + XSelectInput (xdisplay, current_dm_sn_owner, StructureNotifyMask); + } + + 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, + dm_name_atom, + utf8_string_atom, 8, + PropModeReplace, + (unsigned char *) name, + strlen (name)); + + XWindowEvent (xdisplay, + new_dm_sn_owner, + PropertyChangeMask, + &event); + + dm_sn_timestamp = event.xproperty.time; + + XSetSelectionOwner (xdisplay, dm_sn_atom, new_dm_sn_owner, + dm_sn_timestamp); + + if (XGetSelectionOwner (xdisplay, dm_sn_atom) != new_dm_sn_owner) + { + XDestroyWindow (xdisplay, new_dm_sn_owner); + + return DECOR_ACQUIRE_STATUS_FAILED; + } + + /* Send client message indicating that we are now the DM */ + event.xclient.type = ClientMessage; + event.xclient.window = XRootWindow (xdisplay, screen); + event.xclient.message_type = manager_atom; + event.xclient.format = 32; + event.xclient.data.l[0] = dm_sn_timestamp; + event.xclient.data.l[1] = dm_sn_atom; + event.xclient.data.l[2] = 0; + event.xclient.data.l[3] = 0; + event.xclient.data.l[4] = 0; + + XSendEvent (xdisplay, XRootWindow (xdisplay, screen), 0, + 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); + } + + *timestamp = dm_sn_timestamp; + + return DECOR_ACQUIRE_STATUS_SUCCESS; +} + +void +decor_set_dm_check_hint (Display *xdisplay, + int screen) +{ + XSetWindowAttributes attrs; + unsigned long data; + Window xroot; + Atom atom; + + attrs.override_redirect = 1; + attrs.event_mask = PropertyChangeMask; + + xroot = RootWindow (xdisplay, screen); + + data = XCreateWindow (xdisplay, + xroot, + -100, -100, 1, 1, + 0, + CopyFromParent, + CopyFromParent, + (Visual *) CopyFromParent, + CWOverrideRedirect | CWEventMask, + &attrs); + + atom = XInternAtom (xdisplay, "_NET_SUPPORTING_DM_CHECK", 0); + + XChangeProperty (xdisplay, xroot, + atom, + XA_WINDOW, + 32, PropModeReplace, (unsigned char *) &data, 1); +} + +/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */ +static int +convert_property (Display *xdisplay, + Window w, + Atom target, + Atom property, + Time dm_sn_timestamp) +{ + +#define N_TARGETS 4 + + Atom conversion_targets[N_TARGETS]; + long icccm_version[] = { 2, 0 }; + + conversion_targets[0] = XInternAtom (xdisplay, "TARGETS", 0); + conversion_targets[1] = XInternAtom (xdisplay, "MULTIPLE", 0); + conversion_targets[2] = XInternAtom (xdisplay, "TIMESTAMP", 0); + conversion_targets[3] = XInternAtom (xdisplay, "VERSION", 0); + + if (target == conversion_targets[0]) + XChangeProperty (xdisplay, w, property, + XA_ATOM, 32, PropModeReplace, + (unsigned char *) conversion_targets, N_TARGETS); + else if (target == conversion_targets[2]) + XChangeProperty (xdisplay, w, property, + XA_INTEGER, 32, PropModeReplace, + (unsigned char *) &dm_sn_timestamp, 1); + else if (target == conversion_targets[3]) + XChangeProperty (xdisplay, w, property, + XA_INTEGER, 32, PropModeReplace, + (unsigned char *) icccm_version, 2); + else + return 0; + + /* Be sure the PropertyNotify has arrived so we + * can send SelectionNotify + */ + XSync (xdisplay, 0); + + return 1; +} + +void +decor_handle_selection_request (Display *xdisplay, + XEvent *event, + Time timestamp) +{ + XSelectionEvent reply; + Atom multiple_atom; + Atom atom_pair_atom; + + reply.type = SelectionNotify; + reply.display = xdisplay; + reply.requestor = event->xselectionrequest.requestor; + reply.selection = event->xselectionrequest.selection; + reply.target = event->xselectionrequest.target; + reply.property = None; + reply.time = event->xselectionrequest.time; + + multiple_atom = XInternAtom (xdisplay, "MULTIPLE", 0); + atom_pair_atom = XInternAtom (xdisplay, "ATOM_PAIR", 0); + + if (event->xselectionrequest.target == multiple_atom) + { + if (event->xselectionrequest.property != None) + { + Atom type, *adata; + int i, format; + unsigned long num, rest; + unsigned char *data; + + if (XGetWindowProperty (xdisplay, + event->xselectionrequest.requestor, + event->xselectionrequest.property, + 0, 256, FALSE, + atom_pair_atom, + &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 (!convert_property (xdisplay, + event->xselectionrequest.requestor, + adata[i], adata[i + 1], + timestamp)) + adata[i + 1] = None; + + i += 2; + } + + XChangeProperty (xdisplay, + event->xselectionrequest.requestor, + event->xselectionrequest.property, + atom_pair_atom, + 32, PropModeReplace, data, num); + } + } + else + { + if (event->xselectionrequest.property == None) + event->xselectionrequest.property = event->xselectionrequest.target; + + if (convert_property (xdisplay, + event->xselectionrequest.requestor, + event->xselectionrequest.target, + event->xselectionrequest.property, + timestamp)) + reply.property = event->xselectionrequest.property; + } + + XSendEvent (xdisplay, + event->xselectionrequest.requestor, + FALSE, 0L, (XEvent *) &reply); +} + +int +decor_handle_selection_clear (Display *xdisplay, + XEvent *xevent, + int screen) +{ + Atom dm_sn_atom; + char buf[128]; + + sprintf (buf, "DM_S%d", screen); + dm_sn_atom = XInternAtom (xdisplay, buf, 0); + + if (xevent->xselectionclear.selection == dm_sn_atom) + return DECOR_SELECTION_GIVE_UP; + + return DECOR_SELECTION_KEEP; +} diff --git a/src/libdeco.h b/src/libdeco.h new file mode 100644 index 0000000..58f1e7e --- /dev/null +++ b/src/libdeco.h @@ -0,0 +1,393 @@ +/* + * Copyright © 2006 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +#ifndef _DECORATION_H +#define _DECORATION_H + +#define DECOR_INTERFACE_VERSION 20061011 + +#include <string.h> +#include <limits.h> + +#include <X11/Xlib.h> +#include <X11/extensions/Xrender.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRAVITY_WEST (1 << 0) +#define GRAVITY_EAST (1 << 1) +#define GRAVITY_NORTH (1 << 2) +#define GRAVITY_SOUTH (1 << 3) + +#define ALIGN_LEFT (0) +#define ALIGN_RIGHT (1 << 0) +#define ALIGN_TOP (0) +#define ALIGN_BOTTOM (1 << 1) + +#define CLAMP_HORZ (1 << 0) +#define CLAMP_VERT (1 << 1) + +#define XX_MASK (1 << 12) +#define XY_MASK (1 << 13) +#define YX_MASK (1 << 14) +#define YY_MASK (1 << 15) + +#define PAD_TOP (1 << 0) +#define PAD_BOTTOM (1 << 1) +#define PAD_LEFT (1 << 2) +#define PAD_RIGHT (1 << 3) + +typedef struct _decor_point { + int x; + int y; + int gravity; +} decor_point_t; + +typedef struct _decor_matrix { + double xx; double yx; + double xy; double yy; + double x0; double y0; +} decor_matrix_t; + +typedef struct _decor_quad { + decor_point_t p1; + decor_point_t p2; + int max_width; + int max_height; + int align; + int clamp; + decor_matrix_t m; +} decor_quad_t; + +typedef struct _decor_extents { + int left; + int right; + int top; + int bottom; +} decor_extents_t; + +typedef struct _decor_context { + decor_extents_t extents; + + int left_space; + int right_space; + int top_space; + int bottom_space; + + int left_corner_space; + int right_corner_space; + int top_corner_space; + int bottom_corner_space; +} decor_context_t; + +typedef struct _decor_box { + int x1; + int y1; + int x2; + int y2; + + int pad; +} decor_box_t; + +typedef struct _decor_layout { + int width; + int height; + + decor_box_t left; + decor_box_t right; + decor_box_t top; + decor_box_t bottom; + + int rotation; +} decor_layout_t; + +typedef struct _decor_shadow_options { + double shadow_radius; + double shadow_opacity; + unsigned short shadow_color[3]; + int shadow_offset_x; + int shadow_offset_y; +} decor_shadow_options_t; + +typedef struct _decor_shadow { + int ref_count; + Pixmap pixmap; + Picture picture; + int width; + int height; +} decor_shadow_t; + +typedef void (*decor_draw_func_t) (Display *xdisplay, + Pixmap pixmap, + Picture picture, + int width, + int height, + decor_context_t *context, + void *closure); + +#define BASE_PROP_SIZE 12 +#define QUAD_PROP_SIZE 9 +#define N_QUADS_MAX 24 + +int +decor_version (void); + +void +decor_quads_to_property (long *data, + Pixmap pixmap, + decor_extents_t *input, + decor_extents_t *max_input, + int min_width, + int min_height, + decor_quad_t *quad, + int nQuad); + +int +decor_property_get_version (long *data); + +int +decor_property_to_quads (long *data, + int size, + Pixmap *pixmap, + decor_extents_t *input, + decor_extents_t *max_input, + int *min_width, + int *min_height, + decor_quad_t *quad); + +int +decor_set_vert_quad_row (decor_quad_t *q, + int top, + int top_corner, + int bottom, + int bottom_corner, + int left, + int right, + int gravity, + int height, + int splitY, + int splitGravity, + double x0, + double y0, + int rotation); + +int +decor_set_horz_quad_line (decor_quad_t *q, + int left, + int left_corner, + int right, + int right_corner, + int top, + int bottom, + int gravity, + int width, + int splitX, + int splitGravity, + double x0, + double y0); + +int +decor_set_lSrS_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l); + +int +decor_set_lSrStSbS_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l); + +int +decor_set_lSrStXbS_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l, + int top_stretch_offset); + +int +decor_set_lSrStSbX_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l, + int bottom_stretch_offset); + +int +decor_set_lXrXtXbX_window_quads (decor_quad_t *q, + decor_context_t *c, + decor_layout_t *l, + int left_stretch_offset, + int right_stretch_offset, + int top_stretch_offset, + int bottom_stretch_offset); + +decor_shadow_t * +decor_shadow_create (Display *xdisplay, + Screen *screen, + int width, + int height, + int left, + int right, + int top, + int bottom, + int solid_left, + int solid_right, + int solid_top, + int solid_bottom, + decor_shadow_options_t *opt, + decor_context_t *context, + decor_draw_func_t draw, + void *closure); + +void +decor_shadow_destroy (Display *xdisplay, + decor_shadow_t *shadow); + +void +decor_shadow_reference (decor_shadow_t *shadow); + +void +decor_shadow (Display *xdisplay, + decor_shadow_t *shadow); + +void +decor_draw_simple (Display *xdisplay, + Pixmap pixmap, + Picture picture, + int width, + int height, + decor_context_t *c, + void *closure); + +void +decor_get_default_layout (decor_context_t *c, + int width, + int height, + decor_layout_t *layout); + +void +decor_get_best_layout (decor_context_t *c, + int width, + int height, + decor_layout_t *layout); + +void +decor_fill_picture_extents_with_shadow (Display *xdisplay, + decor_shadow_t *shadow, + decor_context_t *context, + Picture picture, + decor_layout_t *layout); + +void +decor_blend_transform_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha); + +void +decor_blend_top_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha); + +void +decor_blend_bottom_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha); + +void +decor_blend_left_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha); + +void +decor_blend_right_border_picture (Display *xdisplay, + decor_context_t *context, + Picture src, + int xSrc, + int ySrc, + Picture dst, + decor_layout_t *layout, + Region region, + unsigned short alpha, + int shade_alpha); + +#define DECOR_ACQUIRE_STATUS_SUCCESS 0 +#define DECOR_ACQUIRE_STATUS_FAILED 1 +#define DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING 2 + +int +decor_acquire_dm_session (Display *xdisplay, + int screen, + char *name, + int replace_current_dm, + Time *timestamp); + +void +decor_set_dm_check_hint (Display *xdisplay, + int screen); + +#define DECOR_SELECTION_KEEP 0 +#define DECOR_SELECTION_GIVE_UP 1 + +int +decor_handle_selection_clear (Display *xdisplay, + XEvent *xevent, + int screen); + +void +decor_handle_selection_request (Display *xdisplay, + XEvent *event, + Time dm_sn_timestamp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/options.cpp b/src/options.cpp index 982a39c..97abb1f 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -3,10 +3,9 @@ * * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> * Copyright (c) 2006 Volker Krause <vkrause@kde.org> + * Copyright (c) 2006 David Reveman <davidr@novell.com> * * Uses code of: - * Emerald window decorator (www.beryl-project.org) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) * KWin window manager (www.kde.org) * * This program is free software; you can redistribute it and/or modify @@ -30,88 +29,103 @@ #include <kconfig.h> #include <kdecoration_p.h> -Aquamarine::Options::Options (KConfig * config): -KDecorationOptions (), m_config (config) +Aquamarine::Options::Options (KConfig *config): KDecorationOptions (), mConfig (config) { d = new KDecorationOptionsPrivate; updateSettings (); } unsigned long -Aquamarine::Options::updateSettings () +Aquamarine::Options::updateSettings (void) { unsigned long changed = 0; - changed |= d->updateKWinSettings (m_config); - m_config->setGroup( "Windows" ); + changed |= d->updateKWinSettings (mConfig); + + mConfig->setGroup ("Windows"); + OpTitlebarDblClick = - windowOperation (m_config-> - readEntry ("TitlebarDoubleClickCommand", "Shade"), - true); + windowOperation (mConfig->readEntry ("TitlebarDoubleClickCommand", + "Shade"), true); d->OpMaxButtonLeftClick = - windowOperation (m_config-> - readEntry ("MaximizeButtonLeftClickCommand", - "Maximize"), true); + windowOperation (mConfig->readEntry ("MaximizeButtonLeftClickCommand", + "Maximize"), true); d->OpMaxButtonMiddleClick = - windowOperation (m_config-> - readEntry ("MaximizeButtonMiddleClickCommand", - "Maximize (vertical only)"), true); + windowOperation (mConfig->readEntry ("MaximizeButtonMiddleClickCommand", + "Maximize (vertical only)"), true); d->OpMaxButtonRightClick = - windowOperation (m_config-> - readEntry ("MaximizeButtonRightClickCommand", - "Maximize (horizontal only)"), true); + windowOperation (mConfig->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 ); + mConfig->setGroup ("MouseBindings"); - CmdTitlebarWheel = mouseWheelCommand(m_config->readEntry("CommandTitlebarWheel","Nothing")); + CmdActiveTitlebar1 = + mouseCommand (mConfig->readEntry ("CommandActiveTitlebar1", + "Raise"), true); + CmdActiveTitlebar2 = + mouseCommand (mConfig->readEntry ("CommandActiveTitlebar2", + "Lower"), true); + CmdActiveTitlebar3 = + mouseCommand (mConfig->readEntry ("CommandActiveTitlebar3", + "Operations menu"), true); + CmdInactiveTitlebar1 = + mouseCommand (mConfig->readEntry ("CommandInactiveTitlebar1", + "Activate and raise"), true); + CmdInactiveTitlebar2 = + mouseCommand (mConfig->readEntry ("CommandInactiveTitlebar2", + "Activate and lower"), true); + CmdInactiveTitlebar3 = + mouseCommand (mConfig->readEntry ("CommandInactiveTitlebar3", + "Operations menu"), true); + + CmdTitlebarWheel = + mouseWheelCommand (mConfig->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) +// 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) +Aquamarine::Options::windowOperation (const QString &name, bool restricted) { if (name == "Move") - return restricted ? Aquamarine::Options::MoveOp : - Aquamarine::Options::UnrestrictedMoveOp; + return restricted ? Aquamarine::Options::MoveOp : + Aquamarine::Options::UnrestrictedMoveOp; else if (name == "Resize") - return restricted ? Aquamarine::Options::ResizeOp : - Aquamarine::Options::UnrestrictedResizeOp; + return restricted ? Aquamarine::Options::ResizeOp : + Aquamarine::Options::UnrestrictedResizeOp; else if (name == "Maximize") - return Aquamarine::Options::MaximizeOp; + return Aquamarine::Options::MaximizeOp; else if (name == "Minimize") - return Aquamarine::Options::MinimizeOp; + return Aquamarine::Options::MinimizeOp; else if (name == "Close") - return Aquamarine::Options::CloseOp; + return Aquamarine::Options::CloseOp; else if (name == "OnAllDesktops") - return Aquamarine::Options::OnAllDesktopsOp; + return Aquamarine::Options::OnAllDesktopsOp; else if (name == "Shade") - return Aquamarine::Options::ShadeOp; + return Aquamarine::Options::ShadeOp; else if (name == "Operations") - return Aquamarine::Options::OperationsOp; + return Aquamarine::Options::OperationsOp; else if (name == "Maximize (vertical only)") - return Aquamarine::Options::VMaximizeOp; + return Aquamarine::Options::VMaximizeOp; else if (name == "Maximize (horizontal only)") - return Aquamarine::Options::HMaximizeOp; + return Aquamarine::Options::HMaximizeOp; else if (name == "Lower") - return Aquamarine::Options::LowerOp; + return Aquamarine::Options::LowerOp; return Aquamarine::Options::NoOp; } Aquamarine::Options::MouseCommand -Aquamarine::Options::mouseCommand(const QString &name, bool restricted ) +Aquamarine::Options::mouseCommand (const QString &name, + bool restricted) { - QString lowerName = name.lower(); + QString lowerName = name.lower (); + if (lowerName == "raise") return MouseRaise; if (lowerName == "lower") return MouseLower; if (lowerName == "operations menu") return MouseOperationsMenu; @@ -119,50 +133,58 @@ Aquamarine::Options::mouseCommand(const QString &name, bool restricted ) 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 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; + 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) +Aquamarine::Options::mouseWheelCommand (const QString &name) { - QString lowerName = name.lower(); + 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 == "previous/next desktop") + return MouseWheelPreviousNextDesktop; if (lowerName == "change opacity") return MouseWheelChangeOpacity; + return MouseWheelNothing; } Aquamarine::Options::MouseCommand -Aquamarine::Options::wheelToMouseCommand(MouseWheelCommand com, int delta) +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; + 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 index 4feb6dc..38ee58a 100644 --- a/src/options.h +++ b/src/options.h @@ -3,10 +3,9 @@ * * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> * Copyright (c) 2006 Volker Krause <vkrause@kde.org> + * Copyright (c) 2006 David Reveman <davidr@novell.com> * * Uses code of: - * Emerald window decorator (www.beryl-project.org) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) * KWin window manager (www.kde.org) * * This program is free software; you can redistribute it and/or modify @@ -25,8 +24,8 @@ * */ -#ifndef AQUAMARINE_OPTIONS_H -#define AQUAMARINE_OPTIONS_H +#ifndef _OPTIONS_H +#define _OPTIONS_H #include <kdecoration.h> @@ -35,89 +34,108 @@ class KConfig; namespace Aquamarine { - class Options : public KDecorationOptions +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 - }; + 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); - Options (KConfig * config); - virtual unsigned long updateSettings (); + virtual unsigned long updateSettings (void); - WindowOperation operationTitlebarDblClick () - { - return OpTitlebarDblClick; - } + WindowOperation operationTitlebarDblClick (void) + { + 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 commandActiveTitlebar1 (void) + { + return CmdActiveTitlebar1; + } + MouseCommand commandActiveTitlebar2 (void) + { + return CmdActiveTitlebar2; + } + MouseCommand commandActiveTitlebar3 (void) + { + return CmdActiveTitlebar3; + } + MouseCommand commandInactiveTitlebar1 (void) + { + return CmdInactiveTitlebar1; + } + MouseCommand commandInactiveTitlebar2 (void) + { + return CmdInactiveTitlebar2; + } + MouseCommand commandInactiveTitlebar3 (void) + { + return CmdInactiveTitlebar3; + } - MouseCommand operationTitlebarMouseWheel( int delta ) - { - return wheelToMouseCommand( CmdTitlebarWheel, delta ); - } + 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: + 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; + private: + KDecorationDefines::WindowOperation OpTitlebarDblClick; + MouseCommand CmdActiveTitlebar1; + MouseCommand CmdActiveTitlebar2; + MouseCommand CmdActiveTitlebar3; + MouseCommand CmdInactiveTitlebar1; + MouseCommand CmdInactiveTitlebar2; + MouseCommand CmdInactiveTitlebar3; + MouseWheelCommand CmdTitlebarWheel; - KConfig *m_config; + KConfig *mConfig; }; } diff --git a/src/switcher.cpp b/src/switcher.cpp deleted file mode 100644 index 02523fb..0000000 --- a/src/switcher.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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); - - - Pixmap pix = m_qpixmap.handle (); - XGCValues gcv; - gcv.foreground = 0x00000000; - gcv.plane_mask = 0xffffffff; - GC gc = XCreateGC (qt_xdisplay (), pix, GCForeground, &gcv); - - XFillRectangle (qt_xdisplay (), pix, gc, 0, 0, - width + LEFT + RIGHT, height + TOP + BOTTOM); - - XFreeGC (qt_xdisplay (), gc); - - 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++ = DECOR_INTERFACE_VERSION; - 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) | (0 << 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) | (0 << 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) | (0 << 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) | (0 << 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 deleted file mode 100644 index 8577c77..0000000 --- a/src/switcher.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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 index 9761055..0aebc12 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -3,10 +3,9 @@ * * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> * Copyright (c) 2006 Volker Krause <vkrause@kde.org> + * Copyright (c) 2006 David Reveman <davidr@novell.com> * * Uses code of: - * Emerald window decorator (www.beryl-project.org) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) * KWin window manager (www.kde.org) * * This program is free software; you can redistribute it and/or modify @@ -30,497 +29,170 @@ #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; +static int trappedErrorCode = 0; 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; - - Atom change_frame_window; - + Atom switchSelectWindow; + Atom netFrameWindow; + Atom netWindowDecor; + Atom netWindowDecorNormal; + Atom netWindowDecorActive; + Atom netWindowDecorBare; + Atom wmTakeFocus; + Atom netWmContextHelp; + Atom wmProtocols; Atom toolkitActionAtom; Atom toolkitActionWindowMenuAtom; Atom toolkitActionMainMenuAtom; Atom toolkitActionRunDialogAtom; Atom toolkitActionForceQuitDialogAtom; - + Atom wmSn; + Atom wmName; + Atom netDesktopViewport; + Atom netDesktopGeometry; + + Atom netWmWindowOpacity; + Atom netWmWindowSaturation; + Atom netWmWindowBrightness; } } -static int (*old_error_handler) (Display * d, XErrorEvent * e); -static int -xErrorHandler (Display *, XErrorEvent * error) +static int (*oldErrorHandler) (Display *display, XErrorEvent *error); + +static int xErrorHandler (Display *display, XErrorEvent *error) { - trapped_error_code = error->error_code; + (void) display; + trappedErrorCode = error->error_code; return 0; } -void -Aquamarine::trapXError (void) +void Aquamarine::trapXError (void) { - trapped_error_code = 0; - old_error_handler = XSetErrorHandler (xErrorHandler); + trappedErrorCode = 0; + oldErrorHandler = XSetErrorHandler (xErrorHandler); } -int -Aquamarine::popXError (void) +int Aquamarine::popXError (void) { - XSetErrorHandler (old_error_handler); - return trapped_error_code; + XSync (qt_xdisplay(), false); + XSetErrorHandler (oldErrorHandler); + + return trappedErrorCode; } -void * -Aquamarine::readXProperty (WId window, Atom property, Atom type, int *items) +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; + long offset = 0, length = 2048L; + Atom actualType; + int format; + unsigned long nItems, bytesRemaining; unsigned char *data = 0l; + int result; Aquamarine::trapXError (); - int result = - XGetWindowProperty (qt_xdisplay (), window, property, offset, length, - false, type, - &actual_type, &actual_format, &nitems, - &bytes_remaining, &data); + result = XGetWindowProperty (qt_xdisplay (), window, property, offset, + length, false, type, + &actualType, &format, &nItems, + &bytesRemaining, &data); if (Aquamarine::popXError ()) - return NULL; - if (result == Success && actual_type == type - && actual_format == 32 && nitems > 0) + return NULL; + + if (result == Success && actualType == type && format == 32 && nItems > 0) { - if (items) - *items = nitems; + if (items) + *items = nItems; - return reinterpret_cast < void *>(data); + return reinterpret_cast <void *>(data); } if (data) - XFree (data); + XFree (data); if (items) - *items = 0; + *items = 0; return NULL; } -bool -Aquamarine::readWindowProperty (long window, long property, long *value) +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); + if (value) + *value = *reinterpret_cast <int *>(data); + + XFree (data); - return true; + return true; } return false; } -unsigned short -Aquamarine::readWindowPropertyDefault (WId id, Atom property, - unsigned short defaultValue) +unsigned short Aquamarine::readPropertyShort (WId id, + Atom property, + unsigned short defaultValue) { - Atom actual; - int result, format; + Atom actual; + int result, format; unsigned long n, left; unsigned char *data; + Aquamarine::trapXError (); result = XGetWindowProperty (qt_xdisplay (), id, property, - 0L, 1L, FALSE, XA_CARDINAL, &actual, &format, - &n, &left, &data); + 0L, 1L, FALSE, XA_CARDINAL, &actual, &format, + &n, &left, &data); + if (Aquamarine::popXError ()) + return defaultValue; if (result == Success && n && data) { - CARD32 value; + unsigned int value; - memcpy (&value, data, sizeof (CARD32)); + memcpy (&value, data, sizeof (unsigned int)); - XFree (data); + XFree (data); - return value >> 16; + return value >> 16; } return defaultValue; } -void -Aquamarine::setWindowProperty (WId id, Atom property, unsigned short value) -{ - CARD32 value32; - - value32 = value << 16 | value; - - XEvent ev; - - memset (&ev, 0, sizeof (ev)); - ev.xclient.type = ClientMessage; - ev.xclient.window = id; - ev.xclient.message_type = property; - ev.xclient.format = 32; - ev.xclient.data.l[0] = value32; - ev.xclient.data.l[1] = 0; - ev.xclient.data.l[2] = 0; - ev.xclient.data.l[3] = 0; - ev.xclient.data.l[4] = 0; - - XSendEvent (qt_xdisplay (), qt_xrootwin(), False, - SubstructureRedirectMask | SubstructureNotifyMask, &ev); -} - - - -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) +void Aquamarine::Atoms::init (void) { - 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); - - change_frame_window = - XInternAtom (xdisplay, "_BERYL_CHANGE_FRAME_WINDOW", false); - + Display *xdisplay = qt_xdisplay (); + + netFrameWindow = XInternAtom (xdisplay, "_NET_FRAME_WINDOW", false); + netWindowDecor = XInternAtom (xdisplay, "_NET_WINDOW_DECOR", false); + netWindowDecorNormal = + XInternAtom (xdisplay, "_NET_WINDOW_DECOR_NORMAL", false); + netWindowDecorActive = + XInternAtom (xdisplay, "_NET_WINDOW_DECOR_ACTIVE", false); + netWindowDecorBare = + XInternAtom (xdisplay, "_NET_WINDOW_DECOR_BARE", false); + switchSelectWindow = XInternAtom (xdisplay, "_SWITCH_SELECT_WINDOW", false); + wmTakeFocus = XInternAtom (xdisplay, "WM_TAKE_FOCUS", false); + netWmContextHelp = + XInternAtom (xdisplay, "_NET_WM_CONTEXT_HELP", false); + wmProtocols = XInternAtom (xdisplay, "WM_PROTOCOLS", false); + netWmWindowOpacity = + XInternAtom (xdisplay, "_NET_WM_WINDOW_OPACITY", false); toolkitActionAtom = XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION", false); toolkitActionWindowMenuAtom = XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_WINDOW_MENU", false); @@ -529,6 +201,20 @@ Aquamarine::Atoms::init () toolkitActionRunDialogAtom = XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_RUN_DIALOG", false); toolkitActionForceQuitDialogAtom = - XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_FORCE_QUIT_DIALOG", false); - + XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_FORCE_QUIT_DIALOG", + false); + + wmName = XInternAtom (xdisplay, "_NET_WM_NAME", false); + char buf[128]; + sprintf(buf,"WM_S%d",qt_xscreen()); + wmSn = XInternAtom (xdisplay, buf, false); + + netDesktopViewport = + XInternAtom (xdisplay, "_NET_DESKTOP_VIEWPORT", false); + netDesktopGeometry = + XInternAtom (xdisplay, "_NET_DESKTOP_GEOMETRY", false); + + netWmWindowOpacity = XInternAtom (xdisplay, "_NET_WM_WINDOW_OPACITY", false); + netWmWindowBrightness = XInternAtom (xdisplay, "_NET_WM_WINDOW_BRIGHTNESS", false); + netWmWindowSaturation = XInternAtom (xdisplay, "_NET_WM_WINDOW_SATURATION", false); } diff --git a/src/utils.h b/src/utils.h index 1c64ad1..e71a73c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -3,10 +3,9 @@ * * Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> * Copyright (c) 2006 Volker Krause <vkrause@kde.org> + * Copyright (c) 2006 David Reveman <davidr@novell.com> * * Uses code of: - * Emerald window decorator (www.beryl-project.org) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) * KWin window manager (www.kde.org) * * This program is free software; you can redistribute it and/or modify @@ -23,86 +22,53 @@ * 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 +#ifndef _UTILS_H +#define _UTILS_H #include <X11/Xlib.h> #include <fixx11h.h> - #include <qwidget.h> namespace Aquamarine { namespace Atoms { - extern Atom select_window; - - 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; - - extern Atom change_frame_window; - + extern Atom switchSelectWindow; + extern Atom netFrameWindow; + extern Atom netWindowDecor; + extern Atom netWindowDecorNormal; + extern Atom netWindowDecorActive; + extern Atom netWindowDecorBare; + extern Atom wmTakeFocus; + extern Atom netWmContextHelp; + extern Atom wmProtocols; extern Atom toolkitActionAtom; extern Atom toolkitActionWindowMenuAtom; extern Atom toolkitActionMainMenuAtom; extern Atom toolkitActionRunDialogAtom; extern Atom toolkitActionForceQuitDialogAtom; - - 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); + extern Atom wmSn; + extern Atom wmName; + extern Atom netDesktopViewport; + extern Atom netDesktopGeometry; + + extern Atom netWmWindowOpacity; + extern Atom netWmWindowSaturation; + extern Atom netWmWindowBrightness; + + void init (void); + } + + 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); + unsigned short readPropertyShort (WId id, + Atom property, + unsigned short defaultValue); } #endif diff --git a/src/window.cpp b/src/window.cpp index d3b9658..18bc1fe 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,29 +1,28 @@ /* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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. - * - */ +* Aquamarine the KDE window decorator +* +* Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> +* Copyright (c) 2006 Volker Krause <vkrause@kde.org> +* Copyright (c) 2006 David Reveman <davidr@novell.com> +* +* Uses code of: +* 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" @@ -32,19 +31,14 @@ #include "settings.h" #include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xcomposite.h> #include <X11/extensions/shape.h> -#include <X11/extensions/Xrender.h> - -#include <math.h> +#include <X11/extensions/Xcomposite.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> @@ -52,8 +46,6 @@ #include <kprocess.h> #include <kstandarddirs.h> -#include <netwm.h> - #include <qapplication.h> #include <qlayout.h> #include <qevent.h> @@ -65,707 +57,642 @@ #include <qcursor.h> #include <qpopupmenu.h> -#define BERYL_ADVANCED_DECORATION_VERSION 10121980 - -#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): -QWidget(0,0,Qt::WX11BypassWM), -m_wid (wid), -m_active (false), -m_deco (0), -m_fakeMaximized (false), -m_shapeSet (false), -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), -mProcessKiller (0) -{ - 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); - - setBackgroundColor(QColor(0,0)); - - double op = Settings::shadowOpacity() / 100.0; - op *= 0xffff; - - m_sradius = Settings::shadowRadius(); - QColor color = Settings::shadowColor(); - m_scolor[0] = short((color.red() / 256.0) * 0xffff); - m_scolor[1] = short((color.green() / 256.0) * 0xffff); - m_scolor[2] = short((color.blue() / 256.0) * 0xffff); - m_scolor[3] = short(op); - - int offX = Settings::shadowOffsetX(); - int offY = Settings::shadowOffsetY(); - offX = KMAX(-m_sradius,KMIN(m_sradius,offX)); - offY = KMAX(-m_sradius,KMIN(m_sradius,offY)); - - if (Settings::drawShadows()) - m_soffset.setCoords(-m_sradius + offX,-m_sradius + offY, - m_sradius + offX,m_sradius + offY); - else - m_soffset.setCoords(0,0,0,0); +Aquamarine::Window::Window (QWidget *parent, WId clientId, WId frame, Type type, + int x, int y, int w, int h): QWidget (parent, 0), + mType (type), + mFrame (0), + mClientId (clientId), + mSelectedId (0), + mDecor (0), + mPixmap (0), + mDamageId (0), + mShadow (0), + mPicture (0), + mTexturePicture (0), + mDecorationPicture (0), + mUpdateProperty (false), + mShapeSet (false), + mUniqueHorzShape (false), + mUniqueVertShape (false), + mPopup (0), + mAdvancedMenu (0), + mDesktopMenu (0), + mViewportMenu (0), + mAppearanceMenu (0), + mBrightnessMenu (0), + mSaturationMenu (0), + mOpacityMenu (0), + mMapped (false), + mPendingMap (0), + mPendingConfigure (0), + mProcessKiller (0) +{ + if (mType == Normal || mType == Switcher) + { + KWin::WindowInfo wInfo = KWin::windowInfo (mClientId, NET::WMState, 0); - m_currentPixmap = None; - m_updatePixmap = true; - m_mapped = true; + mState = wInfo.state (); - setWState (Qt::WState_Visible); - updateFrame (frame); + if (mType == Normal) + { + mName = KWin::readNameProperty (mClientId, XA_WM_NAME); + mIcons = QIconSet (KWin::icon (mClientId, 16, 16, TRUE), + KWin::icon (mClientId, 32, 32, TRUE)); + mOpacity = readPropertyShort (mClientId, Atoms::netWmWindowOpacity, + 0xffff); + } + else + { + mIcons = QIconSet (); + mName = QString (""); + } - int x, y; - unsigned int width, height, border, depth; - installEventFilter(this); + updateFrame (frame); - ::Window root; - XGetGeometry (qt_xdisplay (), m_wid, &root, &x, &y, &width, &height, - &border, &depth); - m_geometry = QRect (x, y, width, height); + mGeometry = QRect (x, y, w, h); getWindowProtocols (); + } + else + { + mIcons = QIconSet (); + mName = QString (""); + mGeometry = QRect (50, 50, 30, 1); + } + + setGeometry (QRect (mGeometry.x () + ROOT_OFF_X, + mGeometry.y () + ROOT_OFF_Y, + mGeometry.width (), mGeometry.height ())); + createDecoration (); + + mActiveChild = NULL; } -Aquamarine::Window::~Window () +Aquamarine::Window::~Window (void) { - delete m_deco; - delete m_popup; + if (mShadow) + decor_shadow_destroy (qt_xdisplay (), mShadow); - Atom my_atom = Atoms::net_window_decor; + if (mPicture) + XRenderFreePicture (qt_xdisplay (), mPicture); - Aquamarine::trapXError (); - XWindowAttributes - attr; - if (XGetWindowAttributes (qt_xdisplay (), m_wid, &attr) - && !Aquamarine::popXError ()) - { - XDeleteProperty (qt_xdisplay (), m_wid, my_atom); - } + if (mTexturePicture) + XRenderFreePicture (qt_xdisplay (), mTexturePicture); - if (m_currentPixmap != None) - XFreePixmap (qt_xdisplay(), m_currentPixmap); + if (mDecorationPicture) + XRenderFreePicture (qt_xdisplay (), mDecorationPicture); + if (mDecor) + delete mDecor; - Aquamarine::popXError (); -} - + if (mPopup) + delete mPopup; + if (mProcessKiller) + delete mProcessKiller; +} bool -Aquamarine::Window::isActive () const +Aquamarine::Window::isActive (void) const { - return m_active; + if (mType == DefaultActive) + return true; + + return Decorator::activeId () == mClientId; } bool -Aquamarine::Window::isCloseable () const +Aquamarine::Window::isCloseable (void) const { - return true; + if (mType != Normal) + return false; + + return true; } bool -Aquamarine::Window::isMaximizable () const +Aquamarine::Window::isMaximizable (void) const { - return true; + if (mType != Normal) + return false; + + return true; } -KDecoration::MaximizeMode Aquamarine::Window::maximizeMode () const +KDecoration::MaximizeMode +Aquamarine::Window::maximizeMode (void) const { - if (m_fakeMaximized) - return MaximizeVertical | MaximizeHorizontal; + MaximizeMode mode = MaximizeRestore; - MaximizeMode cur = ((m_state & NET::MaxVert) - ? MaximizeVertical : MaximizeRestore) | - ((m_state & NET::MaxHoriz) ? MaximizeHorizontal : MaximizeRestore); - return cur; + if (mType != Normal) + return mode; + + mode = + ((mState & NET::MaxVert) ? MaximizeVertical : MaximizeRestore) | + ((mState & NET::MaxHoriz) ? MaximizeHorizontal : MaximizeRestore); + + return mode; } bool -Aquamarine::Window::isMinimizable () const +Aquamarine::Window::isMinimizable (void) const { - return true; + if (mType != Normal) + return false; + + return true; } bool -Aquamarine::Window::providesContextHelp () const +Aquamarine::Window::providesContextHelp (void) const { - return m_supportContextHelp; + if (mType != Normal) + return false; + + return mSupportContextHelp; } int -Aquamarine::Window::desktop () const +Aquamarine::Window::desktop (void) const { - return (m_state & NET::Sticky) ? NET::OnAllDesktops : 1; + KWin::WindowInfo wInfo = KWin::windowInfo (mClientId, NET::WMDesktop, 0); + + return wInfo.desktop (); } bool -Aquamarine::Window::isModal () const +Aquamarine::Window::isModal (void) const { - return m_state & NET::Modal; + return mState & NET::Modal; } bool -Aquamarine::Window::isShadeable () const +Aquamarine::Window::isShadeable (void) const { - return true; + KWin::WindowInfo wInfo = KWin::windowInfo (mClientId, NET::WMPid, + NET::WM2AllowedActions); + + return wInfo.actionSupported (NET::ActionShade); } bool -Aquamarine::Window::isShade () const +Aquamarine::Window::isShade (void) const { - return (m_state & NET::Shaded); + if (mType != Normal) + return false; + + return (mState & NET::Shaded); } bool -Aquamarine::Window::isSetShade () const +Aquamarine::Window::isSetShade (void) const { - return isShade (); + return isShade (); } bool -Aquamarine::Window::keepAbove () const +Aquamarine::Window::keepAbove (void) const { - return (m_state & NET::KeepAbove); + if (mType != Normal) + return false; + + return (mState & NET::KeepAbove); } bool -Aquamarine::Window::keepBelow () const +Aquamarine::Window::keepBelow (void) const { - return (m_state & NET::KeepBelow); + if (mType != Normal) + return false; + + return (mState & NET::KeepBelow); } bool -Aquamarine::Window::isMovable () const +Aquamarine::Window::isMovable (void) const { - return true; + KWin::WindowInfo wInfo = KWin::windowInfo (mClientId, NET::WMPid, + NET::WM2AllowedActions); + + return wInfo.actionSupported (NET::ActionMove); } -NET::WindowType Aquamarine::Window::windowType (unsigned long) const +NET::WindowType +Aquamarine::Window::windowType (unsigned long mask) const { - return NET::Normal; + KWin::WindowInfo wInfo = KWin::windowInfo (mClientId, NET::WMWindowType, 0); + + return wInfo.windowType (mask); } bool -Aquamarine::Window::isResizable () const +Aquamarine::Window::isResizable (void) const { - return true; + KWin::WindowInfo wInfo = KWin::windowInfo (mClientId, NET::WMPid, + NET::WM2AllowedActions); + + return wInfo.actionSupported (NET::ActionResize); } QIconSet -Aquamarine::Window::icon () const +Aquamarine::Window::icon (void) const { - return m_icons; + return mIcons; } QString -Aquamarine::Window::caption () const +Aquamarine::Window::caption (void) const { - return m_name; + return mName; } +/* TODO: We should use libtaskmanager, which is part of kdebase to create +the window menu instead but the headers for that library are currently +not installed. If kdebase could install those headers, we wouldn't have +to have our own window menu implementaion here. */ 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); + if (!mPopup) + { + mPopup = new QPopupMenu (); + mPopup->setCheckable (true); + mPopup->setFont (KGlobalSettings::menuFont ()); + + mAdvancedMenu = new QPopupMenu (mPopup); + mAdvancedMenu->setCheckable (true); + mAdvancedMenu->setFont (KGlobalSettings::menuFont ()); + + connect (mAdvancedMenu, SIGNAL (activated (int)), + SLOT (handlePopupActivated (int))); + + mAdvancedMenu->insertItem (SmallIconSet ("up"), + i18n ("Keep &Above Others"), + Options::KeepAboveOp); + mAdvancedMenu->insertItem (SmallIconSet ("down"), + i18n ("Keep &Below Others"), + Options::KeepBelowOp); + mAdvancedMenu->insertItem (SmallIconSet ("window_fullscreen"), + i18n ("&Fullscreen"), + Options::FullScreenOp); + + mPopup->insertItem (i18n ("Ad&vanced"), mAdvancedMenu); + + mDesktopMenu = new QPopupMenu (mPopup); + mDesktopMenu->setCheckable (true); + mDesktopMenu->setFont (KGlobalSettings::menuFont ()); + + connect (mDesktopMenu, SIGNAL (activated (int)), + SLOT (handleDesktopPopupActivated (int))); + + mPopup->insertItem (i18n ("To &Desktop"), mDesktopMenu, Options::NoOp); + + mViewportMenu = new QPopupMenu (mPopup); + mViewportMenu->setCheckable (true); + mViewportMenu->setFont (KGlobalSettings::menuFont ()); + connect (mViewportMenu, SIGNAL (activated (int)), + SLOT (handleChangeViewport (int))); + + mViewportMenu->insertItem (i18n ("On all Viewports"), 0); + mViewportMenu->insertSeparator (); + for (int i = 1; i <= + Decorator::viewports ().height () * + Decorator::viewports ().width (); ++i) + mViewportMenu->insertItem (i18n ("Move to Viewport %1").arg (i), + i); + + mPopup->insertItem (i18n ("To Viewport"), mViewportMenu); + + mAppearanceMenu = new QPopupMenu (mPopup); + mAppearanceMenu->setFont (KGlobalSettings::menuFont ()); + + mOpacityMenu = new QPopupMenu (mAppearanceMenu); + mOpacityMenu->setFont (KGlobalSettings::menuFont ()); + mOpacityMenu->insertItem ("25%", ChangeOpacity25); + mOpacityMenu->insertItem ("50%", ChangeOpacity50); + mOpacityMenu->insertItem ("75%", ChangeOpacity75); + mOpacityMenu->insertItem ("100%", ChangeOpacity100); + + mBrightnessMenu = new QPopupMenu (mAppearanceMenu); + mBrightnessMenu->setFont (KGlobalSettings::menuFont ()); + mBrightnessMenu->insertItem ("25%", ChangeBrightness25); + mBrightnessMenu->insertItem ("50%", ChangeBrightness50); + mBrightnessMenu->insertItem ("75%", ChangeBrightness75); + mBrightnessMenu->insertItem ("100%", ChangeBrightness100); + + mSaturationMenu = new QPopupMenu (mAppearanceMenu); + mSaturationMenu->setFont (KGlobalSettings::menuFont ()); + mSaturationMenu->insertItem ("25%", ChangeSaturation25); + mSaturationMenu->insertItem ("50%", ChangeSaturation50); + mSaturationMenu->insertItem ("75%", ChangeSaturation75); + mSaturationMenu->insertItem ("100%", ChangeSaturation100); + + mAppearanceMenu->insertItem (i18n ("Opacity"), mOpacityMenu); + mAppearanceMenu->insertItem (i18n ("Brightness"), + mBrightnessMenu); + mAppearanceMenu->insertItem (i18n ("Saturation"), + mSaturationMenu); + mAppearanceMenu->insertSeparator (); + mAppearanceMenu->insertItem (i18n ("Reset settings"), ResetValues); + + mPopup->insertItem (i18n ("Appearance"), mAppearanceMenu); + + connect (mAppearanceMenu, SIGNAL (activated (int)), + SLOT (handleAppearanceChange (int))); + connect (mOpacityMenu, SIGNAL (activated (int)), + SLOT (handleAppearanceChange (int))); + connect (mBrightnessMenu, SIGNAL (activated (int)), + SLOT (handleAppearanceChange (int))); + connect (mSaturationMenu, SIGNAL (activated (int)), + SLOT (handleAppearanceChange (int))); + + + mPopup->insertItem (SmallIconSet ("move"), i18n ("&Move"), + Options::MoveOp); + mPopup->insertItem (i18n ("Re&size"), Options::ResizeOp); + + mPopup->insertItem (i18n ("Mi&nimize"), Options::MinimizeOp); + mPopup->insertItem (i18n ("Ma&ximize"), Options::MaximizeOp); + mPopup->insertItem (i18n ("Sh&ade"), Options::ShadeOp); + + mPopup->insertSeparator (); + + mPopup->insertItem (SmallIconSet ("fileclose"), i18n ("&Close"), + Options::CloseOp); + + connect (mPopup, SIGNAL (aboutToShow ()), + SLOT (handlePopupAboutToShow ())); + connect (mPopup, SIGNAL (activated (int)), + SLOT (handlePopupActivated (int))); + } + + mPopup->exec (pos); } void -Aquamarine::Window::showWindowMenu (const QRect & pos) +Aquamarine::Window::showWindowMenu (const QRect &pos) { - showWindowMenu (pos.bottomLeft ()); + 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); +Aquamarine::Window::processMousePressEvent (QMouseEvent *qme) +{ + Options::MouseCommand com = Options::MouseNothing; + bool active = isActive (); + + if (!mSupportTakeFocus) + 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 (); + default: + break; + } + + if (qme->button () == Qt::LeftButton) + { + // actions where it's not possible to get the matching release event + if (com != Options::MouseOperationsMenu && + com != Options::MouseMinimize) + { + moveWindow (qme); + return; + } + } + + 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: - { - 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; - } + 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 (mState & NET::FullScreen) + KWin::clearState (mClientId, NET::FullScreen); + else + KWin::setState (mClientId, NET::FullScreen); + break; + case KDecoration::MoveOp: + Decorator::rootInfo ()->moveResizeRequest (mClientId, + mGeometry.x () + + mGeometry.width () / 2, + mGeometry.y () + + mGeometry.height () / 2, + NET::KeyboardMove); + break; + case KDecoration::ResizeOp: + Decorator::rootInfo ()->moveResizeRequest (mClientId, + mGeometry.x () + + mGeometry.width () / 2, + mGeometry.y () + + mGeometry.height () / 2, + NET::KeyboardSize); + default: + break; + } } -void -Aquamarine::Window::setMask (const QRegion & reg, int) +bool +Aquamarine::Window::isPreview (void) const { - kdDebug () << k_funcinfo << endl; - - int top, bottom, left, right; - m_deco->borders (left, right, top, bottom); - - if (m_shapeSet) - m_shapeChange += m_shape.eor(reg); - else - m_shapeChange = reg; - - m_shape = QRegion (reg); - m_shapeSet = true; - - if (m_deco) - m_deco->widget()->setMask(reg); - - QRegion moved = QRegion (reg); - moved.translate(-m_soffset.left(),-m_soffset.top()); - - XShapeCombineRegion (qt_xdisplay (), handle(), ShapeInput, 0, 0, - moved.handle (), ShapeSet); - - //renderShadow(); + return false; } -bool -Aquamarine::Window::isPreview () const +QRect +Aquamarine::Window::geometry (void) const { - return false; + QRect rect = QWidget::geometry (); + + return QRect (rect.x () - ROOT_OFF_X, + rect.y () - ROOT_OFF_Y, + rect.width (), + rect.height ()); } QRect -Aquamarine::Window::geometry () const +Aquamarine::Window::iconGeometry (void) 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; + return QRect (); } QRect -Aquamarine::Window::iconGeometry () const +Aquamarine::Window::clientGeometry (void) { - return QRect (); + QRect frame = geometry (); + + return QRect (frame.x () + mBorder.left, + frame.y () + mBorder.top, + frame.width () - mBorder.left - mBorder.right, + frame.height () - mBorder.top - mBorder.bottom); } QRegion Aquamarine::Window::unobscuredRegion (const QRegion & r) const { - return r; + return r; } QWidget * -Aquamarine::Window::workspaceWidget () const +Aquamarine::Window::workspaceWidget (void) const { - return 0; + return const_cast <Window *> (this); } WId -Aquamarine::Window::windowId () const +Aquamarine::Window::windowId (void) const { - return m_wid; + return mClientId; } 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); - } +Aquamarine::Window::closeWindow (void) +{ + Decorator::rootInfo ()->closeWindowRequest (mClientId); } 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)); + KWin::setState (mClientId, + ((mode & MaximizeVertical) ? NET::MaxVert : 0) | + ((mode & MaximizeHorizontal) ? NET::MaxHoriz : 0)); + KWin::clearState (mClientId, + ((mode & MaximizeVertical) ? 0 : NET::MaxVert) | + ((mode & MaximizeHorizontal) ? 0 : NET::MaxHoriz)); } void -Aquamarine::Window::minimize () +Aquamarine::Window::minimize (void) { - kdDebug () << k_funcinfo << endl; - KWin::iconifyWindow (m_wid, false); + KWin::iconifyWindow (mClientId, false); } void -Aquamarine::Window::showContextHelp () +Aquamarine::Window::showContextHelp (void) { - kdDebug () << k_funcinfo << endl; - if (m_supportContextHelp) - { - Aquamarine::Decorator::sendClientMessage (m_wid, Atoms::wm_protocols, - Atoms::net_wm_context_help); - } + if (mSupportContextHelp) + Aquamarine::Decorator::sendClientMessage (mClientId, mClientId, + Atoms::wmProtocols, + Atoms::netWmContextHelp); } void -Aquamarine::Window::titlebarDblClickOperation () +Aquamarine::Window::titlebarDblClickOperation (void) { - kdDebug () << k_funcinfo << endl; - performWindowOperation (Aquamarine::Decorator::options ()-> - operationTitlebarDblClick ()); + WindowOperation op; + + op = Aquamarine::Decorator::options ()->operationTitlebarDblClick (); + performWindowOperation (op); } 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); - } + KWin::setOnDesktop (mClientId, desktop); } 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); + if (set) + { + KWin::clearState (mClientId, NET::KeepAbove); + KWin::setState (mClientId, NET::KeepBelow); + } + else + { + KWin::clearState (mClientId, 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); + if (set) + { + KWin::clearState (mClientId, NET::KeepBelow); + KWin::setState (mClientId, NET::KeepAbove); + } + else + { + KWin::clearState (mClientId, 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 (); + if (set) + KWin::setState (mClientId, NET::Shaded); + else + KWin::clearState (mClientId, NET::Shaded); + + mDecor->shadeChange (); } void Aquamarine::Window::titlebarMouseWheelOperation (int delta) { - kdDebug () << k_funcinfo << endl; - performMouseCommand( Decorator::options()->operationTitlebarMouseWheel( delta ), 0); -} + Options::MouseCommand com; + com = Decorator::options()->operationTitlebarMouseWheel (delta); + performMouseCommand (com, 0); +} int -Aquamarine::Window::currentDesktop () const +Aquamarine::Window::currentDesktop (void) const { - return 1; + return KWin::currentDesktop (); } QWidget * -Aquamarine::Window::initialParentWidget () const +Aquamarine::Window::initialParentWidget (void) const { - return const_cast < Window * >(this); + return const_cast <Window *> (this); } -Qt::WFlags Aquamarine::Window::initialWFlags () const +Qt::WFlags +Aquamarine::Window::initialWFlags (void) const { - return 0; + return 0; } void @@ -779,1111 +706,1429 @@ Aquamarine::Window::grabXServer (bool) } void -Aquamarine::Window::createDecoration () +Aquamarine::Window::createDecoration (void) { - if (m_deco) - return; - KDecoration * - deco = Decorator::pluginManager ()->createDecoration (this); - deco->init (); - deco->widget()->move(-m_soffset.left(),-m_soffset.top()); - m_deco = deco; - m_deco->widget()->installEventFilter(this); - resizeDecoration (); + KDecoration *decor; - updateFrame(m_frame); + if (mDecor) + return; + + decor = Decorator::pluginManager ()->createDecoration (this); + decor->init (); + + mDecor = decor; + + if (mType == Normal && mFrame) + { + Aquamarine::trapXError (); + XSelectInput (qt_xdisplay (), mFrame, + StructureNotifyMask | PropertyChangeMask | + ButtonPressMask | ButtonReleaseMask | PointerMotionMask | + EnterWindowMask | LeaveWindowMask); + if (Aquamarine::popXError ()) + return; + } + + resizeDecoration (true); } -void -Aquamarine::Window::resizeDecoration () -{ - int top, bottom, left, right; - m_deco->borders (left, right, top, bottom); +static void +fillQRegion (Display *xdisplay, + Picture picture, + int clipX1, + int clipY1, + int clipX2, + int clipY2, + int xOff, + int yOff, + QRegion *region) +{ + static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; + QMemArray <QRect> rects = region->rects (); + QMemArray <QRect>::ConstIterator it; + int x1, y1, x2, y2; + + for (it = rects.begin (); it != rects.end (); it++) + { + x1 = it->x (); + y1 = it->y (); + x2 = x1 + it->width (); + y2 = y1 + it->height (); + + if (x1 < clipX1) + x1 = clipX1; + if (y1 < clipY1) + y1 = clipY1; + if (x2 > clipX2) + x2 = clipX2; + if (y2 > clipY2) + y2 = clipY2; + + if (x1 < x2 && y1 < y2) + XRenderFillRectangle (xdisplay, PictOpSrc, picture, &white, + xOff + x1, + yOff + y1, + x2 - x1, + y2 - y1); + } +} + +static void +drawBorderShape (Display *xdisplay, + Pixmap pixmap, + Picture picture, + int width, + int height, + decor_context_t *c, + void *closure) +{ + static XRenderColor clear = { 0x0000, 0x0000, 0x0000, 0x0000 }; + static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; + Aquamarine::Window *w = (Aquamarine::Window *) closure; + QRegion *shape; + bool uniqueHorzShade; + bool uniqueVertShade; + int xOffLeft, yOffTop, xOffRight, yOffBottom; + QRect rect = w->geometry (); + int x1, y1, x2, y2; + + (void) pixmap; - kdDebug () << k_funcinfo << endl; + XRenderFillRectangle (xdisplay, PictOpSrc, picture, &clear, + 0, 0, width, height); - m_updatePixmap = true; + shape = w->getShape (); + w->getShapeInfo (&uniqueHorzShade, &uniqueVertShade); - move (m_geometry.x() - left + m_soffset.left(), - m_geometry.y() - top + m_soffset.top()); + xOffLeft = c->left_space - c->extents.left; + yOffTop = c->top_space - c->extents.top; - if (m_geometry.width () + left + right + m_soffset.width() != width() || - m_geometry.height () + top + bottom + m_soffset.height() != height()) + xOffRight = c->left_space - c->extents.left; + yOffBottom = c->top_space - c->extents.top; + + x1 = c->left_space; + y1 = c->top_space; + x2 = width - c->right_space; + y2 = height - c->bottom_space; + + if (shape) + { + if (uniqueHorzShade && uniqueVertShade) + { + fillQRegion (xdisplay, picture, + 0, 0, + rect.width (), rect.height (), + xOffLeft, yOffTop, shape); + } + else { - m_shapeSet = false; - resize (m_geometry.width () + left + right + m_soffset.width(), - m_geometry.height () + top + bottom + m_soffset.height()); + if (!uniqueHorzShade) + xOffRight = x2 - (rect.width () - c->extents.right); - m_deco->resize (QSize(m_geometry.width () + left + right, - m_geometry.height () + top + bottom)); + if (!uniqueVertShade) + yOffBottom = y2 - (rect.height () - c->extents.bottom); + + if (uniqueHorzShade) + { + fillQRegion (xdisplay, picture, + 0, 0, + rect.width (), c->extents.top, + xOffLeft, yOffTop, shape); + fillQRegion (xdisplay, picture, + 0, rect.height () - c->extents.bottom, + rect.width (), rect.height (), + xOffLeft, yOffBottom, shape); + } + else + { + fillQRegion (xdisplay, picture, + 0, 0, + c->extents.left, c->extents.top, + xOffLeft, yOffTop, shape); + fillQRegion (xdisplay, picture, + rect.width () - c->extents.right, 0, + rect.width (), c->extents.top, + xOffRight, yOffTop, shape); + fillQRegion (xdisplay, picture, + 0, rect.height () - c->extents.bottom, + c->extents.left, rect.height (), + xOffLeft, yOffBottom, shape); + fillQRegion (xdisplay, picture, + rect.width () - c->extents.right, + rect.height () - c->extents.bottom, + rect.width (), rect.height (), + xOffRight, yOffBottom, shape); + + y1 -= c->extents.top; + y2 += c->extents.bottom; + } + + if (uniqueVertShade) + { + fillQRegion (xdisplay, picture, + 0, c->extents.top, + c->extents.left, + rect.height () - c->extents.bottom, + xOffLeft, yOffTop, shape); + fillQRegion (xdisplay, picture, + rect.width () - c->extents.right, c->extents.top, + rect.width (), + rect.height () - c->extents.bottom, + xOffRight, yOffTop, shape); + } + else + { + x1 -= c->extents.left; + x2 += c->extents.right; + } + } + } + else + { + x1 -= c->extents.left; + x2 += c->extents.right; + y1 -= c->extents.top; + y2 += c->extents.bottom; } - m_deco->widget ()->setShown (true); -} -void -Aquamarine::Window::updateWindowProperties () -{ - - Pixmap pix = XCompositeNameWindowPixmap(qt_xdisplay(),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 (); - - int otop = top - m_soffset.top(); - int obottom = bottom + m_soffset.bottom(); - int oleft = left - m_soffset.left(); - int oright = right + m_soffset.right(); - - long mdata[256]; - - long *data = mdata; - - *data++ = BERYL_ADVANCED_DECORATION_VERSION; - - memcpy (data++, &pix, sizeof (pix)); - - *data++ = left; - *data++ = right; - *data++ = top; - *data++ = bottom; - - *data++ = mleft; - *data++ = mright; - *data++ = mtop; - *data++ = mbottom; - - *data++ = 0; - *data++ = 0; - - *data++ = 0; - *data++ = (unsigned short)((Settings::activeOpacity() / 100.0) * 0xffff); - *data++ = (unsigned short)((Settings::inactiveOpacity() / 100.0) * 0xffff); - - // TOP LEFT - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_NORTH | GRAVITY_WEST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = -oleft; - *data++ = -otop; - *data++ = 0; - *data++ = 0; - *data++ = oleft; - *data++ = otop; - *data++ = 0; - *data++ = 0; - - // TOP RIGHT - *data++ = - ((GRAVITY_NORTH | GRAVITY_EAST) << 0) | - ((GRAVITY_NORTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = -otop; - *data++ = oright; - *data++ = 0; - *data++ = oright; - *data++ = otop; - *data++ = oleft + w_w; - *data++ = 0; - - // BOTTOM LEFT - *data++ = - ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = -oleft; - *data++ = 0; - *data++ = 0; - *data++ = obottom; - *data++ = oleft; - *data++ = obottom; - *data++ = 0; - *data++ = w_h + otop; - - // BOTTOM RIGHT - *data++ = - ((GRAVITY_SOUTH | GRAVITY_EAST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = 0; - *data++ = oright; - *data++ = obottom; - *data++ = oright; - *data++ = obottom; - *data++ = oleft + w_w; - *data++ = w_h + otop; - - // TOP CENTER - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_NORTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = -otop; - *data++ = 0; - *data++ = 0; - *data++ = w_w; - *data++ = otop; - *data++ = oleft; - *data++ = 0; - - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_NORTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_HORZ << 10) | (YY_MASK); - - *data++ = w_w; - *data++ = -otop; - *data++ = 0; - *data++ = 0; - *data++ = SHRT_MAX; - *data++ = otop; - *data++ = oleft + w_w; - *data++ = 0; - - // BOTTOM CENTER - *data++ = - ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = 0; - *data++ = 0; - *data++ = obottom; - *data++ = w_w; - *data++ = obottom; - *data++ = oleft; - *data++ = w_h + otop; - - *data++ = - ((GRAVITY_SOUTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_HORZ << 10) | (YY_MASK); - - *data++ = w_w; - *data++ = 0; - *data++ = 0; - *data++ = obottom; - *data++ = SHRT_MAX; - *data++ = obottom; - *data++ = oleft + w_w; - *data++ = w_h + otop; - - //LEFT - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = -oleft; - *data++ = 0; - *data++ = 0; - *data++ = 0; - *data++ = oleft; - *data++ = w_h; - *data++ = 0; - *data++ = otop; - - *data++ = - ((GRAVITY_NORTH | GRAVITY_WEST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_WEST) << 4) | - (0 << 8) | (CLAMP_VERT << 10) | (XX_MASK); - - *data++ = -oleft; - *data++ = w_h; - *data++ = 0; - *data++ = 0; - *data++ = oleft; - *data++ = SHRT_MAX; - *data++ = 0; - *data++ = otop + w_h; - - //RIGHT - *data++ = - ((GRAVITY_NORTH | GRAVITY_EAST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (0 << 10) | (XX_MASK) | (YY_MASK); - - *data++ = 0; - *data++ = 0; - *data++ = oright; - *data++ = 0; - *data++ = oright; - *data++ = w_h; - *data++ = w_w + oleft; - *data++ = otop; - - *data++ = - ((GRAVITY_NORTH | GRAVITY_EAST) << 0) | - ((GRAVITY_SOUTH | GRAVITY_EAST) << 4) | - (0 << 8) | (CLAMP_VERT << 10) | (XX_MASK); - - *data++ = 0; - *data++ = w_h; - *data++ = oright; - *data++ = 0; - *data++ = oright; - *data++ = SHRT_MAX; - *data++ = w_w + oleft; - *data++ = otop + w_h; - - Aquamarine::trapXError (); - XChangeProperty (qt_xdisplay (), m_wid, - Atoms::net_window_decor, - XA_INTEGER, - 32, PropModeReplace, (unsigned char *)mdata, - 15 + (12 * 9)); - Aquamarine::popXError (); - XSync (qt_xdisplay (), FALSE); - if (m_currentPixmap != None) - XFreePixmap(qt_xdisplay(),m_currentPixmap); - m_currentPixmap = pix; + XRenderFillRectangle (xdisplay, PictOpSrc, picture, &white, + x1, + y1, + x2 - x1, + y2 - y1); } -void -Aquamarine::Window::setActive (bool active) -{ - m_active = active; - m_deco->activeChange (); - resizeDecoration (); +static void +cornersFromQRegion (QRegion *region, + int width, + int height, + int left, + int right, + int top, + int bottom, + int *leftCorner, + int *rightCorner, + int *topCorner, + int *bottomCorner) +{ + QRegion l, r, t, b; + + l = QRegion (0, top, left, height - top - bottom) - *region; + r = QRegion (width - right, top, right, height - top - bottom) - *region; + t = QRegion (0, 0, width, top) - *region; + b = QRegion (0, height - bottom, width, bottom) - *region; + + if (l.isEmpty ()) + *leftCorner = left; + else + *leftCorner = left - + (l.boundingRect ().x () + l.boundingRect ().width ()); + + if (r.isEmpty ()) + *rightCorner = right; + else + *rightCorner = r.boundingRect ().x () - width + right; + + if (t.isEmpty ()) + *topCorner = top; + else + *topCorner = top - + (t.boundingRect ().y () + t.boundingRect ().height ()); + + if (b.isEmpty ()) + *bottomCorner = bottom; + else + *bottomCorner = b.boundingRect ().y () - height + bottom; } void -Aquamarine::Window::updateFrame (WId frame) +Aquamarine::Window::updateShadow (void) { - m_frame = frame; - if (m_deco && frame != handle()) + Display *xdisplay = qt_xdisplay (); + Screen *xscreen = ScreenOfDisplay (xdisplay, qt_xscreen ()); + XRenderPictFormat *xformat; + int leftCorner, rightCorner, topCorner, bottomCorner; + + if (mShadow) + { + decor_shadow_destroy (qt_xdisplay (), mShadow); + mShadow = NULL; + } + + if (mShapeSet) + { + cornersFromQRegion (&mShape, + mGeometry.width () + mBorder.left + mBorder.right, + mGeometry.height () + mBorder.top + mBorder.bottom, + mBorder.left, + mBorder.right, + mBorder.top, + mBorder.bottom, + &leftCorner, + &rightCorner, + &topCorner, + &bottomCorner); + } + else + { + leftCorner = mBorder.left; + rightCorner = mBorder.right; + topCorner = mBorder.top; + bottomCorner = mBorder.bottom; + } + + /* use default shadow if such exist */ + if (!mUniqueHorzShape && !mUniqueVertShape) + { + mShadow = Decorator::defaultWindowShadow (&mContext); + if (mShadow) + decor_shadow_reference (mShadow); + } + + if (!mShadow) { - XEvent ev; - - memset (&ev, 0, sizeof (ev)); - ev.xclient.type = ClientMessage; - ev.xclient.window = m_wid; - ev.xclient.message_type = Atoms::change_frame_window; - ev.xclient.format = 32; - ev.xclient.data.l[0] = handle(); - ev.xclient.data.l[1] = TRUE; - ev.xclient.data.l[2] = 0; - ev.xclient.data.l[3] = 0; - ev.xclient.data.l[4] = 0; - - XSendEvent (qt_xdisplay (), qt_xrootwin(), False, - SubstructureRedirectMask | SubstructureNotifyMask, &ev); + mShadow = decor_shadow_create (xdisplay, + xscreen, + mUniqueHorzShape ? + mGeometry.width () : 1, + mUniqueVertShape ? + mGeometry.height () : 1, + mBorder.left, + mBorder.right, + mBorder.top, + mBorder.bottom, + leftCorner, + rightCorner, + topCorner, + bottomCorner, + Aquamarine::Decorator::shadowOptions (), + &mContext, + drawBorderShape, + (void *) this); + + if (mType == Default) + Aquamarine::Decorator::updateDefaultShadow (this); } - if (m_deco && frame == handle()) + + /* create new layout */ + if (mType == Normal || mType == Switcher) + decor_get_best_layout (&mContext, + mGeometry.width (), + mGeometry.height (), + &mLayout); + else + decor_get_default_layout (&mContext, + mGeometry.width (), + mGeometry.height (), + &mLayout); + + if (mDecorationPicture) + XRenderFreePicture (qt_xdisplay (), mDecorationPicture); + + if (mTexturePicture) + XRenderFreePicture (qt_xdisplay (), mTexturePicture); + + if (!mTexturePixmapBuffer.isNull ()) + mTexturePixmapBuffer.resize (0, 0); + + if (!mTexturePixmap.isNull ()) + mTexturePixmap.resize (0, 0); + + mTexturePixmap = QPixmap (mLayout.width, mLayout.height, 32); + mTexturePixmapBuffer = QPixmap (mLayout.width, mLayout.height, 32); + + xformat = XRenderFindStandardFormat (qt_xdisplay (), + PictStandardARGB32); + + mDecorationPicture = + XRenderCreatePicture (qt_xdisplay (), + mTexturePixmap.handle (), + xformat, 0, NULL); + mTexturePicture = + XRenderCreatePicture (qt_xdisplay (), + mTexturePixmapBuffer.handle (), + xformat, 0, NULL); + + decor_fill_picture_extents_with_shadow (qt_xdisplay (), + mShadow, + &mContext, + mTexturePicture, + &mLayout); + + if (mPixmap) { - //updateWindowProperties (); - XSelectInput (qt_xdisplay (), m_frame, - defaultMask | ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | EnterWindowMask | LeaveWindowMask); + /* hm, update or repaint doesn't seem to do it */ + mDecor->widget ()->hide (); + mDecor->widget ()->show (); } + + mUpdateProperty = true; } void -Aquamarine::Window::updateWindowGeometry () +Aquamarine::Window::setMask (const QRegion ®, int) { - 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 (); + QRegion top, bottom, left, right; + bool uniqueHorzShape, uniqueVertShape; + + if (mShapeSet && reg == mShape) + return; + + mShape = reg; + mShapeSet = true; + + if (mFrame) + { + QRegion r; + + r = reg - QRegion (mBorder.left, mBorder.top, + mGeometry.width (), mGeometry.height ()); + + Aquamarine::trapXError (); + XShapeCombineRegion (qt_xdisplay (), + mFrame, + ShapeInput, + 0, + 0, + r.handle (), + ShapeSet); + Aquamarine::popXError (); + } + + top = QRegion (mBorder.left, 0, + mGeometry.width (), mBorder.top) - reg; + bottom = QRegion (mBorder.left, mGeometry.height () + mBorder.top, + mGeometry.width (), mBorder.bottom) - reg; + left = QRegion (0, mBorder.top, mBorder.left, + mGeometry.height ()) - reg; + right = QRegion (mBorder.left + mGeometry.width (), mBorder.top, + mBorder.right, mGeometry.height ()) - reg; + + uniqueHorzShape = !top.isEmpty () || !bottom.isEmpty (); + uniqueVertShape = !left.isEmpty () || !right.isEmpty (); + + if (uniqueHorzShape || mUniqueHorzShape || + uniqueVertShape || mUniqueVertShape) + { + mUniqueHorzShape = uniqueHorzShape; + mUniqueVertShape = uniqueVertShape; + + if (mPixmap) + updateShadow (); + } } -void -Aquamarine::Window::updateConfig () +bool +Aquamarine::Window::resizeDecoration (bool force) { - if (!m_deco) return; + int w, h; - double op = Settings::shadowOpacity() / 100.0; - op *= 0xffff; + mDecor->borders (mBorder.left, mBorder.right, mBorder.top, mBorder.bottom); - m_sradius = Settings::shadowRadius(); - QColor color = Settings::shadowColor(); - m_scolor[0] = short((color.red() / 256.0) * 0xffff); - m_scolor[1] = short((color.green() / 256.0) * 0xffff); - m_scolor[2] = short((color.blue() / 256.0) * 0xffff); - m_scolor[3] = short(op); + w = mGeometry.width () + mBorder.left + mBorder.right; + h = mGeometry.height () + mBorder.top + mBorder.bottom; - int offX = Settings::shadowOffsetX(); - int offY = Settings::shadowOffsetY(); - offX = KMAX(-m_sradius,KMIN(m_sradius,offX)); - offY = KMAX(-m_sradius,KMIN(m_sradius,offY)); + if (!force) + { + if (w == width () && h == height ()) + return FALSE; + } + + /* reset shape */ + mShapeSet = false; + mUniqueHorzShape = false; + mUniqueVertShape = false; + + if (mType != Normal && mType != Switcher) + { + Display *xdisplay = qt_xdisplay (); + Screen *xscreen = ScreenOfDisplay (xdisplay, qt_xscreen ()); + decor_shadow_t *tmpShadow; + decor_context_t c; + + /* XXX: we have to create a temporary shadow to get the client + geometry. libdecoration should be fixed so it's able to just + fill out a context struct and not necessarily generate a + shadow for this purpose. */ + tmpShadow = decor_shadow_create (xdisplay, + xscreen, + 1, 1, + mBorder.left, + mBorder.right, + mBorder.top, + mBorder.bottom, + mBorder.left, + mBorder.right, + mBorder.top, + mBorder.bottom, + Aquamarine::Decorator::shadowOptions (), + &c, + decor_draw_simple, + (void *) 0); + + decor_shadow_destroy (xdisplay, tmpShadow); + + w = c.left_corner_space + 1 + c.right_corner_space; + + /* most styles render something useful at least 30 px width */ + if (w < 30) + w = 30; + + mGeometry = QRect (50, 50, w, + c.top_corner_space + 1 + c.bottom_corner_space); + } - m_deco->widget()->move(m_soffset.left(),m_soffset.top()); + w = mGeometry.width () + mBorder.left + mBorder.right; + h = mGeometry.height () + mBorder.top + mBorder.bottom; - if (Settings::drawShadows()) - m_soffset.setCoords(-m_sradius + offX,-m_sradius + offY, - m_sradius + offX,m_sradius + offY); + if (mPixmap) + { + XFreePixmap (qt_xdisplay (), mPixmap); + mPixmap = None; + } + + if (mPicture) + { + XRenderFreePicture (qt_xdisplay (), mPicture); + mPicture = 0; + } + + setGeometry (QRect (mGeometry.x () + ROOT_OFF_X - mBorder.left, + mGeometry.y () + ROOT_OFF_Y - mBorder.top, + w, h)); + + if (mMapped) + { + mPendingConfigure++; + } else - m_soffset.setCoords(0,0,0,0); + { + mPendingMap = 1; + + show (); - m_deco->widget()->move(-m_soffset.left(),-m_soffset.top()); + mMapped = true; - resizeDecoration(); - updateWindowProperties(); + /* XXX: is there a more appropriate way to achieve this? + add WType_TopLevel flag so that visualRect isn't clipped + to parent. */ + setWFlags (getWFlags () | WType_TopLevel); - if (m_shapeSet) + if (mDamageId != winId ()) { - m_shapeChange = m_shape; - renderShadow(); + mDamageId = winId (); + XDamageCreate (qt_xdisplay (), mDamageId, + XDamageReportRawRectangles); } + } + + mDecor->resize (QSize (w, h)); + mDecor->widget ()->show (); + + return TRUE; } void -Aquamarine::Window::reloadDecoration () +Aquamarine::Window::rebindPixmap (void) { - delete m_deco; - m_deco = 0; + XRenderPictFormat *xformat; + QPaintEvent *e; + + if (mPicture) + XRenderFreePicture (qt_xdisplay (), mPicture); + + if (mPixmap) + XFreePixmap (qt_xdisplay (), mPixmap); + + mPixmap = XCompositeNameWindowPixmap (qt_xdisplay (), winId ()); - createDecoration (); + xformat = XRenderFindVisualFormat (qt_xdisplay (), + (Visual *) x11Visual ()); + + mPicture = XRenderCreatePicture (qt_xdisplay (), mPixmap, + xformat, 0, NULL); + + updateShadow (); + + e = new QPaintEvent (mDecor->widget ()->rect (), false); + QApplication::postEvent (mDecor->widget (), e); } -void -Aquamarine::Window::updateCursor (QPoint pos) +bool +Aquamarine::Window::handleMap (void) { - 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; - } + if (!mPendingMap) + return FALSE; + + mPendingMap = 0; + if (mPendingConfigure) + return FALSE; + + rebindPixmap (); + + return TRUE; } -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); - } +bool +Aquamarine::Window::handleConfigure (void) +{ + if (!mPendingConfigure) + return FALSE; + + mPendingConfigure--; + if (mPendingConfigure || mPendingMap) + return FALSE; + + rebindPixmap (); + + return TRUE; } void -Aquamarine::Window::slotPopupActivated (int id) -{ - WindowOperation - op = static_cast < WindowOperation > (id); - performWindowOperation (op); +Aquamarine::Window::updateProperty (void) +{ + Atom atom = Atoms::netWindowDecor; + decor_extents_t maxExtents; + long data[256]; + decor_quad_t quads[N_QUADS_MAX]; + int nQuad; + int lh, rh; + int w; + int minWidth; + unsigned int saveState; + + if (mType == Default) + atom = Atoms::netWindowDecorNormal; + else if (mType == DefaultActive) + atom = Atoms::netWindowDecorActive; + + saveState = mState; + mState = NET::MaxVert | NET::MaxHoriz; + mDecor->borders (maxExtents.left, maxExtents.right, + maxExtents.top, maxExtents.bottom); + mState = saveState; + + if (mLayout.rotation) + lh = mLayout.left.x2 - mLayout.left.x1; + else + lh = mLayout.left.y2 - mLayout.left.y1; + + if (mLayout.rotation) + rh = mLayout.right.x2 - mLayout.right.x1; + else + rh = mLayout.right.y2 - mLayout.right.y1; + + w = mLayout.top.x2 - mLayout.top.x1 - mContext.left_space - + mContext.right_space; + + if (mType == Normal || mType == Switcher) + { + int topXOffset = w / 2; + + if (mDecor) + { + const QObjectList *children = mDecor->widget ()->children (); + QWidget *child; + int x; + + x = w - mContext.left_space - mContext.left_corner_space; + if (x > topXOffset) + topXOffset = x; + + for (QObjectListIt it(*children); it.current (); ++it) + { + if (!it.current ()->isWidgetType ()) + continue; + + child = static_cast <QWidget *> (it.current ()); + + x = child->x () - mBorder.left - 2; + if (x > w / 2 && x < topXOffset) + topXOffset = x; + } + } + + nQuad = decor_set_lXrXtXbX_window_quads (quads, + &mContext, + &mLayout, + lh / 2, + rh / 2, + topXOffset, + w / 2); + + minWidth = mContext.left_corner_space + 1 + mContext.right_corner_space; + } + else + { + nQuad = decor_set_lSrStSbS_window_quads (quads, &mContext, &mLayout); + + minWidth = 1; + } + + decor_quads_to_property (data, mTexturePixmap.handle (), + &mBorder, &maxExtents, + minWidth, 0, + quads, nQuad); + + Aquamarine::trapXError (); + XChangeProperty (qt_xdisplay (), mClientId, atom, + XA_INTEGER, + 32, PropModeReplace, (unsigned char *) data, + BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad); + Aquamarine::popXError (); + + mUpdateProperty = false; } 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); - } - } +Aquamarine::Window::handleActiveChange (void) +{ + mDecor->activeChange (); + resizeDecoration (); } 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 (); - } - 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 (); +Aquamarine::Window::updateFrame (WId frame) +{ + mFrame = frame; + + Aquamarine::trapXError (); + XSelectInput (qt_xdisplay (), mFrame, + StructureNotifyMask | PropertyChangeMask | + ButtonPressMask | ButtonReleaseMask | PointerMotionMask | + EnterWindowMask | LeaveWindowMask); + Aquamarine::popXError (); } void -Aquamarine::Window::updateName () +Aquamarine::Window::updateSelected (WId selectedId) { - m_name = KWin::readNameProperty (m_wid, XA_WM_NAME); - m_deco->captionChange (); + mSelectedId = selectedId; + + updateName (); } void -Aquamarine::Window::updateIcons () +Aquamarine::Window::updateWindowGeometry (void) { - kdDebug () << k_funcinfo << endl; - m_icons = - QIconSet (KWin::icon (m_wid, 16, 16, TRUE), - KWin::icon (m_wid, 32, 32, TRUE)); - m_deco->iconChange (); + unsigned int w, h, bw, d; + int x, y; + XID root; + + Aquamarine::trapXError (); + XGetGeometry (qt_xdisplay (), mClientId, &root, &x, &y, &w, &h, &bw, &d); + if (Aquamarine::popXError ()) + return; + + w += bw * 2; + h += bw * 2; + + mGeometry = QRect (x, y, w, h); + if (resizeDecoration ()) + return; + + move (x + ROOT_OFF_X - mBorder.left, + y + ROOT_OFF_Y - mBorder.top); } void -Aquamarine::Window::slotChangeViewport (int id) +Aquamarine::Window::reloadDecoration (void) { - if (id == 0) - setDesktop ((desktop () == - NET::OnAllDesktops) ? 1 : NET::OnAllDesktops); - else - Decorator::moveToViewport (m_wid, id); + delete mDecor; + mDecor = 0; + + setWFlags (getWFlags () & ~WType_TopLevel); + hide (); + + mMapped = false; + mShapeSet = false; + + if (mShadow) + { + decor_shadow_destroy (qt_xdisplay (), mShadow); + mShadow = NULL; + } + + createDecoration (); +} + +Cursor +Aquamarine::Window::positionToCursor (QPoint pos) +{ + switch (mDecor->mousePosition (pos)) { + case PositionCenter: + return cursors[1][1].cursor; + case PositionLeft: + return cursors[1][0].cursor; + case PositionRight: + return cursors[1][2].cursor; + case PositionTop: + return cursors[0][1].cursor; + case PositionBottom: + return cursors[2][1].cursor; + case PositionTopLeft: + return cursors[0][0].cursor; + case PositionTopRight: + return cursors[0][2].cursor; + case PositionBottomLeft: + return cursors[2][0].cursor; + case PositionBottomRight: + return cursors[2][2].cursor; + default: + break; + } + + return cursors[1][1].cursor; } 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; - } +Aquamarine::Window::updateCursor (QPoint pos) +{ + Aquamarine::trapXError (); + XDefineCursor (qt_xdisplay (), mFrame, positionToCursor (pos)); + Aquamarine::popXError (); } 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() +Aquamarine::Window::getWindowProtocols (void) { - // force menu regeneration - delete m_popup; - m_popup = 0; -} - - -void Aquamarine::Window::performMouseCommand(Options::MouseCommand command, QMouseEvent *qme) -{ - switch (command) - { - case Options::MouseRaise: - case Options::MouseActivateAndRaise: - 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; - } -} - -void Aquamarine::Window::setMapping (bool map) -{ - m_mapped = map; - if (!m_mapped) - m_shapeSet = false; -} - -void Aquamarine::Window::updateWindow () -{ - if (!m_mapped) return; - - if (m_updatePixmap) + Atom *p; + int n; + int status; + + mSupportTakeFocus = false; + mSupportContextHelp = false; + + Aquamarine::trapXError (); + status = XGetWMProtocols (qt_xdisplay (), mClientId, &p, &n); + if (Aquamarine::popXError ()) + return; + + if (status) + { + int i; + + for (i = 0; i < n; i++) { - updateWindowProperties(); - m_updatePixmap = false; + if (p[i] == Atoms::wmTakeFocus) + mSupportTakeFocus = true; + else if (p[i] == Atoms::netWmContextHelp) + mSupportContextHelp = true; + } + + if (n > 0) + XFree (p); } - renderShadow(); } -#if INT_MAX != LONG_MAX -/* XRenderSetPictureFilter used to be broken on LP64. This - * works with either the broken or fixed version. - */ -static void -XRenderSetPictureFilter_wrapper (Display *dpy, - Picture picture, - char *filter, - XFixed *params, - int nparams) +void +Aquamarine::Window::handlePopupActivated (int id) { - Aquamarine::trapXError (); - XRenderSetPictureFilter (dpy, picture, filter, params, nparams); - XSync (dpy, False); - if (Aquamarine::popXError ()) - { - long *long_params = new long[nparams]; - int i; + WindowOperation op = static_cast <WindowOperation> (id); - for (i = 0; i < nparams; i++) - long_params[i] = params[i]; + performWindowOperation (op); +} - XRenderSetPictureFilter (dpy, picture, filter, - (XFixed *) long_params, nparams); - delete long_params; - } +void +Aquamarine::Window::handleDesktopPopupActivated (int id) +{ + if (id) + setDesktop (id); + else + KWin::setOnAllDesktops (mClientId, true); } +void +Aquamarine::Window::handlePopupAboutToShow (void) +{ + int numberOfDesktops; -#define XRenderSetPictureFilter XRenderSetPictureFilter_wrapper -#endif + numberOfDesktops = KWin::numberOfDesktops (); + if (numberOfDesktops > 1) + { + NETRootInfo *rootInfo = Decorator::rootInfo (); + QString name; + int id, i; + int winDesktop = desktop (); -#define SIGMA(r) ((r) / 2.0) -#define ALPHA(r) (r) + mDesktopMenu->clear (); -void Aquamarine::Window::renderShadow () -{ - if (m_shapeChange.isEmpty() || !Settings::drawShadows()) return; - kdDebug () << k_funcinfo << endl; + id = mDesktopMenu->insertItem (i18n ("&All Desktops"), 0); - int top, bottom, left, right; - m_deco->borders (left, right, top, bottom); + mDesktopMenu->setItemChecked (id, (winDesktop == NET::OnAllDesktops)); + mDesktopMenu->insertSeparator (); - renderShadow(m_shapeChange.intersect(QRegion(0,0,m_deco->width(),top))); - renderShadow(m_shapeChange.intersect(QRegion(0,m_deco->height() - bottom,m_deco->width(),bottom))); - renderShadow(m_shapeChange.intersect(QRegion(0,top,left,m_geometry.height()))); - renderShadow(m_shapeChange.intersect(QRegion(m_deco->width() - right,top,right,m_geometry.height()))); + for (i = 1; i <= numberOfDesktops; i++) + { + QString name; - m_shapeChange = QRegion(); -} + name = + QString ("&%1 ").arg (i) + + QString (rootInfo->desktopName (i)).replace ('&', "&&"); -void Aquamarine::Window::renderShadow (QRegion reg) -{ + id = mDesktopMenu->insertItem (name, i); + mDesktopMenu->setItemChecked (id, (winDesktop == i)); + } - if (reg.isEmpty()) - return; + mPopup->setItemVisible (Options::NoOp, true); + } + else + { + mPopup->setItemVisible (Options::NoOp, false); + } + + mViewportMenu->setItemChecked (0, desktop () == NET::OnAllDesktops); + for (int i = 1;i <= + Decorator::viewports ().width () * Decorator::viewports ().height (); + ++i) + { + if (Decorator:: onViewport (QPoint (mGeometry.x (), mGeometry.y ())) == i) + { + mViewportMenu->setItemEnabled (i, false); + } + else + { + mViewportMenu->setItemEnabled (i, true); + } + } - int s2 = m_sradius * 2; + mPopup->setItemEnabled (Options::ResizeOp, isResizable ()); + mPopup->setItemEnabled (Options::MoveOp, isMovable ()); - QRect rect = reg.boundingRect(); + mPopup->setItemEnabled (Options::MaximizeOp, isMaximizable ()); + mPopup->setItemChecked (Options::MaximizeOp, + maximizeMode () == MaximizeFull); - rect.setLeft(rect.left() - s2); - rect.setTop(rect.top() - s2); - rect.setRight(rect.right() + s2); - rect.setBottom(rect.bottom() + s2); + mPopup->setItemChecked (Options::ShadeOp, isShade ()); + mPopup->setItemEnabled (Options::ShadeOp, isShadeable ()); - QRegion bound(rect); - bound = m_shape.intersect(bound); + mAdvancedMenu->setItemChecked (Options::KeepAboveOp, keepAbove ()); + mAdvancedMenu->setItemChecked (Options::KeepBelowOp, keepBelow ()); + mAdvancedMenu->setItemChecked (Options::FullScreenOp, + mState & NET::FullScreen); - bound.translate(-rect.left(),-rect.top()); + mPopup->setItemEnabled (Options::MinimizeOp, isMinimizable ()); + mPopup->setItemEnabled (Options::CloseOp, isCloseable ()); - QPixmap qRegPix(rect.width(), rect.height(), 32); - QPixmap qTmpPix(rect.width() + s2, rect.height(), 32); - qRegPix.fill( QColor(0,0)); + mOpacityMenu->setItemEnabled (ChangeOpacity25, mOpacity != 0x3fff); + mOpacityMenu->setItemEnabled (ChangeOpacity50, mOpacity != 0x7fff); + mOpacityMenu->setItemEnabled (ChangeOpacity75, mOpacity != 0xbfff); + mOpacityMenu->setItemEnabled (ChangeOpacity100, mOpacity != 0xffff); - QPainter p(&qRegPix); - QBrush b(QColor(0, ((m_scolor[3] >> 8) << 24) + 0xffffff)); - p.setClipRegion(bound); - p.fillRect(0, 0, rect.width(), rect.height(), b); + mBrightnessMenu->setItemEnabled (ChangeBrightness25, + mBrightness != 0x3fff); + mBrightnessMenu->setItemEnabled (ChangeBrightness50, + mBrightness != 0x7fff); + mBrightnessMenu->setItemEnabled (ChangeBrightness75, + mBrightness != 0xbfff); + mBrightnessMenu->setItemEnabled (ChangeBrightness100, + mBrightness != 0xffff); - XFixed *params; - int n_params = 0; - int size; + mSaturationMenu->setItemEnabled (ChangeSaturation25, + mSaturation != 0x3fff); + mSaturationMenu->setItemEnabled (ChangeSaturation50, + mSaturation != 0x7fff); + mSaturationMenu->setItemEnabled (ChangeSaturation75, + mSaturation != 0xbfff); + mSaturationMenu->setItemEnabled (ChangeSaturation100, + mSaturation != 0xffff); - params = createGaussianKernel (&size); + mAppearanceMenu->setItemEnabled (ResetValues, mOpacity != 0xffff + || mBrightness != 0xffff || mSaturation != 0xffff); - n_params = size + 2; - size = size / 2; +} - params[0] = (n_params - 2) << 16; - params[1] = 1 << 16; +void +Aquamarine::Window::updateState (void) +{ + KWin::WindowInfo wInfo = KWin::windowInfo (mClientId, NET::WMState, 0); + unsigned long newState = wInfo.state (); + unsigned long stateChange = mState ^ newState; - XRenderPictFormat *format; - format = XRenderFindStandardFormat (qt_xdisplay(), PictStandardARGB32); + mState = newState; - char *filter = NULL; - XFilters* filters = XRenderQueryFilters (qt_xdisplay(), qRegPix.handle()); - if (filters) + if (stateChange & NET::Max) { - int i; + mDecor->maximizeChange (); + resizeDecoration (false); + } - for (i = 0; i < filters->nfilter; i++) - { - if (strcmp (filters->filter[i], FilterConvolution) == 0) - { - filter = (char *) FilterConvolution; - break; - } - } + if (stateChange & NET::KeepAbove && !(mState & NET::KeepAbove)) + mDecor->emitKeepAboveChanged (mState & NET::KeepAbove); + if (stateChange & NET::KeepBelow && !(mState & NET::KeepBelow)) + mDecor->emitKeepBelowChanged (mState & NET::KeepBelow); + if (stateChange & NET::KeepAbove && mState & NET::KeepAbove) + mDecor->emitKeepAboveChanged (mState & NET::KeepAbove); + if (stateChange & NET::KeepBelow && mState & NET::KeepBelow) + mDecor->emitKeepBelowChanged (mState & NET::KeepBelow); + if (stateChange & NET::Shaded) + mDecor->shadeChange (); + if (stateChange & NET::Sticky) + mDecor->desktopChange (); +} - XFree (filters); - } - if (!filter) +void +Aquamarine::Window::updateName (void) +{ + if (mType == Switcher) + { + if (!mSelectedId) return; - static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; + mName = KWin::readNameProperty (mSelectedId, XA_WM_NAME); + } + else + { + mName = KWin::readNameProperty (mClientId, XA_WM_NAME); + } - Picture fill = XRenderCreateSolidFill (qt_xdisplay(), &white); - Picture src = XRenderCreatePicture(qt_xdisplay(), qRegPix.handle(), format, 0, NULL); - Picture tmp = XRenderCreatePicture(qt_xdisplay(), qTmpPix.handle(), format, 0, NULL); - Picture dst = XRenderCreatePicture(qt_xdisplay(), handle(), format, 0, NULL); + mDecor->captionChange (); +} - setPictureTransform(src,size,0); - XRenderSetPictureFilter (qt_xdisplay(), src, filter, params, n_params); - XRenderComposite (qt_xdisplay(), PictOpSrc, fill, src, tmp, 0, 0, 0, 0, 0, 0, rect.width() + s2, rect.height()); +void +Aquamarine::Window::updateIcons (void) +{ + mIcons = QIconSet (KWin::icon (mClientId, 16, 16, TRUE), + KWin::icon (mClientId, 32, 32, TRUE)); + mDecor->iconChange (); +} + +NET::Direction +Aquamarine::Window::positionToDirection (int pos) +{ + switch (pos) { + case PositionLeft: + return NET::Left; + case PositionRight: + return NET::Right; + case PositionTop: + return NET::Top; + case PositionBottom: + return NET::Bottom; + case PositionTopLeft: + return NET::TopLeft; + case PositionTopRight: + return NET::TopRight; + case PositionBottomLeft: + return NET::BottomLeft; + case PositionBottomRight: + return NET::BottomRight; + default: + break; + } - XRenderFreePicture (qt_xdisplay(), fill); + return NET::Move; +} - params[0] = 1 << 16; - params[1] = (n_params - 2) << 16; +void +Aquamarine::Window::moveWindow (QMouseEvent *qme) +{ + NET::Direction direction; - XRenderFreePicture (qt_xdisplay(), src); - XRenderColor color = { m_scolor[0], m_scolor[1], m_scolor[2], 0xffff }; + direction = positionToDirection (mDecor->mousePosition (qme->pos ())); - src = XRenderCreateSolidFill (qt_xdisplay(), &color); + XUngrabPointer (qt_xdisplay (), CurrentTime); + XUngrabKeyboard (qt_xdisplay (), CurrentTime); - setPictureTransform(tmp,0,size); - XRenderSetPictureFilter (qt_xdisplay(), tmp, filter, params, n_params); + Decorator::rootInfo ()->moveResizeRequest (mClientId, + qme->globalX (), + qme->globalY (), + direction); +} - XRenderComposite (qt_xdisplay(), PictOpSrc, src, tmp, dst, s2, s2, s2, s2, rect.left() + s2, rect.top() + s2, rect.width() - s2, rect.height() - s2); +#define OPACITY_STEP (0xffff / 10) - XRenderFreePicture (qt_xdisplay(), src); - XRenderFreePicture (qt_xdisplay(), tmp); - XRenderFreePicture (qt_xdisplay(), dst); +void +Aquamarine::Window::performMouseCommand (Options::MouseCommand command, + QMouseEvent *qme) +{ + switch (command) { + case Options::MouseRaise: + KWin::raiseWindow (mClientId); + break; + case Options::MouseLower: + KWin::lowerWindow (mClientId); + 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: + break; + case Options::MouseNextDesktop: + break; + case Options::MouseOpacityMore: + { + int opacity = mOpacity; + + if (opacity < 0xffff) + { + opacity += OPACITY_STEP; + if (opacity > 0xffff) + opacity = 0xffff; + + Decorator::sendClientMessage (qt_xrootwin (), + mClientId, + Atoms::netWmWindowOpacity, + (opacity << 16) | opacity); + } + } break; + case Options::MouseOpacityLess: + { + int opacity = mOpacity; - delete params; + if (opacity > OPACITY_STEP) + { + opacity -= OPACITY_STEP; + if (opacity < OPACITY_STEP) + opacity = OPACITY_STEP; + + Decorator::sendClientMessage (qt_xrootwin (), + mClientId, + Atoms::netWmWindowOpacity, + (opacity << 16) | opacity); + } + } break; + case Options::MouseActivateRaiseAndMove: + case Options::MouseActivateRaiseAndUnrestrictedMove: + case Options::MouseMove: + case Options::MouseUnrestrictedMove: + case Options::MouseResize: + case Options::MouseUnrestrictedResize: + if (qme) + moveWindow (qme); + case Options::MouseNothing: + default: + break; + } } -XFixed *Aquamarine::Window::createGaussianKernel (int *r_size) +void +Aquamarine::Window::processDamage (void) { - double sigma = m_sradius / 2.0; - double alpha = m_sradius; - double radius = m_sradius; + QRegion r1, r2; + int xOff, yOff, w; + double alpha; + int shade_alpha; - XFixed *params; - double *amp, scale, x_scale, fx, sum; - int size, half_size, x, i, n; + if (isActive ()) + { + alpha = Settings::activeOpacity() / 100.0; + shade_alpha = 0; + } + else + { + alpha = Settings::inactiveOpacity() / 100.0; + shade_alpha = 0; + } - scale = 1.0f / (2.0f * M_PI * sigma * sigma); - half_size = int(alpha + 0.5f); + if (!mPixmap) + return; - if (half_size == 0) - half_size = 1; + if (mDamage.isEmpty ()) + return; - size = half_size * 2 + 1; - x_scale = 2.0f * radius / size; + if (mShapeSet) + mDamage = mShape.intersect (mDamage); - if (size < 3) - return NULL; + w = mGeometry.width () + mContext.extents.left + mContext.extents.right; - n = size; + if (mType == Switcher) + shade_alpha = 0; - amp = new double[n]; - if (!amp) - return NULL; + xOff = 0; + yOff = 0; - n += 2; + r1 = QRegion (xOff, yOff, w, mContext.extents.top); + r2 = r1.intersect (mDamage); - params = new XFixed[n]; - if (!params) - return NULL; + if (!r2.isEmpty ()) + { + r2.translate (-xOff, -yOff); + + decor_blend_top_border_picture (qt_xdisplay (), + &mContext, + mPicture, + xOff, xOff, + mTexturePicture, + &mLayout, + r2.handle (), + (unsigned short) (alpha * 0xffff), + shade_alpha); + } - i = 0; - sum = 0.0f; + xOff = 0; + yOff = mContext.extents.top + mGeometry.height (); - for (x = 0; x < size; x++) - { - fx = x_scale * (x - half_size); + r1 = QRegion (xOff, yOff, w, mContext.extents.bottom); + r2 = r1.intersect (mDamage); - amp[i] = scale * exp ((-1.0f * (fx * fx)) / (2.0f * sigma * sigma)); + if (!r2.isEmpty ()) + { + r2.translate (-xOff, -yOff); + + decor_blend_bottom_border_picture (qt_xdisplay (), + &mContext, + mPicture, + xOff, yOff, + mTexturePicture, + &mLayout, + r2.handle (), + (unsigned short) (alpha * 0xffff), + shade_alpha); + } - sum += amp[i]; + xOff = 0; + yOff = mContext.extents.top; - i++; - } + r1 = QRegion (xOff, yOff, mContext.extents.left, mGeometry.height ()); + r2 = r1.intersect (mDamage); - /* normalize */ - if (sum != 0.0) - sum = 1.0 / sum; + if (!r2.isEmpty ()) + { + r2.translate (-xOff, -yOff); + + decor_blend_left_border_picture (qt_xdisplay (), + &mContext, + mPicture, + xOff, yOff, + mTexturePicture, + &mLayout, + r2.handle (), + (unsigned short) (alpha * 0xffff), + shade_alpha); + } - params[0] = params[1] = 0; + xOff = mContext.extents.left + mGeometry.width (); + yOff = mContext.extents.top; - for (i = 2; i < n; i++) - params[i] = XDoubleToFixed (amp[i - 2] * sum); + r1 = QRegion (xOff, yOff, mContext.extents.right, mGeometry.height ()); + r2 = r1.intersect (mDamage); - delete amp; + if (!r2.isEmpty ()) + { + r2.translate (-xOff, -yOff); + + decor_blend_right_border_picture (qt_xdisplay (), + &mContext, + mPicture, + xOff, yOff, + mTexturePicture, + &mLayout, + r2.handle (), + (unsigned short) (alpha * 0xffff), + shade_alpha); + } - *r_size = size; + mDamage = QRegion (); - return params; -} + XRenderComposite (qt_xdisplay (), + PictOpSrc, + mTexturePicture, + None, + mDecorationPicture, + 0, 0, + 0, 0, + 0, 0, + mTexturePixmap.width (), + mTexturePixmap.height ()); -void Aquamarine::Window::setPictureTransform (Picture p, int dx, int dy) -{ - XTransform transform = { + if (mUpdateProperty) + { + if (mType == Switcher) { - { 1 << 16, 0, -dx << 16 }, - { 0, 1 << 16, -dy << 16 }, - { 0, 0, 1 << 16 }, + QPainter p (this); + unsigned long pixel; + QColor bg = p.backgroundColor (); + + pixel = (((int) (alpha * 0xff) << 24) | + ((int) (alpha * bg.red ()) << 16) | + ((int) (alpha * bg.green ()) << 8) | + ((int) (alpha * bg.blue ()) << 0)); + + Aquamarine::trapXError (); + XSetWindowBackground (qt_xdisplay (), mClientId, pixel); + XClearWindow (qt_xdisplay (), mClientId); + Aquamarine::popXError (); } - }; - - XRenderSetPictureTransform (qt_xdisplay(), p, &transform); -} - -bool -Aquamarine::Window::eventFilter (QObject * watched, QEvent * event) -{ - bool rv = QWidget::eventFilter (watched, event); - if (event->type () == QEvent::Paint) - { - QTimer::singleShot (0, this, SLOT(updateWindow())); - } - - return rv; + updateProperty (); + } } -void Aquamarine::Window::handleProcessKillerExited (void) +void +Aquamarine::Window::handleProcessKillerExited (void) { - if (mProcessKiller) - { - delete mProcessKiller; - mProcessKiller = NULL; - } + if (mProcessKiller) + { + delete mProcessKiller; + mProcessKiller = NULL; + } } -void Aquamarine::Window::showKillProcessDialog (Time timestamp) +void +Aquamarine::Window::showKillProcessDialog (Time timestamp) { - KWin::WindowInfo kWinInfo = - KWin::windowInfo (m_wid, 0, NET::WM2WindowClass | NET::WM2ClientMachine); - NETWinInfo wInfo = NETWinInfo (qt_xdisplay(), m_wid, - qt_xrootwin (), NET::WMPid); - QCString clientMachine, resourceClass; - pid_t pid; - char buf[257]; + KWin::WindowInfo kWinInfo = + KWin::windowInfo (mClientId, 0, + NET::WM2WindowClass | NET::WM2ClientMachine); + NETWinInfo wInfo = NETWinInfo (qt_xdisplay(), mClientId, + qt_xrootwin (), NET::WMPid); + QCString clientMachine, resourceClass; + pid_t pid; + char buf[257]; - if (mProcessKiller) - return; + if (mProcessKiller) + return; - clientMachine = kWinInfo.clientMachine (); - resourceClass = kWinInfo.windowClassClass (); - pid = wInfo.pid (); + clientMachine = kWinInfo.clientMachine (); + resourceClass = kWinInfo.windowClassClass (); + pid = wInfo.pid (); - if (gethostname (buf, sizeof (buf) - 1) == 0) - { - if (strcmp (buf, clientMachine) == 0) - clientMachine = "localhost"; - } + if (gethostname (buf, sizeof (buf) - 1) == 0) + { + if (strcmp (buf, clientMachine) == 0) + clientMachine = "localhost"; + } - mProcessKiller = new KProcess (this); + mProcessKiller = new KProcess (this); - *mProcessKiller << KStandardDirs::findExe ("kwin_killer_helper") << + *mProcessKiller << KStandardDirs::findExe ("kwin_killer_helper") << "--pid" << QCString ().setNum (pid) << "--hostname" << clientMachine << - "--windowname" << m_name.utf8 () << + "--windowname" << mName.utf8 () << "--applicationname" << resourceClass << - "--wid" << QCString ().setNum (m_wid) << + "--wid" << QCString ().setNum (mClientId) << "--timestamp" << QCString ().setNum (timestamp); - connect (mProcessKiller, SIGNAL (processExited (KProcess *)), - SLOT (handleProcessKillerExited ())); + connect (mProcessKiller, SIGNAL (processExited (KProcess *)), + SLOT (handleProcessKillerExited ())); - if (!mProcessKiller->start (KProcess::NotifyOnExit)) - { - delete mProcessKiller; - mProcessKiller = NULL; - } + if (!mProcessKiller->start (KProcess::NotifyOnExit)) + { + delete mProcessKiller; + mProcessKiller = NULL; + } +} + +void +Aquamarine::Window::hideKillProcessDialog (void) +{ + handleProcessKillerExited (); } -void Aquamarine::Window::hideKillProcessDialog (void) +void Aquamarine::Window::handleChangeViewport (int id) { - handleProcessKillerExited (); + if (id == 0) + setDesktop ((desktop () == NET::OnAllDesktops) ? 1 : NET::OnAllDesktops); + else + Decorator::moveToViewport (mClientId, id); +} + +void Aquamarine::Window::handleDesktopGeometryChanged() +{ + // force menu regeneration + delete mPopup; + mPopup = 0; +} + +void Aquamarine::Window::handleAppearanceChange (int id) +{ + int opacity = mOpacity; + int brightness = mBrightness; + int saturation = mSaturation; + + switch (id) + { + case ResetValues: + opacity = brightness = saturation = 0xffff; + break; + case ChangeOpacity25: + opacity = 0x3fff; + break; + case ChangeOpacity50: + opacity = 0x7fff; + break; + case ChangeOpacity75: + opacity = 0xbfff; + break; + case ChangeOpacity100: + opacity = 0xffff; + break; + case ChangeBrightness25: + brightness = 0x3fff; + break; + case ChangeBrightness50: + brightness = 0x7fff; + break; + case ChangeBrightness75: + brightness = 0xbfff; + break; + case ChangeBrightness100: + brightness = 0xffff; + break; + case ChangeSaturation25: + saturation = 0x3fff; + break; + case ChangeSaturation50: + saturation = 0x7fff; + break; + case ChangeSaturation75: + saturation = 0xbfff; + break; + case ChangeSaturation100: + saturation = 0xffff; + break; + default: + break; + } + if (opacity != mOpacity) + Decorator::sendClientMessage (qt_xrootwin (), + mClientId, + Atoms::netWmWindowOpacity, + (opacity << 16) | opacity); + if (brightness != mBrightness) + Decorator::sendClientMessage (qt_xrootwin (), + mClientId, + Atoms::netWmWindowBrightness, + (brightness << 16) | brightness); + if (saturation != mSaturation) + Decorator::sendClientMessage (qt_xrootwin (), + mClientId, + Atoms::netWmWindowSaturation, + (saturation << 16) | saturation); } diff --git a/src/window.h b/src/window.h index e3f757e..a38d66d 100644 --- a/src/window.h +++ b/src/window.h @@ -1,243 +1,286 @@ /* - * 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) - * gtk-window-decorator (www.freedesktop.org/wiki/Software/Compiz) - * 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 +* Aquamarine the KDE window decorator +* +* Copyright (c) 2006 Dennis Kasprzyk <onestone@beryl-project.org> +* Copyright (c) 2006 Volker Krause <vkrause@kde.org> +* Copyright (c) 2006 David Reveman <davidr@novell.com> +* +* Uses code of: +* 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 _WINDOW_H +#define _WINDOW_H #include <kdecoration_p.h> #include <qpixmap.h> #include <qwidget.h> -#include <X11/extensions/Xrender.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xdamage.h> + + +//#include <beryl-decoration.h> +#include "libdeco.h" #include "utils.h" #include "options.h" + +class KProcess; class KDecoration; class QPopupMenu; -class KProcess; namespace Aquamarine { - - class Window:public QWidget, public KDecorationBridge - { - Q_OBJECT public: - - public: - Window (WId wid, WId frame); - ~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; - } - - void moveWindow (QMouseEvent * qme); - - void reloadDecoration (); - void updateConfig (); - - 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); - } - - void setMapping (bool map); - +class Window:public QWidget, public KDecorationBridge { + Q_OBJECT public: + + enum Type + { + Normal, + Switcher, + Default, + DefaultActive + }; + + public: + Window (QWidget *parent, WId clientId, WId frame, Type type, + int x = 0, int y = 0, int w = 1, int h = 1); + ~Window (void); + + virtual bool isActive (void) const; + virtual bool isCloseable (void) const; + virtual bool isMaximizable (void) const; + virtual MaximizeMode maximizeMode (void) const; + virtual bool isMinimizable (void) const; + virtual bool providesContextHelp (void) const; + virtual int desktop (void) const; + virtual bool isModal (void) const; + virtual bool isShadeable (void) const; + virtual bool isShade (void) const; + virtual bool isSetShade (void) const; + virtual bool keepAbove (void) const; + virtual bool keepBelow (void) const; + virtual bool isMovable (void) const; + virtual bool isResizable (void) const; + virtual NET::WindowType + windowType (unsigned long supported_types) const; + virtual QIconSet icon (void) const; + virtual QString caption (void) 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 (void) const; + virtual QRect geometry (void) const; + virtual QRect iconGeometry (void) const; + virtual QRegion unobscuredRegion (const QRegion & r) const; + virtual QWidget *workspaceWidget (void) const; + virtual WId windowId (void) const; + virtual void closeWindow (void); + virtual void maximize (MaximizeMode mode); + virtual void minimize (void); + virtual void showContextHelp (void); + virtual void setDesktop (int desktop); + virtual void titlebarDblClickOperation (void); + virtual void titlebarMouseWheelOperation (int delta); + virtual void setShade (bool set); + virtual void setKeepAbove (bool); + virtual void setKeepBelow (bool); + virtual int currentDesktop (void) const; + virtual QWidget *initialParentWidget (void) const; + virtual Qt::WFlags initialWFlags (void) const; + virtual void helperShowHide (bool); + virtual void grabXServer (bool grab); + + void handleActiveChange (void); + void updateFrame (WId frame); + void updateWindowGeometry (void); + void updateCursor (QPoint pos); + void updateSelected (WId selected); + WId frameId (void) const + { + return mFrame; + } + KDecoration *decoration (void) const + { + return mDecor; + } + QWidget *activeChild (void) const + { + return mActiveChild; + } + void setActiveChild (QWidget * child) + { + mActiveChild = child; + } + QRegion *getShape (void) + { + if (mShapeSet) + return &mShape; + + return NULL; + } + void getShapeInfo (bool *horz, bool *vert) + { + *horz = mUniqueHorzShape; + *vert = mUniqueVertShape; + } + void moveWindow (QMouseEvent *qme); + void reloadDecoration (void); + void updateState (void); + void updateName (void); + void updateIcons (void); + + Drawable pixmapId (void) const + { + return mPixmap; + } + void addDamageRect (int x, int y, int w, int h) + { + mDamage += QRegion (x, y, w, h); + } + bool handleMap (void); + bool handleConfigure (void); + void processDamage (void); + decor_context_t *context (void) + { + return &mContext; + } + decor_shadow_t *shadow (void) + { + return mShadow; + } + QRect clientGeometry (void); void showKillProcessDialog (Time timestamp); void hideKillProcessDialog (void); - 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 (); - void getWindowProtocols (); - void performMouseCommand( Options::MouseCommand, QMouseEvent *qme ); - XFixed *createGaussianKernel (int *r_size); - void setPictureTransform (Picture p, int dx, int dy); - void renderShadow (); - void renderShadow (QRegion reg); - - private slots: - void updateWindow (); - void updateWindowProperties (); - void slotPopupActivated (int id); - void slotPopupAboutToShow (); - void slotChangeViewport (int id); - void slotAppearanceChange (int id); - void slotDesktopGeometryChanged (); + void updateShadow (void); + + void updateOpacity () + { + mOpacity = + readPropertyShort (mClientId, Atoms::netWmWindowOpacity, 0xffff); + } + void updateBrightness () + { + mBrightness = + readPropertyShort (mClientId, Atoms::netWmWindowBrightness, 0xffff); + } + void updateSaturation () + { + mSaturation = + readPropertyShort (mClientId, Atoms::netWmWindowSaturation, 0xffff); + } + + private: + enum WindowAppearance + { + ResetValues, + ChangeOpacity25, + ChangeOpacity50, + ChangeOpacity75, + ChangeOpacity100, + ChangeBrightness25, + ChangeBrightness50, + ChangeBrightness75, + ChangeBrightness100, + ChangeSaturation25, + ChangeSaturation50, + ChangeSaturation75, + ChangeSaturation100 + }; + + private: + void createDecoration (void); + + bool resizeDecoration (bool force = false); + void updateProperty (void); + void getWindowProtocols (void); + void performMouseCommand (Aquamarine::Options::MouseCommand command, + QMouseEvent *qme); + NET::Direction positionToDirection (int pos); + Cursor positionToCursor (QPoint pos); + void rebindPixmap (void); + + + private slots: + void handlePopupActivated (int id); + void handleDesktopPopupActivated (int id); + void handlePopupAboutToShow (void); void handleProcessKillerExited (void); - - 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; - Pixmap m_currentPixmap; - bool m_updatePixmap; - bool m_mapped; - bool m_fakeMaximized; - - // shape stuff - bool m_shapeSet; - QRegion m_shape; - QRegion m_shapeChange; - - // window handling - bool m_supportDeleteWindow; - bool m_supportTakeFocus; - bool m_supportTakeActivity; - bool m_supportContextHelp; - bool m_supportPing; - - // 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; - - // shadow - QRect m_soffset; - int m_sradius; - short m_scolor[4]; - + void handleChangeViewport (int id); + void handleDesktopGeometryChanged (); + void handleAppearanceChange (int id); + + + private: + Type mType; + WId mFrame; + WId mClientId; + WId mSelectedId; + QRect mGeometry; + QString mName; + QIconSet mIcons; + decor_extents_t mBorder; + KDecoration *mDecor; + QPixmap mTexturePixmap; + QPixmap mTexturePixmapBuffer; + Pixmap mPixmap; + QRegion mDamage; + WId mDamageId; + decor_layout_t mLayout; + decor_context_t mContext; + decor_shadow_t *mShadow; + Picture mPicture; + Picture mTexturePicture; + Picture mDecorationPicture; + bool mUpdateProperty; + bool mShapeSet; + bool mUniqueHorzShape; + bool mUniqueVertShape; + QRegion mShape; + QWidget *mActiveChild; + bool mSupportTakeFocus; + bool mSupportContextHelp; + + QPopupMenu *mPopup; + QPopupMenu *mAdvancedMenu; + QPopupMenu *mDesktopMenu; + QPopupMenu *mViewportMenu; + QPopupMenu *mAppearanceMenu; + QPopupMenu *mBrightnessMenu; + QPopupMenu *mSaturationMenu; + QPopupMenu *mOpacityMenu; + + unsigned long mState; + bool mMapped; + int mPendingMap; + int mPendingConfigure; KProcess *mProcessKiller; - }; + unsigned short mOpacity; + unsigned short mBrightness; + unsigned short mSaturation; + }; } #endif |