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

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

@ -1986,6 +1986,16 @@ Description:
Specify the widget style for the greeter. Empty means to use the
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
Type: bool
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 "kdmshutdown.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/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
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
GreeterApp::timerEvent( TQTimerEvent * )
{
@ -145,13 +170,65 @@ kg_main( const char *argv0 )
kde_have_kipc = false;
KApplication::disableAutoDcopRegistration();
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 );
TQString login_user;
Display *dpy = qt_xdisplay();
if (!_GUIStyle.isEmpty())
app.setStyle( _GUIStyle );
app->setStyle( _GUIStyle );
// Load up the systemwide ICC profile
TQString iccConfigFile = TQString(KDE_CONFDIR);
@ -168,14 +245,15 @@ kg_main( const char *argv0 )
if (!_colorScheme.isEmpty()) {
KSimpleConfig config( _colorScheme, true );
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 );
SecureDisplay( dpy );
KProcess *proc = 0;
KProcess *comp = 0;
if (!_grabServer) {
if (_useBackground) {
proc = new KProcess;
@ -187,10 +265,16 @@ kg_main( const char *argv0 )
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 );
kdDebug() << timestamp() << " main1" << endl;
setCursor( dpy, app.desktop()->winId(), XC_left_ptr );
setCursor( dpy, app->desktop()->winId(), XC_left_ptr );
for (;;) {
int rslt, cmd = GRecvInt();
@ -214,7 +298,7 @@ kg_main( const char *argv0 )
}
KProcess *proc2 = 0;
app.setOverrideCursor( Qt::WaitCursor );
app->setOverrideCursor( Qt::WaitCursor );
FDialog *dialog;
#ifdef XDMCP
if (cmd == G_Choose) {
@ -247,7 +331,7 @@ kg_main( const char *argv0 )
proc2->start();
}
}
app.restoreOverrideCursor();
app->restoreOverrideCursor();
Debug( "entering event loop\n" );
// 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
@ -255,6 +339,9 @@ kg_main( const char *argv0 )
rslt = dialog->exec();
XSetErrorHandler( (XErrorHandler)0 );
Debug( "left event loop\n" );
login_user = static_cast<KGreeter*>(dialog)->curUser;
delete dialog;
delete proc2;
#ifdef XDMCP
@ -274,11 +361,30 @@ kg_main( const char *argv0 )
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;
UnsecureDisplay( dpy );
restore_modifiers();
XSetInputFocus( qt_xdisplay(), PointerRoot, PointerRoot, CurrentTime );
delete app;
}
} // extern "C"

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

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

