diff options
Diffstat (limited to 'kdeui/kcursor.cpp')
-rw-r--r-- | kdeui/kcursor.cpp | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/kdeui/kcursor.cpp b/kdeui/kcursor.cpp new file mode 100644 index 000000000..74e37327d --- /dev/null +++ b/kdeui/kcursor.cpp @@ -0,0 +1,434 @@ +/* This file is part of the KDE libraries + Copyright (C) 1998 Kurt Granroth (granroth@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifdef KDE_USE_FINAL +#ifdef KeyRelease +#undef KeyRelease +#endif +#endif + +#include <kcursor.h> + +#include <qbitmap.h> +#include <qcursor.h> +#include <qevent.h> +#include <qtimer.h> +#include <qwidget.h> + +#include <kglobal.h> +#include <kconfig.h> +#include <qscrollview.h> + +#include "kcursor_private.h" + +KCursor::KCursor() +{ +} + +QCursor KCursor::handCursor() +{ + static QCursor *hand_cursor = 0; + + if (!hand_cursor) + { + KConfig *config = KGlobal::config(); + KConfigGroupSaver saver( config, "General" ); + +#ifndef Q_WS_WIN // this mask doesn't work too well on win32 + if ( config->readEntry("handCursorStyle", "Windows") == "Windows" ) + { + static const unsigned char HAND_BITS[] = { + 0x80, 0x01, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, + 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x1e, 0x00, 0x40, + 0xf2, 0x00, 0x40, 0x92, 0x01, 0x70, 0x92, 0x02, 0x50, 0x92, 0x04, + 0x48, 0x80, 0x04, 0x48, 0x00, 0x04, 0x48, 0x00, 0x04, 0x08, 0x00, + 0x04, 0x08, 0x00, 0x04, 0x10, 0x00, 0x04, 0x10, 0x00, 0x04, 0x20, + 0x00, 0x02, 0x40, 0x00, 0x02, 0x40, 0x00, 0x01, 0xc0, 0xff, 0x01}; + static const unsigned char HAND_MASK_BITS[] = { + 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, + 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x1f, 0x00, 0xc0, + 0xff, 0x00, 0xc0, 0xff, 0x01, 0xf0, 0xff, 0x03, 0xf0, 0xff, 0x07, + 0xf8, 0xff, 0x07, 0xf8, 0xff, 0x07, 0xf8, 0xff, 0x07, 0xf8, 0xff, + 0x07, 0xf8, 0xff, 0x07, 0xf0, 0xff, 0x07, 0xf0, 0xff, 0x07, 0xe0, + 0xff, 0x03, 0xc0, 0xff, 0x03, 0xc0, 0xff, 0x01, 0xc0, 0xff, 0x01}; + QBitmap hand_bitmap(22, 22, HAND_BITS, true); + QBitmap hand_mask(22, 22, HAND_MASK_BITS, true); + hand_cursor = new QCursor(hand_bitmap, hand_mask, 7, 0); + // Hack to force QCursor to call XCreatePixmapCursor() immediately + // so the bitmaps don't get pushed out of the Xcursor LRU cache. + hand_cursor->handle(); + } + else +#endif //! Q_WS_WIN + hand_cursor = new QCursor(PointingHandCursor); + } + + Q_CHECK_PTR(hand_cursor); + return *hand_cursor; +} + +/* XPM */ +static const char * const working_cursor_xpm[]={ +"32 32 3 1", +"# c None", +"a c #000000", +". c #ffffff", +"..##############################", +".a.##########.aaaa.#############", +".aa.#########.aaaa.#############", +".aaa.#######.aaaaaa.############", +".aaaa.#####.a...a..a..##########", +".aaaaa.####a....a...aa##########", +".aaaaaa.###a...aa...aa##########", +".aaaaaaa.##a..a.....aa##########", +".aaaaaaaa.#.aa.....a..##########", +".aaaaa....##.aaaaaa.############", +".aa.aa.######.aaaa.#############", +".a.#.aa.#####.aaaa.#############", +"..##.aa.########################", +"#####.aa.#######################", +"#####.aa.#######################", +"######..########################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################", +"################################"}; + + +QCursor KCursor::workingCursor() +{ + static QCursor *working_cursor = 0; + + if (!working_cursor) + { + QPixmap pm( const_cast< const char** >( working_cursor_xpm )); + working_cursor = new QCursor( pm, 1, 1 ); + // Hack to force QCursor to call XCreatePixmapCursor() immediately + // so the bitmaps don't get pushed out of the Xcursor LRU cache. + working_cursor->handle(); + } + + Q_CHECK_PTR(working_cursor); + return *working_cursor; +} + +/** + * All of the follow functions will return the Qt default for now regardless + * of the style. This will change at some later date + */ +QCursor KCursor::arrowCursor() +{ + return Qt::arrowCursor; +} + + +QCursor KCursor::upArrowCursor() +{ + return Qt::upArrowCursor; +} + + +QCursor KCursor::crossCursor() +{ + return Qt::crossCursor; +} + + +QCursor KCursor::waitCursor() +{ + return Qt::waitCursor; +} + + +QCursor KCursor::ibeamCursor() +{ + return Qt::ibeamCursor; +} + + +QCursor KCursor::sizeVerCursor() +{ + return Qt::sizeVerCursor; +} + + +QCursor KCursor::sizeHorCursor() +{ + return Qt::sizeHorCursor; +} + + +QCursor KCursor::sizeBDiagCursor() +{ + return Qt::sizeBDiagCursor; +} + + +QCursor KCursor::sizeFDiagCursor() +{ + return Qt::sizeFDiagCursor; +} + + +QCursor KCursor::sizeAllCursor() +{ + return Qt::sizeAllCursor; +} + + +QCursor KCursor::blankCursor() +{ + return Qt::blankCursor; +} + +QCursor KCursor::whatsThisCursor() +{ + return Qt::whatsThisCursor; +} + +// auto-hide cursor stuff + +void KCursor::setAutoHideCursor( QWidget *w, bool enable ) +{ + setAutoHideCursor( w, enable, false ); +} + +void KCursor::setAutoHideCursor( QWidget *w, bool enable, + bool customEventFilter ) +{ + KCursorPrivate::self()->setAutoHideCursor( w, enable, customEventFilter ); +} + +void KCursor::autoHideEventFilter( QObject *o, QEvent *e ) +{ + KCursorPrivate::self()->eventFilter( o, e ); +} + +void KCursor::setHideCursorDelay( int ms ) +{ + KCursorPrivate::self()->hideCursorDelay = ms; +} + +int KCursor::hideCursorDelay() +{ + return KCursorPrivate::self()->hideCursorDelay; +} + +// ************************************************************************** + +KCursorPrivateAutoHideEventFilter::KCursorPrivateAutoHideEventFilter( QWidget* widget ) + : m_widget( widget ) + , m_wasMouseTracking( m_widget->hasMouseTracking() ) + , m_isCursorHidden( false ) + , m_isOwnCursor( false ) +{ + m_widget->setMouseTracking( true ); + connect( &m_autoHideTimer, SIGNAL( timeout() ), + this, SLOT( hideCursor() ) ); +} + +KCursorPrivateAutoHideEventFilter::~KCursorPrivateAutoHideEventFilter() +{ + if( m_widget != NULL ) + m_widget->setMouseTracking( m_wasMouseTracking ); +} + +void KCursorPrivateAutoHideEventFilter::resetWidget() +{ + m_widget = NULL; +} + +void KCursorPrivateAutoHideEventFilter::hideCursor() +{ + m_autoHideTimer.stop(); + + if ( m_isCursorHidden ) + return; + + m_isCursorHidden = true; + + QWidget* w = actualWidget(); + + m_isOwnCursor = w->ownCursor(); + if ( m_isOwnCursor ) + m_oldCursor = w->cursor(); + + w->setCursor( KCursor::blankCursor() ); +} + +void KCursorPrivateAutoHideEventFilter::unhideCursor() +{ + m_autoHideTimer.stop(); + + if ( !m_isCursorHidden ) + return; + + m_isCursorHidden = false; + + QWidget* w = actualWidget(); + + if ( w->cursor().shape() != Qt::BlankCursor ) // someone messed with the cursor already + return; + + if ( m_isOwnCursor ) + w->setCursor( m_oldCursor ); + else + w->unsetCursor(); +} + +QWidget* KCursorPrivateAutoHideEventFilter::actualWidget() const +{ + QWidget* w = m_widget; + + // Is w a scrollview ? Call setCursor on the viewport in that case. + QScrollView * sv = dynamic_cast<QScrollView *>( w ); + if ( sv ) + w = sv->viewport(); + + return w; +} + +bool KCursorPrivateAutoHideEventFilter::eventFilter( QObject *o, QEvent *e ) +{ + Q_ASSERT( o == m_widget ); + + switch ( e->type() ) + { + case QEvent::Create: + // Qt steals mouseTracking on create() + m_widget->setMouseTracking( true ); + break; + case QEvent::Leave: + case QEvent::FocusOut: + case QEvent::WindowDeactivate: + unhideCursor(); + break; + case QEvent::KeyPress: + case QEvent::AccelOverride: + hideCursor(); + break; + case QEvent::Enter: + case QEvent::FocusIn: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::Show: + case QEvent::Hide: + case QEvent::Wheel: + unhideCursor(); + if ( m_widget->hasFocus() ) + m_autoHideTimer.start( KCursorPrivate::self()->hideCursorDelay, true ); + break; + default: + break; + } + + return false; +} + +KCursorPrivate * KCursorPrivate::s_self = 0L; + +KCursorPrivate * KCursorPrivate::self() +{ + if ( !s_self ) + s_self = new KCursorPrivate; + // WABA: We never delete KCursorPrivate. Don't change. + + return s_self; +} + +KCursorPrivate::KCursorPrivate() +{ + hideCursorDelay = 5000; // 5s default value + + KConfig *kc = KGlobal::config(); + KConfigGroupSaver ks( kc, QString::fromLatin1("KDE") ); + enabled = kc->readBoolEntry( + QString::fromLatin1("Autohiding cursor enabled"), true ); +} + +KCursorPrivate::~KCursorPrivate() +{ +} + +void KCursorPrivate::setAutoHideCursor( QWidget *w, bool enable, bool customEventFilter ) +{ + if ( !w || !enabled ) + return; + + if ( enable ) + { + if ( m_eventFilters.find( w ) != NULL ) + return; + KCursorPrivateAutoHideEventFilter* filter = new KCursorPrivateAutoHideEventFilter( w ); + m_eventFilters.insert( w, filter ); + if ( !customEventFilter ) + w->installEventFilter( filter ); + connect( w, SIGNAL( destroyed(QObject*) ), + this, SLOT( slotWidgetDestroyed(QObject*) ) ); + } + else + { + KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( w ); + if ( filter == NULL ) + return; + w->removeEventFilter( filter ); + delete filter; + disconnect( w, SIGNAL( destroyed(QObject*) ), + this, SLOT( slotWidgetDestroyed(QObject*) ) ); + } +} + +bool KCursorPrivate::eventFilter( QObject *o, QEvent *e ) +{ + if ( !enabled ) + return false; + + KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.find( o ); + + Q_ASSERT( filter != NULL ); + if ( filter == NULL ) + return false; + + return filter->eventFilter( o, e ); +} + +void KCursorPrivate::slotWidgetDestroyed( QObject* o ) +{ + KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( o ); + + Q_ASSERT( filter != NULL ); + + filter->resetWidget(); // so that dtor doesn't access it + delete filter; +} + +#include "kcursor_private.moc" |