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));
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);

View file

@ -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);
}
}
}

View file

@ -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();