diff --git a/autotests/integration/start_test.cpp b/autotests/integration/start_test.cpp --- a/autotests/integration/start_test.cpp +++ b/autotests/integration/start_test.cpp @@ -43,6 +43,7 @@ void testScreens(); void testNoWindowsAtStart(); void testCreateWindow(); + void testHideShowCursor(); }; void StartTest::initTestCase() @@ -129,6 +130,33 @@ QVERIFY(waylandServer()->clients().isEmpty()); } + +void StartTest::testHideShowCursor() +{ + QCOMPARE(kwinApp()->platform()->isCursorHidden(), false); + kwinApp()->platform()->hideCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), true); + kwinApp()->platform()->showCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), false); + + + kwinApp()->platform()->hideCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), true); + kwinApp()->platform()->hideCursor(); + kwinApp()->platform()->hideCursor(); + kwinApp()->platform()->hideCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), true); + + kwinApp()->platform()->showCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), true); + kwinApp()->platform()->showCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), true); + kwinApp()->platform()->showCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), true); + kwinApp()->platform()->showCursor(); + QCOMPARE(kwinApp()->platform()->isCursorHidden(), false); +} + } WAYLANDTEST_MAIN(KWin::StartTest) diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -176,6 +176,34 @@ **/ virtual PlatformCursorImage cursorImage() const; + /** + * The Platform cursor image should be hidden. + * @see showCursor + * @see doHideCursor + * @see isCursorHidden + * @since 5.9 + **/ + void hideCursor(); + + /** + * The Platform cursor image should be shown again. + * @see hideCursor + * @see doShowCursor + * @see isCursorHidden + * @since 5.9 + **/ + void showCursor(); + + /** + * Whether the cursor is currently hidden. + * @see showCursor + * @see hideCursor + * @since 5.9 + **/ + bool isCursorHidden() const { + return m_hideCursorCounter > 0; + } + bool handlesOutputs() const { return m_handlesOutputs; } @@ -248,6 +276,30 @@ m_pointerWarping = set; } + /** + * Actual platform specific way to hide the cursor. + * Sub-classes need to implement if they support hiding the cursor. + * + * This method is invoked by hideCursor if the cursor needs to be hidden. + * The default implementation does nothing. + * + * @see doShowCursor + * @see hideCursor + * @see showCursor + **/ + virtual void doHideCursor(); + /** + * Actual platform specific way to show the cursor. + * Sub-classes need to implement if they support showing the cursor. + * + * This method is invoked by showCursor if the cursor needs to be shown again. + * + * @see doShowCursor + * @see hideCursor + * @see showCursor + **/ + virtual void doShowCursor(); + private: void triggerCursorRepaint(); bool m_softWareCursor = false; @@ -262,6 +314,7 @@ bool m_outputsEnabled = true; int m_initialOutputCount = 1; EGLDisplay m_eglDisplay; + int m_hideCursorCounter = 0; }; } diff --git a/platform.cpp b/platform.cpp --- a/platform.cpp +++ b/platform.cpp @@ -59,6 +59,30 @@ return PlatformCursorImage(softwareCursor(), softwareCursorHotspot()); } +void Platform::hideCursor() +{ + m_hideCursorCounter++; + if (m_hideCursorCounter == 1) { + doHideCursor(); + } +} + +void Platform::doHideCursor() +{ +} + +void Platform::showCursor() +{ + m_hideCursorCounter--; + if (m_hideCursorCounter == 0) { + doShowCursor(); + } +} + +void Platform::doShowCursor() +{ +} + Screens *Platform::createScreens(QObject *parent) { Q_UNUSED(parent) diff --git a/plugins/platforms/drm/drm_backend.h b/plugins/platforms/drm/drm_backend.h --- a/plugins/platforms/drm/drm_backend.h +++ b/plugins/platforms/drm/drm_backend.h @@ -113,6 +113,11 @@ void outputRemoved(KWin::DrmOutput *output); void outputAdded(KWin::DrmOutput *output); +protected: + + void doHideCursor() override; + void doShowCursor() override; + private: static void pageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data); void openDrm(); @@ -122,7 +127,6 @@ void queryResources(); void setCursor(); void updateCursor(); - void hideCursor(); void moveCursor(); void initCursor(); quint32 findCrtc(drmModeRes *res, drmModeConnector *connector, bool *ok = nullptr); diff --git a/plugins/platforms/drm/drm_backend.cpp b/plugins/platforms/drm/drm_backend.cpp --- a/plugins/platforms/drm/drm_backend.cpp +++ b/plugins/platforms/drm/drm_backend.cpp @@ -619,9 +619,12 @@ if (usesSoftwareCursor()) { return; } + if (isCursorHidden()) { + return; + } const QImage &cursorImage = softwareCursor(); if (cursorImage.isNull()) { - hideCursor(); + doHideCursor(); return; } QImage *c = m_cursor[m_cursorIndex]->image(); @@ -635,7 +638,12 @@ moveCursor(); } -void DrmBackend::hideCursor() +void DrmBackend::doShowCursor() +{ + updateCursor(); +} + +void DrmBackend::doHideCursor() { if (!m_cursorEnabled) { return; @@ -648,7 +656,7 @@ void DrmBackend::moveCursor() { const QPoint p = Cursor::pos() - softwareCursorHotspot(); - if (!m_cursorEnabled) { + if (!m_cursorEnabled || isCursorHidden()) { return; } for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -51,6 +51,10 @@ PlatformCursorImage cursorImage() const override; +protected: + void doHideCursor() override; + void doShowCursor() override; + private: /** * Tests whether GLX is supported and returns @c true diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -262,4 +262,14 @@ return PlatformCursorImage(qcursorimg.copy(), QPoint(cursor->xhot, cursor->yhot)); } +void X11StandalonePlatform::doHideCursor() +{ + xcb_xfixes_hide_cursor(kwinApp()->x11Connection(), kwinApp()->x11RootWindow()); +} + +void X11StandalonePlatform::doShowCursor() +{ + xcb_xfixes_show_cursor(kwinApp()->x11Connection(), kwinApp()->x11RootWindow()); +} + }