kdeui Library API Documentation

kcursor.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 1998 Kurt Granroth (granroth@kde.org)
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00016    Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #ifdef KDE_USE_FINAL
00020 #ifdef KeyRelease
00021 #undef KeyRelease
00022 #endif
00023 #endif
00024 
00025 #include <kcursor.h>
00026 #include <kapplication.h>
00027 
00028 #include <qbitmap.h>
00029 #include <qcursor.h>
00030 #include <qevent.h>
00031 #include <qtimer.h>
00032 #include <qwidget.h>
00033 
00034 #include <kglobal.h>
00035 #include <kconfig.h>
00036 #include <qscrollview.h>
00037 
00038 #include "kcursor_private.h"
00039 
00040 KCursor::KCursor()
00041 {
00042 }
00043 
00044 QCursor KCursor::handCursor()
00045 {
00046         static QCursor *hand_cursor = 0;
00047 
00048         if (hand_cursor == 0)
00049         {
00050                 KConfig *config = KGlobal::config();
00051                 KConfigGroupSaver saver( config, "General" );
00052 
00053                 if ( config->readEntry("handCursorStyle", "Windows") == "Windows" )
00054                 {
00055                         static const unsigned char HAND_BITS[] = {
00056                                 0x80, 0x01, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02,
00057                                 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x1e, 0x00, 0x40,
00058                                 0xf2, 0x00, 0x40, 0x92, 0x01, 0x70, 0x92, 0x02, 0x50, 0x92, 0x04,
00059                                 0x48, 0x80, 0x04, 0x48, 0x00, 0x04, 0x48, 0x00, 0x04, 0x08, 0x00,
00060                                 0x04, 0x08, 0x00, 0x04, 0x10, 0x00, 0x04, 0x10, 0x00, 0x04, 0x20,
00061                                 0x00, 0x02, 0x40, 0x00, 0x02, 0x40, 0x00, 0x01, 0xc0, 0xff, 0x01};
00062                         static const unsigned char HAND_MASK_BITS[] = {
00063                                 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03,
00064                                 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x1f, 0x00, 0xc0,
00065                                 0xff, 0x00, 0xc0, 0xff, 0x01, 0xf0, 0xff, 0x03, 0xf0, 0xff, 0x07,
00066                                 0xf8, 0xff, 0x07, 0xf8, 0xff, 0x07, 0xf8, 0xff, 0x07, 0xf8, 0xff,
00067                                 0x07, 0xf8, 0xff, 0x07, 0xf0, 0xff, 0x07, 0xf0, 0xff, 0x07, 0xe0,
00068                                 0xff, 0x03, 0xc0, 0xff, 0x03, 0xc0, 0xff, 0x01, 0xc0, 0xff, 0x01};
00069                         QBitmap hand_bitmap(22, 22, HAND_BITS, true);
00070                         QBitmap hand_mask(22, 22, HAND_MASK_BITS, true);
00071                         hand_cursor = new QCursor(hand_bitmap, hand_mask, 7, 0);
00072                         // Hack to force QCursor to call XCreatePixmapCursor() immediately
00073                         // so the bitmaps don't get pushed out of the Xcursor LRU cache.
00074                         hand_cursor->handle();
00075                 }
00076                 else
00077                         hand_cursor = new QCursor(PointingHandCursor);
00078         }
00079 
00080         Q_CHECK_PTR(hand_cursor);
00081         return *hand_cursor;
00082 }
00083 
00084 /* XPM */
00085 static const char * const working_cursor_xpm[]={
00086 "32 32 3 1",
00087 "# c None",
00088 "a c #000000",
00089 ". c #ffffff",
00090 "..##############################",
00091 ".a.##########.aaaa.#############",
00092 ".aa.#########.aaaa.#############",
00093 ".aaa.#######.aaaaaa.############",
00094 ".aaaa.#####.a...a..a..##########",
00095 ".aaaaa.####a....a...aa##########",
00096 ".aaaaaa.###a...aa...aa##########",
00097 ".aaaaaaa.##a..a.....aa##########",
00098 ".aaaaaaaa.#.aa.....a..##########",
00099 ".aaaaa....##.aaaaaa.############",
00100 ".aa.aa.######.aaaa.#############",
00101 ".a.#.aa.#####.aaaa.#############",
00102 "..##.aa.########################",
00103 "#####.aa.#######################",
00104 "#####.aa.#######################",
00105 "######..########################",
00106 "################################",
00107 "################################",
00108 "################################",
00109 "################################",
00110 "################################",
00111 "################################",
00112 "################################",
00113 "################################",
00114 "################################",
00115 "################################",
00116 "################################",
00117 "################################",
00118 "################################",
00119 "################################",
00120 "################################",
00121 "################################"};
00122 
00123 
00124 QCursor KCursor::workingCursor()
00125 {
00126         static QCursor *working_cursor = 0;
00127 
00128         if (working_cursor == 0)
00129         {
00130             QPixmap pm( const_cast< const char** >( working_cursor_xpm ));
00131             working_cursor = new QCursor( pm, 1, 1 );
00132             // Hack to force QCursor to call XCreatePixmapCursor() immediately
00133             // so the bitmaps don't get pushed out of the Xcursor LRU cache.
00134             working_cursor->handle();
00135         }
00136 
00137         Q_CHECK_PTR(working_cursor);
00138         return *working_cursor;
00139 }
00140 
00145 QCursor KCursor::arrowCursor()
00146 {
00147     return Qt::arrowCursor;
00148 }
00149 
00150 
00151 QCursor KCursor::upArrowCursor()
00152 {
00153     return Qt::upArrowCursor;
00154 }
00155 
00156 
00157 QCursor KCursor::crossCursor()
00158 {
00159     return Qt::crossCursor;
00160 }
00161 
00162 
00163 QCursor KCursor::waitCursor()
00164 {
00165     return Qt::waitCursor;
00166 }
00167 
00168 
00169 QCursor KCursor::ibeamCursor()
00170 {
00171     return Qt::ibeamCursor;
00172 }
00173 
00174 
00175 QCursor KCursor::sizeVerCursor()
00176 {
00177     return Qt::sizeVerCursor;
00178 }
00179 
00180 
00181 QCursor KCursor::sizeHorCursor()
00182 {
00183     return Qt::sizeHorCursor;
00184 }
00185 
00186 
00187 QCursor KCursor::sizeBDiagCursor()
00188 {
00189     return Qt::sizeBDiagCursor;
00190 }
00191 
00192 
00193 QCursor KCursor::sizeFDiagCursor()
00194 {
00195     return Qt::sizeFDiagCursor;
00196 }
00197 
00198 
00199 QCursor KCursor::sizeAllCursor()
00200 {
00201     return Qt::sizeAllCursor;
00202 }
00203 
00204 
00205 QCursor KCursor::blankCursor()
00206 {
00207     return Qt::blankCursor;
00208 }
00209 
00210 QCursor KCursor::whatsThisCursor()
00211 {
00212     return Qt::whatsThisCursor;
00213 }
00214 
00215 // auto-hide cursor stuff
00216 
00217 void KCursor::setAutoHideCursor( QWidget *w, bool enable )
00218 {
00219     setAutoHideCursor( w, enable, false );
00220 }
00221 
00222 void KCursor::setAutoHideCursor( QWidget *w, bool enable,
00223                  bool customEventFilter )
00224 {
00225     if ( !w )
00226         return;
00227 
00228     KCursorPrivate *kp = KCursorPrivate::self();
00229     if ( !kp->enabled )
00230     return;
00231 
00232     if ( enable ) {
00233         kp->start();
00234         w->setMouseTracking( true );
00235 
00236     if ( !customEventFilter )
00237         w->installEventFilter( kp );
00238     else // safety
00239         w->removeEventFilter( kp );
00240     }
00241 
00242     else {
00243         w->setMouseTracking( false );
00244         w->removeEventFilter( kp );
00245         kp->stop();
00246     }
00247 }
00248 
00249 void KCursor::autoHideEventFilter( QObject *o, QEvent *e )
00250 {
00251     KCursorPrivate::self()->eventFilter( o, e );
00252 }
00253 
00254 void KCursor::setHideCursorDelay( int ms )
00255 {
00256     KCursorPrivate::self()->hideCursorDelay = ms;
00257 }
00258 
00259 int KCursor::hideCursorDelay()
00260 {
00261     return KCursorPrivate::self()->hideCursorDelay;
00262 }
00263 
00264 
00265 // **************************************************************************
00266 // **************************************************************************
00267 
00268 KCursorPrivate * KCursorPrivate::s_self = 0L;
00269 
00270 KCursorPrivate * KCursorPrivate::self()
00271 {
00272     if ( !s_self )
00273         s_self = new KCursorPrivate;
00274     // WABA: We never delete KCursorPrivate. Don't change.
00275 
00276     return s_self;
00277 }
00278 
00279 KCursorPrivate::KCursorPrivate()
00280 {
00281     count = 0;
00282     autoHideTimer = 0;
00283     hideCursorDelay = 5000; // 5s default value
00284     isCursorHidden = false;
00285     isOwnCursor = false;
00286     hideWidget = 0L;
00287 
00288     KConfig *kc = KGlobal::config();
00289     KConfigGroupSaver ks( kc, QString::fromLatin1("KDE") );
00290     enabled = kc->readBoolEntry(
00291           QString::fromLatin1("Autohiding cursor enabled"), true );
00292 }
00293 
00294 KCursorPrivate::~KCursorPrivate()
00295 {
00296 }
00297 
00298 void KCursorPrivate::start()
00299 {
00300     if ( !autoHideTimer ) {
00301         autoHideTimer = new QTimer(qApp);
00302         QObject::connect( autoHideTimer, SIGNAL( timeout() ),
00303                           this, SLOT( slotHideCursor() ));
00304     }
00305     count++;
00306 }
00307 
00308 void KCursorPrivate::stop()
00309 {
00310     count--;
00311     if ( count <= 0 ) {
00312         delete autoHideTimer;
00313         autoHideTimer = 0L;
00314         count = 0;
00315     }
00316 }
00317 
00318 void KCursorPrivate::hideCursor( QWidget *w )
00319 {
00320     if ( !w )
00321         return;
00322     // Is w a scrollview ? Call setCursor on the viewport in that case.
00323     QScrollView * sv = dynamic_cast<QScrollView *>( w );
00324     if ( sv )
00325         w = sv->viewport();
00326 
00327     isCursorHidden = true;
00328     isOwnCursor = w->ownCursor();
00329     if ( isOwnCursor )
00330         oldCursor = w->cursor();
00331 
00332     w->setCursor( KCursor::blankCursor() );
00333 }
00334 
00335 void KCursorPrivate::unhideCursor( QWidget *w )
00336 {
00337     isCursorHidden = false;
00338 
00339     if ( w ) {
00340         QScrollView * sv = dynamic_cast<QScrollView *>( w );
00341         if ( sv )
00342             w = sv->viewport();
00343 
00344         if ( isOwnCursor )
00345             w->setCursor( oldCursor );
00346         else
00347             w->unsetCursor();
00348     }
00349 }
00350 
00351 
00352 // what a mess :-/
00353 // no kidding!
00354 bool KCursorPrivate::eventFilter( QObject *o, QEvent *e )
00355 {
00356     if ( !enabled || !o->isWidgetType() )
00357         return false;
00358 
00359     int t = e->type();
00360     
00361     // If it is not one of the events we respond to, ignore it.
00362     if( ! ( (t >= QEvent::MouseButtonPress && t <= QEvent::Leave) ||
00363             (t >= QEvent::Destroy && t <= QEvent::Hide) ||
00364              t == QEvent::AccelOverride ||
00365              t == QEvent::Wheel ) )
00366       return false;
00367     
00368     // disconnect() and connect() on events for a new widget
00369     if ( o != hideWidget ) {
00370         if ( hideWidget ) {
00371             disconnect( hideWidget, SIGNAL( destroyed() ),
00372                         this, SLOT( slotWidgetDestroyed()));
00373         }
00374         connect( o, SIGNAL( destroyed() ),
00375                  this, SLOT( slotWidgetDestroyed()));
00376     }
00377 
00378     QWidget *w = static_cast<QWidget *>( o );
00379     hideWidget = w;
00380 
00381     if ( t == QEvent::Leave || t == QEvent::FocusOut || t == QEvent::Destroy) {
00382     if ( autoHideTimer )
00383             autoHideTimer->stop();
00384 
00385         if ( isCursorHidden && t != QEvent::Destroy )
00386             unhideCursor( w );
00387 
00388         return false;
00389     }
00390 
00391     if ( t == QEvent::Create ) // Qt steals mouseTracking on create()
00392         w->setMouseTracking( true );
00393 
00394     // don't process events not coming from the focus-window
00395     // or from widgets that accept focus, but don't have it.
00396     if ( !w->isActiveWindow() || (w->isFocusEnabled() && !w->hasFocus()) ) {
00397         disconnect( hideWidget, SIGNAL( destroyed() ),
00398                     this, SLOT( slotWidgetDestroyed() ));
00399     hideWidget = 0L;
00400     return false;
00401     }
00402 
00403     else if ( t == QEvent::Enter ) {
00404         if ( isCursorHidden )
00405             unhideCursor( w );
00406         if ( autoHideTimer )
00407             autoHideTimer->start( hideCursorDelay, true );
00408     }
00409 
00410     else { // other than enter/leave/focus events
00411         
00412         if ( isCursorHidden ) {
00413             if ( t == QEvent::MouseButtonPress ||
00414                  t == QEvent::MouseButtonRelease ||
00415                  t == QEvent::MouseButtonDblClick || t == QEvent::MouseMove ||
00416                  t == QEvent::Show || t == QEvent::Hide ) {
00417                 unhideCursor( w );
00418         autoHideTimer->start( hideCursorDelay, true );
00419         }
00420     }
00421 
00422         else { // cursor not hidden yet
00423             if ( t == QEvent::KeyPress || t == QEvent::AccelOverride ) { //t == QEvent::KeyRelease ) {
00424                 if ( insideWidget( QCursor::pos(), w )) {
00425                     hideCursor( w );
00426                     autoHideTimer->stop();
00427         }
00428             }
00429 
00430         // restart the timer on user-input
00431             else if ( (t >= QEvent::MouseButtonPress &&
00432                t <= QEvent::KeyRelease) ||
00433               t == QEvent::Wheel || t == QEvent::AccelOverride ) {
00434 
00435                 if ( insideWidget( QCursor::pos(), w ) && autoHideTimer )
00436                     autoHideTimer->start( hideCursorDelay, true );
00437             }
00438         }
00439     }
00440     return false;
00441 }
00442 
00443 void KCursorPrivate::slotHideCursor()
00444 {
00445     if ( !isCursorHidden )
00446         hideCursor( hideWidget );
00447 }
00448 
00449 void KCursorPrivate::slotWidgetDestroyed()
00450 {
00451     isCursorHidden = false;
00452     hideWidget = 0L;
00453 }
00454 
00455 bool KCursorPrivate::insideWidget( const QPoint &p, QWidget *w )
00456 {
00457     return w->rect().contains( w->mapFromGlobal( p ) );
00458 }
00459 
00460 #include "kcursor_private.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:20:58 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001