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
This commit is contained in:
Martin Gräßlin 2016-02-10 14:40:56 +01:00
parent 16a33f662b
commit a311f9bfda
3 changed files with 50 additions and 36 deletions

View file

@ -434,13 +434,15 @@ void LockScreenTest::testKeyboard()
QCOMPARE(keyChangedSpy.at(1).at(2).value<quint32>(), quint32(2)); QCOMPARE(keyChangedSpy.at(1).at(2).value<quint32>(), quint32(2));
LOCK LOCK
QVERIFY(leftSpy.wait());
KEYPRESS(KEY_B); KEYPRESS(KEY_B);
KEYRELEASE(KEY_B); KEYRELEASE(KEY_B);
QVERIFY(leftSpy.wait());
QCOMPARE(leftSpy.count(), 1); QCOMPARE(leftSpy.count(), 1);
QCOMPARE(keyChangedSpy.count(), 2); QCOMPARE(keyChangedSpy.count(), 2);
UNLOCK UNLOCK
QVERIFY(enteredSpy.wait());
QCOMPARE(enteredSpy.count(), 2);
KEYPRESS(KEY_C); KEYPRESS(KEY_C);
QVERIFY(keyChangedSpy.wait()); QVERIFY(keyChangedSpy.wait());
QCOMPARE(keyChangedSpy.count(), 3); QCOMPARE(keyChangedSpy.count(), 3);

View file

@ -385,31 +385,12 @@ public:
if (!waylandServer()->isScreenLocked()) { if (!waylandServer()->isScreenLocked()) {
return false; return false;
} }
const ToplevelList &stacking = Workspace::self()->stackingOrder(); input()->updateKeyboardWindow();
auto seat = waylandServer()->seat(); if (!keyboardSurfaceAllowed()) {
seat->setTimestamp(event->timestamp()); // don't pass event to seat
Toplevel *found = nullptr; return true;
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());
} }
// if we reach this point it's time to unset auto seat = waylandServer()->seat();
seat->setFocusedKeyboardSurface(found ? found->surface() : nullptr);
switch (event->type()) { switch (event->type()) {
case QEvent::KeyPress: case QEvent::KeyPress:
seat->keyPressed(event->nativeScanCode()); seat->keyPressed(event->nativeScanCode());
@ -423,8 +404,8 @@ public:
return true; return true;
} }
private: private:
bool pointerSurfaceAllowed() const { bool surfaceAllowed(KWayland::Server::SurfaceInterface *(KWayland::Server::SeatInterface::*method)() const) const {
if (KWayland::Server::SurfaceInterface *s = waylandServer()->seat()->focusedPointerSurface()) { if (KWayland::Server::SurfaceInterface *s = (waylandServer()->seat()->*method)()) {
if (Toplevel *t = waylandServer()->findClient(s)) { if (Toplevel *t = waylandServer()->findClient(s)) {
return t->isLockScreen() || t->isInputMethod(); return t->isLockScreen() || t->isInputMethod();
} }
@ -432,6 +413,12 @@ private:
} }
return true; return true;
} }
bool pointerSurfaceAllowed() const {
return surfaceAllowed(&KWayland::Server::SeatInterface::focusedPointerSurface);
}
bool keyboardSurfaceAllowed() const {
return surfaceAllowed(&KWayland::Server::SeatInterface::focusedKeyboardSurface);
}
}; };
class EffectsFilter : public InputEventFilter { class EffectsFilter : public InputEventFilter {
@ -707,10 +694,7 @@ public:
return false; return false;
} }
auto seat = waylandServer()->seat(); auto seat = waylandServer()->seat();
if (workspace()->activeClient() && input()->updateKeyboardWindow();
(seat->focusedKeyboardSurface() != workspace()->activeClient()->surface())) {
seat->setFocusedKeyboardSurface(workspace()->activeClient()->surface());
}
seat->setTimestamp(event->timestamp()); seat->setTimestamp(event->timestamp());
switch (event->type()) { switch (event->type()) {
case QEvent::KeyPress: case QEvent::KeyPress:
@ -887,6 +871,7 @@ void InputRedirection::setupWorkspace()
connect(workspace(), &Workspace::configChanged, this, &InputRedirection::reconfigure); 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::updatePointerWindow);
connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &InputRedirection::updateKeyboardWindow);
} }
setupInputFilters(); setupInputFilters();
} }
@ -1300,11 +1285,37 @@ void InputRedirection::updateKeyboardWindow()
} }
if (auto seat = findSeat()) { if (auto seat = findSeat()) {
// TODO: this needs better integration // TODO: this needs better integration
Toplevel *t = workspace()->activeClient(); Toplevel *found = nullptr;
if (t && t->surface()) { if (waylandServer()->isScreenLocked()) {
if (t->surface() != seat->focusedKeyboardSurface()) { const ToplevelList &stacking = Workspace::self()->stackingOrder();
seat->setFocusedKeyboardSurface(t->surface()); 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);
} }
} }
} }

View file

@ -155,6 +155,8 @@ public:
qint32 touchId(quint32 internalId); qint32 touchId(quint32 internalId);
void removeTouchId(quint32 internalId); void removeTouchId(quint32 internalId);
void updateKeyboardWindow();
public Q_SLOTS: public Q_SLOTS:
void updatePointerWindow(); void updatePointerWindow();
@ -213,7 +215,6 @@ private:
void pointerInternalWindowVisibilityChanged(bool visible); void pointerInternalWindowVisibilityChanged(bool visible);
void installCursorFromDecoration(); void installCursorFromDecoration();
bool areButtonsPressed() const; bool areButtonsPressed() const;
void updateKeyboardWindow();
void setupWorkspace(); void setupWorkspace();
void reconfigure(); void reconfigure();
void setupInputFilters(); void setupInputFilters();