Skip to content

Commit bf235d3

Browse files
committed
wayland/layershell: ensure bridge is nulled on layer destruction
Fixes rare race condition crashes.
1 parent 2bcd9e0 commit bf235d3

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

src/wayland/wlr_layershell/surface.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,10 @@ LayerSurface::LayerSurface(LayerShellIntegration* shell, QtWaylandClient::QWayla
173173
this->bridge->surface = this;
174174
}
175175

176-
LayerSurface::~LayerSurface() { this->destroy(); }
176+
LayerSurface::~LayerSurface() {
177+
delete this->bridge;
178+
this->destroy();
179+
}
177180

178181
void LayerSurface::zwlr_layer_surface_v1_configure(quint32 serial, quint32 width, quint32 height) {
179182
this->ack_configure(serial);

src/wayland/wlr_layershell/wlr_layershell.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ ProxiedWindow* WlrLayershell::retrieveWindow(QObject* oldInstance) {
3434
auto* window = old == nullptr ? nullptr : old->disownWindow();
3535

3636
if (window != nullptr) {
37-
this->bridge = LayerSurfaceBridge::init(window, this->computeState());
37+
this->connectBridge(LayerSurfaceBridge::init(window, this->computeState()));
38+
3839
if (this->bridge) {
3940
return window;
4041
} else {
@@ -48,7 +49,7 @@ ProxiedWindow* WlrLayershell::retrieveWindow(QObject* oldInstance) {
4849
ProxiedWindow* WlrLayershell::createQQuickWindow() {
4950
auto* window = this->ProxyWindowBase::createQQuickWindow();
5051

51-
this->bridge = LayerSurfaceBridge::init(window, this->computeState());
52+
this->connectBridge(LayerSurfaceBridge::init(window, this->computeState()));
5253
if (!this->bridge) {
5354
qWarning() << "Could not attach Layershell extension to new QQuickWindow. Layer will not "
5455
"behave correctly.";
@@ -72,6 +73,30 @@ void WlrLayershell::connectWindow() {
7273
this->updateAutoExclusion();
7374
}
7475

76+
ProxiedWindow* WlrLayershell::disownWindow(bool keepItemOwnership) {
77+
auto* window = this->ProxyWindowBase::disownWindow(keepItemOwnership);
78+
79+
if (this->bridge) {
80+
this->connectBridge(nullptr);
81+
}
82+
83+
return window;
84+
}
85+
86+
void WlrLayershell::connectBridge(LayerSurfaceBridge* bridge) {
87+
if (this->bridge) {
88+
QObject::disconnect(this->bridge, nullptr, this, nullptr);
89+
}
90+
91+
this->bridge = bridge;
92+
93+
if (bridge) {
94+
QObject::connect(this->bridge, &QObject::destroyed, this, &WlrLayershell::onBridgeDestroyed);
95+
}
96+
}
97+
98+
void WlrLayershell::onBridgeDestroyed() { this->bridge = nullptr; }
99+
75100
bool WlrLayershell::deleteOnInvisible() const {
76101
// Qt windows behave weirdly when geometry is modified and setVisible(false)
77102
// is subsequently called in the same frame.

src/wayland/wlr_layershell/wlr_layershell.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class WlrLayershell: public ProxyWindowBase {
122122
ProxiedWindow* retrieveWindow(QObject* oldInstance) override;
123123
ProxiedWindow* createQQuickWindow() override;
124124
void connectWindow() override;
125+
ProxiedWindow* disownWindow(bool keepItemOwnership = false) override;
125126
[[nodiscard]] bool deleteOnInvisible() const override;
126127

127128
void onPolished() override;
@@ -175,10 +176,12 @@ class WlrLayershell: public ProxyWindowBase {
175176

176177
private slots:
177178
void updateAutoExclusion();
179+
void onBridgeDestroyed();
178180

179181
private:
180182
[[nodiscard]] LayerSurfaceState computeState() const;
181183

184+
void connectBridge(LayerSurfaceBridge* bridge);
182185
void onStateChanged();
183186

184187
bool compositorPicksScreen = true;

0 commit comments

Comments
 (0)