rendered paste body--- kdebase-3.5.2/ksmserver/shutdowndlg.cpp 2006-03-17 07:17:10.000000000 -0300
+++ kdebase-3.5.2/ksmserver/shutdowndlg.cpp.fade 2006-05-08 22:07:59.121505750 -0300
@@ -2,6 +2,8 @@
ksmserver - the KDE session management server
Copyright (C) 2000 Matthias Ettrich <ettrich@kde.org>
+Copyright (C) 2005 Tobias Doerffel <tobias@doerffel.de>
+Copyright (C) 2006 Christian Tosta <tosta@users.sourceforge.net>
******************************************************************/
#include <config.h>
@@ -20,6 +22,7 @@
#include <qmessagebox.h>
#include <qbuttongroup.h>
#include <qiconset.h>
+#include <qpixmap.h>
#include <qpopupmenu.h>
#include <qtooltip.h>
#include <qimage.h>
@@ -33,7 +36,6 @@
#include <kglobalsettings.h>
#include <kwin.h>
#include <kuser.h>
-#include <kpixmap.h>
#include <kimageeffect.h>
#include <kdialog.h>
#include <kseparator.h>
@@ -42,6 +44,7 @@
#include <sys/utsname.h>
#include <unistd.h>
#include <stdlib.h>
+#include <math.h>
#include <dmctl.h>
#include <X11/Xlib.h>
@@ -49,10 +52,21 @@
#include "shutdowndlg.moc"
KSMShutdownFeedback * KSMShutdownFeedback::s_pSelf = 0L;
+// maybe one day we can make these fading-settings configurable in kcontrol...
+const float FADE_TIME = 5000.0f; // 5000 ms = 5.0 s
+const float FADE_BACK_TIME = 1000.0f; // 1000 ms = 1.0 s
+const float ADDITIONAL_DARKNESS = 0.6f; // the smaller this value, the darker the final image
KSMShutdownFeedback::KSMShutdownFeedback()
: QWidget( 0L, "feedbackwidget", WType_Popup ),
- 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() );
@@ -60,27 +74,134 @@
m_root.resize( width(), height() );
}
+// 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;
- }
+ // 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 ) * ADDITIONAL_DARKNESS / 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() / FADE_TIME;
+ if ( m_grayOpacity > 1.0f )
+ m_grayOpacity = 1.0f;
+ }
+ else
+ {
+ m_grayOpacity = 1.0f - m_fadeTime.elapsed() / FADE_BACK_TIME - 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<int>( 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<short int>( 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() ) );
- 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() ) );
}
//////
--- kdebase-3.5.2/ksmserver/shutdowndlg.h 2006-01-19 15:01:08.000000000 -0200
+++ kdebase-3.5.2/ksmserver/shutdowndlg.h.fade 2006-05-08 22:10:54.624474000 -0300
@@ -7,8 +7,9 @@
#ifndef SHUTDOWNDLG_H
#define SHUTDOWNDLG_H
-#include <qpixmap.h>
#include <qdialog.h>
+#include <qimage.h>
+#include <qdatetime.h>
#include <kpushbutton.h>
class QPushButton;
class QVButtonGroup;
@@ -16,15 +17,16 @@
class QTimer;
#include <kapplication.h>
+#include <kpixmapio.h>
-// The (singleton) widget that makes the desktop gray.
+// The (singleton) widget that 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:
@@ -36,7 +38,15 @@
private:
static KSMShutdownFeedback * s_pSelf;
KSMShutdownFeedback();
- int m_currentY;
+ 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;
QPixmap m_root;
};