summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--kdecore/kapplication.cpp122
-rw-r--r--kdecore/kapplication.h3
-rw-r--r--kdecore/kdetcompmgr.cpp7
-rw-r--r--kdefx/kstyle.cpp147
4 files changed, 233 insertions, 46 deletions
diff --git a/kdecore/kapplication.cpp b/kdecore/kapplication.cpp
index 3bdf0b4cc..91aa2a967 100644
--- a/kdecore/kapplication.cpp
+++ b/kdecore/kapplication.cpp
@@ -140,6 +140,8 @@
#include <fixx11h.h>
#endif
+#include <pwd.h>
+
#ifndef Q_WS_WIN
#include <KDE-ICE/ICElib.h>
#else
@@ -1764,16 +1766,43 @@ public:
#if defined(Q_WS_X11) && defined(COMPOSITE)
bool KApplication::isCompositionManagerAvailable() {
- KConfigGroup pConfig (KGlobal::config(), "General");
- return pConfig.readBoolEntry("compositingManagerAvailable", false);
+ bool have_manager = false;
+ const char *home;
+ struct passwd *p;
+ p = getpwuid(getuid());
+ if (p)
+ home = p->pw_dir;
+ else
+ home = getenv("HOME");
+
+ char *filename;
+ const char *configfile = "/.kompmgr.available";
+ int n = strlen(home)+strlen(configfile)+1;
+ filename = (char*)malloc(n*sizeof(char));
+ memset(filename,0,n);
+ strcat(filename, home);
+ strcat(filename, configfile);
+
+ // Now that we did all that by way of introduction...read the file!
+ FILE *pFile;
+ char buffer[255];
+ pFile = fopen(filename, "r");
+ int kompmgrpid = 0;
+ if (pFile) {
+ have_manager = true;
+ fclose(pFile);
+ }
+
+ free(filename);
+ filename = NULL;
-return false;
+ return have_manager;
}
-bool KApplication::detectCompositionManagerAvailable(bool force_available) {
+bool KApplication::detectCompositionManagerAvailable(bool force_available, bool available) {
bool compositing_manager_available;
if (force_available) {
- compositing_manager_available = true;
+ compositing_manager_available = available;
}
else {
// See if compositing has been enabled
@@ -1781,7 +1810,7 @@ bool KApplication::detectCompositionManagerAvailable(bool force_available) {
char *displayname = 0;
if ( qtargs->isSet("display"))
displayname = qtargs->getOption( "display" ).data();
-
+
Display *dpy = XOpenDisplay( displayname );
x11_composite_error_generated = false;
@@ -1807,12 +1836,39 @@ bool KApplication::detectCompositionManagerAvailable(bool force_available) {
}
}
- KConfigGroup pConfig (KGlobal::config(), "General");
- bool cmanager_enabled = pConfig.readBoolEntry("compositingManagerAvailable", false);
- if (cmanager_enabled != compositing_manager_available) {
- pConfig.writeEntry("compositingManagerAvailable", compositing_manager_available, true, true);
+ const char *home;
+ struct passwd *p;
+ p = getpwuid(getuid());
+ if (p)
+ home = p->pw_dir;
+ else
+ home = getenv("HOME");
+
+ char *filename;
+ const char *configfile = "/.kompmgr.available";
+ int n = strlen(home)+strlen(configfile)+1;
+ filename = (char*)malloc(n*sizeof(char));
+ memset(filename,0,n);
+ strcat(filename, home);
+ strcat(filename, configfile);
+
+ /* now that we did all that by way of introduction...create or remove the file! */
+ if (compositing_manager_available) {
+ FILE *pFile;
+ char buffer[255];
+ sprintf(buffer, "available");
+ pFile = fopen(filename, "w");
+ if (pFile) {
+ fwrite(buffer,1,strlen(buffer), pFile);
+ fclose(pFile);
+ }
}
- pConfig.sync();
+ else {
+ unlink(filename);
+ }
+
+ free(filename);
+ filename = NULL;
return compositing_manager_available;
}
@@ -1822,28 +1878,38 @@ Display* KApplication::openX11RGBADisplay() {
char *display = 0;
if ( qtargs->isSet("display"))
display = qtargs->getOption( "display" ).data();
-
+
Display *dpy = XOpenDisplay( display );
if ( !dpy ) {
kdError() << "cannot connect to X server " << display << endl;
exit( 1 );
}
-
+
return dpy;
}
Qt::HANDLE KApplication::getX11RGBAVisual(Display *dpy) {
getX11RGBAInformation(dpy);
- return argb_x11_visual;
+ if (KApplication::isCompositionManagerAvailable() == true) {
+ return argb_x11_visual;
+ }
+ else {
+ return NULL;
+ }
}
Qt::HANDLE KApplication::getX11RGBAColormap(Display *dpy) {
getX11RGBAInformation(dpy);
- return argb_x11_colormap;
+ if (KApplication::isCompositionManagerAvailable() == true) {
+ return argb_x11_colormap;
+ }
+ else {
+ return NULL;
+ }
}
bool KApplication::isX11CompositionAvailable() {
- return argb_visual & isCompositionManagerAvailable();
+ return (argb_visual & isCompositionManagerAvailable());
}
void KApplication::getX11RGBAInformation(Display *dpy) {
@@ -1851,7 +1917,7 @@ void KApplication::getX11RGBAInformation(Display *dpy) {
argb_visual = false;
return;
}
-
+
int screen = DefaultScreen( dpy );
Colormap colormap = 0;
Visual *visual = 0;
@@ -1896,6 +1962,28 @@ bool KApplication::isCompositionManagerAvailable() {
}
bool KApplication::detectCompositionManagerAvailable(bool force_available) {
+ const char *home;
+ struct passwd *p;
+ p = getpwuid(getuid());
+ if (p)
+ home = p->pw_dir;
+ else
+ home = getenv("HOME");
+
+ char *filename;
+ const char *configfile = "/.kompmgr.available";
+ int n = strlen(home)+strlen(configfile)+1;
+ filename = (char*)malloc(n*sizeof(char));
+ memset(filename,0,n);
+ strcat(filename, home);
+ strcat(filename, configfile);
+
+ /* now that we did all that by way of introduction...remove the file! */
+ unlink(filename);
+
+ free(filename);
+ filename = NULL;
+
return false;
}
diff --git a/kdecore/kapplication.h b/kdecore/kapplication.h
index ee0d48f02..c16f105f2 100644
--- a/kdecore/kapplication.h
+++ b/kdecore/kapplication.h
@@ -914,9 +914,10 @@ public:
* Note that calling this method will probably cause the screen to flicker.
* @see isCompositionManagerAvailable()
* @param force_available If set, force TDE to assume a composition manager is available
+ * @param available Whether or not the composition manager is available (only used if force_available is TRUE)
* @return whether the composition manager is enabled
*/
- bool detectCompositionManagerAvailable(bool force_available=false);
+ bool detectCompositionManagerAvailable(bool force_available=false, bool available=true);
/**
* @internal
diff --git a/kdecore/kdetcompmgr.cpp b/kdecore/kdetcompmgr.cpp
index 0b143d5de..c5cbd415f 100644
--- a/kdecore/kdetcompmgr.cpp
+++ b/kdecore/kdetcompmgr.cpp
@@ -49,16 +49,17 @@ int main(int argc, char **argv)
KApplication app;
app.detectCompositionManagerAvailable();
- if (!app.isCompositionManagerAvailable()) {
+// if (!app.isCompositionManagerAvailable()) {
KConfig config("kwinrc", true);
config.setGroup( "Notification Messages" );
if (config.readBoolEntry("UseTranslucency",false)) {
- app.detectCompositionManagerAvailable(true);
+ app.detectCompositionManagerAvailable(true, true);
return 2;
}
else {
+ app.detectCompositionManagerAvailable(true, false);
return 0;
}
- }
+// }
}
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);