Make sure wayland object destructors are called

Always at least call the generated "interface"_destroy method which does
destroy the proxy. For not already wrapped classes a small template
is introduced to pass a function that is called in the destructor.

Fixes: QTBUG-111576
Change-Id: I373463710764958ddea42ef0f7dc010c427b2ce8
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
David Redondo 2023-06-13 14:02:59 +02:00
parent 2d4b077534
commit c15b219108
25 changed files with 133 additions and 34 deletions

View File

@ -18,6 +18,12 @@ QWaylandWlShellIntegration::QWaylandWlShellIntegration() : QWaylandShellIntegrat
<< "by setting the environment variable QT_WAYLAND_SHELL_INTEGRATION";
}
QWaylandWlShellIntegration::~QWaylandWlShellIntegration()
{
if (object())
wl_shell_destroy(object());
}
QWaylandShellSurface *QWaylandWlShellIntegration::createShellSurface(QWaylandWindow *window)
{
return new QWaylandWlShellSurface(get_shell_surface(window->wlSurface()), window);

View File

@ -29,6 +29,7 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandWlShellIntegration
{
public:
QWaylandWlShellIntegration();
~QWaylandWlShellIntegration();
QWaylandShellSurface *createShellSurface(QWaylandWindow *window) override;
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override;

View File

@ -43,6 +43,10 @@ QWaylandXdgActivationV1::requestXdgActivationToken(QWaylandDisplay *display,
return provider;
}
QWaylandXdgActivationTokenV1::~QWaylandXdgActivationTokenV1()
{
destroy();
}
}
QT_END_NAMESPACE

View File

@ -33,6 +33,7 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandXdgActivationTokenV1
{
Q_OBJECT
public:
~QWaylandXdgActivationTokenV1() override;
void xdg_activation_token_v1_done(const QString &token) override { Q_EMIT done(token); }
Q_SIGNALS:

View File

@ -43,6 +43,8 @@ QWaylandDataDevice::~QWaylandDataDevice()
{
if (version() >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
release();
else
wl_data_device_destroy(object());
}
QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const

View File

@ -260,14 +260,14 @@ Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorize
struct wl_surface *QWaylandDisplay::createSurface(void *handle)
{
struct wl_surface *surface = mCompositor.create_surface();
struct wl_surface *surface = mGlobals.compositor->create_surface();
wl_surface_set_user_data(surface, handle);
return surface;
}
struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
{
struct ::wl_region *region = mCompositor.create_region();
struct ::wl_region *region = mGlobals.compositor->create_region();
for (const QRect &rect : qregion)
wl_region_add(region, rect.x(), rect.y(), rect.width(), rect.height());
@ -371,8 +371,12 @@ QWaylandDisplay::~QWaylandDisplay(void)
if (m_frameEventQueue)
wl_event_queue_destroy(m_frameEventQueue);
// Reset the globals manually since they need to be destroyed before the wl_display
mGlobals = {};
if (object())
wl_registry_destroy(object());
if (mDisplay)
wl_display_disconnect(mDisplay);
}
@ -425,8 +429,6 @@ void QWaylandDisplay::reconnect()
QWindowSystemInterface::handleScreenRemoved(screen);
}
// mCompositor
mShm.reset();
mCursorThemes.clear();
mCursor.reset();
@ -602,6 +604,16 @@ void QWaylandDisplay::handleScreenInitialized(QWaylandScreen *screen)
}
}
template <typename T, auto f>
struct WithDestructor : public T
{
using T::T;
~WithDestructor()
{
f(this->object());
}
};
void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uint32_t version)
{
struct ::wl_registry *registry = object();
@ -614,9 +626,11 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
if (interface == QLatin1String(QtWayland::wl_output::interface()->name)) {
mWaitingScreens << mWaylandIntegration->createPlatformScreen(this, version, id);
} else if (interface == QLatin1String(QtWayland::wl_compositor::interface()->name)) {
mCompositor.init(registry, id, qMin((int)version, 6));
mGlobals.compositor.reset(
new WithDestructor<QtWayland::wl_compositor, wl_compositor_destroy>(
registry, id, qMin((int)version, 6)));
} else if (interface == QLatin1String(QWaylandShm::interface()->name)) {
mShm.reset(new QWaylandShm(this, version, id));
mGlobals.shm.reset(new QWaylandShm(this, version, id));
} else if (interface == QLatin1String(QWaylandInputDevice::interface()->name)) {
QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, version, id);
mInputDevices.append(inputDevice);
@ -625,9 +639,13 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mGlobals.dndSelectionHandler.reset(new QWaylandDataDeviceManager(this, version, id));
#endif
} else if (interface == QLatin1String(QtWayland::qt_surface_extension::interface()->name)) {
mGlobals.surfaceExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
mGlobals.surfaceExtension.reset(
new WithDestructor<QtWayland::qt_surface_extension, qt_surface_extension_destroy>(
registry, id, 1));
} else if (interface == QLatin1String(QtWayland::wl_subcompositor::interface()->name)) {
mGlobals.subCompositor.reset(new QtWayland::wl_subcompositor(registry, id, 1));
mGlobals.subCompositor.reset(
new WithDestructor<QtWayland::wl_subcompositor, wl_subcompositor_destroy>(registry,
id, 1));
} else if (interface == QLatin1String(QWaylandTouchExtension::interface()->name)) {
mGlobals.touchExtension.reset(new QWaylandTouchExtension(this, id));
} else if (interface == QLatin1String(QWaylandQtKeyExtension::interface()->name)) {
@ -658,7 +676,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
}
mGlobals.textInputMethodManager.reset(
new QtWayland::qt_text_input_method_manager_v1(registry, id, 1));
new WithDestructor<QtWayland::qt_text_input_method_manager_v1,
qt_text_input_method_manager_v1_destroy>(registry, id, 1));
for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
inputDevice->setTextInputMethod(new QWaylandTextInputMethod(
this,
@ -678,7 +697,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
}
mGlobals.textInputManagerv1.reset(
new QtWayland::zwp_text_input_manager_v1(registry, id, 1));
new WithDestructor<QtWayland::zwp_text_input_manager_v1,
zwp_text_input_manager_v1_destroy>(registry, id, 1));
for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices)) {
auto textInput =
new QWaylandTextInputv1(this, mGlobals.textInputManagerv1->create_text_input());
@ -700,7 +720,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
}
mGlobals.textInputManagerv2.reset(
new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
new WithDestructor<QtWayland::zwp_text_input_manager_v2,
zwp_text_input_manager_v2_destroy>(registry, id, 1));
for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
inputDevice->setTextInput(new QWaylandTextInputv2(
this, mGlobals.textInputManagerv2->get_text_input(inputDevice->wl_seat())));
@ -715,9 +736,9 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
inputDevice->setTextInputMethod(nullptr);
}
mGlobals.textInputManagerv3.reset(
new QtWayland::zwp_text_input_manager_v3(registry, id, 1));
new WithDestructor<QtWayland::zwp_text_input_manager_v3,
zwp_text_input_manager_v3_destroy>(registry, id, 1));
for (QWaylandInputDevice *inputDevice : std::as_const(mInputDevices))
inputDevice->setTextInput(new QWaylandTextInputv3(
this, mGlobals.textInputManagerv3->get_text_input(inputDevice->wl_seat())));
@ -738,16 +759,21 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
screen->initXdgOutput(xdgOutputManager());
} else if (interface == QLatin1String(QtWayland::wp_fractional_scale_manager_v1::interface()->name)) {
mGlobals.fractionalScaleManager.reset(
new QtWayland::wp_fractional_scale_manager_v1(registry, id, 1));
new WithDestructor<QtWayland::wp_fractional_scale_manager_v1,
wp_fractional_scale_manager_v1_destroy>(registry, id, 1));
} else if (interface == QLatin1String("wp_viewporter")) {
mGlobals.viewporter.reset(new QtWayland::wp_viewporter(registry, id, qMin(1u, version)));
mGlobals.viewporter.reset(
new WithDestructor<QtWayland::wp_viewporter, wp_viewporter_destroy>(
registry, id, qMin(1u, version)));
} else if (interface == QLatin1String(QtWayland::wp_cursor_shape_manager_v1::interface()->name)) {
mGlobals.cursorShapeManager.reset(
new QtWayland::wp_cursor_shape_manager_v1(registry, id, std::min(1u, version)));
mGlobals.cursorShapeManager.reset(new WithDestructor<QtWayland::wp_cursor_shape_manager_v1,
wp_cursor_shape_manager_v1_destroy>(
registry, id, std::min(1u, version)));
} else if (
interface == QLatin1String(QtWayland::qt_toplevel_drag_manager_v1::interface()->name)) {
mGlobals.xdgToplevelDragManager.reset(
new QtWayland::qt_toplevel_drag_manager_v1(registry, id, 1));
new WithDestructor<QtWayland::qt_toplevel_drag_manager_v1,
qt_toplevel_drag_manager_v1_destroy>(registry, id, 1));
}
mRegistryGlobals.append(RegistryGlobal(id, interface, version, registry));

