summaryrefslogtreecommitdiffstats
path: root/kdefx
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-08-15 01:49:14 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-08-15 01:49:14 +0000
commit79a4d6dfad2786fb412167638c5beb4af614b9e8 (patch)
tree5a764aab2aaa4a7485895662a59d22a39bcdaee6 /kdefx
parent7d7b2c04e147670ed65c5be42de7b7b131122856 (diff)
downloadtdelibs-79a4d6dfad2786fb412167638c5beb4af614b9e8.tar.gz
tdelibs-79a4d6dfad2786fb412167638c5beb4af614b9e8.zip
Use true transparency when drawing menu shadows for apps that support ARGB visuals
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1247204 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdefx')
-rw-r--r--kdefx/kstyle.cpp147
1 files changed, 122 insertions, 25 deletions
diff --git a/kdefx/kstyle.cpp b/kdefx/kstyle.cpp
index 473a61e43..3f3f36b71 100644
--- a/kdefx/kstyle.cpp
+++ b/kdefx/kstyle.cpp
@@ -63,6 +63,12 @@
#undef HAVE_XRENDER
#endif
+#ifdef HAVE_XCOMPOSITE
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/Xcomposite.h>
+#include <dlfcn.h>
+#endif
+
#include <limits.h>
namespace
@@ -138,6 +144,10 @@ class TransparencyHandler : public TQObject
#ifdef HAVE_XRENDER
void XRenderBlendToPixmap(const TQWidget* p);
#endif
+#ifdef HAVE_XCOMPOSITE
+ bool haveX11RGBASupport();
+#endif
+ TQImage handleRealAlpha(TQImage);
void createShadowWindows(const TQWidget* p);
void removeShadowWindows(const TQWidget* p);
void rightShadow(TQImage& dst);
@@ -1951,9 +1961,24 @@ TransparencyHandler::~TransparencyHandler()
{
}
+bool TransparencyHandler::haveX11RGBASupport()
+{
+ // Simple way
+ if (TQPaintDevice::x11AppDepth() == 32) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+#define REAL_ALPHA_STRENGTH 255.0
+
// This is meant to be ugly but fast.
void TransparencyHandler::rightShadow(TQImage& dst)
{
+ bool have_composite = haveX11RGBASupport();
+
if (dst.depth() != 32)
dst = dst.convertDepth(32);
@@ -1965,34 +1990,60 @@ void TransparencyHandler::rightShadow(TQImage& dst)
register unsigned char* data = dst.bits(); // Skip alpha
#endif
for(register int i = 0; i < 16; i++) {
- *data = (unsigned char)((*data)*top_right_corner[i]); data++;
- *data = (unsigned char)((*data)*top_right_corner[i]); data++;
- *data = (unsigned char)((*data)*top_right_corner[i]); data++;
- data++; // skip alpha
+ if (have_composite) {
+ data++;
+ data++;
+ data++;
+ *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-top_right_corner[i])); data++;
+ }
+ else {
+ *data = (unsigned char)((*data)*top_right_corner[i]); data++;
+ *data = (unsigned char)((*data)*top_right_corner[i]); data++;
+ *data = (unsigned char)((*data)*top_right_corner[i]); data++;
+ data++; // skip alpha
+ }
}
pixels -= 32; // tint right strip without rounded edges.
register int c = 0;
for(register int i = 0; i < pixels; i++) {
- *data = (unsigned char)((*data)*shadow_strip[c]); data++;
- *data = (unsigned char)((*data)*shadow_strip[c]); data++;
- *data = (unsigned char)((*data)*shadow_strip[c]); data++;
- data++; // skip alpha
- ++c;
+ if (have_composite) {
+ data++;
+ data++;
+ data++;;
+ *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-shadow_strip[c])); data++;
+ }
+ else {
+ *data = (unsigned char)((*data)*shadow_strip[c]); data++;
+ *data = (unsigned char)((*data)*shadow_strip[c]); data++;
+ *data = (unsigned char)((*data)*shadow_strip[c]); data++;
+ data++; // skip alpha
+ }
+ ++c;
c %= 4;
}
// tint bottom edge
for(register int i = 0; i < 16; i++) {
- *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
- *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
- *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
- data++; // skip alpha
+ if (have_composite) {
+ data++;
+ data++;
+ data++;
+ *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-bottom_right_corner[i])); data++;
+ }
+ else {
+ *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
+ *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
+ *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
+ data++; // skip alpha
+ }
}
}
void TransparencyHandler::bottomShadow(TQImage& dst)
{
+ bool have_composite = haveX11RGBASupport();
+
if (dst.depth() != 32)
dst = dst.convertDepth(32);
@@ -2011,25 +2062,59 @@ void TransparencyHandler::bottomShadow(TQImage& dst)
{
// Bottom-left Corner
for(register int x = 0; x < 4; x++) {
- *data = (unsigned char)((*data)*(*corner)); data++;
- *data = (unsigned char)((*data)*(*corner)); data++;
- *data = (unsigned char)((*data)*(*corner)); data++;
- data++; // skip alpha
+ if (have_composite) {
+ data++;
+ data++;
+ data++;
+ *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-(*corner))); data++;
+ }
+ else {
+ *data = (unsigned char)((*data)*(*corner)); data++;
+ *data = (unsigned char)((*data)*(*corner)); data++;
+ *data = (unsigned char)((*data)*(*corner)); data++;
+ data++; // skip alpha
+ }
corner++;
}
// Scanline
for(register int x = 0; x < width; x++) {
- *data = (unsigned char)((*data)*strip_data); data++;
- *data = (unsigned char)((*data)*strip_data); data++;
- *data = (unsigned char)((*data)*strip_data); data++;
- data++;
+ if (have_composite) {
+ data++;
+ data++;
+ data++;
+ *data = (unsigned char)(REAL_ALPHA_STRENGTH*(1.0-strip_data)); data++;
+ }
+ else {
+ *data = (unsigned char)((*data)*strip_data); data++;
+ *data = (unsigned char)((*data)*strip_data); data++;
+ *data = (unsigned char)((*data)*strip_data); data++;
+ data++; // skip alpha
+ }
}
strip_data = shadow_strip[++line];
}
}
+TQImage TransparencyHandler::handleRealAlpha(TQImage img) {
+ TQImage clearImage = img.convertDepth(32);
+ clearImage.setAlphaBuffer(true);
+
+ int w = clearImage.width();
+ int h = clearImage.height();
+
+ for (int y = 0; y < h; ++y) {
+ TQRgb *ls = (TQRgb *)clearImage.scanLine( y );
+ for (int x = 0; x < w; ++x) {
+ TQRgb l = ls[x];
+ ls[x] = tqRgba( 0, 0, 0, 0 );
+ }
+ }
+
+ return clearImage;
+}
+
// Create a shadow of thickness 4.
void TransparencyHandler::createShadowWindows(const TQWidget* p)
{
@@ -2039,6 +2124,8 @@ void TransparencyHandler::createShadowWindows(const TQWidget* p)
TQRect shadow1(x2, p->y() + 4, 4, p->height());
TQRect shadow2(p->x() + 4, y2, p->width() - 4, 4);
+ bool have_composite = haveX11RGBASupport();
+
// Create a fake drop-down shadow effect via blended Xwindows
ShadowElements se;
se.w1 = new TQWidget(0, 0, (WFlags)(WStyle_Customize | WType_Popup | WX11BypassWM) );
@@ -2052,16 +2139,26 @@ void TransparencyHandler::createShadowWindows(const TQWidget* p)
shadowMap()[p] = se;
// Some hocus-pocus here to create the drop-shadow.
- TQPixmap pix_shadow1 = TQPixmap::grabWindow(qt_xrootwin(),
- shadow1.x(), shadow1.y(), shadow1.width(), shadow1.height());
- TQPixmap pix_shadow2 = TQPixmap::grabWindow(qt_xrootwin(),
- shadow2.x(), shadow2.y(), shadow2.width(), shadow2.height());
+ TQPixmap pix_shadow1;
+ TQPixmap pix_shadow2;
+ if (have_composite) {
+ pix_shadow1 = TQPixmap(shadow1.width(), shadow1.height());
+ pix_shadow2 = TQPixmap(shadow2.width(), shadow2.height());
+ }
+ else {
+ pix_shadow1 = TQPixmap::grabWindow(qt_xrootwin(),
+ shadow1.x(), shadow1.y(), shadow1.width(), shadow1.height());
+ pix_shadow2 = TQPixmap::grabWindow(qt_xrootwin(),
+ shadow2.x(), shadow2.y(), shadow2.width(), shadow2.height());
+ }
TQImage img;
img = pix_shadow1.convertToImage();
+ if (have_composite) img = handleRealAlpha(img);
rightShadow(img);
pix_shadow1.convertFromImage(img);
img = pix_shadow2.convertToImage();
+ if (have_composite) img = handleRealAlpha(img);
bottomShadow(img);
pix_shadow2.convertFromImage(img);