26 #include "kcursor_p.h"
32 #include <QAbstractScrollArea>
47 #include <X11/cursorfont.h>
50 # include <X11/Xcursor/Xcursor.h>
54 # include <X11/extensions/Xfixes.h>
63 static const char *
const standard_names[] = {
65 "X_cursor",
"arrow",
"based_arrow_down",
"based_arrow_up",
66 "boat",
"bogosity",
"bottom_left_corner",
"bottom_right_corner",
67 "bottom_side",
"bottom_tee",
"box_spiral",
"center_ptr",
68 "circle",
"clock",
"coffee_mug",
"cross",
71 "cross_reverse",
"crosshair",
"diamond_cross",
"dot",
72 "dotbox",
"double_arrow",
"draft_large",
"draft_small",
73 "draped_box",
"exchange",
"fleur",
"gobbler",
74 "gumby",
"hand1",
"hand2",
"heart",
77 "icon",
"iron_cross",
"left_ptr",
"left_side",
78 "left_tee",
"leftbutton",
"ll_angle",
"lr_angle",
79 "man",
"middlebutton",
"mouse",
"pencil",
80 "pirate",
"plus",
"question_arrow",
"right_ptr",
83 "right_side",
"right_tee",
"rightbutton",
"rtl_logo",
84 "sailboat",
"sb_down_arrow",
"sb_h_double_arrow",
"sb_left_arrow",
85 "sb_right_arrow",
"sb_up_arrow",
"sb_v_double_arrow",
"shuttle",
86 "sizing",
"spider",
"spraycan",
"star",
89 "target",
"tcross",
"top_left_arrow",
"top_left_corner",
90 "top_right_corner",
"top_side",
"top_tee",
"trek",
91 "ul_angle",
"umbrella",
"ur_angle",
"watch",
95 static Qt::HANDLE x11LoadXcursor(
const QString &
name)
98 return XcursorLibraryLoadCursor(QX11Info::display(), QFile::encodeName(name));
104 static int x11CursorShape(
const QString &name)
112 if (shapes.isEmpty())
114 int num = XC_num_glyphs / 2;
115 shapes.reserve(num + 5);
117 for (
int i = 0; i < num; ++i)
118 shapes.insert(standard_names[i], i << 1);
121 shapes.insert(
"size_all", XC_fleur);
122 shapes.insert(
"up_arrow", XC_center_ptr);
123 shapes.insert(
"ibeam", XC_xterm);
124 shapes.insert(
"wait", XC_watch);
125 shapes.insert(
"pointing_hand", XC_hand2);
128 return shapes.value(name, -1);
131 static Qt::HANDLE x11LoadFontCursor(
const QString &name)
133 int shape = x11CursorShape(name);
136 return XCreateFontCursor(QX11Info::display(), shape);
146 int event_base, error_base;
147 if (XFixesQueryExtension(QX11Info::display(), &event_base, &error_base))
150 XFixesQueryVersion(QX11Info::display(), &major, &minor);
151 result = (major >= 2);
157 static void x11SetCursorName(Qt::HANDLE handle,
const QString &name)
160 static bool haveXfixes = x11HaveXfixes();
163 XFixesSetCursorName(QX11Info::display(), handle, QFile::encodeName(name));
175 Qt::HANDLE handle = x11LoadXcursor(name);
178 handle = x11LoadFontCursor(name);
184 x11SetCursorName(QCursor::handle(), name);
198 QCursor::operator=( cursor );
203 bool customEventFilter )
205 KCursorPrivate::self()->setAutoHideCursor( w, enable, customEventFilter );
210 KCursorPrivate::self()->eventFilter( o, e );
215 KCursorPrivate::self()->hideCursorDelay = ms;
220 return KCursorPrivate::self()->hideCursorDelay;
225 KCursorPrivateAutoHideEventFilter::KCursorPrivateAutoHideEventFilter(
QWidget* widget )
227 , m_wasMouseTracking( m_widget->hasMouseTracking() )
228 , m_isCursorHidden( false )
229 , m_isOwnCursor( false )
231 mouseWidget()->setMouseTracking(
true );
232 connect( &m_autoHideTimer, SIGNAL(
timeout()),
233 this, SLOT(hideCursor()) );
236 KCursorPrivateAutoHideEventFilter::~KCursorPrivateAutoHideEventFilter()
238 if( m_widget != NULL )
239 mouseWidget()->setMouseTracking( m_wasMouseTracking );
242 void KCursorPrivateAutoHideEventFilter::resetWidget()
247 void KCursorPrivateAutoHideEventFilter::hideCursor()
249 m_autoHideTimer.stop();
251 if ( m_isCursorHidden )
254 m_isCursorHidden =
true;
258 m_isOwnCursor = w->testAttribute(Qt::WA_SetCursor);
260 m_oldCursor = w->cursor();
262 w->setCursor(
QCursor( Qt::BlankCursor ) );
265 void KCursorPrivateAutoHideEventFilter::unhideCursor()
267 m_autoHideTimer.stop();
269 if ( !m_isCursorHidden )
272 m_isCursorHidden =
false;
276 if ( w->cursor().shape() != Qt::BlankCursor )
280 w->setCursor( m_oldCursor );
287 QWidget* KCursorPrivateAutoHideEventFilter::mouseWidget()
const
292 QAbstractScrollArea * sv = qobject_cast<QAbstractScrollArea *>( w );
299 bool KCursorPrivateAutoHideEventFilter::eventFilter(
QObject *o, QEvent *e )
308 case QEvent::FocusOut:
309 case QEvent::WindowDeactivate:
312 case QEvent::KeyPress:
313 case QEvent::ShortcutOverride:
317 case QEvent::FocusIn:
318 case QEvent::MouseButtonPress:
319 case QEvent::MouseButtonRelease:
320 case QEvent::MouseButtonDblClick:
321 case QEvent::MouseMove:
326 if ( m_widget->hasFocus() )
328 m_autoHideTimer.setSingleShot(
true );
329 m_autoHideTimer.start( KCursorPrivate::self()->hideCursorDelay );
339 KCursorPrivate * KCursorPrivate::s_self = 0L;
341 KCursorPrivate * KCursorPrivate::self()
344 s_self =
new KCursorPrivate;
353 KCursorPrivate::KCursorPrivate()
355 hideCursorDelay = 5000;
358 enabled = cg.readEntry( QLatin1String(
"Autohiding cursor enabled"),
true);
361 KCursorPrivate::~KCursorPrivate()
365 void KCursorPrivate::setAutoHideCursor(
QWidget *w,
bool enable,
bool customEventFilter )
367 if ( !w || !enabled )
371 QAbstractScrollArea * sv = qobject_cast<QAbstractScrollArea *>( w );
373 viewport = sv->viewport();
377 if ( m_eventFilters.contains( w ) )
379 KCursorPrivateAutoHideEventFilter* filter =
new KCursorPrivateAutoHideEventFilter( w );
380 m_eventFilters.insert( w, filter );
382 m_eventFilters.insert( viewport, filter );
383 connect(viewport, SIGNAL(destroyed(
QObject*)),
this, SLOT(slotViewportDestroyed(
QObject*)));
385 if ( !customEventFilter ) {
386 w->installEventFilter( filter );
388 viewport->installEventFilter( filter );
390 connect( w, SIGNAL(destroyed(
QObject*)),
391 this, SLOT(slotWidgetDestroyed(
QObject*)) );
395 KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( w );
398 w->removeEventFilter( filter );
400 m_eventFilters.remove( viewport );
401 disconnect(viewport, SIGNAL(destroyed(
QObject*)),
this, SLOT(slotViewportDestroyed(
QObject*)));
402 viewport->removeEventFilter( filter );
405 disconnect( w, SIGNAL(destroyed(
QObject*)),
406 this, SLOT(slotWidgetDestroyed(
QObject*)) );
410 bool KCursorPrivate::eventFilter(
QObject *o, QEvent *e )
415 KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.value( o );
417 Q_ASSERT( filter != 0 );
421 return filter->eventFilter( o, e );
424 void KCursorPrivate::slotViewportDestroyed(
QObject *o)
426 m_eventFilters.remove(o);
429 void KCursorPrivate::slotWidgetDestroyed(
QObject* o )
431 KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( o );
433 Q_ASSERT( filter != 0 );
435 filter->resetWidget();
439 #include "kcursor_p.moc"
static void setHideCursorDelay(int ms)
Sets the delay time in milliseconds for auto-hiding.
KCursor(const QString &name, Qt::CursorShape fallback=Qt::ArrowCursor)
Attempts to load the requested name cursor from the current theme.
static int hideCursorDelay()
const char * name(StandardAction id)
This will return the internal name of a given standard action.
KCursor & operator=(const KCursor &cursor)
Assigns cursor to this cursor, and returns a reference to this cursor.
static void autoHideEventFilter(QObject *, QEvent *)
KCursor has to install an eventFilter over the widget you want to auto-hide.
KSharedConfigPtr config()
static void setAutoHideCursor(QWidget *w, bool enable, bool customEventFilter=false)
Sets auto-hiding the cursor for widget w.
The KCursor class extends QCursor with the ability to create an arbitrary named cursor from the curso...