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
v3.5.13-sru
tpearson 14 years ago
parent 7d7b2c04e1
commit 79a4d6dfad

@ -140,6 +140,8 @@
#include <fixx11h.h> #include <fixx11h.h>
#endif #endif
#include <pwd.h>
#ifndef Q_WS_WIN #ifndef Q_WS_WIN
#include <KDE-ICE/ICElib.h> #include <KDE-ICE/ICElib.h>
#else #else
@ -1764,16 +1766,43 @@ public:
#if defined(Q_WS_X11) && defined(COMPOSITE) #if defined(Q_WS_X11) && defined(COMPOSITE)
bool KApplication::isCompositionManagerAvailable() { bool KApplication::isCompositionManagerAvailable() {
KConfigGroup pConfig (KGlobal::config(), "General"); bool have_manager = false;
return pConfig.readBoolEntry("compositingManagerAvailable", 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; bool compositing_manager_available;
if (force_available) { if (force_available) {
compositing_manager_available = true; compositing_manager_available = available;
} }
else { else {
// See if compositing has been enabled // See if compositing has been enabled
@ -1781,7 +1810,7 @@ bool KApplication::detectCompositionManagerAvailable(bool force_available) {
char *displayname = 0; char *displayname = 0;
if ( qtargs->isSet("display")) if ( qtargs->isSet("display"))
displayname = qtargs->getOption( "display" ).data(); displayname = qtargs->getOption( "display" ).data();
Display *dpy = XOpenDisplay( displayname ); Display *dpy = XOpenDisplay( displayname );
x11_composite_error_generated = false; x11_composite_error_generated = false;
@ -1807,12 +1836,39 @@ bool KApplication::detectCompositionManagerAvailable(bool force_available) {
} }
} }
KConfigGroup pConfig (KGlobal::config(), "General"); const char *home;
bool cmanager_enabled = pConfig.readBoolEntry("compositingManagerAvailable", false); struct passwd *p;
if (cmanager_enabled != compositing_manager_available) { p = getpwuid(getuid());
pConfig.writeEntry("compositingManagerAvailable", compositing_manager_available, true, true); 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; return compositing_manager_available;
} }
@ -1822,28 +1878,38 @@ Display* KApplication::openX11RGBADisplay() {
char *display = 0; char *display = 0;
if ( qtargs->isSet("display")) if ( qtargs->isSet("display"))
display = qtargs->getOption( "display" ).data(); display = qtargs->getOption( "display" ).data();
Display *dpy = XOpenDisplay( display ); Display *dpy = XOpenDisplay( display );
if ( !dpy ) { if ( !dpy ) {
kdError() << "cannot connect to X server " << display << endl; kdError() << "cannot connect to X server " << display << endl;
exit( 1 ); exit( 1 );
} }
return dpy; return dpy;
} }
Qt::HANDLE KApplication::getX11RGBAVisual(Display *dpy) { Qt::HANDLE KApplication::getX11RGBAVisual(Display *dpy) {
getX11RGBAInformation(dpy); getX11RGBAInformation(dpy);
return argb_x11_visual; if (KApplication::isCompositionManagerAvailable() == true) {
return argb_x11_visual;
}
else {
return NULL;
}
} }
Qt::HANDLE KApplication::getX11RGBAColormap(Display *dpy) { Qt::HANDLE KApplication::getX11RGBAColormap(Display *dpy) {
getX11RGBAInformation(dpy); getX11RGBAInformation(dpy);
return argb_x11_colormap; if (KApplication::isCompositionManagerAvailable() == true) {
return argb_x11_colormap;
}
else {
return NULL;
}
} }
bool KApplication::isX11CompositionAvailable() { bool KApplication::isX11CompositionAvailable() {
return argb_visual & isCompositionManagerAvailable(); return (argb_visual & isCompositionManagerAvailable());
} }
void KApplication::getX11RGBAInformation(Display *dpy) { void KApplication::getX11RGBAInformation(Display *dpy) {
@ -1851,7 +1917,7 @@ void KApplication::getX11RGBAInformation(Display *dpy) {
argb_visual = false; argb_visual = false;
return; return;
} }
int screen = DefaultScreen( dpy ); int screen = DefaultScreen( dpy );
Colormap colormap = 0; Colormap colormap = 0;
Visual *visual = 0; Visual *visual = 0;
@ -1896,6 +1962,28 @@ bool KApplication::isCompositionManagerAvailable() {
} }
bool KApplication::detectCompositionManagerAvailable(bool force_available) { 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; return false;
} }

