kscreensaver.cpp
00001 /* This file is part of the KDE libraries 00002 00003 Copyright (c) 2001 Martin R. Jones <mjones@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include <qpainter.h> 00022 #include <qtimer.h> 00023 #include <kapplication.h> 00024 #include "kscreensaver.h" 00025 #ifdef Q_WS_X11 00026 #include <X11/Xlib.h> 00027 #else 00028 typedef WId Window; 00029 #endif 00030 00031 #undef KeyPress 00032 #undef KeyRelease 00033 00034 //----------------------------------------------------------------------------- 00035 00036 class KScreenSaverPrivate 00037 { 00038 public: 00039 QWidget *owner; 00040 }; 00041 00042 KScreenSaver::KScreenSaver( WId id ) : QWidget() 00043 { 00044 Window root; 00045 int ai; 00046 unsigned int au; 00047 unsigned int w = 0; 00048 unsigned int h = 0; 00049 00050 d = new KScreenSaverPrivate; 00051 d->owner = find( id ); 00052 if ( d->owner ) 00053 installEventFilter( this ); 00054 00055 if ( id ) 00056 { 00057 #ifdef Q_WS_X11 //FIXME 00058 XGetGeometry(qt_xdisplay(), (Drawable)id, &root, &ai, &ai, 00059 &w, &h, &au, &au); 00060 #endif 00061 00062 create( id, false, true ); 00063 } 00064 00065 if ( w == 0 ) w = 600; 00066 if ( h == 0 ) h = 420; 00067 resize( w, h ); 00068 KApplication::sendPostedEvents(); 00069 show(); 00070 } 00071 00072 KScreenSaver::~KScreenSaver() 00073 { 00074 destroy( false, false ); 00075 delete d; 00076 } 00077 00078 void KScreenSaver::embed( QWidget *w ) 00079 { 00080 KApplication::sendPostedEvents(); 00081 #ifdef Q_WS_X11 //FIXME 00082 XReparentWindow(qt_xdisplay(), w->winId(), winId(), 0, 0); 00083 #endif 00084 w->setGeometry( 0, 0, width(), height() ); 00085 KApplication::sendPostedEvents(); 00086 } 00087 00088 bool KScreenSaver::eventFilter( QObject *o, QEvent *e ) 00089 { 00090 // make sure events get to the original window owner 00091 if ( d->owner && o == this ) { 00092 QApplication::sendEvent( d->owner, e ); 00093 return false; 00094 } 00095 00096 return QWidget::eventFilter( o, e ); 00097 } 00098 00099 //============================================================================ 00100 00101 class KBlankEffectPrivate 00102 { 00103 public: 00104 KBlankEffect::BlankEffect currentEffect; 00105 int effectProgress; 00106 QTimer *timer; 00107 QWidget *widget; 00108 }; 00109 00110 KBlankEffect::BlankEffect KBlankEffect::effects[] = { 00111 &KBlankEffect::blankNormal, 00112 &KBlankEffect::blankSweepRight, 00113 &KBlankEffect::blankSweepDown, 00114 &KBlankEffect::blankBlocks 00115 }; 00116 00117 KBlankEffect::KBlankEffect( QObject *parent ) : QObject( parent ) 00118 { 00119 d = new KBlankEffectPrivate; 00120 d->currentEffect = &KBlankEffect::blankNormal; 00121 d->effectProgress = 0; 00122 d->timer = new QTimer( this ); 00123 connect( d->timer, SIGNAL(timeout()), this, SLOT(timeout()) ); 00124 } 00125 00126 00127 KBlankEffect::~KBlankEffect() 00128 { 00129 delete d; 00130 } 00131 00132 void KBlankEffect::finished() 00133 { 00134 d->timer->stop(); 00135 d->effectProgress = 0; 00136 emit doneBlank(); 00137 } 00138 00139 00140 void KBlankEffect::blank( QWidget *w, Effect effect ) 00141 { 00142 if ( !w ) { 00143 emit doneBlank(); 00144 return; 00145 } 00146 00147 if ( effect == Random ) 00148 effect = (Effect)(kapp->random() % MaximumEffects); 00149 00150 d->effectProgress = 0; 00151 d->widget = w; 00152 d->currentEffect = effects[ (int)effect ]; 00153 d->timer->start( 10 ); 00154 } 00155 00156 void KBlankEffect::timeout() 00157 { 00158 (this->*d->currentEffect)(); 00159 } 00160 00161 void KBlankEffect::blankNormal() 00162 { 00163 QPainter p( d->widget ); 00164 p.fillRect( 0, 0, d->widget->width(), d->widget->height(), black ); 00165 finished(); 00166 } 00167 00168 00169 void KBlankEffect::blankSweepRight() 00170 { 00171 QPainter p( d->widget ); 00172 p.fillRect( d->effectProgress, 0, 50, d->widget->height(), black ); 00173 kapp->flushX(); 00174 d->effectProgress += 50; 00175 if ( d->effectProgress >= d->widget->width() ) 00176 finished(); 00177 } 00178 00179 00180 void KBlankEffect::blankSweepDown() 00181 { 00182 QPainter p( d->widget ); 00183 p.fillRect( 0, d->effectProgress, d->widget->width(), 50, black ); 00184 kapp->flushX(); 00185 d->effectProgress += 50; 00186 if ( d->effectProgress >= d->widget->height() ) 00187 finished(); 00188 } 00189 00190 00191 void KBlankEffect::blankBlocks() 00192 { 00193 static int *block = 0; 00194 00195 int bx = (d->widget->width()+63)/64; 00196 int by = (d->widget->height()+63)/64; 00197 00198 if ( !d->effectProgress ) { 00199 block = new int [ bx*by ]; 00200 00201 for ( int i = 0; i < bx*by; i++ ) 00202 block[i] = i; 00203 for ( int i = 0; i < bx*by; i++ ) { 00204 int swap = kapp->random()%(bx*by); 00205 int tmp = block[i]; 00206 block[i] = block[swap]; 00207 block[swap] = tmp; 00208 } 00209 } 00210 00211 QPainter p( d->widget ); 00212 00213 // erase a couple of blocks at a time, otherwise it looks too slow 00214 for ( int i = 0; i < 2 && d->effectProgress < bx*by; i++ ) { 00215 int x = block[d->effectProgress]%bx; 00216 int y = block[d->effectProgress]/bx; 00217 p.fillRect( x*64, y*64, 64, 64, black ); 00218 d->effectProgress++; 00219 } 00220 00221 kapp->flushX(); 00222 00223 if ( d->effectProgress >= bx*by ) { 00224 delete[] block; 00225 finished(); 00226 } 00227 } 00228 00229 #include "kscreensaver.moc"