summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoronestone <onestone>2006-12-14 22:27:32 +0000
committeronestone <onestone>2006-12-14 22:27:32 +0000
commit3e5b79c544c3ec59f72bc2619a1d9fa4c3fca484 (patch)
tree5b8d0d2b2d4ccebcfebe7ff1577fce64aad1dee8
parent0f51914d77b0d1d00a998bf1aa61db1139ed0401 (diff)
downloadaquamarine-3e5b79c544c3ec59f72bc2619a1d9fa4c3fca484.tar.gz
aquamarine-3e5b79c544c3ec59f72bc2619a1d9fa4c3fca484.tar.bz2
aquamarine: added shadows for non decorated windows like menus
-rw-r--r--src/Makefile.am1
-rw-r--r--src/decorator.cpp5
-rw-r--r--src/decorator.h2
-rw-r--r--src/defaultShadow.cpp456
-rw-r--r--src/defaultShadow.h66
-rw-r--r--src/window.cpp2
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);
}