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 | |
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)
-rw-r--r-- | configure.in.in | 1 | ||||
-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 |
19 files changed, 6353 insertions, 4947 deletions
diff --git a/configure.in.in b/configure.in.in index d23e58c..c5297dd 100644 --- a/configure.in.in +++ b/configure.in.in @@ -19,6 +19,7 @@ AC_ARG_ENABLE(berylsettings, AC_HELP_STRING([--disable-berylsettings], [disable AM_CONDITIONAL(include_bs, test "$berylsettings" = "yes") KDE_PKG_CHECK_MODULES(XCOMPOSITE, "xcomposite",[],AC_MSG_ERROR([xcomposite not found])) +#KDE_PKG_CHECK_MODULES(DECOLIB, "libberyldecoration",[],AC_MSG_ERROR([libberyldecoration not found])) if test "$berylsettings" = "yes"; then KDE_PKG_CHECK_MODULES(BERYLSETTINGS, $BERYL_SETTINGS_REQUIRES, 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, + |