Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions qwlroots/src/types/qwxwayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class QW_CLASS_OBJECT(xwayland)
QW_FUNC_MEMBER(xwayland, set_seat, void, wlr_seat *seat)

QW_FUNC_MEMBER(xwayland, get_xwm_connection, xcb_connection_t*)

protected:
QW_FUNC_MEMBER(xwayland, destroy, void)
};

QW_END_NAMESPACE
5 changes: 5 additions & 0 deletions src/core/treeland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ class TreelandPrivate : public QObject
it->second->deleteLater();
pluginTs.erase(it++);
}
// UserModel must be deleted before Helper, to remove client surfaces before rendering ends.
delete qmlEngine->singletonInstance<UserModel *>("Treeland", "UserModel");
// Helper must be deleted before QmlEngine, for surfaces to be cleanly removed.
qmlEngine->clearSingletons();
}

#ifndef DISABLE_DDM
Expand Down Expand Up @@ -490,6 +494,7 @@ void Treeland::quit()
// make sure all deleted before app exit
d_ptr.reset();
qApp->quit();
// TODO: release drm master and return tty to text mode
}

} // namespace Treeland
Expand Down
10 changes: 8 additions & 2 deletions src/seat/helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,15 @@ Helper::Helper(QObject *parent)

Helper::~Helper()
{
Q_ASSERT(m_instance == this);
m_instance = nullptr;
for (auto s : m_rootSurfaceContainer->surfaces()) {
m_rootSurfaceContainer->destroyForSurface(s);
}

// destroy before m_rootSurfaceContainer
delete m_shellHandler;
delete m_rootSurfaceContainer;
Q_ASSERT(m_instance == this);
m_instance = nullptr;
}

Helper *Helper::instance()
Expand Down Expand Up @@ -1609,12 +1609,18 @@ bool Helper::beforeDisposeEvent(WSeat *seat, QWindow *, QInputEvent *event)
if (event->type() == QEvent::KeyPress) {
auto kevent = static_cast<QKeyEvent *>(event);

#ifndef QT_NO_DEBUG
if (QKeySequence(kevent->keyCombination()) ==
QKeySequence(Qt::MetaModifier | Qt::Key_F12)) {
std::terminate();
}
// The debug view shortcut should always handled first
if (QKeySequence(kevent->keyCombination())
== QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::MetaModifier | Qt::Key_F11)) {
if (toggleDebugMenuBar())
return true;
}
#endif

// Switch TTY with Ctrl + Alt + F1-F12
if (kevent->modifiers() == (Qt::ControlModifier | Qt::AltModifier)) {
Expand Down
1 change: 0 additions & 1 deletion src/seat/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ class Helper : public WSeatEventFilter

void addSocket(WSocket *socket);
[[nodiscard]] WXWayland *createXWayland();
void removeXWayland(WXWayland *xwayland);

PersonalizationV1 *personalization() const;

Expand Down
12 changes: 9 additions & 3 deletions src/session/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,16 @@ Session::~Session()
delete m_settingManager;
m_settingManager = nullptr;
}
if (m_xwayland)
Helper::instance()->shellHandler()->removeXWayland(m_xwayland);
if (m_socket)
if (m_xwayland) {
// if shellHandler is already destructed, wait for WServer to clean up the interface.
if (auto *helper = Helper::instance())
helper->shellHandler()->removeXWayland(m_xwayland);
m_xwayland = nullptr;
}
if (m_socket) {
delete m_socket;
m_socket = nullptr;
}
}

int Session::id() const
Expand Down
2 changes: 1 addition & 1 deletion src/treeland-shortcut/shortcuts/_treeland-quit.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[Shortcut]
Shortcut=Meta+F12
Shortcut=Meta+Shift+Q
Type="Action"

[Type.Action]
Expand Down
10 changes: 10 additions & 0 deletions waylib/src/server/protocols/wxwayland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class Q_DECL_HIDDEN WXWaylandPrivate : public WWrapObjectPrivate
QList<WXWaylandSurface*> toplevelSurfaces;

WSocket *socket = nullptr;

protected:
void instantRelease() override;
};

void WXWaylandPrivate::init()
Expand Down Expand Up @@ -91,6 +94,10 @@ void WXWaylandPrivate::init()
}
}

void WXWaylandPrivate::instantRelease() {
delete handle<qw_xwayland>();
}

