Skip to content
Draft
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
27 changes: 27 additions & 0 deletions src/core/shellhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,11 @@ void ShellHandler::updateWrapperContainer(SurfaceWrapper *wrapper, WSurface *par

// Prelaunch splash request: create a SurfaceWrapper that is not yet bound to a shellSurface
void ShellHandler::handlePrelaunchSplashRequested(const QString &appId,
const QString &instanceId,
QW_NAMESPACE::qw_buffer *iconBuffer)
{
Q_UNUSED(instanceId); // TODO: will be provided by AM DBus in future

if (!Helper::instance()->globalConfig()->enablePrelaunchSplash())
return;
if (!m_appIdResolverManager)
Expand Down Expand Up @@ -140,6 +143,7 @@ void ShellHandler::handlePrelaunchSplashRequested(const QString &appId,
std::bind(&ShellHandler::createPrelaunchSplash,
this,
appId,
instanceId,
iconBuffer,
std::placeholders::_1,
std::placeholders::_2,
Expand All @@ -150,12 +154,15 @@ void ShellHandler::handlePrelaunchSplashRequested(const QString &appId,
}

void ShellHandler::createPrelaunchSplash(const QString &appId,
const QString &instanceId,
QW_NAMESPACE::qw_buffer *iconBuffer,
const QSize &lastSize,
const QString &darkPalette,
const QString &lightPalette,
qlonglong splashThemeType)
{
Q_UNUSED(instanceId); // TODO: will be provided by AM DBus in future

if (!m_pendingPrelaunchAppIds.contains(appId)) {
if (iconBuffer) {
iconBuffer->unlock();
Expand Down Expand Up @@ -210,6 +217,26 @@ void ShellHandler::createPrelaunchSplash(const QString &appId,
}
}

void ShellHandler::handlePrelaunchSplashClosed(const QString &appId, const QString &instanceId)
{
Q_UNUSED(instanceId); // TODO: will be provided by AM DBus in future

// Remove pending prelaunch request if it hasn't created a wrapper yet
m_pendingPrelaunchAppIds.remove(appId);

// Find and destroy any existing prelaunch wrapper with the matching appId
for (int i = 0; i < m_prelaunchWrappers.size(); ++i) {
auto *wrapper = m_prelaunchWrappers[i];
if (wrapper->appId() == appId) {
qCDebug(treelandShell)
<< "Client requested close_splash, destroy wrapper appId=" << appId;
m_prelaunchWrappers.removeAt(i);
m_rootSurfaceContainer->destroyForSurface(wrapper);
return;
}
}
}

Workspace *ShellHandler::workspace() const
{
return m_workspace;
Expand Down
6 changes: 5 additions & 1 deletion src/core/shellhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,12 @@ private Q_SLOTS:
const QByteArray &value);
// Prelaunch splash related: creates a prelaunch SurfaceWrapper when
// PrelaunchSplash::splashRequested
void handlePrelaunchSplashRequested(const QString &appId, QW_NAMESPACE::qw_buffer *iconBuffer);
void handlePrelaunchSplashRequested(const QString &appId,
const QString &instanceId,
QW_NAMESPACE::qw_buffer *iconBuffer);
void handlePrelaunchSplashClosed(const QString &appId, const QString &instanceId);
void createPrelaunchSplash(const QString &appId,
const QString &instanceId,
QW_NAMESPACE::qw_buffer *iconBuffer,
const QSize &lastSize,
const QString &darkPalette,
Expand Down
8 changes: 4 additions & 4 deletions src/modules/prelaunch-splash/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
find_package(TreelandProtocols REQUIRED)
find_package(TreelandProtocols 0.5.5 REQUIRED)

local_qtwayland_server_protocol_treeland(libtreeland
PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-prelaunch-splash-v1.xml
BASENAME treeland-prelaunch-splash-v1
PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-prelaunch-splash-v2.xml
BASENAME treeland-prelaunch-splash-v2
)
Comment on lines +1 to 6
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

The repo has QtTest-based protocol smoke tests under tests/test_protocol_*, but there is no coverage added for the new treeland-prelaunch-splash-v2 protocol. Add a small test_protocol_prelaunch-splash that at least attaches the PrelaunchSplash interface and exercises the close-notification path (explicit destroy + client disconnect) to prevent regressions.

仓库里已有基于 QtTest 的协议冒烟测试(tests/test_protocol_*),但此次新增/升级的 treeland-prelaunch-splash-v2 协议没有对应测试覆盖。建议新增一个 test_protocol_prelaunch-splash:至少验证 PrelaunchSplash 能 attach 成功,并覆盖关闭通知路径(显式 destroy + 客户端断开)以避免回归。

Copilot uses AI. Check for mistakes.

impl_treeland(
Expand All @@ -11,7 +11,7 @@ impl_treeland(
SOURCE
prelaunchsplash.h
prelaunchsplash.cpp
${CMAKE_BINARY_DIR}/src/modules/prelaunch-splash/wayland-treeland-prelaunch-splash-v1-server-protocol.c
${CMAKE_BINARY_DIR}/src/modules/prelaunch-splash/wayland-treeland-prelaunch-splash-v2-server-protocol.c
INCLUDE
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
LINK
Expand Down
79 changes: 66 additions & 13 deletions src/modules/prelaunch-splash/prelaunchsplash.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (C) 2025 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "prelaunchsplash.h"
#include "qwayland-server-treeland-prelaunch-splash-v1.h"
#include "qwayland-server-treeland-prelaunch-splash-v2.h"

Check warning on line 4 in src/modules/prelaunch-splash/prelaunchsplash.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "qwayland-server-treeland-prelaunch-splash-v2.h" not found.

#include <wserver.h>

Check warning on line 6 in src/modules/prelaunch-splash/prelaunchsplash.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wserver.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <qwdisplay.h>
#include <qwbuffer.h>
Expand All @@ -19,9 +19,47 @@

Q_LOGGING_CATEGORY(prelaunchSplash, "treeland.prelaunchsplash", QtInfoMsg)

#define TREELAND_PRELAUNCH_SPLASH_MANAGER_V1_VERSION 1
#define TREELAND_PRELAUNCH_SPLASH_MANAGER_V2_VERSION 1

class PrelaunchSplashPrivate : public QtWaylandServer::treeland_prelaunch_splash_manager_v1
class SplashResource : public QtWaylandServer::treeland_prelaunch_splash_v2
{
public:
SplashResource(PrelaunchSplash *owner,
struct ::wl_resource *resource,
const QString &appId,
const QString &instanceId)
: QtWaylandServer::treeland_prelaunch_splash_v2(resource)
, m_owner(owner)
, m_appId(appId)
, m_instanceId(instanceId)
{
}

QString appId() const { return m_appId; }
QString instanceId() const { return m_instanceId; }

Check warning on line 39 in src/modules/prelaunch-splash/prelaunchsplash.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'instanceId' is never used.

protected:
void treeland_prelaunch_splash_v2_destroy(Resource *resource) override

Check warning on line 42 in src/modules/prelaunch-splash/prelaunchsplash.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_prelaunch_splash_v2_destroy' is never used.
{
qCInfo(prelaunchSplash)
<< "Client destroy splash appId=" << m_appId << " instanceId=" << m_instanceId;
wl_resource_destroy(resource->handle);
}

void treeland_prelaunch_splash_v2_destroy_resource(Resource *) override

Check warning on line 49 in src/modules/prelaunch-splash/prelaunchsplash.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_prelaunch_splash_v2_destroy_resource' is never used.
{
// Covers both explicit destroy() and client crash/disconnect
Q_EMIT m_owner->splashCloseRequested(m_appId, m_instanceId);
delete this;
}

private:
PrelaunchSplash *m_owner;
QString m_appId;
QString m_instanceId;
};

class PrelaunchSplashPrivate : public QtWaylandServer::treeland_prelaunch_splash_manager_v2
{
public:
explicit PrelaunchSplashPrivate(PrelaunchSplash *q)
Expand All @@ -35,22 +73,38 @@
}

protected:
void treeland_prelaunch_splash_manager_v1_destroy(Resource *resource) override
void treeland_prelaunch_splash_manager_v2_destroy(Resource *resource) override

Check warning on line 76 in src/modules/prelaunch-splash/prelaunchsplash.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_prelaunch_splash_manager_v2_destroy' is never used.
{
wl_resource_destroy(resource->handle);
}

void treeland_prelaunch_splash_manager_v1_create_splash(
void treeland_prelaunch_splash_manager_v2_create_splash(

Check warning on line 81 in src/modules/prelaunch-splash/prelaunchsplash.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_prelaunch_splash_manager_v2_create_splash' is never used.
Resource *resource,
uint32_t id,
const QString &app_id,
const QString &instance_id,
const QString &sandboxEngineName,
struct ::wl_resource *icon_buffer) override
{
Q_UNUSED(resource);
qCInfo(prelaunchSplash)
<< "create_splash request sandbox=" << sandboxEngineName << " app_id=" << app_id;
<< "create_splash request sandbox=" << sandboxEngineName
<< " app_id=" << app_id << " instance_id=" << instance_id;

auto *splashResource =
wl_resource_create(resource->client(),
&treeland_prelaunch_splash_v2_interface,
wl_resource_get_version(resource->handle),
id);
if (!splashResource) {
wl_resource_post_no_memory(resource->handle);
return;
}

// SplashResource self-destructs via destroy_resource callback
new SplashResource(q, splashResource, app_id, instance_id);

auto qb = icon_buffer ? QW_NAMESPACE::qw_buffer::try_from_resource(icon_buffer) : nullptr;
Q_EMIT q->splashRequested(app_id, qb);
Q_EMIT q->splashRequested(app_id, instance_id, qb);
}

private:
Expand All @@ -69,9 +123,8 @@
{
if (d->isGlobal())
return;
// server->handle() returns qw_display* which can be implicitly converted to wl_display*
d->init(*server->handle(), TREELAND_PRELAUNCH_SPLASH_MANAGER_V1_VERSION);
qCDebug(prelaunchSplash) << "PrelaunchSplash global created";
d->init(*server->handle(), TREELAND_PRELAUNCH_SPLASH_MANAGER_V2_VERSION);
qCDebug(prelaunchSplash) << "PrelaunchSplash v2 global created";
}

void PrelaunchSplash::destroy(WAYLIB_SERVER_NAMESPACE::WServer *server)
Expand All @@ -80,7 +133,7 @@
if (!d->isGlobal())
return;
d->globalRemove();
qCDebug(prelaunchSplash) << "PrelaunchSplash global removed";
qCDebug(prelaunchSplash) << "PrelaunchSplash v2 global removed";
}

wl_global *PrelaunchSplash::global() const
Expand All @@ -90,7 +143,7 @@

QByteArrayView PrelaunchSplash::interfaceName() const
{
return QtWaylandServer::treeland_prelaunch_splash_manager_v1::interfaceName();
return QtWaylandServer::treeland_prelaunch_splash_manager_v2::interfaceName();
}

// End of file
5 changes: 4 additions & 1 deletion src/modules/prelaunch-splash/prelaunchsplash.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ class PrelaunchSplash
~PrelaunchSplash() override;

Q_SIGNALS:
void splashRequested(const QString &appId, QW_NAMESPACE::qw_buffer *iconBuffer);
void splashRequested(const QString &appId,
const QString &instanceId,
QW_NAMESPACE::qw_buffer *iconBuffer);
void splashCloseRequested(const QString &appId, const QString &instanceId);

protected: // WServerInterface
void create(WAYLIB_SERVER_NAMESPACE::WServer *server) override;
Expand Down
13 changes: 11 additions & 2 deletions src/seat/helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1229,9 +1229,18 @@ void Helper::init(Treeland::Treeland *treeland)
connect(m_prelaunchSplash,
&PrelaunchSplash::splashRequested,
m_shellHandler,
[this](const QString &appId, QW_NAMESPACE::qw_buffer *iconBuffer) {
[this](const QString &appId,
const QString &instanceId,
QW_NAMESPACE::qw_buffer *iconBuffer) {
if (m_shellHandler)
m_shellHandler->handlePrelaunchSplashRequested(appId, iconBuffer);
m_shellHandler->handlePrelaunchSplashRequested(appId, instanceId, iconBuffer);
});
connect(m_prelaunchSplash,
&PrelaunchSplash::splashCloseRequested,
m_shellHandler,
[this](const QString &appId, const QString &instanceId) {
if (m_shellHandler)
m_shellHandler->handlePrelaunchSplashClosed(appId, instanceId);
});
connect(m_ddeShellV1, &DDEShellManagerInterfaceV1::toggleMultitaskview, this, [this] {
if (m_multitaskView) {
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ add_subdirectory(test_protocol_shortcut)
add_subdirectory(test_protocol_virtual-output)
add_subdirectory(test_protocol_wallpaper-color)
add_subdirectory(test_protocol_window-management)
add_subdirectory(test_protocol_prelaunch-splash)
19 changes: 19 additions & 0 deletions tests/test_protocol_prelaunch-splash/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
find_package(Qt6 REQUIRED COMPONENTS Test)

add_executable(test_protocol_prelaunch-splash main.cpp)

target_link_libraries(test_protocol_prelaunch-splash
PRIVATE
libtreeland
Qt::Test
)

add_test(NAME test_protocol_prelaunch-splash COMMAND test_protocol_prelaunch-splash)

set_property(TEST test_protocol_prelaunch-splash PROPERTY
ENVIRONMENT "QT_QPA_PLATFORM=offscreen"
)

set_property(TEST test_protocol_prelaunch-splash PROPERTY
TIMEOUT 3
)
65 changes: 65 additions & 0 deletions tests/test_protocol_prelaunch-splash/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (C) 2025 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "modules/prelaunch-splash/prelaunchsplash.h"

Check warning on line 4 in tests/test_protocol_prelaunch-splash/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "modules/prelaunch-splash/prelaunchsplash.h" not found.

#include <wserver.h>

Check warning on line 6 in tests/test_protocol_prelaunch-splash/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <wserver.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <QObject>

Check warning on line 8 in tests/test_protocol_prelaunch-splash/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QObject> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QSignalSpy>
#include <QTest>

class PrelaunchSplashTest : public QObject
{
Q_OBJECT

WAYLIB_SERVER_NAMESPACE::WServer *m_server = nullptr;
PrelaunchSplash *m_protocol = nullptr;

public:
PrelaunchSplashTest(QObject *parent = nullptr)
: QObject(parent)
{
}

private Q_SLOTS:

void initTestCase()
{
m_server = new WAYLIB_SERVER_NAMESPACE::WServer();
}

void testCreate()
{
m_protocol = m_server->attach<PrelaunchSplash>();
QVERIFY(m_protocol != nullptr);
}

void verifyPrelaunchSplash()
{
QVERIFY(m_protocol != nullptr);
}

void testSignals()
{
QVERIFY(m_protocol != nullptr);

QSignalSpy splashRequestedSpy(m_protocol,
&PrelaunchSplash::splashRequested);
QVERIFY(splashRequestedSpy.isValid());

QSignalSpy splashCloseSpy(m_protocol,
&PrelaunchSplash::splashCloseRequested);
QVERIFY(splashCloseSpy.isValid());
}

void cleanupTestCase()
{
m_server->deleteLater();
m_server = nullptr;
m_protocol = nullptr;
}
};

QTEST_MAIN(PrelaunchSplashTest)
#include "main.moc"