Improve keyboard handling for internal windows

So far the key handler in the InternalWindowEventFilter used the
PointerInputRedirection's internal window. This had the result that
key events were only delivered to an internal window if the window
was under the cursor.

This change tries sending the event to the latest created and visible
window. Thus e.g. with nested context menus it goes to the current
sub menu as expected. The return value of sendEvent is used to filter
out the event.
This commit is contained in:
Martin Gräßlin 2016-02-17 13:34:24 +01:00
parent 36facda110
commit 521470b04a
2 changed files with 29 additions and 5 deletions

View file

@ -44,6 +44,7 @@ private Q_SLOTS:
void testEnterLeave(); void testEnterLeave();
void testPointerPressRelease(); void testPointerPressRelease();
void testPointerAxis(); void testPointerAxis();
void testKeyboard_data();
void testKeyboard(); void testKeyboard();
}; };
@ -237,6 +238,14 @@ void InternalWindowTest::testPointerAxis()
QTRY_COMPARE(wheelSpy.count(), 2); QTRY_COMPARE(wheelSpy.count(), 2);
} }
void InternalWindowTest::testKeyboard_data()
{
QTest::addColumn<QPoint>("cursorPos");
QTest::newRow("on Window") << QPoint(50, 50);
QTest::newRow("outside Window") << QPoint(250, 250);
}
void InternalWindowTest::testKeyboard() void InternalWindowTest::testKeyboard()
{ {
QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded); QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
@ -252,7 +261,8 @@ void InternalWindowTest::testKeyboard()
QCOMPARE(clientAddedSpy.count(), 1); QCOMPARE(clientAddedSpy.count(), 1);
quint32 timestamp = 1; quint32 timestamp = 1;
waylandServer()->backend()->pointerMotion(QPoint(50, 50), timestamp++); QFETCH(QPoint, cursorPos);
waylandServer()->backend()->pointerMotion(cursorPos, timestamp++);
waylandServer()->backend()->keyboardKeyPressed(KEY_A, timestamp++); waylandServer()->backend()->keyboardKeyPressed(KEY_A, timestamp++);
QTRY_COMPARE(pressSpy.count(), 1); QTRY_COMPARE(pressSpy.count(), 1);

View file

@ -385,13 +385,27 @@ class InternalWindowEventFilter : public InputEventFilter {
return e.isAccepted(); return e.isAccepted();
} }
bool keyEvent(QKeyEvent *event) override { bool keyEvent(QKeyEvent *event) override {
auto internal = input()->pointer()->internalWindow(); const auto &internalClients = waylandServer()->internalClients();
if (!internal) { if (internalClients.isEmpty()) {
return false;
}
QWindow *found = nullptr;
auto it = internalClients.end();
do {
it--;
if (QWindow *w = (*it)->internalWindow()) {
if (!w->isVisible()) {
continue;
}
found = w;
break;
}
} while (it != internalClients.begin());
if (!found) {
return false; return false;
} }
event->setAccepted(false); event->setAccepted(false);
QCoreApplication::sendEvent(internal.data(), event); return QCoreApplication::sendEvent(found, event);
return true;
} }
}; };