diff options
author | onestone <onestone> | 2006-12-14 22:27:32 +0000 |
---|---|---|
committer | onestone <onestone> | 2006-12-14 22:27:32 +0000 |
commit | 3e5b79c544c3ec59f72bc2619a1d9fa4c3fca484 (patch) | |
tree | 5b8d0d2b2d4ccebcfebe7ff1577fce64aad1dee8 /src | |
parent | 0f51914d77b0d1d00a998bf1aa61db1139ed0401 (diff) | |
download | aquamarine-3e5b79c544c3ec59f72bc2619a1d9fa4c3fca484.tar.gz aquamarine-3e5b79c544c3ec59f72bc2619a1d9fa4c3fca484.tar.bz2 |
aquamarine: added shadows for non decorated windows like menus
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/decorator.cpp | 5 | ||||
-rw-r--r-- | src/decorator.h | 2 | ||||
-rw-r--r-- | src/defaultShadow.cpp | 456 | ||||
-rw-r--r-- | src/defaultShadow.h | 66 | ||||
-rw-r--r-- | src/window.cpp | 2 |
6 files changed, 531 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 46ec774..6638858 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,6 +12,7 @@ aquamarine_SOURCES = aquamarine.cpp \ KWinInterface.skel \ options.cpp \ defaultDeco.cpp \ + defaultShadow.cpp \ settings.kcfgc aquamarine_LDADD = $(LIB_KDECORE) -lkdecorations $(BERYLSETTINGS_LIBS) diff --git a/src/decorator.cpp b/src/decorator.cpp index 6a3c160..f4a6b25 100644 --- a/src/decorator.cpp +++ b/src/decorator.cpp @@ -154,6 +154,7 @@ m_kwinmodule (new KWinModule (this, KWinModule::INFO_ALL)), m_switcher (0) 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))); @@ -198,6 +199,7 @@ Aquamarine::Decorator::~Decorator () m_defDeco; delete m_defDecoActive; + delete m_defShadow; delete m_options; delete @@ -407,6 +409,9 @@ Aquamarine::Decorator::reconfigure () it.data ()->reloadDecoration (); m_defDeco->reloadDecoration (); m_defDecoActive->reloadDecoration (); + if (m_defShadow) + delete m_defShadow; + m_defShadow = (Settings::drawShadows())? new Aquamarine::DefaultShadow () : NULL; m_plugins->destroyPreviousPlugin (); } } diff --git a/src/decorator.h b/src/decorator.h index 519e3d1..a3a3c76 100644 --- a/src/decorator.h +++ b/src/decorator.h @@ -45,6 +45,7 @@ #include "window.h" #include "defaultDeco.h" +#include "defaultShadow.h" #include "KWinInterface.h" #define C(name) { 0, XC_ ## name } @@ -139,6 +140,7 @@ namespace Aquamarine Aquamarine::DefaultDecoration * m_defDeco; Aquamarine::DefaultDecoration * m_defDecoActive; + Aquamarine::DefaultShadow * m_defShadow; QMap < WId, Aquamarine::Window * >m_windows; QMap < WId, Aquamarine::Window * >m_frames; diff --git a/src/defaultShadow.cpp b/src/defaultShadow.cpp new file mode 100644 index 0000000..83f2246 --- /dev/null +++ b/src/defaultShadow.cpp @@ -0,0 +1,456 @@ +/* + * 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 DECOR_WINDOW_MASK (1 << 0) + +#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 () +{ + 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(Settings::shadowOpacity() * 0xffff); + + // 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 new file mode 100644 index 0000000..45b7d80 --- /dev/null +++ b/src/defaultShadow.h @@ -0,0 +1,66 @@ +/* + * 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/window.cpp b/src/window.cpp index 071b6c3..268bb90 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1035,7 +1035,7 @@ Aquamarine::Window::updateWindowProperties () Atoms::net_window_decor, XA_INTEGER, 32, PropModeReplace, (unsigned char *)mdata, - 12 + (12 * 9)); + 15 + (12 * 9)); Aquamarine::popXError (); XSync (qt_xdisplay (), FALSE); } |