diff -Naur kdebase-3.5.8.orig/ksmserver/shutdowndlg.cpp kdebase-3.5.8/ksmserver/shutdowndlg.cpp --- kdebase-3.5.8.orig/ksmserver/shutdowndlg.cpp 2007-11-21 06:56:58.000000000 +0100 +++ kdebase-3.5.8/ksmserver/shutdowndlg.cpp 2007-11-21 06:57:20.000000000 +0100 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include #include @@ -106,35 +108,187 @@ KSMShutdownFeedback::KSMShutdownFeedback() : QWidget( 0L, "feedbackwidget", WType_Popup ), - m_currentY( 0 ) + m_currentY( 0 ), + m_grayOpacity( 0.0f ), + m_compensation( 0.0f ), + m_fadeBackwards( FALSE ), + m_unfadedImage( QPixmap::grabWindow(qt_xrootwin(), 0, 0, QApplication::desktop()->width(), + QApplication::desktop()->height()).convertToImage() ), + m_grayImage(), + m_fadeTime(), + m_pmio() + { setBackgroundMode( QWidget::NoBackground ); setGeometry( QApplication::desktop()->geometry() ); QTimer::singleShot( 10, this, SLOT( slotPaintEffect() ) ); - m_root.resize( width(), height() ); + m_root.resize( width(), height() ); // for the default logout } +// called after stopping shutdown-feedback -> smooth fade-back to color-mode +void KSMShutdownFeedback::fadeBack( void ) +{ + m_fadeTime.restart(); + m_fadeBackwards = TRUE; + // its possible that we have to fade back, before all is completely gray, so we cannot start + // with completely gray when fading back... + m_compensation = 1.0f - m_grayOpacity; + // wait until we're completely back in color-mode... + while ( m_grayOpacity > 0.0f ) + slotPaintEffect(); +} void KSMShutdownFeedback::slotPaintEffect() { - if ( m_currentY >= height() ) { - if ( backgroundMode() == QWidget::NoBackground ) { - setBackgroundMode( QWidget::NoBackground ); - setBackgroundPixmap( m_root ); - } - return; + // determine which fade to use + if (KConfigGroup(KGlobal::config(), "Logout").readBoolEntry("doFancyLogout", true)) + { + + float doFancyLogoutAdditionalDarkness = (float)KConfigGroup(KGlobal::config(), "Logout").readDoubleNumEntry("doFancyLogoutAdditionalDarkness", 0.6); + + float doFancyLogoutFadeTime = (float)KConfigGroup(KGlobal::config(), "Logout").readDoubleNumEntry("doFancyLogoutFadeTime", 4000); + + float doFancyLogoutFadeBackTime = (float)KConfigGroup(KGlobal::config(), "Logout").readDoubleNumEntry("doFancyLogoutFadeBackTime", 1000); + + + // if slotPaintEffect() is called first time, we have to initialize the gray image + // we also could do that in the constructor, but then the displaying of the + // logout-UI would be too much delayed... + if ( m_grayImage.isNull() ) + { + m_grayImage = m_unfadedImage.copy(); + register uchar * r = m_grayImage.bits(); + register uchar * g = m_grayImage.bits() + 1; + register uchar * b = m_grayImage.bits() + 2; + uchar * end = m_grayImage.bits() + m_grayImage.numBytes(); + + while ( r != end ) { + *r = *g = *b = (uchar) ( ( (*r)*11 + ((*g)<<4) + (*b)*5 ) * doFancyLogoutAdditionalDarkness / 32.0f ); + r += 4; + g += 4; + b += 4; + } + // start timer which is used for cpu-speed-independent fading + m_fadeTime.start(); + m_rowsDone = 0; + } + + // return if fading is completely done... + if ( ( m_grayOpacity >= 1.0f && m_fadeBackwards == FALSE ) || ( m_grayOpacity <= 0.0f && m_fadeBackwards == TRUE ) ) + return; + + + if ( m_fadeBackwards == FALSE ) + { + m_grayOpacity = m_fadeTime.elapsed() / doFancyLogoutFadeTime; + if ( m_grayOpacity > 1.0f ) + m_grayOpacity = 1.0f; + } + else + { + m_grayOpacity = 1.0f - m_fadeTime.elapsed() / doFancyLogoutFadeBackTime - m_compensation; + if ( m_grayOpacity < 0.0f ) + m_grayOpacity = 0.0f; + } + + const int imgWidth = m_unfadedImage.width(); + int imgHeight = m_unfadedImage.height(); + int heightUnit = imgHeight / 3; + if( heightUnit < 1 ) + heightUnit = 1; + + int y1 = static_cast( imgHeight*m_grayOpacity - heightUnit + m_grayOpacity*heightUnit*2.0f ); + if( y1 > imgHeight ) + y1 = imgHeight; + + int y2 = y1+heightUnit; + if( y2 > imgHeight ) + y2 = imgHeight; + + if( m_fadeBackwards == FALSE ) + { + if( y1 > 0 && y1 < imgHeight && y1-m_rowsDone > 0 && m_rowsDone < imgHeight ) + { + QImage img( imgWidth, y1-m_rowsDone, 32 ); + memcpy( img.bits(), m_grayImage.scanLine( m_rowsDone ), imgWidth*(y1-m_rowsDone)*4 ); + // conversion is slow as hell if desktop-depth != 24bpp... + QPixmap pm = m_pmio.convertToPixmap( img ); + bitBlt( this, 0, m_rowsDone, &pm ); + m_rowsDone = y1; + } + } + else + { + // when fading back we have to blit area which isnt gray anymore to unfaded image + if( y2 > 0 && y2 < imgHeight && m_rowsDone > y2 ) + { + QImage img( imgWidth, m_rowsDone-y2, 32 ); + memcpy( img.bits(), m_unfadedImage.scanLine( y2 ), imgWidth*(m_rowsDone-y2)*4 ); + // conversion is slow as hell if desktop-depth != 24bpp... + QPixmap pm = m_pmio.convertToPixmap( img ); + bitBlt( this, 0, y2, &pm ); + m_rowsDone = y2; + } + } + + int start_y1 = y1; + if( start_y1 < 0 ) + start_y1 = 0; + if( y2 > start_y1 ) + { + QImage img( imgWidth, y2-start_y1, 32 ); + memcpy( img.bits(), m_grayImage.scanLine( start_y1 ), ( y2-start_y1 ) * imgWidth * 4 ); + register uchar * rs = m_unfadedImage.scanLine( start_y1 ); + register uchar * gs = rs + 1; + register uchar * bs = gs + 1; + register uchar * rd = img.bits(); + register uchar * gd = rd + 1; + register uchar * bd = gd + 1; + for( int y = start_y1; y < y2; ++y ) + { + // linear gradients look bad, so use cos-function + short int opac = static_cast( 128 - cosf( M_PI*(y-y1)/heightUnit )*128.0f ); + for( short int x = 0; x < imgWidth; ++x ) + { + *rd += ( ( ( *rs - *rd ) * opac ) >> 8 ); + rs += 4; rd += 4; + *gd += ( ( ( *gs - *gd ) * opac ) >> 8 ); + gs += 4; gd += 4; + *bd += ( ( ( *bs - *bd ) * opac ) >> 8 ); + bs += 4; bd += 4; + } + } + // conversion is slow as hell if desktop-depth != 24bpp... + QPixmap pm = m_pmio.convertToPixmap( img ); + bitBlt( this, 0, start_y1, &pm ); + } + + QTimer::singleShot( 5, this, SLOT( slotPaintEffect() ) ); + + } + // standard logout fade + else + { + if ( m_currentY >= height() ) { + if ( backgroundMode() == QWidget::NoBackground ) { + setBackgroundMode( QWidget::NoBackground ); + setBackgroundPixmap( m_root ); + } + return; + } + + KPixmap pixmap; + pixmap = QPixmap::grabWindow( qt_xrootwin(), 0, m_currentY, width(), 10 ); + QImage image = pixmap.convertToImage(); + KImageEffect::blend( Qt::black, image, 0.4 ); + KImageEffect::toGray( image, true ); + pixmap.convertFromImage( image ); + bitBlt( this, 0, m_currentY, &pixmap ); + bitBlt( &m_root, 0, m_currentY, &pixmap ); + m_currentY += 10; + QTimer::singleShot( 1, this, SLOT( slotPaintEffect() ) ); } - KPixmap pixmap; - pixmap = QPixmap::grabWindow( qt_xrootwin(), 0, m_currentY, width(), 10 ); - QImage image = pixmap.convertToImage(); - KImageEffect::blend( Qt::black, image, 0.4 ); - KImageEffect::toGray( image, true ); - pixmap.convertFromImage( image ); - bitBlt( this, 0, m_currentY, &pixmap ); - bitBlt( &m_root, 0, m_currentY, &pixmap ); - m_currentY += 10; - QTimer::singleShot( 1, this, SLOT( slotPaintEffect() ) ); } ////// diff -Naur kdebase-3.5.8.orig/ksmserver/shutdowndlg.h kdebase-3.5.8/ksmserver/shutdowndlg.h --- kdebase-3.5.8.orig/ksmserver/shutdowndlg.h 2007-11-21 06:56:58.000000000 +0100 +++ kdebase-3.5.8/ksmserver/shutdowndlg.h 2007-11-21 06:57:20.000000000 +0100 @@ -8,6 +8,8 @@ #define SHUTDOWNDLG_H #include +#include +#include #include #include class QPushButton; @@ -16,6 +18,7 @@ class QTimer; #include +#include #include #include #include @@ -39,14 +42,14 @@ }; -// The (singleton) widget that makes the desktop gray. +// The (singleton) widget that makes/fades the desktop gray. class KSMShutdownFeedback : public QWidget { Q_OBJECT public: static void start() { s_pSelf = new KSMShutdownFeedback(); s_pSelf->show(); } - static void stop() { delete s_pSelf; s_pSelf = 0L; } + static void stop() { if ( s_pSelf != 0L ) s_pSelf->fadeBack(); delete s_pSelf; s_pSelf = 0L; } static KSMShutdownFeedback * self() { return s_pSelf; } protected: @@ -60,6 +63,15 @@ KSMShutdownFeedback(); int m_currentY; QPixmap m_root; + void fadeBack( void ); + float m_grayOpacity; + float m_compensation; + bool m_fadeBackwards; + QImage m_unfadedImage; + QImage m_grayImage; + QTime m_fadeTime; + int m_rowsDone; + KPixmapIO m_pmio; };