void WXWaylandPrivate::on_new_surface(wlr_xwayland_surface *xwl_surface)
{
W_Q(WXWayland);
Expand Down Expand Up @@ -347,6 +354,9 @@ void WXWayland::destroy([[maybe_unused]] WServer *server)
d->screen = nullptr;

for (auto surface : std::as_const(list)) {
// disconnect from on_surface_destroy
disconnect(surface->handle(), &qw_xwayland_surface::before_destroy,
this, nullptr);
removeSurface(surface);
surface->safeDeleteLater();
}
Expand Down
31 changes: 23 additions & 8 deletions waylib/src/server/qtquick/private/wbufferrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,17 @@ WBufferRenderer::WBufferRenderer(QQuickItem *parent)
, m_cacheBuffer(true)
, m_hideSource(false)
{

// ensure graphical resources are released before scene graph is invalidated
// since WBufferRenderer's ItemHasContent bit is unset
// the invalidateSceneGraph slot will not be called through QQuickWindowPrivate::cleanupNodesOnShutdown
QMetaObject::Connection windowConn;
if (window())
windowConn = connect(window(), &QQuickWindow::sceneGraphInvalidated, this, &WBufferRenderer::invalidateSceneGraph);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该不需要,这个slot会在QQuickWindowPrivate::cleanupNodesOnShutdown种被主动调用。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要的,它那个自动调用并不稳定

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那应该解决不稳定的问题,不稳定时指什么?

connect(this, &QQuickItem::windowChanged, this, [this, windowConn](auto *window) mutable {
disconnect(windowConn);
if (window)
windowConn = connect(window, &QQuickWindow::sceneGraphInvalidated, this, &WBufferRenderer::invalidateSceneGraph);
});
}

WBufferRenderer::~WBufferRenderer()
Expand Down Expand Up @@ -142,7 +152,6 @@ void WBufferRenderer::setSourceList(QList<QQuickItem*> sources, bool hideSource)
return;

resetSources();
m_sourceList.clear();
m_hideSource = hideSource;

for (auto s : std::as_const(sources)) {
Expand All @@ -154,7 +163,7 @@ void WBufferRenderer::setSourceList(QList<QQuickItem*> sources, bool hideSource)
connect(s, &QQuickItem::destroyed, this, [this] {
const int index = indexOfSource(static_cast<QQuickItem*>(sender()));
Q_ASSERT(index >= 0);
removeSource(index);
destroySource(index);
m_sourceList.removeAt(index);
});

Expand Down Expand Up @@ -687,11 +696,13 @@ void WBufferRenderer::invalidateSceneGraph()
{
if (m_textureProvider)
m_textureProvider.reset();
resetSources();
}

void WBufferRenderer::releaseResources()
{
cleanTextureProvider();
resetSources();
}

void WBufferRenderer::cleanTextureProvider()
Expand Down Expand Up @@ -723,19 +734,23 @@ void WBufferRenderer::cleanTextureProvider()
void WBufferRenderer::resetSources()
{
for (int i = 0; i < m_sourceList.size(); ++i) {
removeSource(i);
destroySource(i);
}
m_sourceList.clear();
}

void WBufferRenderer::removeSource(int index)
void WBufferRenderer::destroySource(int index)
{
auto s = m_sourceList.at(index);
auto &s = m_sourceList[index];
if (isRootItem(s.source))
return;

// Renderer of source is delay initialized in ensureRenderer. It might be null here.
if (s.renderer)
s.renderer->deleteLater();
if (s.renderer) {
delete s.renderer;
s.renderer = nullptr;
}

auto d = QQuickItemPrivate::get(s.source);
if (d->inDestructor)
return;
Expand Down
4 changes: 2 additions & 2 deletions waylib/src/server/qtquick/private/wbufferrenderer_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class WAYLIB_SERVER_EXPORT WBufferRenderer : public QQuickItem

private:
inline WOutputRenderWindow *renderWindow() const {
return qobject_cast<WOutputRenderWindow*>(parent());
return qobject_cast<WOutputRenderWindow*>(window());
}

inline bool shouldCacheBuffer() const {
Expand All @@ -125,7 +125,7 @@ class WAYLIB_SERVER_EXPORT WBufferRenderer : public QQuickItem
}

void resetSources();
void removeSource(int index);
void destroySource(int index);
int indexOfSource(QQuickItem *item);
QSGRenderer *ensureRenderer(int sourceIndex, QSGRenderContext *rc);

Expand Down
16 changes: 13 additions & 3 deletions waylib/src/server/qtquick/private/wrenderbuffernode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,17 @@ class Q_DECL_HIDDEN DataManagerBase : public QObject
mutable QAtomicInt ref;

explicit DataManagerBase(QQuickWindow *owner)
: QObject(owner) {}
: QObject(owner)
{
Q_ASSERT(owner->isSceneGraphInitialized());
connect(owner, &QQuickWindow::sceneGraphInvalidated, this, [this]() {
setParent(nullptr);
// per request from zccrs.
// Be Warned: objects may not be expected to be deleted in the rendering thread.
delete this;
}, static_cast<Qt::ConnectionType>(Qt::DirectConnection | Qt::SingleShotConnection));
}
virtual ~DataManagerBase() {};
};

template <class T>
Expand Down Expand Up @@ -260,7 +270,7 @@ class Q_DECL_HIDDEN DataManager : public DataManagerBase
}

using QObject::deleteLater;
~DataManager() {
~DataManager() override {
for (auto data : std::as_const(dataList)) {
Derive::destroy(data->data);
}
Expand Down Expand Up @@ -452,7 +462,7 @@ class Q_DECL_HIDDEN RhiManager : public DataManager<RhiManager, void>
isBatchRenderer = dynamic_cast<QSGBatchRenderer::Renderer*>(renderer);
}

~RhiManager() {
~RhiManager() override {
delete renderer;
}

Expand Down