Add Xorg composition support to kdm

KDM composition can be enabled in the control center
When enabled, it provides seamless composited logins to Trinity sessions
It also gets rid of the remaining artifacts in the themed kdm login screen


git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1246834 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
v3.5.13-sru
tpearson 13 years ago
parent ecb591aa84
commit f50ce50331

@ -169,14 +169,25 @@ KDMAppearanceWidget::KDMAppearanceWidget(TQWidget *parent, const char *name)
grid->addLayout(hglay, 3, 1); grid->addLayout(hglay, 3, 1);
hglay->setColStretch(3, 1); hglay->setColStretch(3, 1);
compositorcombo = new KBackedComboBox(group);
compositorcombo->insertItem( "", i18n("None") );
compositorcombo->insertItem( "kompmgr", i18n("Trinity compositor") );
label = new TQLabel(compositorcombo, i18n("Compositor:"), group);
connect(compositorcombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed()));
hglay->addWidget(label, 0, 0);
hglay->addWidget(compositorcombo, 0, 1);
wtstr = i18n("Choose a compositor to be used in KDM. Note that the chosen compositor will continue to run after login.");
TQWhatsThis::add( label, wtstr );
TQWhatsThis::add( compositorcombo, wtstr );
guicombo = new KBackedComboBox(group); guicombo = new KBackedComboBox(group);
guicombo->insertItem( "", i18n("<default>") ); guicombo->insertItem( "", i18n("<default>") );
loadGuiStyles(guicombo); loadGuiStyles(guicombo);
guicombo->listBox()->sort(); guicombo->listBox()->sort();
label = new TQLabel(guicombo, i18n("GUI s&tyle:"), group); label = new TQLabel(guicombo, i18n("GUI s&tyle:"), group);
connect(guicombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed())); connect(guicombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed()));
hglay->addWidget(label, 0, 0); hglay->addWidget(label, 1, 0);
hglay->addWidget(guicombo, 0, 1); hglay->addWidget(guicombo, 1, 1);
wtstr = i18n("You can choose a basic GUI style here that will be " wtstr = i18n("You can choose a basic GUI style here that will be "
"used by KDM only."); "used by KDM only.");
TQWhatsThis::add( label, wtstr ); TQWhatsThis::add( label, wtstr );
@ -188,8 +199,8 @@ KDMAppearanceWidget::KDMAppearanceWidget(TQWidget *parent, const char *name)
colcombo->listBox()->sort(); colcombo->listBox()->sort();
label = new TQLabel(colcombo, i18n("&Color scheme:"), group); label = new TQLabel(colcombo, i18n("&Color scheme:"), group);
connect(colcombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed())); connect(colcombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed()));
hglay->addWidget(label, 1, 0); hglay->addWidget(label, 2, 0);
hglay->addWidget(colcombo, 1, 1); hglay->addWidget(colcombo, 2, 1);
wtstr = i18n("You can choose a basic Color Scheme here that will be " wtstr = i18n("You can choose a basic Color Scheme here that will be "
"used by KDM only."); "used by KDM only.");
TQWhatsThis::add( label, wtstr ); TQWhatsThis::add( label, wtstr );
@ -201,8 +212,8 @@ KDMAppearanceWidget::KDMAppearanceWidget(TQWidget *parent, const char *name)
echocombo->insertItem("ThreeStars", i18n("Three Stars")); echocombo->insertItem("ThreeStars", i18n("Three Stars"));
label = new TQLabel(echocombo, i18n("Echo &mode:"), group); label = new TQLabel(echocombo, i18n("Echo &mode:"), group);
connect(echocombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed())); connect(echocombo, TQT_SIGNAL(activated(int)), TQT_SLOT(changed()));
hglay->addWidget(label, 2, 0); hglay->addWidget(label, 3, 0);
hglay->addWidget(echocombo, 2, 1); hglay->addWidget(echocombo, 3, 1);
wtstr = i18n("You can choose whether and how KDM shows your password when you type it."); wtstr = i18n("You can choose whether and how KDM shows your password when you type it.");
TQWhatsThis::add( label, wtstr ); TQWhatsThis::add( label, wtstr );
TQWhatsThis::add( echocombo, wtstr ); TQWhatsThis::add( echocombo, wtstr );
@ -241,6 +252,7 @@ void KDMAppearanceWidget::makeReadOnly()
logoRadio->setEnabled(false); logoRadio->setEnabled(false);
xLineEdit->setEnabled(false); xLineEdit->setEnabled(false);
yLineEdit->setEnabled(false); yLineEdit->setEnabled(false);
compositorcombo->setEnabled(false);
guicombo->setEnabled(false); guicombo->setEnabled(false);
colcombo->setEnabled(false); colcombo->setEnabled(false);
echocombo->setEnabled(false); echocombo->setEnabled(false);
@ -425,6 +437,8 @@ void KDMAppearanceWidget::save()
config->writeEntry("LogoPixmap", KGlobal::iconLoader()->iconPath(logopath, KIcon::Desktop, true)); config->writeEntry("LogoPixmap", KGlobal::iconLoader()->iconPath(logopath, KIcon::Desktop, true));
config->writeEntry("Compositor", compositorcombo->currentId());
config->writeEntry("GUIStyle", guicombo->currentId()); config->writeEntry("GUIStyle", guicombo->currentId());
config->writeEntry("ColorScheme", colcombo->currentId()); config->writeEntry("ColorScheme", colcombo->currentId());
@ -460,6 +474,9 @@ void KDMAppearanceWidget::load()
// See if we use alternate logo // See if we use alternate logo
setLogo(config->readEntry("LogoPixmap")); setLogo(config->readEntry("LogoPixmap"));
// Check the current compositor type
compositorcombo->setCurrentId(config->readEntry("Compositor"));
// Check the GUI type // Check the GUI type
guicombo->setCurrentId(config->readEntry("GUIStyle")); guicombo->setCurrentId(config->readEntry("GUIStyle"));
@ -489,6 +506,7 @@ void KDMAppearanceWidget::defaults()
logoRadio->setChecked( true ); logoRadio->setChecked( true );
slotAreaRadioClicked( KdmLogo ); slotAreaRadioClicked( KdmLogo );
setLogo( "" ); setLogo( "" );
compositorcombo->setCurrentId( "" );
guicombo->setCurrentId( "" ); guicombo->setCurrentId( "" );
colcombo->setCurrentId( "" ); colcombo->setCurrentId( "" );
echocombo->setCurrentItem( "OneStar" ); echocombo->setCurrentItem( "OneStar" );

