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:
parent
36facda110
commit
521470b04a
2 changed files with 29 additions and 5 deletions
|
@ -44,6 +44,7 @@ private Q_SLOTS:
|
|||
void testEnterLeave();
|
||||
void testPointerPressRelease();
|
||||
void testPointerAxis();
|
||||
void testKeyboard_data();
|
||||
void testKeyboard();
|
||||
};
|
||||
|
||||
|
@ -237,6 +238,14 @@ void InternalWindowTest::testPointerAxis()
|
|||
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()
|
||||
{
|
||||
QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
|
||||
|
@ -252,7 +261,8 @@ void InternalWindowTest::testKeyboard()
|
|||
QCOMPARE(clientAddedSpy.count(), 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++);
|
||||
QTRY_COMPARE(pressSpy.count(), 1);
|
||||
|
|
22
input.cpp
22
input.cpp
|
@ -385,13 +385,27 @@ class InternalWindowEventFilter : public InputEventFilter {
|
|||
return e.isAccepted();
|
||||
}
|
||||
bool keyEvent(QKeyEvent *event) override {
|
||||
auto internal = input()->pointer()->internalWindow();
|
||||
if (!internal) {
|
||||
const auto &internalClients = waylandServer()->internalClients();
|
||||
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;
|
||||
}
|
||||
event->setAccepted(false);
|
||||
QCoreApplication::sendEvent(internal.data(), event);
|
||||
return true;
|
||||
return QCoreApplication::sendEvent(found, event);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue