diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp
index 8092d3059a..ee611af600 100644
--- a/autotests/integration/internal_window.cpp
+++ b/autotests/integration/internal_window.cpp
@@ -28,8 +28,15 @@ along with this program. If not, see .
#include
#include
+#include
+#include
+#include
+#include
+
#include
+using namespace KWayland::Client;
+
namespace KWin
{
@@ -41,6 +48,7 @@ class InternalWindowTest : public QObject
private Q_SLOTS:
void initTestCase();
void init();
+ void cleanup();
void testEnterLeave();
void testPointerPressRelease();
void testPointerAxis();
@@ -173,6 +181,13 @@ void InternalWindowTest::initTestCase()
void InternalWindowTest::init()
{
Cursor::setPos(QPoint(1280, 512));
+ QVERIFY(Test::setupWaylandConnection(s_socketName, Test::AdditionalWaylandInterface::Seat));
+ QVERIFY(Test::waitForWaylandKeyboard());
+}
+
+void InternalWindowTest::cleanup()
+{
+ Test::destroyWaylandConnection();
}
void InternalWindowTest::testEnterLeave()
@@ -285,6 +300,9 @@ void InternalWindowTest::testKeyboard()
QVERIFY(releaseSpy.isValid());
QVERIFY(clientAddedSpy.wait());
QCOMPARE(clientAddedSpy.count(), 1);
+ auto internalClient = clientAddedSpy.first().first().value();
+ QVERIFY(internalClient);
+ QVERIFY(internalClient->isInternal());
quint32 timestamp = 1;
QFETCH(QPoint, cursorPos);
@@ -296,6 +314,51 @@ void InternalWindowTest::testKeyboard()
kwinApp()->platform()->keyboardKeyReleased(KEY_A, timestamp++);
QTRY_COMPARE(releaseSpy.count(), 1);
QCOMPARE(pressSpy.count(), 1);
+
+ // let's hide the window again and create a "real" window
+ win.hide();
+ clientAddedSpy.clear();
+
+ QScopedPointer keyboard(Test::waylandSeat()->createKeyboard());
+ QVERIFY(!keyboard.isNull());
+ QVERIFY(keyboard->isValid());
+ QSignalSpy enteredSpy(keyboard.data(), &Keyboard::entered);
+ QVERIFY(enteredSpy.isValid());
+ QSignalSpy leftSpy(keyboard.data(), &Keyboard::left);
+ QVERIFY(leftSpy.isValid());
+ QScopedPointer surface(Test::createSurface());
+ QScopedPointer shellSurface(Test::createShellSurface(Test::ShellSurfaceType::WlShell, surface.data()));
+
+ // now let's render
+ auto c = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
+ QVERIFY(c);
+ QVERIFY(c->isActive());
+
+ if (enteredSpy.isEmpty()) {
+ QVERIFY(enteredSpy.wait());
+ }
+ QCOMPARE(enteredSpy.count(), 1);
+
+ QSignalSpy windowShownSpy(internalClient, &ShellClient::windowShown);
+ QVERIFY(windowShownSpy.isValid());
+ win.show();
+ QCOMPARE(windowShownSpy.count(), 1);
+ QVERIFY(leftSpy.isEmpty());
+ QVERIFY(!leftSpy.wait(100));
+
+ // now let's trigger a key, which should result in a leave
+ kwinApp()->platform()->keyboardKeyPressed(KEY_A, timestamp++);
+ QVERIFY(leftSpy.wait());
+ QCOMPARE(pressSpy.count(), 2);
+
+ kwinApp()->platform()->keyboardKeyReleased(KEY_A, timestamp++);
+ QTRY_COMPARE(releaseSpy.count(), 2);
+
+ // after hiding the internal window, next key press should trigger an enter
+ win.hide();
+ kwinApp()->platform()->keyboardKeyPressed(KEY_A, timestamp++);
+ QVERIFY(enteredSpy.wait());
+ kwinApp()->platform()->keyboardKeyReleased(KEY_A, timestamp++);
}
void InternalWindowTest::testTouch()
diff --git a/autotests/integration/kwin_wayland_test.h b/autotests/integration/kwin_wayland_test.h
index 76ce6b3e49..81f6f80131 100644
--- a/autotests/integration/kwin_wayland_test.h
+++ b/autotests/integration/kwin_wayland_test.h
@@ -109,6 +109,7 @@ KWayland::Client::PlasmaWindowManagement *waylandWindowManagement();
bool waitForWaylandPointer();
bool waitForWaylandTouch();
+bool waitForWaylandKeyboard();
void flushWaylandConnection();
diff --git a/autotests/integration/test_helpers.cpp b/autotests/integration/test_helpers.cpp
index 1bf3d4afd5..9496f2a94f 100644
--- a/autotests/integration/test_helpers.cpp
+++ b/autotests/integration/test_helpers.cpp
@@ -247,6 +247,18 @@ bool waitForWaylandTouch()
return hasTouchSpy.wait();
}
+bool waitForWaylandKeyboard()
+{
+ if (!s_waylandConnection.seat) {
+ return false;
+ }
+ QSignalSpy hasKeyboardSpy(s_waylandConnection.seat, &Seat::hasKeyboardChanged);
+ if (!hasKeyboardSpy.isValid()) {
+ return false;
+ }
+ return hasKeyboardSpy.wait();
+}
+
void render(Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format)
{
QImage img(size, format);
diff --git a/input.cpp b/input.cpp
index 81630ad3dd..1bc5a71222 100644
--- a/input.cpp
+++ b/input.cpp
@@ -340,6 +340,7 @@ public:
if (!effects || !static_cast< EffectsHandlerImpl* >(effects)->hasKeyboardGrab()) {
return false;
}
+ waylandServer()->seat()->setFocusedKeyboardSurface(nullptr);
static_cast< EffectsHandlerImpl* >(effects)->grabbedKeyboardEvent(event);
return true;
}
@@ -487,7 +488,11 @@ class InternalWindowEventFilter : public InputEventFilter {
return false;
}
event->setAccepted(false);
- return QCoreApplication::sendEvent(found, event);
+ if (QCoreApplication::sendEvent(found, event)) {
+ waylandServer()->seat()->setFocusedKeyboardSurface(nullptr);
+ return true;
+ }
+ return false;
}
bool touchDown(quint32 id, const QPointF &pos, quint32 time) override {
@@ -718,6 +723,7 @@ public:
if (!TabBox::TabBox::self() || !TabBox::TabBox::self()->isGrabbed()) {
return false;
}
+ waylandServer()->seat()->setFocusedKeyboardSurface(nullptr);
if (event->type() == QEvent::KeyPress)
TabBox::TabBox::self()->keyPress(event->modifiers() | event->key());
return true;