From 79a4d6dfad2786fb412167638c5beb4af614b9e8 Mon Sep 17 00:00:00 2001 From: tpearson Date: Mon, 15 Aug 2011 01:49:14 +0000 Subject: 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 --- kdefx/kstyle.cpp | 147 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 122 insertions(+), 25 deletions(-) (limited to 'kdefx') 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 +#include +#include +#endif + #include 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); -- cgit v1.2.1