@ -85,6 +85,7 @@ private:
TQRadioButton *logoRadio; TQRadioButton *logoRadio;
TQLineEdit *xLineEdit; TQLineEdit *xLineEdit;
TQLineEdit *yLineEdit; TQLineEdit *yLineEdit;
KBackedComboBox *compositorcombo;
KBackedComboBox *guicombo; KBackedComboBox *guicombo;
KBackedComboBox *colcombo; KBackedComboBox *colcombo;
KBackedComboBox *echocombo; KBackedComboBox *echocombo;

@ -1986,6 +1986,16 @@ Description:
Specify the widget style for the greeter. Empty means to use the Specify the widget style for the greeter. Empty means to use the
built-in default which currently is <literal>Plastik</literal>. built-in default which currently is <literal>Plastik</literal>.
Key: Compositor
Type: string
Default: ""
User: greeter
Instance: #*/""
Comment:
Compositor binary name, if compositing is desired. "" means no compositing support.
Description:
Specify the Xorg compositing manager. Currently only kompmgr is supported.
Key: UseAdminSession Key: UseAdminSession
Type: bool Type: bool
Default: false Default: false

@ -22,6 +22,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include <config.h>
#include "kdm_greet.h" #include "kdm_greet.h"
#include "kdmshutdown.h" #include "kdmshutdown.h"
#include "kdmconfig.h" #include "kdmconfig.h"
@ -52,6 +54,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
#ifdef HAVE_XCOMPOSITE
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xcomposite.h>
#endif
#include <pwd.h>
bool argb_visual_available = false;
static int static int
ignoreXError( Display *dpy ATTR_UNUSED, XErrorEvent *event ATTR_UNUSED ) ignoreXError( Display *dpy ATTR_UNUSED, XErrorEvent *event ATTR_UNUSED )
{ {
@ -82,6 +93,20 @@ GreeterApp::GreeterApp()
} }
} }
GreeterApp::GreeterApp(Display *dpy) : KApplication(dpy)
{
pingInterval = _isLocal ? 0 : _pingInterval;
if (pingInterval) {
struct sigaction sa;
sigemptyset( &sa.sa_mask );
sa.sa_flags = 0;
sa.sa_handler = sigAlarm;
sigaction( SIGALRM, &sa, 0 );
alarm( pingInterval * 70 ); // sic! give the "proper" pinger enough time
startTimer( pingInterval * 60000 );
}
}
void void
GreeterApp::timerEvent( TQTimerEvent * ) GreeterApp::timerEvent( TQTimerEvent * )
{ {
@ -145,13 +170,65 @@ kg_main( const char *argv0 )
kde_have_kipc = false; kde_have_kipc = false;
KApplication::disableAutoDcopRegistration(); KApplication::disableAutoDcopRegistration();
KCrash::setSafer( true ); KCrash::setSafer( true );
GreeterApp app;
#ifdef HAVE_XCOMPOSITE
// Begin ARGB initialization
XSetErrorHandler( ignoreXError );
argb_visual_available = false;
char *display = 0;
Display *dpyi = XOpenDisplay( display );
if ( !dpyi ) {
kdError() << "cannot connect to X server " << display << endl;
exit( 1 );
}
int screen = DefaultScreen( dpyi );
Colormap colormap = 0;
Visual *visual = 0;
int event_base, error_base;
if ( XRenderQueryExtension( dpyi, &event_base, &error_base ) ) {
int nvi;
XVisualInfo templ;
templ.screen = screen;
templ.depth = 32;
templ.c_class = TrueColor;
XVisualInfo *xvi = XGetVisualInfo( dpyi, VisualScreenMask | VisualDepthMask
| VisualClassMask, &templ, &nvi );
for ( int i = 0; i < nvi; i++ ) {
XRenderPictFormat *format = XRenderFindVisualFormat( dpyi, xvi[i].visual );
if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
visual = xvi[i].visual;
colormap = XCreateColormap( dpyi, RootWindow( dpyi, screen ), visual, AllocNone );
kdDebug() << "found visual with alpha support" << endl;
argb_visual_available = true;
break;
}
}
}
XSetErrorHandler( (XErrorHandler)0 );
GreeterApp *app;
if( argb_visual_available ) {
app = new GreeterApp(dpyi);
}
else {
app = new GreeterApp();
}
// End ARGB initialization
#else
GreeterApp *app = new GreeterApp();
#endif
XSetIOErrorHandler( xIOErr ); XSetIOErrorHandler( xIOErr );
TQString login_user;
Display *dpy = qt_xdisplay(); Display *dpy = qt_xdisplay();
if (!_GUIStyle.isEmpty()) if (!_GUIStyle.isEmpty())
app.setStyle( _GUIStyle ); app->setStyle( _GUIStyle );
// Load up the systemwide ICC profile // Load up the systemwide ICC profile
TQString iccConfigFile = TQString(KDE_CONFDIR); TQString iccConfigFile = TQString(KDE_CONFDIR);
@ -168,14 +245,15 @@ kg_main( const char *argv0 )
if (!_colorScheme.isEmpty()) { if (!_colorScheme.isEmpty()) {
KSimpleConfig config( _colorScheme, true ); KSimpleConfig config( _colorScheme, true );
config.setGroup( "Color Scheme" ); config.setGroup( "Color Scheme" );
app.setPalette( app.createApplicationPalette( &config, 7 ) ); app->setPalette( app->createApplicationPalette( &config, 7 ) );
} }
app.setFont( _normalFont ); app->setFont( _normalFont );
setup_modifiers( dpy, _numLockStatus ); setup_modifiers( dpy, _numLockStatus );
SecureDisplay( dpy ); SecureDisplay( dpy );
KProcess *proc = 0; KProcess *proc = 0;
KProcess *comp = 0;
if (!_grabServer) { if (!_grabServer) {
if (_useBackground) { if (_useBackground) {
proc = new KProcess; proc = new KProcess;
@ -187,10 +265,16 @@ kg_main( const char *argv0 )
GRecvInt(); GRecvInt();
} }
if (!_compositor.isEmpty()) {
comp = new KProcess;
*comp << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + _compositor.ascii();
comp->start(KProcess::NotifyOnExit, KProcess::Stdin);
}
GSendInt( G_Ready ); GSendInt( G_Ready );
kdDebug() << timestamp() << " main1" << endl; kdDebug() << timestamp() << " main1" << endl;
setCursor( dpy, app.desktop()->winId(), XC_left_ptr ); setCursor( dpy, app->desktop()->winId(), XC_left_ptr );
for (;;) { for (;;) {
int rslt, cmd = GRecvInt(); int rslt, cmd = GRecvInt();
@ -214,7 +298,7 @@ kg_main( const char *argv0 )
} }
KProcess *proc2 = 0; KProcess *proc2 = 0;
app.setOverrideCursor( Qt::WaitCursor ); app->setOverrideCursor( Qt::WaitCursor );
FDialog *dialog; FDialog *dialog;
#ifdef XDMCP #ifdef XDMCP
if (cmd == G_Choose) { if (cmd == G_Choose) {
@ -247,7 +331,7 @@ kg_main( const char *argv0 )
proc2->start(); proc2->start();
} }
} }
app.restoreOverrideCursor(); app->restoreOverrideCursor();
Debug( "entering event loop\n" ); Debug( "entering event loop\n" );
// Qt4 has a nasty habit of generating BadWindow errors in normal operation, so we simply ignore them // Qt4 has a nasty habit of generating BadWindow errors in normal operation, so we simply ignore them
// This also prevents the user from being dropped to a console login if Xorg glitches or is buggy // This also prevents the user from being dropped to a console login if Xorg glitches or is buggy
@ -255,6 +339,9 @@ kg_main( const char *argv0 )
rslt = dialog->exec(); rslt = dialog->exec();
XSetErrorHandler( (XErrorHandler)0 ); XSetErrorHandler( (XErrorHandler)0 );
Debug( "left event loop\n" ); Debug( "left event loop\n" );
login_user = static_cast<KGreeter*>(dialog)->curUser;
delete dialog; delete dialog;
delete proc2; delete proc2;
#ifdef XDMCP #ifdef XDMCP
@ -274,11 +361,30 @@ kg_main( const char *argv0 )
KGVerify::done(); KGVerify::done();
if (comp) {
if (_compositor == "kompmgr") {
// Change process UID
// Get user UID
passwd* userinfo = getpwnam(login_user.ascii());
TQString newuid = TQString("%1").arg(userinfo->pw_uid);
// kompmgr allows us to change its uid in this manner:
// 1.) Send SIGUSER1
// 2.) Send the new UID to it on the command line
comp->kill(SIGUSR1);
comp->writeStdin(newuid.ascii(), newuid.length());
usleep(50000); // Give the above function some time to execute. Note that on REALLY slow systems this could fail, leaving kompmgr running as root. TODO: Look into ways to make this more robust.
}
comp->closeStdin();
comp->detach();
delete comp;
}
delete proc; delete proc;
UnsecureDisplay( dpy ); UnsecureDisplay( dpy );
restore_modifiers(); restore_modifiers();
XSetInputFocus( qt_xdisplay(), PointerRoot, PointerRoot, CurrentTime ); XSetInputFocus( qt_xdisplay(), PointerRoot, PointerRoot, CurrentTime );
delete app;
} }
} // extern "C" } // extern "C"