View File

@ -128,8 +128,10 @@ public:
struct wl_display *wl_display() const { return mDisplay; }
struct ::wl_registry *wl_registry() { return object(); }
const struct wl_compositor *wl_compositor() const { return mCompositor.object(); }
QtWayland::wl_compositor *compositor() { return &mCompositor; }
QtWayland::wl_compositor *compositor()
{
return mGlobals.compositor.get();
}
QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
QWaylandInputDevice *defaultInputDevice() const;
@ -225,7 +227,10 @@ public:
void addRegistryListener(RegistryListener listener, void *data);
void removeListener(RegistryListener listener, void *data);
QWaylandShm *shm() const { return mShm.data(); }
QWaylandShm *shm() const
{
return mGlobals.shm.get();
}
void forceRoundTrip();
@ -281,8 +286,6 @@ private:
std::unique_ptr<EventThread> m_eventThread;
wl_event_queue *m_frameEventQueue = nullptr;
QScopedPointer<EventThread> m_frameEventQueueThread;
QtWayland::wl_compositor mCompositor;
QScopedPointer<QWaylandShm> mShm;
QList<QWaylandScreen *> mWaitingScreens;
QList<QWaylandScreen *> mScreens;
QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
@ -313,6 +316,8 @@ private:
struct GlobalHolder
{
std::unique_ptr<QtWayland::wl_compositor> compositor;
std::unique_ptr<QWaylandShm> shm;
#if QT_CONFIG(wayland_datadevice)
std::unique_ptr<QWaylandDataDeviceManager> dndSelectionHandler;
#endif

View File

@ -418,8 +418,13 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
#endif
}
// Can't be in header because dtors for scoped pointers aren't known there.
QWaylandInputDevice::~QWaylandInputDevice() = default;
QWaylandInputDevice::~QWaylandInputDevice()
{
if (version() >= WL_SEAT_RELEASE_SINCE_VERSION)
release();
else
wl_seat_destroy(object());
}
void QWaylandInputDevice::seat_capabilities(uint32_t caps)
{

View File

@ -25,6 +25,7 @@ QWaylandTextInputMethod::QWaylandTextInputMethod(QWaylandDisplay *display, struc
QWaylandTextInputMethod::~QWaylandTextInputMethod()
{
qt_text_input_method_v1_destroy(object());
}
void QWaylandTextInputMethod::text_input_method_v1_visible_changed(int32_t visible)

View File

@ -35,8 +35,10 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re
if (lowerCaseResource == "display" || lowerCaseResource == "wl_display" || lowerCaseResource == "nativedisplay")
return m_integration->display()->wl_display();
if (lowerCaseResource == "compositor")
return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
if (lowerCaseResource == "compositor") {
if (auto compositor = m_integration->display()->compositor())
return compositor->object();
}
if (lowerCaseResource == "server_buffer_integration")
return m_integration->serverBufferIntegration();
@ -76,7 +78,9 @@ wl_display *QtWaylandClient::QWaylandNativeInterface::display() const
wl_compositor *QtWaylandClient::QWaylandNativeInterface::compositor() const
{
return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
if (auto compositor = m_integration->display()->compositor())
return compositor->object();
return nullptr;
}
wl_seat *QtWaylandClient::QWaylandNativeInterface::seat() const
@ -129,8 +133,10 @@ void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourc
if (lowerCaseResource == "display")
return m_integration->display()->wl_display();
if (lowerCaseResource == "compositor")
return const_cast<wl_compositor *>(m_integration->display()->wl_compositor());
if (lowerCaseResource == "compositor") {
if (auto compositor = m_integration->display()->compositor())
return compositor->object();
}
if (lowerCaseResource == "surface") {
QWaylandWindow *w = static_cast<QWaylandWindow*>(window->handle());
return w ? w->wlSurface() : nullptr;

View File

@ -14,6 +14,14 @@ QWaylandPointerGestures::QWaylandPointerGestures(QWaylandDisplay *display, uint
{
}
QWaylandPointerGestures::~QWaylandPointerGestures() noexcept
{
if (version() >= ZWP_POINTER_GESTURES_V1_RELEASE_SINCE_VERSION)
release();
else
zwp_pointer_gestures_v1_destroy(object());
}
QWaylandPointerGestureSwipe *
QWaylandPointerGestures::createPointerGestureSwipe(QWaylandInputDevice *device)
{

View File

@ -36,6 +36,7 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandPointerGestures : public QtWayland::zwp_poi
{
public:
explicit QWaylandPointerGestures(QWaylandDisplay *display, uint id, uint version);
~QWaylandPointerGestures();
QWaylandPointerGestureSwipe *createPointerGestureSwipe(QWaylandInputDevice *device);
QWaylandPointerGesturePinch *createPointerGesturePinch(QWaylandInputDevice *device);

View File

@ -20,6 +20,11 @@ QWaylandPrimarySelectionDeviceManagerV1::QWaylandPrimarySelectionDeviceManagerV1
{
}
QWaylandPrimarySelectionDeviceManagerV1::~QWaylandPrimarySelectionDeviceManagerV1()
{
destroy();
}
QWaylandPrimarySelectionDeviceV1 *QWaylandPrimarySelectionDeviceManagerV1::createDevice(QWaylandInputDevice *seat)
{
return new QWaylandPrimarySelectionDeviceV1(this, seat);

View File

@ -37,6 +37,7 @@ class QWaylandPrimarySelectionDeviceManagerV1 : public QtWayland::zwp_primary_se
{
public:
explicit QWaylandPrimarySelectionDeviceManagerV1(QWaylandDisplay *display, uint id, uint version);
~QWaylandPrimarySelectionDeviceManagerV1();
QWaylandPrimarySelectionDeviceV1 *createDevice(QWaylandInputDevice *seat);
QWaylandDisplay *display() const { return m_display; }

View File

@ -15,6 +15,11 @@ QWaylandQtKeyExtension::QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_
{
}
QWaylandQtKeyExtension::~QWaylandQtKeyExtension()
{
zqt_key_v1_destroy(object());
}
void QWaylandQtKeyExtension::zqt_key_v1_key(struct wl_surface *surface,
uint32_t time,
uint32_t type,

View File

@ -31,6 +31,7 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandQtKeyExtension : public QtWayland::zqt_key_
{
public:
QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_t id);
~QWaylandQtKeyExtension();
private:
QWaylandDisplay *m_display = nullptr;

View File

@ -22,6 +22,11 @@ QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandDisplay* display,
{
}
QWaylandXdgOutputManagerV1::~QWaylandXdgOutputManagerV1()
{
destroy();
}
QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id)
: QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 3))
, m_outputId(id)
@ -44,8 +49,10 @@ QWaylandScreen::~QWaylandScreen()
{
if (zxdg_output_v1::isInitialized())
zxdg_output_v1::destroy();
if (wl_output::isInitialized() && wl_output::version() >= WL_OUTPUT_RELEASE_SINCE_VERSION)
if (wl_output::version() >= WL_OUTPUT_RELEASE_SINCE_VERSION)
wl_output::release();
else
wl_output_destroy(wl_output::object());
}
uint QWaylandScreen::requiredEvents() const

View File

@ -33,6 +33,7 @@ class QWaylandCursor;
class Q_WAYLANDCLIENT_EXPORT QWaylandXdgOutputManagerV1 : public QtWayland::zxdg_output_manager_v1 {
public:
QWaylandXdgOutputManagerV1(QWaylandDisplay *display, uint id, uint version);
~QWaylandXdgOutputManagerV1();
};
class Q_WAYLANDCLIENT_EXPORT QWaylandScreen : public QPlatformScreen,

View File

@ -16,7 +16,7 @@ QWaylandShm::QWaylandShm(QWaylandDisplay *display, int version, uint32_t id)
QWaylandShm::~QWaylandShm()
{
wl_shm_destroy(object());
}
void QWaylandShm::shm_format(uint32_t format)

View File

@ -20,6 +20,11 @@ QWaylandTabletManagerV2::QWaylandTabletManagerV2(QWaylandDisplay *display, uint
createTabletSeat(seat);
}
QWaylandTabletManagerV2::~QWaylandTabletManagerV2()
{
destroy();
}
QWaylandTabletSeatV2 *QWaylandTabletManagerV2::createTabletSeat(QWaylandInputDevice *seat)
{
return new QWaylandTabletSeatV2(this, seat);

View File

@ -42,6 +42,7 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandTabletManagerV2 : public QtWayland::zwp_tab
{
public:
explicit QWaylandTabletManagerV2(QWaylandDisplay *display, uint id, uint version);
~QWaylandTabletManagerV2() override;
QWaylandTabletSeatV2 *createTabletSeat(QWaylandInputDevice *seat);
};

View File

@ -46,6 +46,7 @@ QWaylandTextInputv1::~QWaylandTextInputv1()
{
if (m_resetCallback)
wl_callback_destroy(m_resetCallback);
zwp_text_input_v1_destroy(object());
}
void QWaylandTextInputv1::reset()

View File

@ -23,6 +23,11 @@ QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_
{
}
QWaylandTouchExtension::~QWaylandTouchExtension()
{
qt_touch_extension_destroy(object());
}
void QWaylandTouchExtension::registerDevice(int caps)
{
// TODO number of touchpoints, actual name and ID

View File

@ -32,6 +32,7 @@ class Q_WAYLANDCLIENT_EXPORT QWaylandTouchExtension : public QtWayland::qt_touch
{
public:
QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id);
~QWaylandTouchExtension() override;
void touchCanceled();

View File

@ -34,7 +34,6 @@ public:
QWaylandWindowManagerIntegrationPrivate::QWaylandWindowManagerIntegrationPrivate(QWaylandDisplay *waylandDisplay)
: m_waylandDisplay(waylandDisplay)
{
}
QWaylandWindowManagerIntegration::QWaylandWindowManagerIntegration(QWaylandDisplay *waylandDisplay)
@ -45,7 +44,8 @@ QWaylandWindowManagerIntegration::QWaylandWindowManagerIntegration(QWaylandDispl
QWaylandWindowManagerIntegration::~QWaylandWindowManagerIntegration()
{
if (object())
qt_windowmanager_destroy(object());
}
bool QWaylandWindowManagerIntegration::showIsFullScreen() const