Add wrapper for wl_global_remove
Summary: Removes the Global from the registry, but does not delete the underlying wl_global Removal of a global is racey in wayland. A client could be trying to bind at that moment. Typically globals are static for the lifespan of the compositor, however there are exceptions For those cases this call will can remove the global from the registry, but still keep the wl_global instance alive and handling bind requests. The compositor can then remove the Global wrapper (this object) deleting the wl_global after an arbitrary delay or keep it around for re-use for the duration of the compositor. Test Plan: Unit test Made blur global outlive BlurEffect - no longer disconnects plasma on config changes Reviewers: #plasma, apol Reviewed By: apol Subscribers: kde-frameworks-devel Tags: #frameworks Differential Revision: https://phabricator.kde.org/D28883
This commit is contained in:
parent
ad44b0f08c
commit
78a8b6877c
3 changed files with 66 additions and 1 deletions
|
@ -31,6 +31,7 @@ private Q_SLOTS:
|
||||||
|
|
||||||
void testCreate();
|
void testCreate();
|
||||||
void testSurfaceDestroy();
|
void testSurfaceDestroy();
|
||||||
|
void testGlobalDestroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KWayland::Server::Display *m_display;
|
KWayland::Server::Display *m_display;
|
||||||
|
@ -197,5 +198,41 @@ void TestBlur::testSurfaceDestroy()
|
||||||
QVERIFY(blurDestroyedSpy.wait());
|
QVERIFY(blurDestroyedSpy.wait());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TestBlur::testGlobalDestroy()
|
||||||
|
{
|
||||||
|
Registry registry;
|
||||||
|
QSignalSpy blurAnnouncedSpy(®istry, &Registry::blurAnnounced);
|
||||||
|
QSignalSpy blurRemovedSpy(®istry, &Registry::blurRemoved);
|
||||||
|
|
||||||
|
registry.setEventQueue(m_queue);
|
||||||
|
|
||||||
|
registry.create(m_connection->display());
|
||||||
|
QVERIFY(registry.isValid());
|
||||||
|
registry.setup();
|
||||||
|
|
||||||
|
QVERIFY(blurAnnouncedSpy.wait());
|
||||||
|
|
||||||
|
QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWayland::Server::CompositorInterface::surfaceCreated);
|
||||||
|
QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
|
||||||
|
QVERIFY(serverSurfaceCreated.wait());
|
||||||
|
|
||||||
|
auto serverSurface = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>();
|
||||||
|
QSignalSpy blurChanged(serverSurface, &KWayland::Server::SurfaceInterface::blurChanged);
|
||||||
|
|
||||||
|
m_blurManagerInterface->remove();
|
||||||
|
|
||||||
|
// we've deleted our global, but the clients have some operations in flight as they haven't processed this yet
|
||||||
|
// when we process them, we should not throw an error and kill the client
|
||||||
|
|
||||||
|
QScopedPointer<KWayland::Client::Blur> blur(m_blurManager->createBlur(surface.data()));
|
||||||
|
blur->setRegion(m_compositor->createRegion(QRegion(0, 0, 10, 20), nullptr));
|
||||||
|
blur->commit();
|
||||||
|
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||||
|
|
||||||
|
// client finally sees the blur is gone
|
||||||
|
QVERIFY(blurRemovedSpy.wait());
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TestBlur)
|
QTEST_GUILESS_MAIN(TestBlur)
|
||||||
#include "test_wayland_blur.moc"
|
#include "test_wayland_blur.moc"
|
||||||
|
|
|
@ -26,12 +26,14 @@ Global::Private::~Private() = default;
|
||||||
void Global::Private::bind(wl_client *client, void *data, uint32_t version, uint32_t id)
|
void Global::Private::bind(wl_client *client, void *data, uint32_t version, uint32_t id)
|
||||||
{
|
{
|
||||||
auto d = reinterpret_cast<Private*>(data);
|
auto d = reinterpret_cast<Private*>(data);
|
||||||
|
if (!d) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
d->bind(client, version, id);
|
d->bind(client, version, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Global::Private::create()
|
void Global::Private::create()
|
||||||
{
|
{
|
||||||
Q_ASSERT(!global);
|
|
||||||
global = wl_global_create(*display, m_interface, m_version, this, bind);
|
global = wl_global_create(*display, m_interface, m_version, this, bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +53,14 @@ void Global::create()
|
||||||
d->create();
|
d->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Global::remove()
|
||||||
|
{
|
||||||
|
if (!d->global) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_global_remove(d->global);
|
||||||
|
}
|
||||||
|
|
||||||
void Global::destroy()
|
void Global::destroy()
|
||||||
{
|
{
|
||||||
if (!d->global) {
|
if (!d->global) {
|
||||||
|
|
|
@ -53,6 +53,24 @@ public:
|
||||||
* to the clients.
|
* to the clients.
|
||||||
**/
|
**/
|
||||||
void create();
|
void create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the Global from the registry, but does not delete the underlying wl_global
|
||||||
|
*
|
||||||
|
* Removal of a global is racey. A client could be trying to bind at that moment.
|
||||||
|
* Typically globals are static for the lifespan of the compositor, however there are exceptions
|
||||||
|
*
|
||||||
|
* For those cases this call will remove the global from the registry, but keep the wl_global instance alive
|
||||||
|
* and handling bind requests.
|
||||||
|
*
|
||||||
|
* The compositor can then remove the Global wrapper (this object) deleting the wl_global after an arbitrary delay or
|
||||||
|
* keep it around for re-use for the duration of the compositor.
|
||||||
|
*
|
||||||
|
* See https://gitlab.freedesktop.org/wayland/wayland/issues/10
|
||||||
|
*
|
||||||
|
* @since 5.70
|
||||||
|
*/
|
||||||
|
void remove();
|
||||||
/**
|
/**
|
||||||
* Destroys the low level wl_global. Afterwards the Global is no longer shown to clients.
|
* Destroys the low level wl_global. Afterwards the Global is no longer shown to clients.
|
||||||
**/
|
**/
|
||||||
|
|
Loading…
Reference in a new issue