Recommended backport of [1] by the kde community[2] to avoid several crashes when unplugging a tablet (missed the 6.8.1 window, will be in 6.8.2). [1] https://github.com/qt/qtwayland/commit/24002ac6cbd01dbde4944b63c1f7c87ed2bd72b5 [2] https://mail.kde.org/pipermail/distributions/2024-November/001550.html --- a/src/client/qwaylandtabletv2.cpp +++ b/src/client/qwaylandtabletv2.cpp @@ -188,10 +188,4 @@ QWaylandTabletSeatV2::~QWaylandTabletSeatV2() { - for (auto *tablet : m_tablets) - tablet->destroy(); - for (auto *tool : m_tools) - tool->destroy(); - for (auto *pad : m_pads) - pad->destroy(); qDeleteAll(m_tablets); qDeleteAll(m_tools); @@ -255,4 +249,9 @@ } +QWaylandTabletV2::~QWaylandTabletV2() +{ + destroy(); +} + void QWaylandTabletV2::zwp_tablet_v2_name(const QString &name) { @@ -293,5 +292,4 @@ void QWaylandTabletV2::zwp_tablet_v2_removed() { - destroy(); deleteLater(); } @@ -317,5 +315,8 @@ } -QWaylandTabletToolV2::~QWaylandTabletToolV2() = default; +QWaylandTabletToolV2::~QWaylandTabletToolV2() +{ + destroy(); +} void QWaylandTabletToolV2::zwp_tablet_tool_v2_type(uint32_t tool_type) @@ -411,5 +412,4 @@ void QWaylandTabletToolV2::zwp_tablet_tool_v2_removed() { - destroy(); m_tabletSeat->toolRemoved(this); } @@ -603,4 +603,9 @@ } +QWaylandTabletPadV2::~QWaylandTabletPadV2() +{ + destroy(); +} + void QWaylandTabletPadV2::zwp_tablet_pad_v2_path(const QString &path) { @@ -622,5 +627,4 @@ void QWaylandTabletPadV2::zwp_tablet_pad_v2_removed() { - destroy(); delete this; } --- a/src/client/qwaylandtabletv2_p.h +++ b/src/client/qwaylandtabletv2_p.h @@ -84,4 +84,5 @@ public: explicit QWaylandTabletV2(::zwp_tablet_v2 *tablet, const QString &seatName); + ~QWaylandTabletV2(); protected: @@ -99,5 +100,5 @@ public: QWaylandTabletToolV2(QWaylandTabletSeatV2 *tabletSeat, ::zwp_tablet_tool_v2 *tool); - ~QWaylandTabletToolV2() override; + ~QWaylandTabletToolV2(); void updateCursor(); @@ -182,4 +183,5 @@ public: explicit QWaylandTabletPadV2(::zwp_tablet_pad_v2 *pad); + ~QWaylandTabletPadV2(); protected: --- a/tests/auto/client/tabletv2/tst_tabletv2.cpp +++ b/tests/auto/client/tabletv2/tst_tabletv2.cpp @@ -187,7 +187,7 @@ QList m_tabletsWaitingForDestroy; QList m_tools; - QList m_toolsWaitingForDestroy; + QList m_toolsWaitingForDestroy; QList m_pads; - QList m_padsWaitingForDestroy; + QList m_padsWaitingForDestroy; protected: @@ -275,9 +275,10 @@ void TabletToolV2::sendRemoved() { - for (auto *resource : resourceMap()) + for (auto *resource : resourceMap()) { zwp_tablet_tool_v2_send_removed(resource->handle); + m_tabletSeat->m_toolsWaitingForDestroy.append(resource); + } bool removed = m_tabletSeat->m_tools.removeOne(this); QVERIFY(removed); - m_tabletSeat->m_toolsWaitingForDestroy.append(this); } @@ -334,6 +335,5 @@ { if (m_tabletSeat) { - bool removed = m_tabletSeat->m_toolsWaitingForDestroy.removeOne(this); - QVERIFY(removed); + m_tabletSeat->m_toolsWaitingForDestroy.removeOne(resource); } wl_resource_destroy(resource->handle); @@ -342,9 +342,10 @@ void TabletPadV2::sendRemoved() { - for (auto *resource : resourceMap()) + for (auto *resource : resourceMap()) { zwp_tablet_pad_v2_send_removed(resource->handle); + m_tabletSeat->m_padsWaitingForDestroy.append(resource); + } bool removed = m_tabletSeat->m_pads.removeOne(this); QVERIFY(removed); - m_tabletSeat->m_padsWaitingForDestroy.append(this); } @@ -352,6 +353,5 @@ { if (m_tabletSeat) { - bool removed = m_tabletSeat->m_padsWaitingForDestroy.removeOne(this); - QVERIFY(removed); + m_tabletSeat->m_padsWaitingForDestroy.removeOne(resource); } wl_resource_destroy(resource->handle); @@ -406,4 +406,6 @@ void destroysTool(); void destroysPad(); + void removeTabletBeforeTool(); + void removeTabletBeforePad(); void proximityEvents(); void moveEvent(); @@ -503,4 +505,5 @@ QCOMPOSITOR_TRY_VERIFY(tabletSeat()); exec([&] { + tabletSeat()->addTablet(); tabletSeat()->addTool(); }); @@ -509,4 +512,5 @@ exec([&] { tabletTool()->sendRemoved(); + tablet()->sendRemoved(); }); @@ -529,4 +533,40 @@ QCOMPOSITOR_TRY_VERIFY(!tabletPad()); QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_padsWaitingForDestroy.empty()); +} + +void tst_tabletv2::removeTabletBeforeTool() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addTool(); + }); + QCOMPOSITOR_TRY_VERIFY(tablet()); + QCOMPOSITOR_TRY_VERIFY(tabletTool()); + + exec([&] { tablet()->sendRemoved(); }); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_tabletsWaitingForDestroy.empty()); + + exec([&] { tabletTool()->sendRemoved(); }); + QCOMPOSITOR_TRY_VERIFY(!tabletTool()); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_toolsWaitingForDestroy.empty()); +} + +void tst_tabletv2::removeTabletBeforePad() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addPad(); + }); + QCOMPOSITOR_TRY_VERIFY(tablet()); + QCOMPOSITOR_TRY_VERIFY(tabletPad()); + + exec([&] { tablet()->sendRemoved(); }); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_tabletsWaitingForDestroy.empty()); + + exec([&] { tabletPad()->sendRemoved(); }); + QCOMPOSITOR_TRY_VERIFY(!tabletPad()); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_padsWaitingForDestroy.empty()); }