summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qtwaylandscanner/qtwaylandscanner.cpp23
-rw-r--r--tests/auto/compositor/compositor/mockclient.cpp24
-rw-r--r--tests/auto/compositor/compositor/mockclient.h4
-rw-r--r--tests/auto/compositor/compositor/tst_compositor.cpp17
4 files changed, 62 insertions, 6 deletions
diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp
index ed36a138..d6a83dbb 100644
--- a/src/qtwaylandscanner/qtwaylandscanner.cpp
+++ b/src/qtwaylandscanner/qtwaylandscanner.cpp
@@ -504,6 +504,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" private:\n");
printf(" static void bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id);\n");
printf(" static void destroy_func(struct ::wl_resource *client_resource);\n");
+ printf(" static void display_destroy_func(struct ::wl_listener *listener, void *data);\n");
printf("\n");
printf(" Resource *bind(struct ::wl_client *client, uint32_t id, int version);\n");
printf(" Resource *bind(struct ::wl_resource *handle);\n");
@@ -527,6 +528,10 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" Resource *m_resource;\n");
printf(" struct ::wl_global *m_global;\n");
printf(" uint32_t m_globalVersion;\n");
+ printf(" struct DisplayDestroyedListener : ::wl_listener {\n");
+ printf(" %s *parent;\n", interfaceName);
+ printf(" };\n");
+ printf(" DisplayDestroyedListener m_displayDestroyedListener;\n");
printf(" };\n");
if (j < interfaces.size() - 1)
@@ -607,6 +612,13 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" %s::~%s()\n", interfaceName, interfaceName);
printf(" {\n");
+ printf(" for (auto resource : qAsConst(m_resource_map))\n");
+ printf(" wl_resource_set_implementation(resource->handle, nullptr, nullptr, nullptr);\n");
+ printf("\n");
+ printf(" if (m_global) {\n");
+ printf(" wl_global_destroy(m_global);\n");
+ printf(" wl_list_remove(&m_displayDestroyedListener.link);\n");
+ printf(" }\n");
printf(" }\n");
printf("\n");
@@ -642,6 +654,9 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" {\n");
printf(" m_global = wl_global_create(display, &::%s_interface, version, this, bind_func);\n", interfaceName);
printf(" m_globalVersion = version;\n");
+ printf(" m_displayDestroyedListener.notify = %s::display_destroy_func;\n", interfaceName);
+ printf(" m_displayDestroyedListener.parent = this;\n");
+ printf(" wl_display_add_destroy_listener(display, &m_displayDestroyedListener);\n");
printf(" }\n");
printf("\n");
@@ -674,6 +689,14 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr
printf(" }\n");
printf("\n");
+ printf(" void %s::display_destroy_func(struct ::wl_listener *listener, void *data)\n", interfaceName);
+ printf(" {\n");
+ printf(" Q_UNUSED(data);\n");
+ printf(" %s *that = static_cast<%s::DisplayDestroyedListener *>(listener)->parent;\n", interfaceName, interfaceName);
+ printf(" that->m_global = nullptr;\n");
+ printf(" }\n");
+ printf("\n");
+
printf(" void %s::destroy_func(struct ::wl_resource *client_resource)\n", interfaceName);
printf(" {\n");
printf(" Resource *resource = Resource::fromResource(client_resource);\n");
diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp
index 970890a6..85a89f04 100644
--- a/tests/auto/compositor/compositor/mockclient.cpp
+++ b/tests/auto/compositor/compositor/mockclient.cpp
@@ -42,13 +42,12 @@
const struct wl_registry_listener MockClient::registryListener = {
MockClient::handleGlobal,
- nullptr
+ MockClient::handleGlobalRemove
};
MockClient::MockClient()
: display(wl_display_connect("wayland-qt-test-0"))
, compositor(0)
- , output(0)
, registry(0)
, wlshell(0)
, xdgShell(nullptr)
@@ -75,9 +74,9 @@ MockClient::MockClient()
timeout.start();
do {
QCoreApplication::processEvents();
- } while (!(compositor && output) && timeout.elapsed() < 1000);
+ } while (!(compositor && !m_outputs.isEmpty()) && timeout.elapsed() < 1000);
- if (!compositor || !output)
+ if (!compositor || m_outputs.empty())
qFatal("MockClient(): failed to receive globals from display");
}
@@ -166,12 +165,18 @@ void MockClient::handleGlobal(void *data, wl_registry *registry, uint32_t id, co
resolve(data)->handleGlobal(id, QByteArray(interface));
}
+void MockClient::handleGlobalRemove(void *data, wl_registry *wl_registry, uint32_t id)
+{
+ resolve(data)->handleGlobalRemove(id);
+}
+
void MockClient::handleGlobal(uint32_t id, const QByteArray &interface)
{
if (interface == "wl_compositor") {
compositor = static_cast<wl_compositor *>(wl_registry_bind(registry, id, &wl_compositor_interface, 1));
} else if (interface == "wl_output") {
- output = static_cast<wl_output *>(wl_registry_bind(registry, id, &wl_output_interface, 2));
+ auto output = static_cast<wl_output *>(wl_registry_bind(registry, id, &wl_output_interface, 2));
+ m_outputs.append(output);
wl_output_add_listener(output, &outputListener, this);
} else if (interface == "wl_shm") {
shm = static_cast<wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface, 1));
@@ -187,6 +192,15 @@ void MockClient::handleGlobal(uint32_t id, const QByteArray &interface)
}
}
+void MockClient::handleGlobalRemove(uint32_t id)
+{
+ for (auto output : m_outputs) {
+ auto outputId = wl_proxy_get_id(reinterpret_cast<wl_proxy *>(output));
+ if (outputId == id)
+ m_outputs.removeAll(output);
+ }
+}
+
wl_surface *MockClient::createSurface()
{
flushDisplay();
diff --git a/tests/auto/compositor/compositor/mockclient.h b/tests/auto/compositor/compositor/mockclient.h
index 1881393a..7aa6a3b7 100644
--- a/tests/auto/compositor/compositor/mockclient.h
+++ b/tests/auto/compositor/compositor/mockclient.h
@@ -64,7 +64,7 @@ public:
wl_display *display;
wl_compositor *compositor;
- wl_output *output;
+ QVector<wl_output *> m_outputs;
wl_shm *shm;
wl_registry *registry;
wl_shell *wlshell;
@@ -96,6 +96,7 @@ private:
static MockClient *resolve(void *data) { return static_cast<MockClient *>(data); }
static const struct wl_registry_listener registryListener;
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version);
+ static void handleGlobalRemove(void *data, struct wl_registry *wl_registry, uint32_t id);
static int sourceUpdate(uint32_t mask, void *data);
static void outputGeometryEvent(void *data,
@@ -117,6 +118,7 @@ private:
static void outputScale(void *data, wl_output *output, int factor);
void handleGlobal(uint32_t id, const QByteArray &interface);
+ void handleGlobalRemove(uint32_t id);
static const wl_output_listener outputListener;
};
diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp
index c54903dc..39ae1d48 100644
--- a/tests/auto/compositor/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/compositor/tst_compositor.cpp
@@ -64,6 +64,7 @@ private slots:
void sizeFollowsWindow();
void mapSurface();
void frameCallback();
+ void removeOutput();
void advertisesXdgShellSupport();
void createsXdgSurfaces();
@@ -375,6 +376,22 @@ void tst_WaylandCompositor::frameCallback()
wl_surface_destroy(surface);
}
+void tst_WaylandCompositor::removeOutput()
+{
+ TestCompositor compositor;
+ QWindow window;
+ window.resize(800, 600);
+ auto output = new QWaylandOutput(&compositor, &window);
+
+ compositor.create();
+ MockClient client;
+ QTRY_COMPARE(client.m_outputs.size(), 2);
+
+ delete output;
+ compositor.flushClients();
+ QTRY_COMPARE(client.m_outputs.size(), 1);
+}
+
void tst_WaylandCompositor::seatCapabilities()
{
TestCompositor compositor;