From 16a33f662bf749303964d284ce4302c3b143d37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 9 Feb 2016 17:18:58 +0100 Subject: [PATCH] Improve lock screen interaction for pointer in InputRedirection InputRedirection connects to lockStateChanged to udate the current pointer window. This way we can ensure that the current pointer surface gets reset as soon as the screen locks (c.f. the expect fail in the autotest) and also that it restores to the surface under the mouse once the screen is unlocked. The relevant code was not yet lock screen aware and performed an early exit. Part of the code was fine, e.g. findToplevel is lock screen aware. So this change adjusts the methods for updating the internal window and decoration to be lock screen aware, that is they get reset. With that updatePointerWindow is also lock screen aware. Thus the LockScreenFilter can also use updatePointerWindow just like the normal handling and does not need to reimplement parts of it. As it now relies on other code being correct it has an additional check to verify that the current pointer surface is a surface which is allowed to get events. If it isn't the events are not forwarded. Reviewed-By: Bhushan Shah --- autotests/wayland/lockscreen.cpp | 11 ++---- input.cpp | 62 +++++++++++++++++++------------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/autotests/wayland/lockscreen.cpp b/autotests/wayland/lockscreen.cpp index 4d40bb25a8..c7b304a14e 100644 --- a/autotests/wayland/lockscreen.cpp +++ b/autotests/wayland/lockscreen.cpp @@ -300,16 +300,13 @@ void LockScreenTest::testPointer() LOCK - QEXPECT_FAIL("", "Adding the lock screen window should send left event", Continue); QVERIFY(leftSpy.wait(100)); - QEXPECT_FAIL("", "Adding the lock screen window should send left event", Continue); QCOMPARE(leftSpy.count(), 1); // simulate moving out in and out again MOTION(c->geometry().center()); MOTION(c->geometry().bottomRight() + QPoint(100, 100)); MOTION(c->geometry().bottomRight() + QPoint(100, 100)); - QEXPECT_FAIL("", "Adding the lock screen window should send left event", Continue); QVERIFY(!leftSpy.wait(100)); QCOMPARE(leftSpy.count(), 1); QCOMPARE(enteredSpy.count(), 1); @@ -319,16 +316,14 @@ void LockScreenTest::testPointer() // and unlock UNLOCK - QEXPECT_FAIL("", "Focus doesn't move back on surface removal", Continue); QVERIFY(enteredSpy.wait(100)); - QEXPECT_FAIL("", "Focus doesn't move back on surface removal", Continue); QCOMPARE(enteredSpy.count(), 2); // move on the window MOTION(c->geometry().center() + QPoint(100, 100)); + QVERIFY(leftSpy.wait()); MOTION(c->geometry().center()); - QEXPECT_FAIL("", "Focus doesn't move back on surface removal", Continue); - QVERIFY(!enteredSpy.wait(100)); - QCOMPARE(enteredSpy.count(), 2); + QVERIFY(enteredSpy.wait()); + QCOMPARE(enteredSpy.count(), 3); } void LockScreenTest::testPointerButton() diff --git a/input.cpp b/input.cpp index 0791d871b2..81ec186e30 100644 --- a/input.cpp +++ b/input.cpp @@ -49,6 +49,9 @@ along with this program. If not, see . #include // KDE #include +//screenlocker +#include + #include #include // system @@ -352,19 +355,16 @@ public: auto seat = waylandServer()->seat(); seat->setTimestamp(event->timestamp()); if (event->type() == QEvent::MouseMove) { - Toplevel *t = input()->findToplevel(event->screenPos().toPoint()); - if (t && t->surface()) { - seat->setFocusedPointerSurface(t->surface(), t->inputTransformation()); - } else { - seat->setFocusedPointerSurface(nullptr); + if (event->buttons() == Qt::NoButton) { + // update pointer window only if no button is pressed + input()->updatePointerWindow(); + } + if (pointerSurfaceAllowed()) { + seat->setPointerPos(event->screenPos().toPoint()); } - seat->setPointerPos(event->screenPos().toPoint()); } else if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { - if (KWayland::Server::SurfaceInterface *s = seat->focusedPointerSurface()) { - Toplevel *t = waylandServer()->findClient(s); - if (t->isLockScreen() || t->isInputMethod()) { - event->type() == QEvent::MouseButtonPress ? seat->pointerButtonPressed(nativeButton) : seat->pointerButtonReleased(nativeButton); - } + if (pointerSurfaceAllowed()) { + event->type() == QEvent::MouseButtonPress ? seat->pointerButtonPressed(nativeButton) : seat->pointerButtonReleased(nativeButton); } } return true; @@ -374,13 +374,10 @@ public: return false; } auto seat = waylandServer()->seat(); - if (KWayland::Server::SurfaceInterface *s = seat->focusedPointerSurface()) { - Toplevel *t = waylandServer()->findClient(s); - if (t->isLockScreen() || t->isInputMethod()) { - seat->setTimestamp(event->timestamp()); - const Qt::Orientation orientation = event->angleDelta().x() == 0 ? Qt::Vertical : Qt::Horizontal; - seat->pointerAxis(orientation, orientation == Qt::Horizontal ? event->angleDelta().x() : event->angleDelta().y()); - } + if (pointerSurfaceAllowed()) { + seat->setTimestamp(event->timestamp()); + const Qt::Orientation orientation = event->angleDelta().x() == 0 ? Qt::Vertical : Qt::Horizontal; + seat->pointerAxis(orientation, orientation == Qt::Horizontal ? event->angleDelta().x() : event->angleDelta().y()); } return true; } @@ -425,6 +422,16 @@ public: } return true; } +private: + bool pointerSurfaceAllowed() const { + if (KWayland::Server::SurfaceInterface *s = waylandServer()->seat()->focusedPointerSurface()) { + if (Toplevel *t = waylandServer()->findClient(s)) { + return t->isLockScreen() || t->isInputMethod(); + } + return false; + } + return true; + } }; class EffectsFilter : public InputEventFilter { @@ -878,6 +885,8 @@ void InputRedirection::setupWorkspace() } ); connect(workspace(), &Workspace::configChanged, this, &InputRedirection::reconfigure); + + connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &InputRedirection::updatePointerWindow); } setupInputFilters(); } @@ -1034,9 +1043,6 @@ void InputRedirection::setupLibInputWithScreens() void InputRedirection::updatePointerWindow() { - if (waylandServer() && waylandServer()->isScreenLocked()) { - return; - } // TODO: handle pointer grab aka popups Toplevel *t = findToplevel(m_globalPointer.toPoint()); updatePointerInternalWindow(); @@ -1090,6 +1096,7 @@ void InputRedirection::updatePointerWindow() void InputRedirection::updatePointerDecoration(Toplevel *t) { const auto oldDeco = m_pointerDecoration; + bool needsReset = waylandServer() && waylandServer()->isScreenLocked(); if (AbstractClient *c = dynamic_cast(t)) { // check whether it's on a Decoration if (c->decoratedClient()) { @@ -1097,12 +1104,15 @@ void InputRedirection::updatePointerDecoration(Toplevel *t) if (!clientRect.contains(m_globalPointer.toPoint())) { m_pointerDecoration = c->decoratedClient(); } else { - m_pointerDecoration.clear(); + needsReset = true; } } else { - m_pointerDecoration.clear(); + needsReset = true; } } else { + needsReset = true; + } + if (needsReset) { m_pointerDecoration.clear(); } @@ -1128,6 +1138,7 @@ void InputRedirection::updatePointerInternalWindow() const auto oldInternalWindow = m_pointerInternalWindow; if (waylandServer()) { bool found = false; + bool needsReset = waylandServer()->isScreenLocked(); const auto &internalClients = waylandServer()->internalClients(); const bool change = m_pointerInternalWindow.isNull() || !(m_pointerInternalWindow->flags().testFlag(Qt::Popup) && m_pointerInternalWindow->isVisible()); if (!internalClients.isEmpty() && change) { @@ -1146,9 +1157,12 @@ void InputRedirection::updatePointerInternalWindow() } } while (it != internalClients.begin()); if (!found) { - m_pointerInternalWindow.clear(); + needsReset = true; } } + if (needsReset) { + m_pointerInternalWindow.clear(); + } } if (oldInternalWindow != m_pointerInternalWindow) { // changed