Improve the escape key handling for breaking constrained pointers

Summary:
So far KWin started to filter out the escape key as soon as it gets
pressed. This was done by unsetting keyboard focus. The idea was to
reset keyboard focus when it is only a short press and that then the
keyboard state is correct for the application. But in practice this
does not work. The only application currently supporting pointer
constraints (Xwayland) does not do anything on a key which is pressed
when gaining keyboard focus. The result is escape not working in
pointer constrained Xwayland windows.

This change addresses this problem by changing the interaction to only
unset keyboard focus when our break constraints condition is met. This
should also result in the application not handling the key release, but
it means it gets the key press. Unfortunately I don't have a good way
to test.

BUG: 378452

Test Plan: None

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D5488
This commit is contained in:
Martin Gräßlin 2017-04-18 07:10:46 +02:00 committed by Martin Flöser
parent 52b21b1142
commit 229be65e40
3 changed files with 9 additions and 6 deletions

View file

@ -340,16 +340,17 @@ void TestPointerConstraints::testBreakConstrainedPointer()
// now try to break // now try to break
quint32 timestamp = 0; quint32 timestamp = 0;
kwinApp()->platform()->keyboardKeyPressed(KEY_ESC, timestamp++); kwinApp()->platform()->keyboardKeyPressed(KEY_ESC, timestamp++);
QVERIFY(keyboardLeftSpy.wait()); QVERIFY(keyChangedSpy.wait());
// and just waiting should break constrain // and just waiting should break constrain
QVERIFY(unlockedSpy.wait()); QVERIFY(unlockedSpy.wait());
QCOMPARE(keyboardLeftSpy.count(), 1);
QCOMPARE(input()->pointer()->isConstrained(), false); QCOMPARE(input()->pointer()->isConstrained(), false);
// and should enter again // and should enter again
QTRY_COMPARE(keyboardEnteredSpy.count(), 2); QTRY_COMPARE(keyboardEnteredSpy.count(), 2);
QCOMPARE(waylandServer()->seat()->focusedKeyboardSurface(), c->surface()); QCOMPARE(waylandServer()->seat()->focusedKeyboardSurface(), c->surface());
kwinApp()->platform()->keyboardKeyReleased(KEY_ESC, timestamp++); kwinApp()->platform()->keyboardKeyReleased(KEY_ESC, timestamp++);
QVERIFY(!keyChangedSpy.wait()); QVERIFY(!keyChangedSpy.wait());
QVERIFY(keyChangedSpy.isEmpty()); QCOMPARE(keyChangedSpy.count(), 1);
// now lock again // now lock again
// need to move out and in // need to move out and in

View file

@ -403,6 +403,10 @@ public:
{ {
QObject::connect(m_timer.data(), &QTimer::timeout, QObject::connect(m_timer.data(), &QTimer::timeout,
[this] { [this] {
if (waylandServer()) {
// break keyboard focus, this cancels the pressed ESC
waylandServer()->seat()->setFocusedKeyboardSurface(nullptr);
}
input()->pointer()->breakPointerConstraints(); input()->pointer()->breakPointerConstraints();
input()->pointer()->blockPointerConstraints(); input()->pointer()->blockPointerConstraints();
// TODO: show notification // TODO: show notification
@ -434,10 +438,8 @@ public:
static_cast<KeyEvent*>(event)->modifiersRelevantForGlobalShortcuts() == Qt::KeyboardModifiers()) { static_cast<KeyEvent*>(event)->modifiersRelevantForGlobalShortcuts() == Qt::KeyboardModifiers()) {
// TODO: don't hard code // TODO: don't hard code
m_timer->start(3000); m_timer->start(3000);
input()->keyboard()->update();
m_keyCode = event->nativeScanCode(); m_keyCode = event->nativeScanCode();
passToWaylandServer(event); return false;
return true;
} }
} }
return false; return false;

View file

@ -598,7 +598,7 @@ void KeyboardInputRedirection::update()
break; break;
} while (it != stacking.begin()); } while (it != stacking.begin());
} }
} else if (!input()->isSelectingWindow() && !input()->isBreakingPointerConstraints()) { } else if (!input()->isSelectingWindow()) {
found = workspace()->activeClient(); found = workspace()->activeClient();
} }
if (found && found->surface()) { if (found && found->surface()) {