From a311f9bfda412b74bdf243b1988c0550250351ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 10 Feb 2016 14:40:56 +0100 Subject: [PATCH] Add check for lock screen in InputRedirection::updateKeyboardWindow Instead of only making the active client the focused keyboard surface, the method now also performs the lock screen security restriction. Also just like udatePointerWindow the method becomes public, so that it can be used from the LockScreenEventFilter and is connected for lock state changes. This means as soon as the screen locks the current focused keyboard surface will get a leave event and get an enter event once the screen unlocks. The auto test is adjusted to verify these new conditions. Reviewed-By: Bhushan Shah --- autotests/wayland/lockscreen.cpp | 4 +- input.cpp | 79 ++++++++++++++++++-------------- input.h | 3 +- 3 files changed, 50 insertions(+), 36 deletions(-) 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();