@ -34,6 +34,7 @@ class GreeterApp : public KApplication {
public: public:
GreeterApp(); GreeterApp();
GreeterApp(Display *dpy);
virtual bool x11EventFilter( XEvent * ); virtual bool x11EventFilter( XEvent * );
protected: protected:

@ -72,6 +72,9 @@ class KGreeter : public KGDialog, public KGVerifyHandler {
void slotSessionSelected( int ); void slotSessionSelected( int );
void slotUserEntered(); void slotUserEntered();
public:
TQString curUser, dName;
protected: protected:
void readFacesList(); void readFacesList();
void installUserList(); void installUserList();
@ -82,7 +85,6 @@ class KGreeter : public KGDialog, public KGVerifyHandler {
virtual void pluginSetup(); virtual void pluginSetup();
void setPrevWM( int ); void setPrevWM( int );
TQString curUser, dName;
KSimpleConfig *stsFile; KSimpleConfig *stsFile;
UserListView *userView; UserListView *userView;
TQStringList *userList; TQStringList *userList;

@ -38,6 +38,8 @@
#include <tqimage.h> #include <tqimage.h>
#include <tqpainter.h> #include <tqpainter.h>
extern bool argb_visual_available;
KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name ) KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name )
: TQObject( parent, name ) : TQObject( parent, name )
, boxManager( 0 ) , boxManager( 0 )
@ -289,11 +291,13 @@ KdmItem::paint( TQPainter *p, const TQRect &rect )
if (myWidget || (myLayoutItem && myLayoutItem->widget())) { if (myWidget || (myLayoutItem && myLayoutItem->widget())) {
// KListView because it's missing a Q_OBJECT' // KListView because it's missing a Q_OBJECT'
// FIXME: This is a nice idea intheory, but in practice it is // FIXME: This is a nice idea in theory, but in practice it is
// very confusing for the user not to see the empty list box // very confusing for the user not to see the empty list box
// delineated from the rest of the greeter. // delineated from the rest of the greeter.
// Maybe set a darker version of the background instead of an exact copy? // Maybe set a darker version of the background instead of an exact copy?
if ( myWidget && myWidget->isA( "KListView" ) ) { if ( myWidget && myWidget->isA( "KListView" ) ) {
if ((_compositor.isEmpty()) || (!argb_visual_available)) {
// Software blend only (no compositing support)
TQPixmap copy( myWidget->size() ); TQPixmap copy( myWidget->size() );
kdDebug() << myWidget->tqgeometry() << " " << area << " " << myWidget->size() << endl; kdDebug() << myWidget->tqgeometry() << " " << area << " " << myWidget->size() << endl;
bitBlt( &copy, TQPoint( 0, 0), p->device(), myWidget->geometry(), TQt::CopyROP ); bitBlt( &copy, TQPoint( 0, 0), p->device(), myWidget->geometry(), TQt::CopyROP );
@ -327,6 +331,30 @@ KdmItem::paint( TQPainter *p, const TQRect &rect )
copy = lightVersion; copy = lightVersion;
// Set it // Set it
myWidget->setPaletteBackgroundPixmap( copy ); myWidget->setPaletteBackgroundPixmap( copy );
}
else {
// We have compositing support!
TQRgb blend_color = tqRgba(m_backgroundModifier, m_backgroundModifier, m_backgroundModifier, 0); // RGBA overlay
float alpha = tqAlpha(blend_color) / 255.;
int pixel = tqAlpha(blend_color) << 24 |
int(tqRed(blend_color) * alpha) << 16 |
int(tqGreen(blend_color) * alpha) << 8 |
int(tqBlue(blend_color) * alpha);
TQImage img( myWidget->size(), 32 );
img = img.convertDepth(32);
img.setAlphaBuffer(true);
register uchar * rd = img.bits();
for( int y = 0; y < img.height(); ++y )
{
for( short int x = 0; x < img.width(); ++x )
{
*reinterpret_cast<TQRgb*>(rd) = blend_color;
rd += 4;
}
}
myWidget->setPaletteBackgroundPixmap( img );
}
} }
return; return;
} }

@ -37,6 +37,8 @@
#include <tqpixmap.h> #include <tqpixmap.h>
#include <tqimage.h> #include <tqimage.h>
extern bool argb_visual_available;
KdmPixmap::KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *name ) KdmPixmap::KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *name )
: KdmItem( parent, node, name ) : KdmItem( parent, node, name )
{ {
@ -47,6 +49,7 @@ KdmPixmap::KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *name )
pixmap.normal.alpha = 0.0; pixmap.normal.alpha = 0.0;
pixmap.active.present = false; pixmap.active.present = false;
pixmap.prelight.present = false; pixmap.prelight.present = false;
bool true_transparency = false;
// Read PIXMAP ID // Read PIXMAP ID
// it rarely happens that a pixmap can be a button too! // it rarely happens that a pixmap can be a button too!
@ -66,13 +69,20 @@ KdmPixmap::KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *name )
pixmap.normal.alpha = el.attribute( "alpha", "1.0" ).toFloat(); pixmap.normal.alpha = el.attribute( "alpha", "1.0" ).toFloat();
if (el.attribute( "file", "" ) == "@@@KDMBACKGROUND@@@") { if (el.attribute( "file", "" ) == "@@@KDMBACKGROUND@@@") {
// Use the preset KDM background... if ((_compositor.isEmpty()) || (!argb_visual_available)) {
KStandardDirs *m_pDirs = KGlobal::dirs(); // Software blend only (no compositing support)
KSimpleConfig *config = new KSimpleConfig( TQFile::decodeName( _backgroundCfg ) ); // Use the preset KDM background...
config->setGroup("Desktop0"); KStandardDirs *m_pDirs = KGlobal::dirs();
pixmap.normal.fullpath = m_pDirs->findResource("wallpaper", config->readPathEntry("Wallpaper")); KSimpleConfig *config = new KSimpleConfig( TQFile::decodeName( _backgroundCfg ) );
// TODO: Detect when there is no wallpaper and use the background settings instead config->setGroup("Desktop0");
delete config; pixmap.normal.fullpath = m_pDirs->findResource("wallpaper", config->readPathEntry("Wallpaper"));
// TODO: Detect when there is no wallpaper and use the background settings instead
delete config;
}
else {
true_transparency = true;
pixmap.normal.alpha = 0.0;
}
} }
} else if (tagName == "active") { } else if (tagName == "active") {
@ -189,7 +199,6 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r )
kdDebug() << "draw " << id << " " << pClass->pixmap.isNull() << endl; kdDebug() << "draw " << id << " " << pClass->pixmap.isNull() << endl;
if (pClass->pixmap.isNull()) { if (pClass->pixmap.isNull()) {
if (pClass->fullpath.isEmpty()) // if neither is set, we're empty if (pClass->fullpath.isEmpty()) // if neither is set, we're empty
return; return;
@ -246,7 +255,7 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r )
if (haveTint || haveAlpha) if (haveTint || haveAlpha)
{ {
scaledImage = pClass->pixmap.convertToImage(); scaledImage = pClass->pixmap.convertToImage();
// enforce rgba values for the later // enforce rgba values for the latter
scaledImage = scaledImage.convertDepth( 32 ); scaledImage = scaledImage.convertDepth( 32 );
} }
else else
@ -275,7 +284,31 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r )
ls[x] = tqRgba( r, g, b, a ); ls[x] = tqRgba( r, g, b, a );
} }
} }
}
if ((_compositor.isEmpty()) || (!argb_visual_available)) {
// Software blend only (no compositing support)
}
else {
// We have a compositor!
// Apply the alpha in the same manner as above, exept we are now
// using the hardware blending engine for all painting
scaledImage = pClass->readyPixmap;
scaledImage = scaledImage.convertDepth( 32 );
int w = scaledImage.width();
int h = scaledImage.height();
for (int y = 0; y < h; ++y) {
QRgb *ls = (QRgb *)scaledImage.scanLine( y );
for (int x = 0; x < w; ++x) {
QRgb l = ls[x];
float alpha_adjust = (tqAlpha( l )/256.0);
int r = int( tqRed( l ) * alpha_adjust );
int g = int( tqGreen( l ) * alpha_adjust );
int b = int( tqBlue( l ) * alpha_adjust );
int a = int( tqAlpha( l ) * 1 );
ls[x] = tqRgba( r, g, b, a );
}
}
} }
if (!scaledImage.isNull()) { if (!scaledImage.isNull()) {

@ -21,6 +21,7 @@
#include "kdmrect.h" #include "kdmrect.h"
#include "kdmthemer.h" #include "kdmthemer.h"
#include "kdmconfig.h"
#include <kimageeffect.h> #include <kimageeffect.h>
#include <kdebug.h> #include <kdebug.h>
@ -30,6 +31,8 @@
#include <tqwidget.h> #include <tqwidget.h>
#include <tqlayout.h> #include <tqlayout.h>
extern bool argb_visual_available;
KdmRect::KdmRect( KdmItem *parent, const TQDomNode &node, const char *name ) KdmRect::KdmRect( KdmItem *parent, const TQDomNode &node, const char *name )
: KdmItem( parent, node, name ) : KdmItem( parent, node, name )
{ {
@ -103,14 +106,20 @@ KdmRect::drawContents( TQPainter *p, const TQRect &r )
if (rClass->alpha == 1) if (rClass->alpha == 1)
p->fillRect( area, TQBrush( rClass->color ) ); p->fillRect( area, TQBrush( rClass->color ) );
else { else {
TQRect backRect = r; // if ((_compositor.isEmpty()) || (!argb_visual_available)) {
backRect.moveBy( area.x(), area.y() ); // Software blend only (no compositing support)
TQPixmap backPixmap( backRect.size() ); TQRect backRect = r;
bitBlt( &backPixmap, TQPoint( 0, 0 ), p->device(), backRect ); backRect.moveBy( area.x(), area.y() );
TQImage backImage = backPixmap.convertToImage(); TQPixmap backPixmap( backRect.size() );
KImageEffect::blend( rClass->color, backImage, rClass->alpha ); bitBlt( &backPixmap, TQPoint( 0, 0 ), p->device(), backRect );
p->drawImage( backRect.x(), backRect.y(), backImage ); TQImage backImage = backPixmap.convertToImage();
// area.moveBy(1,1); KImageEffect::blend( rClass->color, backImage, rClass->alpha );
p->drawImage( backRect.x(), backRect.y(), backImage );
// area.moveBy(1,1);
// }
// else {
// // We have compositing support!
// }
} }
} }

@ -46,6 +46,8 @@
#include <unistd.h> #include <unistd.h>
extern bool argb_visual_available;
/* /*
* KdmThemer. The main theming interface * KdmThemer. The main theming interface
*/ */
@ -159,17 +161,35 @@ KdmThemer::widgetEvent( TQEvent *e )
TQRect paintRect = TQT_TQPAINTEVENT(e)->rect(); TQRect paintRect = TQT_TQPAINTEVENT(e)->rect();
kdDebug() << timestamp() << " paint on: " << paintRect << endl; kdDebug() << timestamp() << " paint on: " << paintRect << endl;
if (!backBuffer) if ((_compositor.isEmpty()) || (!argb_visual_available)) {
backBuffer = new TQPixmap( widget()->size() ); // Software blend only (no compositing support)
if (backBuffer->size() != widget()->size()) if (!backBuffer)
backBuffer->resize( widget()->size() ); backBuffer = new TQPixmap( widget()->size() );
if (backBuffer->size() != widget()->size())
TQPainter p; backBuffer->resize( widget()->size() );
p.begin( backBuffer );
rootItem->paint( &p, paintRect ); TQPainter p;
p.end(); p.begin( backBuffer );
rootItem->paint( &p, paintRect );
p.end();
bitBlt( widget(), paintRect.topLeft(), backBuffer, paintRect );
}
else {
// We have compositing support!
TQRgb blend_color = tqRgba(0, 0, 0, 0); // RGBA
float alpha = tqAlpha(blend_color) / 255.;
int pixel = tqAlpha(blend_color) << 24 |
int(tqRed(blend_color) * alpha) << 16 |
int(tqGreen(blend_color) * alpha) << 8 |
int(tqBlue(blend_color) * alpha);
TQPainter p1;
p1.begin( widget() );
p1.fillRect( paintRect, TQColor(blend_color, pixel) );
rootItem->paint( &p1, paintRect );
p1.end();
}
bitBlt( widget(), paintRect.topLeft(), backBuffer, paintRect );
} }
break; break;
default: default:

@ -24,6 +24,7 @@
#include <tqobject.h> #include <tqobject.h>
#include <tqdom.h> #include <tqdom.h>
#include <tqimage.h>
class KdmThemer; class KdmThemer;
class KdmItem; class KdmItem;

@ -34,6 +34,7 @@
* CHANGELOG: * CHANGELOG:
* http://patchwork.freedesktop.org/patch/1049/ [Add default background color option] 08/11/2011 * http://patchwork.freedesktop.org/patch/1049/ [Add default background color option] 08/11/2011
* http://patchwork.freedesktop.org/patch/1052/ [Prevent flicker on root pixmap change] 08/11/2011 * http://patchwork.freedesktop.org/patch/1052/ [Prevent flicker on root pixmap change] 08/11/2011
* Added SIGUSER1 handler to change process UID [Prevent flicker on login] 08/12/2011
* *
* TODO: * TODO:
* http://patchwork.freedesktop.org/patch/1053/ [Fix window mapping with re-used window ids] * http://patchwork.freedesktop.org/patch/1053/ [Fix window mapping with re-used window ids]
@ -50,6 +51,8 @@ check baghira.sf.net for more infos
#include <math.h> #include <math.h>
#include <sys/poll.h> #include <sys/poll.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -135,6 +138,9 @@ typedef struct _fade {
Bool gone; Bool gone;
} fade; } fade;
struct sigaction usr_action;
sigset_t block_mask;
win *list; win *list;
fade *fades; fade *fades;
Display *dpy; Display *dpy;
@ -203,6 +209,7 @@ conv *gaussianMap;
#define TRANS_OPACITY 0.75 #define TRANS_OPACITY 0.75
#define NDEBUG 1
#define DEBUG_REPAINT 0 #define DEBUG_REPAINT 0
#define DEBUG_EVENTS 0 #define DEBUG_EVENTS 0
#define MONITOR_REPAINT 0 #define MONITOR_REPAINT 0
@ -218,7 +225,7 @@ typedef enum _compMode {
static void static void
determine_mode(Display *dpy, win *w); determine_mode(Display *dpy, win *w);
static double static double
get_opacity_percent(Display *dpy, win *w, double def); get_opacity_percent(Display *dpy, win *w, double def);
@ -267,11 +274,28 @@ get_time_in_milliseconds ()
return tv.tv_sec * 1000 + tv.tv_usec / 1000; return tv.tv_sec * 1000 + tv.tv_usec / 1000;
} }
void handle_siguser (int sig)
{
char newuid[1024];
#ifndef NDEBUG
printf("Enter the new user ID:\n\r"); fflush(stdout);
#endif
char *eof;
newuid[0] = '\0';
newuid[sizeof(newuid)-1] = '\0';
eof = fgets(newuid, sizeof(newuid), stdin);
int uidnum = atoi(newuid);
#ifndef NDEBUG
printf("Setting kompmgr process uid to %d...\n\r", uidnum); fflush(stdout);
#endif
setuid(uidnum);
}
fade * fade *
find_fade (win *w) find_fade (win *w)
{ {
fade *f; fade *f;
for (f = fades; f; f = f->next) for (f = fades; f; f = f->next)
{ {
if (f->w == w) if (f->w == w)
@ -2509,7 +2533,7 @@ usage (char *program)
fprintf (stderr, " -o opacity\n Specifies the translucency for client-side shadows. (default .75)\n"); fprintf (stderr, " -o opacity\n Specifies the translucency for client-side shadows. (default .75)\n");
fprintf (stderr, " -l left-offset\n Specifies the left offset for client-side shadows. (default -15)\n"); fprintf (stderr, " -l left-offset\n Specifies the left offset for client-side shadows. (default -15)\n");
fprintf (stderr, " -t top-offset\n Specifies the top offset for clinet-side shadows. (default -15)\n"); fprintf (stderr, " -t top-offset\n Specifies the top offset for clinet-side shadows. (default -15)\n");
fprintf (stderr, " -b color\n Specifies the background color to use if no root pixmap is set. (default is a gray)\n"); fprintf (stderr, " -b color\n Specifies the background color to use if no root pixmap is set. (default is black)\n");
fprintf (stderr, " -I fade-in-step\n Specifies the opacity change between steps while fading in. (default 0.028)\n"); fprintf (stderr, " -I fade-in-step\n Specifies the opacity change between steps while fading in. (default 0.028)\n");
fprintf (stderr, " -O fade-out-step\n Specifies the opacity change between steps while fading out. (default 0.03)\n"); fprintf (stderr, " -O fade-out-step\n Specifies the opacity change between steps while fading out. (default 0.03)\n");
fprintf (stderr, " -D fade-delta-time\n Specifies the time between steps in a fade in milliseconds. (default 10)\n"); fprintf (stderr, " -D fade-delta-time\n Specifies the time between steps in a fade in milliseconds. (default 10)\n");
@ -2568,6 +2592,13 @@ main (int argc, char **argv)
shadowColor.green = 0; shadowColor.green = 0;
shadowColor.blue = 0; shadowColor.blue = 0;
// Initialize signal handlers
sigfillset(&block_mask);
usr_action.sa_handler = handle_siguser;
usr_action.sa_mask = block_mask;
usr_action.sa_flags = 0;
sigaction(SIGUSR1, &usr_action, NULL);
loadConfig(NULL); /*we do that before cmdline-parsing, so config-values can be overridden*/ loadConfig(NULL); /*we do that before cmdline-parsing, so config-values can be overridden*/
/*used for shadow colors*/ /*used for shadow colors*/
while ((o = getopt (argc, argv, "D:I:O:d:r:o:l:t:b:scnfFmCaSx:vh")) != -1) while ((o = getopt (argc, argv, "D:I:O:d:r:o:l:t:b:scnfFmCaSx:vh")) != -1)
@ -2739,7 +2770,7 @@ main (int argc, char **argv)
} }
else else
{ {
fill_color.red = fill_color.green = fill_color.blue = 0x8080; fill_color.red = fill_color.green = fill_color.blue = 0x0;
} }
fill_color.alpha = 0xffff; fill_color.alpha = 0xffff;

Loading…
Cancel
Save