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 13 years ago
parent 7d7b2c04e1
commit 79a4d6dfad

@ -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;
}

@ -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

@ -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;
}
}
// }
}

@ -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);

Loading…
Cancel
Save