23#include <KConfigGroup>
25#include <QAbstractEventDispatcher>
26#include <QDBusConnection>
30#include <xcb/xcb_cursor.h>
34Cursors *Cursors::s_self =
nullptr;
45 Q_ASSERT(!m_cursors.contains(cursor));
49 setCurrentCursor(cursor);
56 m_cursors.removeOne(cursor);
57 if (m_currentCursor == cursor) {
58 if (m_cursors.isEmpty()) {
59 m_currentCursor =
nullptr;
61 setCurrentCursor(m_cursors.constFirst());
64 if (m_mouse == cursor) {
71 m_cursorHideCounter++;
72 if (m_cursorHideCounter == 1) {
79 m_cursorHideCounter--;
80 if (m_cursorHideCounter == 0) {
87 return m_cursorHideCounter > 0;
90void Cursors::setCurrentCursor(
Cursor *cursor)
92 if (m_currentCursor == cursor) {
96 Q_ASSERT(m_cursors.contains(cursor) || !cursor);
98 if (m_currentCursor) {
101 m_currentCursor = cursor;
107void Cursors::emitCurrentCursorChanged()
113 : m_mousePollingCounter(0)
114 , m_cursorTrackingCounter(0)
115 , m_themeName(defaultThemeName())
116 , m_themeSize(defaultThemeSize())
119 QDBusConnection::sessionBus().connect(QString(), QStringLiteral(
"/KGlobalSettings"), QStringLiteral(
"org.kde.KGlobalSettings"),
120 QStringLiteral(
"notifyChange"),
this, SLOT(slotKGlobalSettingsNotifyChange(
int,
int)));
134void Cursor::loadThemeSettings()
136 QString
themeName = QString::fromUtf8(qgetenv(
"XCURSOR_THEME"));
139 const uint
themeSize = qEnvironmentVariableIntValue(
"XCURSOR_SIZE", &ok);
145 loadThemeFromKConfig();
148void Cursor::loadThemeFromKConfig()
150 KConfigGroup mousecfg(kwinApp()->inputConfig(), QStringLiteral(
"Mouse"));
156void Cursor::updateTheme(
const QString &name,
int size)
158 if (m_themeName != name || m_themeSize != size) {
166void Cursor::slotKGlobalSettingsNotifyChange(
int type,
int arg)
169 kwinApp()->inputConfig()->reparseConfiguration();
170 loadThemeFromKConfig();
184 if (Q_UNLIKELY(!m_source)) {
197 if (Q_UNLIKELY(!m_source)) {
200 return QRectF(QPointF(0, 0), m_source->
size());
232 Q_ASSERT(kwinApp()->x11Connection());
233 auto it = m_cursors.constFind(name);
234 if (it != m_cursors.constEnd()) {
238 if (name.isEmpty()) {
239 return XCB_CURSOR_NONE;
242 xcb_cursor_context_t *ctx;
243 if (xcb_cursor_context_new(kwinApp()->x11Connection(), Xcb::defaultScreen(), &ctx) < 0) {
244 return XCB_CURSOR_NONE;
247 xcb_cursor_t cursor = xcb_cursor_load_cursor(ctx, name.constData());
248 if (cursor == XCB_CURSOR_NONE) {
250 for (
const QByteArray &cursorName : names) {
251 cursor = xcb_cursor_load_cursor(ctx, cursorName.constData());
252 if (cursor != XCB_CURSOR_NONE) {
257 if (cursor != XCB_CURSOR_NONE) {
258 m_cursors.insert(name, cursor);
261 xcb_cursor_context_free(ctx);
285 ++m_mousePollingCounter;
286 if (m_mousePollingCounter == 1) {
293 Q_ASSERT(m_mousePollingCounter > 0);
294 --m_mousePollingCounter;
295 if (m_mousePollingCounter == 0) {
310 ++m_cursorTrackingCounter;
311 if (m_cursorTrackingCounter == 1) {
318 Q_ASSERT(m_cursorTrackingCounter > 0);
319 --m_cursorTrackingCounter;
320 if (m_cursorTrackingCounter == 0) {
335 return QStringLiteral(
"default");
345 static const QHash<QByteArray, QList<QByteArray>>
alternatives = {
347 QByteArrayLiteral(
"crosshair"),
349 QByteArrayLiteral(
"cross"),
350 QByteArrayLiteral(
"diamond-cross"),
351 QByteArrayLiteral(
"cross-reverse"),
355 QByteArrayLiteral(
"default"),
357 QByteArrayLiteral(
"left_ptr"),
358 QByteArrayLiteral(
"arrow"),
359 QByteArrayLiteral(
"dnd-none"),
360 QByteArrayLiteral(
"op_left_arrow"),
364 QByteArrayLiteral(
"up-arrow"),
366 QByteArrayLiteral(
"up_arrow"),
367 QByteArrayLiteral(
"sb_up_arrow"),
368 QByteArrayLiteral(
"center_ptr"),
369 QByteArrayLiteral(
"centre_ptr"),
373 QByteArrayLiteral(
"wait"),
375 QByteArrayLiteral(
"watch"),
376 QByteArrayLiteral(
"progress"),
380 QByteArrayLiteral(
"text"),
382 QByteArrayLiteral(
"ibeam"),
383 QByteArrayLiteral(
"xterm"),
387 QByteArrayLiteral(
"all-scroll"),
389 QByteArrayLiteral(
"size_all"),
390 QByteArrayLiteral(
"fleur"),
394 QByteArrayLiteral(
"pointer"),
396 QByteArrayLiteral(
"pointing_hand"),
397 QByteArrayLiteral(
"hand2"),
398 QByteArrayLiteral(
"hand"),
399 QByteArrayLiteral(
"hand1"),
400 QByteArrayLiteral(
"e29285e634086352946a0e7090d73106"),
401 QByteArrayLiteral(
"9d800788f1b08800ae810202380a0822"),
405 QByteArrayLiteral(
"ns-resize"),
407 QByteArrayLiteral(
"size_ver"),
408 QByteArrayLiteral(
"00008160000006810000408080010102"),
409 QByteArrayLiteral(
"sb_v_double_arrow"),
410 QByteArrayLiteral(
"v_double_arrow"),
411 QByteArrayLiteral(
"n-resize"),
412 QByteArrayLiteral(
"s-resize"),
413 QByteArrayLiteral(
"col-resize"),
414 QByteArrayLiteral(
"top_side"),
415 QByteArrayLiteral(
"bottom_side"),
416 QByteArrayLiteral(
"base_arrow_up"),
417 QByteArrayLiteral(
"base_arrow_down"),
418 QByteArrayLiteral(
"based_arrow_down"),
419 QByteArrayLiteral(
"based_arrow_up"),
423 QByteArrayLiteral(
"ew-resize"),
425 QByteArrayLiteral(
"size_hor"),
426 QByteArrayLiteral(
"028006030e0e7ebffc7f7070c0600140"),
427 QByteArrayLiteral(
"sb_h_double_arrow"),
428 QByteArrayLiteral(
"h_double_arrow"),
429 QByteArrayLiteral(
"e-resize"),
430 QByteArrayLiteral(
"w-resize"),
431 QByteArrayLiteral(
"row-resize"),
432 QByteArrayLiteral(
"right_side"),
433 QByteArrayLiteral(
"left_side"),
437 QByteArrayLiteral(
"nesw-resize"),
439 QByteArrayLiteral(
"size_bdiag"),
440 QByteArrayLiteral(
"fcf1c3c7cd4491d801f1e1c78f100000"),
441 QByteArrayLiteral(
"fd_double_arrow"),
442 QByteArrayLiteral(
"bottom_left_corner"),
443 QByteArrayLiteral(
"top_right_corner"),
447 QByteArrayLiteral(
"nwse-resize"),
449 QByteArrayLiteral(
"size_fdiag"),
450 QByteArrayLiteral(
"c7088f0f3e6c8088236ef8e1e3e70000"),
451 QByteArrayLiteral(
"bd_double_arrow"),
452 QByteArrayLiteral(
"bottom_right_corner"),
453 QByteArrayLiteral(
"top_left_corner"),
457 QByteArrayLiteral(
"help"),
459 QByteArrayLiteral(
"whats_this"),
460 QByteArrayLiteral(
"d9ce0ab605698f320427677b458ad60b"),
461 QByteArrayLiteral(
"left_ptr_help"),
462 QByteArrayLiteral(
"question_arrow"),
463 QByteArrayLiteral(
"dnd-ask"),
464 QByteArrayLiteral(
"5c6cd98b3f3ebcb1f9c7f1c204630408"),
468 QByteArrayLiteral(
"col-resize"),
470 QByteArrayLiteral(
"split_h"),
471 QByteArrayLiteral(
"14fef782d02440884392942c11205230"),
472 QByteArrayLiteral(
"size_hor"),
476 QByteArrayLiteral(
"row-resize"),
478 QByteArrayLiteral(
"split_v"),
479 QByteArrayLiteral(
"2870a09082c103050810ffdffffe0204"),
480 QByteArrayLiteral(
"size_ver"),
484 QByteArrayLiteral(
"not-allowed"),
486 QByteArrayLiteral(
"forbidden"),
487 QByteArrayLiteral(
"03b6e0fcb3499374a867c041f52298f0"),
488 QByteArrayLiteral(
"circle"),
489 QByteArrayLiteral(
"dnd-no-drop"),
493 QByteArrayLiteral(
"progress"),
495 QByteArrayLiteral(
"left_ptr_watch"),
496 QByteArrayLiteral(
"3ecb610c1bf2410f44200f48c40d3599"),
497 QByteArrayLiteral(
"00000000000000020006000e7e9ffc3f"),
498 QByteArrayLiteral(
"08e8e1c95fe2fc01f976f1e063a24ccd"),
502 QByteArrayLiteral(
"grab"),
504 QByteArrayLiteral(
"openhand"),
505 QByteArrayLiteral(
"9141b49c8149039304290b508d208c40"),
506 QByteArrayLiteral(
"all_scroll"),
507 QByteArrayLiteral(
"all-scroll"),
511 QByteArrayLiteral(
"grabbing"),
513 QByteArrayLiteral(
"closedhand"),
514 QByteArrayLiteral(
"05e88622050804100c20044008402080"),
515 QByteArrayLiteral(
"4498f0e0c1937ffe01fd06f973665830"),
516 QByteArrayLiteral(
"9081237383d90e509aa00f00170e968f"),
517 QByteArrayLiteral(
"fcf21c00b30f7e3f83fe0dfd12e71cff"),
521 QByteArrayLiteral(
"alias"),
523 QByteArrayLiteral(
"link"),
524 QByteArrayLiteral(
"dnd-link"),
525 QByteArrayLiteral(
"3085a0e285430894940527032f8b26df"),
526 QByteArrayLiteral(
"640fb0e74195791501fd1ed57b41487f"),
527 QByteArrayLiteral(
"a2a266d0498c3104214a47bd64ab0fc8"),
531 QByteArrayLiteral(
"copy"),
533 QByteArrayLiteral(
"dnd-copy"),
534 QByteArrayLiteral(
"1081e37283d90000800003c07f3ef6bf"),
535 QByteArrayLiteral(
"6407b0e94181790501fd1e167b474872"),
536 QByteArrayLiteral(
"b66166c04f8c3109214a4fbd64a50fc8"),
540 QByteArrayLiteral(
"move"),
542 QByteArrayLiteral(
"dnd-move"),
546 QByteArrayLiteral(
"sw-resize"),
548 QByteArrayLiteral(
"size_bdiag"),
549 QByteArrayLiteral(
"fcf1c3c7cd4491d801f1e1c78f100000"),
550 QByteArrayLiteral(
"fd_double_arrow"),
551 QByteArrayLiteral(
"bottom_left_corner"),
555 QByteArrayLiteral(
"se-resize"),
557 QByteArrayLiteral(
"size_fdiag"),
558 QByteArrayLiteral(
"c7088f0f3e6c8088236ef8e1e3e70000"),
559 QByteArrayLiteral(
"bd_double_arrow"),
560 QByteArrayLiteral(
"bottom_right_corner"),
564 QByteArrayLiteral(
"ne-resize"),
566 QByteArrayLiteral(
"size_bdiag"),
567 QByteArrayLiteral(
"fcf1c3c7cd4491d801f1e1c78f100000"),
568 QByteArrayLiteral(
"fd_double_arrow"),
569 QByteArrayLiteral(
"top_right_corner"),
573 QByteArrayLiteral(
"nw-resize"),
575 QByteArrayLiteral(
"size_fdiag"),
576 QByteArrayLiteral(
"c7088f0f3e6c8088236ef8e1e3e70000"),
577 QByteArrayLiteral(
"bd_double_arrow"),
578 QByteArrayLiteral(
"top_left_corner"),
582 QByteArrayLiteral(
"n-resize"),
584 QByteArrayLiteral(
"size_ver"),
585 QByteArrayLiteral(
"00008160000006810000408080010102"),
586 QByteArrayLiteral(
"sb_v_double_arrow"),
587 QByteArrayLiteral(
"v_double_arrow"),
588 QByteArrayLiteral(
"col-resize"),
589 QByteArrayLiteral(
"top_side"),
593 QByteArrayLiteral(
"e-resize"),
595 QByteArrayLiteral(
"size_hor"),
596 QByteArrayLiteral(
"028006030e0e7ebffc7f7070c0600140"),
597 QByteArrayLiteral(
"sb_h_double_arrow"),
598 QByteArrayLiteral(
"h_double_arrow"),
599 QByteArrayLiteral(
"row-resize"),
600 QByteArrayLiteral(
"left_side"),
604 QByteArrayLiteral(
"s-resize"),
606 QByteArrayLiteral(
"size_ver"),
607 QByteArrayLiteral(
"00008160000006810000408080010102"),
608 QByteArrayLiteral(
"sb_v_double_arrow"),
609 QByteArrayLiteral(
"v_double_arrow"),
610 QByteArrayLiteral(
"col-resize"),
611 QByteArrayLiteral(
"bottom_side"),
615 QByteArrayLiteral(
"w-resize"),
617 QByteArrayLiteral(
"size_hor"),
618 QByteArrayLiteral(
"028006030e0e7ebffc7f7070c0600140"),
619 QByteArrayLiteral(
"sb_h_double_arrow"),
620 QByteArrayLiteral(
"h_double_arrow"),
621 QByteArrayLiteral(
"right_side"),
629 return QList<QByteArray>();
635 case Qt::ArrowCursor:
636 return QByteArrayLiteral(
"default");
637 case Qt::UpArrowCursor:
638 return QByteArrayLiteral(
"up-arrow");
639 case Qt::CrossCursor:
640 return QByteArrayLiteral(
"crosshair");
642 return QByteArrayLiteral(
"wait");
643 case Qt::IBeamCursor:
644 return QByteArrayLiteral(
"text");
645 case Qt::SizeVerCursor:
646 return QByteArrayLiteral(
"ns-resize");
647 case Qt::SizeHorCursor:
648 return QByteArrayLiteral(
"ew-resize");
649 case Qt::SizeBDiagCursor:
650 return QByteArrayLiteral(
"nesw-resize");
651 case Qt::SizeFDiagCursor:
652 return QByteArrayLiteral(
"nwse-resize");
653 case Qt::SizeAllCursor:
654 return QByteArrayLiteral(
"all-scroll");
655 case Qt::SplitVCursor:
656 return QByteArrayLiteral(
"row-resize");
657 case Qt::SplitHCursor:
658 return QByteArrayLiteral(
"col-resize");
659 case Qt::PointingHandCursor:
660 return QByteArrayLiteral(
"pointer");
661 case Qt::ForbiddenCursor:
662 return QByteArrayLiteral(
"not-allowed");
663 case Qt::OpenHandCursor:
664 return QByteArrayLiteral(
"grab");
665 case Qt::ClosedHandCursor:
666 return QByteArrayLiteral(
"grabbing");
667 case Qt::WhatsThisCursor:
668 return QByteArrayLiteral(
"help");
670 return QByteArrayLiteral(
"progress");
671 case Qt::DragMoveCursor:
672 return QByteArrayLiteral(
"move");
673 case Qt::DragCopyCursor:
674 return QByteArrayLiteral(
"copy");
675 case Qt::DragLinkCursor:
676 return QByteArrayLiteral(
"alias");
678 return QByteArrayLiteral(
"ne-resize");
680 return QByteArrayLiteral(
"n-resize");
682 return QByteArrayLiteral(
"nw-resize");
684 return QByteArrayLiteral(
"e-resize");
686 return QByteArrayLiteral(
"w-resize");
688 return QByteArrayLiteral(
"se-resize");
690 return QByteArrayLiteral(
"s-resize");
692 return QByteArrayLiteral(
"sw-resize");
720#include "moc_cursor.cpp"
void x11ConnectionChanged()
@ OperationModeWaylandOnly
KWin uses only Wayland.
virtual void doStopCursorTracking()
xcb_cursor_t x11Cursor(CursorShape shape)
static int defaultThemeSize()
virtual void doStopMousePolling()
void setSource(CursorSource *source)
int themeSize() const
The size of the currently used Cursor theme.
static QString defaultThemeName()
void startCursorTracking()
Enables tracking changes of cursor images.
void posChanged(const QPointF &pos)
const QString & themeName() const
The name of the currently used Cursor theme.
void updatePos(const QPointF &pos)
bool isOnOutput(Output *output) const
CursorSource * source() const
virtual void doStartMousePolling()
void cursorChanged()
Signal emitted when the cursor image changes.
void markAsRendered(std::chrono::milliseconds timestamp)
void stopCursorTracking()
Disables tracking changes of cursor images.
void setPos(const QPointF &pos)
virtual void doStartCursorTracking()
void rendered(std::chrono::milliseconds timestamp)
Wrapper round Qt::CursorShape with extensions enums into a single entity.
static QList< QByteArray > alternatives(const QByteArray &name)
QByteArray name() const
The name of a cursor shape in the theme.
void removeCursor(Cursor *cursor)
void addCursor(Cursor *cursor)
void positionChanged(Cursor *cursor, const QPointF &position)
void currentCursorChanged(Cursor *cursor)
bool isCursorHidden() const