@ -38,6 +38,8 @@
#include <tqimage.h>
#include <tqpainter.h>
extern bool argb_visual_available;
KdmItem::KdmItem( KdmItem *parent, const TQDomNode &node, const char *name )
: TQObject( parent, name )
, boxManager( 0 )
@ -289,11 +291,13 @@ KdmItem::paint( TQPainter *p, const TQRect &rect )
if (myWidget || (myLayoutItem && myLayoutItem->widget())) {
// 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
// delineated from the rest of the greeter.
// Maybe set a darker version of the background instead of an exact copy?
if ( myWidget && myWidget->isA( "KListView" ) ) {
if ((_compositor.isEmpty()) || (!argb_visual_available)) {
// Software blend only (no compositing support)
TQPixmap copy( myWidget->size() );
kdDebug() << myWidget->tqgeometry() << " " << area << " " << myWidget->size() << endl;
bitBlt( &copy, TQPoint( 0, 0), p->device(), myWidget->geometry(), TQt::CopyROP );
@ -327,6 +331,30 @@ KdmItem::paint( TQPainter *p, const TQRect &rect )
copy = lightVersion;
// Set it
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;
}

@ -37,6 +37,8 @@
#include <tqpixmap.h>
#include <tqimage.h>
extern bool argb_visual_available;
KdmPixmap::KdmPixmap( KdmItem *parent, const TQDomNode &node, const char *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.active.present = false;
pixmap.prelight.present = false;
bool true_transparency = false;
// Read PIXMAP ID
// 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();
if (el.attribute( "file", "" ) == "@@@KDMBACKGROUND@@@") {
// Use the preset KDM background...
KStandardDirs *m_pDirs = KGlobal::dirs();
KSimpleConfig *config = new KSimpleConfig( TQFile::decodeName( _backgroundCfg ) );
config->setGroup("Desktop0");
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;
if ((_compositor.isEmpty()) || (!argb_visual_available)) {
// Software blend only (no compositing support)
// Use the preset KDM background...
KStandardDirs *m_pDirs = KGlobal::dirs();
KSimpleConfig *config = new KSimpleConfig( TQFile::decodeName( _backgroundCfg ) );
config->setGroup("Desktop0");
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") {
@ -189,7 +199,6 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r )
kdDebug() << "draw " << id << " " << pClass->pixmap.isNull() << endl;
if (pClass->pixmap.isNull()) {
if (pClass->fullpath.isEmpty()) // if neither is set, we're empty
return;
@ -246,7 +255,7 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r )
if (haveTint || haveAlpha)
{
scaledImage = pClass->pixmap.convertToImage();
// enforce rgba values for the later
// enforce rgba values for the latter
scaledImage = scaledImage.convertDepth( 32 );
}
else
@ -275,7 +284,31 @@ KdmPixmap::drawContents( TQPainter *p, const TQRect &r )
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()) {

@ -21,6 +21,7 @@
#include "kdmrect.h"
#include "kdmthemer.h"
#include "kdmconfig.h"
#include <kimageeffect.h>
#include <kdebug.h>
@ -30,6 +31,8 @@
#include <tqwidget.h>
#include <tqlayout.h>
extern bool argb_visual_available;
KdmRect::KdmRect( KdmItem *parent, const TQDomNode &node, const char *name )
: KdmItem( parent, node, name )
{
@ -103,14 +106,20 @@ KdmRect::drawContents( TQPainter *p, const TQRect &r )
if (rClass->alpha == 1)
p->fillRect( area, TQBrush( rClass->color ) );
else {
TQRect backRect = r;
backRect.moveBy( area.x(), area.y() );
TQPixmap backPixmap( backRect.size() );
bitBlt( &backPixmap, TQPoint( 0, 0 ), p->device(), backRect );
TQImage backImage = backPixmap.convertToImage();
KImageEffect::blend( rClass->color, backImage, rClass->alpha );
p->drawImage( backRect.x(), backRect.y(), backImage );
// area.moveBy(1,1);
// if ((_compositor.isEmpty()) || (!argb_visual_available)) {
// Software blend only (no compositing support)
TQRect backRect = r;
backRect.moveBy( area.x(), area.y() );
TQPixmap backPixmap( backRect.size() );
bitBlt( &backPixmap, TQPoint( 0, 0 ), p->device(), backRect );
TQImage backImage = backPixmap.convertToImage();
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>
extern bool argb_visual_available;
/*
* KdmThemer. The main theming interface
*/
@ -159,17 +161,35 @@ KdmThemer::widgetEvent( TQEvent *e )
TQRect paintRect = TQT_TQPAINTEVENT(e)->rect();
kdDebug() << timestamp() << " paint on: " << paintRect << endl;
if (!backBuffer)
backBuffer = new TQPixmap( widget()->size() );
if (backBuffer->size() != widget()->size())
backBuffer->resize( widget()->size() );
TQPainter p;
p.begin( backBuffer );
rootItem->paint( &p, paintRect );
p.end();
if ((_compositor.isEmpty()) || (!argb_visual_available)) {
// Software blend only (no compositing support)
if (!backBuffer)
backBuffer = new TQPixmap( widget()->size() );
if (backBuffer->size() != widget()->size())
backBuffer->resize( widget()->size() );
TQPainter p;
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;
default:

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

@ -34,6 +34,7 @@
* CHANGELOG:
* 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
* Added SIGUSER1 handler to change process UID [Prevent flicker on login] 08/12/2011
*
* TODO:
* 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 <sys/poll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <X11/Xlib.h>
@ -135,6 +138,9 @@ typedef struct _fade {
Bool gone;
} fade;
struct sigaction usr_action;
sigset_t block_mask;
win *list;
fade *fades;
Display *dpy;
@ -203,6 +209,7 @@ conv *gaussianMap;
#define TRANS_OPACITY 0.75
#define NDEBUG 1
#define DEBUG_REPAINT 0
#define DEBUG_EVENTS 0
#define MONITOR_REPAINT 0
@ -218,7 +225,7 @@ typedef enum _compMode {
static void
determine_mode(Display *dpy, win *w);
static double
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;
}
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 *
find_fade (win *w)
{
fade *f;
for (f = fades; f; f = f->next)
{
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, " -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, " -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, " -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");
@ -2568,6 +2592,13 @@ main (int argc, char **argv)
shadowColor.green = 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*/
/*used for shadow colors*/
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
{
fill_color.red = fill_color.green = fill_color.blue = 0x8080;
fill_color.red = fill_color.green = fill_color.blue = 0x0;
}
fill_color.alpha = 0xffff;

Loading…
Cancel
Save