@ -914,9 +914,10 @@ public:
* Note that calling this method will probably cause the screen to flicker. * Note that calling this method will probably cause the screen to flicker.
* @see isCompositionManagerAvailable() * @see isCompositionManagerAvailable()
* @param force_available If set, force TDE to assume a composition manager is available * @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 * @return whether the composition manager is enabled
*/ */
bool detectCompositionManagerAvailable(bool force_available=false); bool detectCompositionManagerAvailable(bool force_available=false, bool available=true);
/** /**
* @internal * @internal

@ -49,16 +49,17 @@ int main(int argc, char **argv)
KApplication app; KApplication app;
app.detectCompositionManagerAvailable(); app.detectCompositionManagerAvailable();
if (!app.isCompositionManagerAvailable()) { // if (!app.isCompositionManagerAvailable()) {
KConfig config("kwinrc", true); KConfig config("kwinrc", true);
config.setGroup( "Notification Messages" ); config.setGroup( "Notification Messages" );
if (config.readBoolEntry("UseTranslucency",false)) { if (config.readBoolEntry("UseTranslucency",false)) {
app.detectCompositionManagerAvailable(true); app.detectCompositionManagerAvailable(true, true);
return 2; return 2;
} }
else { else {
app.detectCompositionManagerAvailable(true, false);
return 0; return 0;
} }
} // }
} }

@ -63,6 +63,12 @@
#undef HAVE_XRENDER #undef HAVE_XRENDER
#endif #endif
#ifdef HAVE_XCOMPOSITE
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xcomposite.h>
#include <dlfcn.h>
#endif
#include <limits.h> #include <limits.h>
namespace namespace
@ -138,6 +144,10 @@ class TransparencyHandler : public TQObject
#ifdef HAVE_XRENDER #ifdef HAVE_XRENDER
void XRenderBlendToPixmap(const TQWidget* p); void XRenderBlendToPixmap(const TQWidget* p);
#endif #endif
#ifdef HAVE_XCOMPOSITE
bool haveX11RGBASupport();
#endif
TQImage handleRealAlpha(TQImage);
void createShadowWindows(const TQWidget* p); void createShadowWindows(const TQWidget* p);
void removeShadowWindows(const TQWidget* p); void removeShadowWindows(const TQWidget* p);
void rightShadow(TQImage& dst); 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. // This is meant to be ugly but fast.
void TransparencyHandler::rightShadow(TQImage& dst) void TransparencyHandler::rightShadow(TQImage& dst)
{ {
bool have_composite = haveX11RGBASupport();
if (dst.depth() != 32) if (dst.depth() != 32)
dst = dst.convertDepth(32); dst = dst.convertDepth(32);
@ -1965,34 +1990,60 @@ void TransparencyHandler::rightShadow(TQImage& dst)
register unsigned char* data = dst.bits(); // Skip alpha register unsigned char* data = dst.bits(); // Skip alpha
#endif #endif
for(register int i = 0; i < 16; i++) { for(register int i = 0; i < 16; i++) {
*data = (unsigned char)((*data)*top_right_corner[i]); data++; if (have_composite) {
*data = (unsigned char)((*data)*top_right_corner[i]); data++; data++;
*data = (unsigned char)((*data)*top_right_corner[i]); data++; data++;
data++; // skip alpha 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. pixels -= 32; // tint right strip without rounded edges.
register int c = 0; register int c = 0;
for(register int i = 0; i < pixels; i++) { for(register int i = 0; i < pixels; i++) {
*data = (unsigned char)((*data)*shadow_strip[c]); data++; if (have_composite) {
*data = (unsigned char)((*data)*shadow_strip[c]); data++; data++;
*data = (unsigned char)((*data)*shadow_strip[c]); data++; data++;
data++; // skip alpha data++;;
++c; *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; c %= 4;
} }
// tint bottom edge // tint bottom edge
for(register int i = 0; i < 16; i++) { for(register int i = 0; i < 16; i++) {
*data = (unsigned char)((*data)*bottom_right_corner[i]); data++; if (have_composite) {
*data = (unsigned char)((*data)*bottom_right_corner[i]); data++; data++;
*data = (unsigned char)((*data)*bottom_right_corner[i]); data++; data++;
data++; // skip alpha 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) void TransparencyHandler::bottomShadow(TQImage& dst)
{ {
bool have_composite = haveX11RGBASupport();
if (dst.depth() != 32) if (dst.depth() != 32)
dst = dst.convertDepth(32); dst = dst.convertDepth(32);
@ -2011,25 +2062,59 @@ void TransparencyHandler::bottomShadow(TQImage& dst)
{ {
// Bottom-left Corner // Bottom-left Corner
for(register int x = 0; x < 4; x++) { for(register int x = 0; x < 4; x++) {
*data = (unsigned char)((*data)*(*corner)); data++; if (have_composite) {
*data = (unsigned char)((*data)*(*corner)); data++; data++;
*data = (unsigned char)((*data)*(*corner)); data++; data++;
data++; // skip alpha 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++; corner++;
} }
// Scanline // Scanline
for(register int x = 0; x < width; x++) { for(register int x = 0; x < width; x++) {
*data = (unsigned char)((*data)*strip_data); data++; if (have_composite) {
*data = (unsigned char)((*data)*strip_data); data++; data++;
*data = (unsigned char)((*data)*strip_data); data++; 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]; 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. // Create a shadow of thickness 4.
void TransparencyHandler::createShadowWindows(const TQWidget* p) 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 shadow1(x2, p->y() + 4, 4, p->height());
TQRect shadow2(p->x() + 4, y2, p->width() - 4, 4); TQRect shadow2(p->x() + 4, y2, p->width() - 4, 4);
bool have_composite = haveX11RGBASupport();
// Create a fake drop-down shadow effect via blended Xwindows // Create a fake drop-down shadow effect via blended Xwindows
ShadowElements se; ShadowElements se;
se.w1 = new TQWidget(0, 0, (WFlags)(WStyle_Customize | WType_Popup | WX11BypassWM) ); 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; shadowMap()[p] = se;
// Some hocus-pocus here to create the drop-shadow. // Some hocus-pocus here to create the drop-shadow.
TQPixmap pix_shadow1 = TQPixmap::grabWindow(qt_xrootwin(), TQPixmap pix_shadow1;
shadow1.x(), shadow1.y(), shadow1.width(), shadow1.height()); TQPixmap pix_shadow2;
TQPixmap pix_shadow2 = TQPixmap::grabWindow(qt_xrootwin(), if (have_composite) {
shadow2.x(), shadow2.y(), shadow2.width(), shadow2.height()); 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; TQImage img;
img = pix_shadow1.convertToImage(); img = pix_shadow1.convertToImage();
if (have_composite) img = handleRealAlpha(img);
rightShadow(img); rightShadow(img);
pix_shadow1.convertFromImage(img); pix_shadow1.convertFromImage(img);
img = pix_shadow2.convertToImage(); img = pix_shadow2.convertToImage();
if (have_composite) img = handleRealAlpha(img);
bottomShadow(img); bottomShadow(img);
pix_shadow2.convertFromImage(img); pix_shadow2.convertFromImage(img);

Loading…
Cancel
Save