diff --git a/autotests/wayland/lockscreen.cpp b/autotests/wayland/lockscreen.cpp index c7b304a14e..831503d94e 100644 --- a/autotests/wayland/lockscreen.cpp +++ b/autotests/wayland/lockscreen.cpp @@ -434,13 +434,15 @@ void LockScreenTest::testKeyboard() QCOMPARE(keyChangedSpy.at(1).at(2).value(), quint32(2)); LOCK + QVERIFY(leftSpy.wait()); KEYPRESS(KEY_B); KEYRELEASE(KEY_B); - QVERIFY(leftSpy.wait()); QCOMPARE(leftSpy.count(), 1); QCOMPARE(keyChangedSpy.count(), 2); UNLOCK + QVERIFY(enteredSpy.wait()); + QCOMPARE(enteredSpy.count(), 2); KEYPRESS(KEY_C); QVERIFY(keyChangedSpy.wait()); QCOMPARE(keyChangedSpy.count(), 3); diff --git a/input.cpp b/input.cpp index 81ec186e30..c501261e8c 100644 --- a/input.cpp +++ b/input.cpp @@ -385,31 +385,12 @@ public: if (!waylandServer()->isScreenLocked()) { return false; } - const ToplevelList &stacking = Workspace::self()->stackingOrder(); - auto seat = waylandServer()->seat(); - seat->setTimestamp(event->timestamp()); - Toplevel *found = nullptr; - if (!stacking.isEmpty()) { - auto it = stacking.end(); - do { - --it; - Toplevel *t = (*it); - if (t->isDeleted()) { - // a deleted window doesn't get mouse events - continue; - } - if (!t->isLockScreen()) { - continue; - } - if (!t->readyForPainting()) { - continue; - } - found = t; - break; - } while (it != stacking.begin()); + input()->updateKeyboardWindow(); + if (!keyboardSurfaceAllowed()) { + // don't pass event to seat + return true; } - // if we reach this point it's time to unset - seat->setFocusedKeyboardSurface(found ? found->surface() : nullptr); + auto seat = waylandServer()->seat(); switch (event->type()) { case QEvent::KeyPress: seat->keyPressed(event->nativeScanCode()); @@ -423,8 +404,8 @@ public: return true; } private: - bool pointerSurfaceAllowed() const { - if (KWayland::Server::SurfaceInterface *s = waylandServer()->seat()->focusedPointerSurface()) { + bool surfaceAllowed(KWayland::Server::SurfaceInterface *(KWayland::Server::SeatInterface::*method)() const) const { + if (KWayland::Server::SurfaceInterface *s = (waylandServer()->seat()->*method)()) { if (Toplevel *t = waylandServer()->findClient(s)) { return t->isLockScreen() || t->isInputMethod(); } @@ -432,6 +413,12 @@ private: } return true; } + bool pointerSurfaceAllowed() const { + return surfaceAllowed(&KWayland::Server::SeatInterface::focusedPointerSurface); + } + bool keyboardSurfaceAllowed() const { + return surfaceAllowed(&KWayland::Server::SeatInterface::focusedKeyboardSurface); + } }; class EffectsFilter : public InputEventFilter { @@ -707,10 +694,7 @@ public: return false; } auto seat = waylandServer()->seat(); - if (workspace()->activeClient() && - (seat->focusedKeyboardSurface() != workspace()->activeClient()->surface())) { - seat->setFocusedKeyboardSurface(workspace()->activeClient()->surface()); - } + input()->updateKeyboardWindow(); seat->setTimestamp(event->timestamp()); switch (event->type()) { case QEvent::KeyPress: @@ -887,6 +871,7 @@ void InputRedirection::setupWorkspace() connect(workspace(), &Workspace::configChanged, this, &InputRedirection::reconfigure); connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &InputRedirection::updatePointerWindow); + connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &InputRedirection::updateKeyboardWindow); } setupInputFilters(); } @@ -1300,11 +1285,37 @@ void InputRedirection::updateKeyboardWindow() } if (auto seat = findSeat()) { // TODO: this needs better integration - Toplevel *t = workspace()->activeClient(); - if (t && t->surface()) { - if (t->surface() != seat->focusedKeyboardSurface()) { - seat->setFocusedKeyboardSurface(t->surface()); + Toplevel *found = nullptr; + if (waylandServer()->isScreenLocked()) { + const ToplevelList &stacking = Workspace::self()->stackingOrder(); + if (!stacking.isEmpty()) { + auto it = stacking.end(); + do { + --it; + Toplevel *t = (*it); + if (t->isDeleted()) { + // a deleted window doesn't get mouse events + continue; + } + if (!t->isLockScreen()) { + continue; + } + if (!t->readyForPainting()) { + continue; + } + found = t; + break; + } while (it != stacking.begin()); } + } else { + found = workspace()->activeClient(); + } + if (found && found->surface()) { + if (found->surface() != seat->focusedKeyboardSurface()) { + seat->setFocusedKeyboardSurface(found->surface()); + } + } else { + seat->setFocusedKeyboardSurface(nullptr); } } } diff --git a/input.h b/input.h index 03e02cf4c4..5820228d6f 100644 --- a/input.h +++ b/input.h @@ -155,6 +155,8 @@ public: qint32 touchId(quint32 internalId); void removeTouchId(quint32 internalId); + void updateKeyboardWindow(); + public Q_SLOTS: void updatePointerWindow(); @@ -213,7 +215,6 @@ private: void pointerInternalWindowVisibilityChanged(bool visible); void installCursorFromDecoration(); bool areButtonsPressed() const; - void updateKeyboardWindow(); void setupWorkspace(); void reconfigure(); void setupInputFilters();