diff --git a/autotests/client/test_wayland_seat.cpp b/autotests/client/test_wayland_seat.cpp --- a/autotests/client/test_wayland_seat.cpp +++ b/autotests/client/test_wayland_seat.cpp @@ -1563,7 +1563,8 @@ QSignalSpy serverSurfaceDestroyedSpy(serverSurface, &QObject::destroyed); QVERIFY(serverSurfaceDestroyedSpy.isValid()); delete s; - QVERIFY(serverSurfaceDestroyedSpy.wait()); + QVERIFY(leftSpy.wait()); + QCOMPARE(serverSurfaceDestroyedSpy.count(), 1); QVERIFY(!m_seatInterface->focusedKeyboardSurface()); QVERIFY(!m_seatInterface->focusedKeyboard()); QVERIFY(!serverKeyboard->focusedSurface()); diff --git a/src/server/keyboard_interface.cpp b/src/server/keyboard_interface.cpp --- a/src/server/keyboard_interface.cpp +++ b/src/server/keyboard_interface.cpp @@ -121,9 +121,12 @@ if (!d->focusedSurface) { return; } - d->destroyConnection = connect(d->focusedSurface, &QObject::destroyed, this, + d->destroyConnection = connect(d->focusedSurface, &Resource::aboutToBeUnbound, this, [this] { Q_D(); + if (d->resource) { + wl_keyboard_send_leave(d->resource, d->global->display()->nextSerial(), d->focusedSurface->resource()); + } d->focusedSurface = nullptr; d->focusedChildSurface.clear(); } diff --git a/src/server/resource.h b/src/server/resource.h --- a/src/server/resource.h +++ b/src/server/resource.h @@ -81,6 +81,16 @@ * @since 5.24 **/ void unbound(); + /** + * This signal is emitted when the client is in the process of unbinding the Resource. + * In opposite to @link{unbound} the @link{resource} is still valid and allows to perform + * cleanup tasks. Example: send a keyboard leave for the Surface which is in the process of + * getting destroyed. + * + * @see unbound + * @since 5.37 + **/ + void aboutToBeUnbound(); protected: class Private; diff --git a/src/server/resource.cpp b/src/server/resource.cpp --- a/src/server/resource.cpp +++ b/src/server/resource.cpp @@ -63,6 +63,7 @@ void Resource::Private::unbind(wl_resource *r) { Private *p = cast(r); + emit p->q->aboutToBeUnbound(); p->resource = nullptr; emit p->q->unbound(); p->q->deleteLater();