Skip to content

feat: make splash screens visible and closable via foreign-toplevel#745

Merged
zccrs merged 2 commits intolinuxdeepin:masterfrom
wineee:titlebar
Feb 26, 2026
Merged

feat: make splash screens visible and closable via foreign-toplevel#745
zccrs merged 2 commits intolinuxdeepin:masterfrom
wineee:titlebar

Conversation

@wineee
Copy link
Member

@wineee wineee commented Feb 12, 2026

protocol

Added foreign-toplevel protocol integration for splash screens to make them visible and manageable in the dock. Splash screens now appear in the dock with proper identification and can be closed directly from the dock. When a splash screen is closed before the actual application window appears, the matching application window will be automatically closed to maintain consistency.

Key changes:

  1. Register splash screens with foreign-toplevel protocol to appear in dock
  2. Implement splash screen closure handling via dock requests
  3. Track closed splash appIds to close matching application windows
  4. Move foreign-toplevel management from Helper to ShellHandler for better integration
  5. Add proper splash screen identification and state management

Log: Splash screens now appear in dock and can be closed via dock interface

Influence:

  1. Test splash screen visibility in dock for various applications
  2. Verify splash screen closure from dock works correctly
  3. Test that closing splash screen prevents matching application window from opening
  4. Verify normal window behavior remains unchanged after splash integration
  5. Check that skipDockPreView property still works correctly for all surface types
  6. Test application launch with and without splash screen closure

feat: 使闪屏通过foreign-toplevel协议在dock栏可见可关闭

为闪屏添加foreign-toplevel协议集成,使其在dock栏中可见并可管理。闪屏现在
会出现在dock栏中并带有适当标识,可以直接从dock栏关闭。如果在实际应用程序
窗口出现之前关闭闪屏,匹配的应用程序窗口将自动关闭以保持一致性。

主要更改:

  1. 将闪屏注册到foreign-toplevel协议以在dock栏显示
  2. 实现通过dock请求处理闪屏关闭功能
  3. 跟踪已关闭闪屏的appId以关闭匹配的应用程序窗口
  4. 将foreign-toplevel管理从Helper移动到ShellHandler以实现更好集成
  5. 添加适当的闪屏标识和状态管理

Log: 闪屏现在可在dock栏显示并可通过dock界面关闭

Influence:

  1. 测试各种应用程序的闪屏在dock栏中的可见性
  2. 验证从dock栏关闭闪屏功能正常工作
  3. 测试关闭闪屏后是否阻止匹配应用程序窗口打开
  4. 验证闪屏集成后正常窗口行为保持不变
  5. 检查skipDockPreView属性对所有表面类型是否仍正常工作
  6. 测试在有和没有关闭闪屏的情况下应用程序启动行为

Summary by Sourcery

Integrate splash screens with the foreign-toplevel protocol so they appear and can be managed from the dock, and centralize foreign-toplevel handling in ShellHandler.

New Features:

  • Expose splash screen surfaces to the foreign-toplevel protocol so they are visible and closable from the dock.
  • Allow dock-triggered close requests to propagate to splash screens and prevent their corresponding application windows from opening if the splash was closed early.

Enhancements:

  • Move Treeland foreign-toplevel management and dock preview handling from Helper to ShellHandler for better integration with surface lifecycle management.
  • Extend ForeignToplevelV1 to support SplashScreen surfaces with proper identifiers, titles, state tracking, and a unified close path via SurfaceWrapper.
  • Refine skipDockPreView handling and ensure surfaces are removed from dock previews when wrappers are destroyed or marked for removal.

protocol

Added foreign-toplevel protocol integration for splash screens to make
them visible and manageable in the dock. Splash screens now appear in
the dock with proper identification and can be closed directly from
the dock. When a splash screen is closed before the actual application
window appears, the matching application window will be automatically
closed to maintain consistency.

Key changes:
1. Register splash screens with foreign-toplevel protocol to appear
in dock
2. Implement splash screen closure handling via dock requests
3. Track closed splash appIds to close matching application windows
4. Move foreign-toplevel management from Helper to ShellHandler for
better integration
5. Add proper splash screen identification and state management

Log: Splash screens now appear in dock and can be closed via dock
interface

Influence:
1. Test splash screen visibility in dock for various applications
2. Verify splash screen closure from dock works correctly
3. Test that closing splash screen prevents matching application window
from opening
4. Verify normal window behavior remains unchanged after splash
integration
5. Check that skipDockPreView property still works correctly for all
surface types
6. Test application launch with and without splash screen closure

feat: 使闪屏通过foreign-toplevel协议在dock栏可见可关闭

为闪屏添加foreign-toplevel协议集成,使其在dock栏中可见并可管理。闪屏现在
会出现在dock栏中并带有适当标识,可以直接从dock栏关闭。如果在实际应用程序
窗口出现之前关闭闪屏,匹配的应用程序窗口将自动关闭以保持一致性。

主要更改:
1. 将闪屏注册到foreign-toplevel协议以在dock栏显示
2. 实现通过dock请求处理闪屏关闭功能
3. 跟踪已关闭闪屏的appId以关闭匹配的应用程序窗口
4. 将foreign-toplevel管理从Helper移动到ShellHandler以实现更好集成
5. 添加适当的闪屏标识和状态管理

Log: 闪屏现在可在dock栏显示并可通过dock界面关闭

Influence:
1. 测试各种应用程序的闪屏在dock栏中的可见性
2. 验证从dock栏关闭闪屏功能正常工作
3. 测试关闭闪屏后是否阻止匹配应用程序窗口打开
4. 验证闪屏集成后正常窗口行为保持不变
5. 检查skipDockPreView属性对所有表面类型是否仍正常工作
6. 测试在有和没有关闭闪屏的情况下应用程序启动行为
@sourcery-ai
Copy link

sourcery-ai bot commented Feb 12, 2026

Reviewer's Guide

Integrates splash screens with the Treeland foreign-toplevel protocol so they appear and are controllable from the dock, centralizes foreign-toplevel handling in ShellHandler, and ensures that closing a splash from the dock prevents the corresponding app window from opening while keeping dock previews in sync with surface lifecycle and skipDockPreView state.

Sequence diagram for closing a splash from dock and suppressing the app window

sequenceDiagram
    actor User
    participant DockUI
    participant ForeignToplevelV1
    participant ToplevelHandle_Splash
    participant SurfaceWrapper_Splash
    participant ShellHandler
    participant AppLauncher
    participant WXdgToplevelSurface
    participant SurfaceWrapper_App

    User->>DockUI: Click close on splash icon
    DockUI->>ForeignToplevelV1: requestClose for splash identifier
    ForeignToplevelV1->>ToplevelHandle_Splash: emit requestClose
    ToplevelHandle_Splash->>SurfaceWrapper_Splash: close()
    activate SurfaceWrapper_Splash
    SurfaceWrapper_Splash->>SurfaceWrapper_Splash: m_type == SplashScreen
    SurfaceWrapper_Splash-->>ShellHandler: requestCloseSplash()
    deactivate SurfaceWrapper_Splash

    activate ShellHandler
    ShellHandler->>ShellHandler: insert appId into m_closedSplashAppIds
    ShellHandler->>ShellHandler: remove wrapper from m_prelaunchWrappers
    ShellHandler->>SurfaceWrapper_Splash: destroy via RootSurfaceContainer
    deactivate ShellHandler

    User->>AppLauncher: Launch app (after splash closed)
    AppLauncher->>WXdgToplevelSurface: create toplevel surface
    WXdgToplevelSurface-->>ShellHandler: onXdgToplevelSurfaceAdded(surface)
    activate ShellHandler
    ShellHandler->>ShellHandler: async resolve appId
    ShellHandler->>ShellHandler: ensureXdgWrapper(surface, targetAppId)
    alt appId was in m_closedSplashAppIds
        ShellHandler->>WXdgToplevelSurface: close()
        ShellHandler->>ShellHandler: remove appId from m_closedSplashAppIds
        ShellHandler-->>WXdgToplevelSurface: return (no wrapper)
    else appId not in m_closedSplashAppIds
        ShellHandler->>SurfaceWrapper_App: create wrapper
        ShellHandler->>ShellHandler: registerSurfaceToForeignToplevel(wrapper)
        ShellHandler-->>SurfaceWrapper_App: surfaceWrapperAdded
    end
    deactivate ShellHandler
Loading

Updated class diagram for ShellHandler, Helper, ForeignToplevelV1, and SurfaceWrapper

classDiagram
    class Helper {
        -RootSurfaceContainer* m_rootSurfaceContainer
        -ShellHandler* m_shellHandler
        -WServer* m_server
        -WForeignToplevel* m_foreignToplevel
        -WExtForeignToplevelListV1* m_extForeignToplevelListV1
        +Helper(QObject* parent)
        +void init(Treeland* treeland)
        +void onSurfaceWrapperAdded(SurfaceWrapper* wrapper)
        +void onSurfaceWrapperAboutToRemove(SurfaceWrapper* wrapper)
    }

    class ShellHandler {
        -RootSurfaceContainer* m_rootSurfaceContainer
        -LayerSurfaceContainer* m_backgroundContainer
        -LayerSurfaceContainer* m_bottomContainer
        -Workspace* m_workspace
        -SurfaceContainer* m_popupContainer
        -WindowConfigStore* m_windowConfigStore
        -ForeignToplevelV1* m_treelandForeignToplevel
        -QList~SurfaceWrapper*~ m_prelaunchWrappers
        -QSet~QString~ m_pendingPrelaunchAppIds
        -QSet~QString~ m_closedSplashAppIds
        -QList~WToplevelSurface*~ m_pendingAppIdResolveToplevels
        -QObject* m_dockPreview
        +ShellHandler(RootSurfaceContainer* rootContainer, WServer* server)
        +Workspace* workspace() const
        +void createComponent(QmlEngine* engine, QQuickItem* parentItem)
        +void initXdgShell(WServer* server)
        +void initLayerShell(WServer* server)
        +WXWayland* createXWayland(WServer* server, const QString& name)
        +void initInputMethodHelper(WServer* server, WSeat* seat)
        +WXWayland* defaultXWaylandSocket() const
        +void setupDockPreview(QObject* dockPreview)
        -- splash management --
        -void createPrelaunchSplash(const QString& appId, uint32_t timeoutMs)
        -void registerSurfaceToForeignToplevel(SurfaceWrapper* wrapper)
        -void setupDockPreview()
        -void onDockPreview(vector~SurfaceWrapper*~ surfaces, WSurface* target, QPoint pos, ForeignToplevelV1::PreviewDirection direction)
        -void onDockPreviewTooltip(QString tooltip, WSurface* target, QPoint pos, ForeignToplevelV1::PreviewDirection direction)
        -void ensureXdgWrapper(WXdgToplevelSurface* surface, const QString& targetAppId)
        -void ensureXwaylandWrapper(WXWaylandSurface* surface, const QString& targetAppId)
        -void setupSurfaceActiveWatcher(SurfaceWrapper* wrapper)
        -void setupSurfaceWindowMenu(SurfaceWrapper* wrapper)
        -void updateLayerSurfaceContainer(SurfaceWrapper* surface)
        <<signal>> void surfaceWrapperAdded(SurfaceWrapper* wrapper)
        <<signal>> void surfaceWrapperAboutToRemove(SurfaceWrapper* wrapper)
    }

    class ForeignToplevelV1 {
        -treeland_foreign_toplevel_manager_v1* m_manager
        -map~SurfaceWrapper*, unique_ptr~treeland_foreign_toplevel_handle_v1~~ m_surfaces
        -uint32_t m_nextIdentifier
        +static ForeignToplevelV1* instance()
        +wl_global* global() const
        +void addSurface(SurfaceWrapper* wrapper)
        +void removeSurface(SurfaceWrapper* wrapper)
        -void initializeToplevelHandle(SurfaceWrapper* wrapper, treeland_foreign_toplevel_handle_v1* handle)
    }

    class SurfaceWrapper {
        <<QQuickItem>>
        -Type m_type
        -bool m_skipDockPreView
        -QString m_appId
        -WToplevelSurface* m_shellSurface
        -QQuickItem* m_surfaceItem
        +QString appId() const
        +bool skipDockPreView() const
        +void setSkipDockPreView(bool skip)
        +bool resize(const QSizeF& size)
        +void close()
        +QRectF titlebarGeometry() const
        +QRectF boundingRect() const
        +void markWrapperToRemoved()
        <<signal>> void requestCloseSplash()
        <<signal>> void skipDockPreViewChanged()
        <<signal>> void surfaceItemCreated()
    }

    class RootSurfaceContainer {
        +void addSurface(SurfaceWrapper* wrapper)
        +SurfaceWrapper* getSurface(WSurface* surface)
        +void destroyForSurface(SurfaceWrapper* wrapper)
    }

    class QmlEngine {
        +QObject* createDockPreview(QQuickItem* parentItem)
        +QObject* createWindowMenu(Helper* helper)
    }

    class DockPreviewQml {
        <<QObject>>
        +void show(vector~SurfaceWrapper*~ surfaces, SurfaceWrapper* dockWrapper, QPoint pos, ForeignToplevelV1::PreviewDirection direction)
        +void showTooltip(QString tooltip, SurfaceWrapper* dockWrapper, QPoint pos, ForeignToplevelV1::PreviewDirection direction)
        +void close()
    }

    Helper --> ShellHandler : owns
    Helper --> RootSurfaceContainer : owns
    Helper --> QmlEngine : uses
    Helper --> WForeignToplevel : uses
    Helper --> WExtForeignToplevelListV1 : uses

    ShellHandler --> RootSurfaceContainer : manages surfaces
    ShellHandler --> ForeignToplevelV1 : registers SurfaceWrapper
    ShellHandler --> QmlEngine : uses
    ShellHandler --> DockPreviewQml : creates and controls

    ForeignToplevelV1 --> SurfaceWrapper : manages handles

    SurfaceWrapper --> RootSurfaceContainer : destroyed by
    SurfaceWrapper --> WToplevelSurface : wraps

    RootSurfaceContainer --> SurfaceWrapper : lookup and lifecycle
    QmlEngine --> DockPreviewQml : creates
Loading

File-Level Changes

Change Details Files
Move Treeland foreign-toplevel and dock preview management from Helper into ShellHandler and wire it to QML.
  • Change ShellHandler constructor to accept WServer, attach ForeignToplevelV1 there, and register it as a QML singleton with meta-type registration for PreviewDirection.
  • Create dock preview QML object in ShellHandler::createComponent and connect ForeignToplevelV1 dock preview and close signals to ShellHandler slots and the dockPreview object.
  • Remove Treeland ForeignToplevelV1, dock preview creation, and related signal handlers from Helper, and update Helper to construct ShellHandler with WServer and delegate component creation.
src/core/shellhandler.cpp
src/core/shellhandler.h
src/seat/helper.cpp
src/seat/helper.h
Register all relevant SurfaceWrapper instances (including splash screens) with ForeignToplevelV1 and keep dock visibility in sync with skipDockPreView and teardown.
  • Introduce ShellHandler::registerSurfaceToForeignToplevel to add/remove SurfaceWrapper to ForeignToplevelV1 depending on skipDockPreView and connect to skipDockPreViewChanged.
  • Call registerSurfaceToForeignToplevel for prelaunch splash wrappers and newly created XDG/XWayland wrappers in ensureXdgWrapper/ensureXwaylandWrapper.
  • In SurfaceWrapper destructor and markWrapperToRemoved, ensure skipDockPreView is set to true so removal signals propagate cleanly to dock state.
  • Relax SurfaceWrapper::setSkipDockPreView so only setting it to false is restricted to XdgToplevel/XWayland; allow setting to true for any type.
src/core/shellhandler.cpp
src/core/shellhandler.h
src/surface/surfacewrapper.cpp
src/surface/surfacewrapper.h
Extend ForeignToplevelV1 to support splash screens and unify toplevel handle initialization and close semantics.
  • Allow ForeignToplevelV1::addSurface to accept splash screen SurfaceWrapper types and create a treeland_foreign_toplevel_handle_v1 with a monotonically increasing identifier.
  • Initialize splash splash handles with title, appId, and default state flags, connect requestClose to SurfaceWrapper::close, and hook surfaceItemCreated to transition into normal toplevel initialization.
  • Factor toplevel initialization into initializeToplevelHandle, moving all title/state wiring and signal connections there, and log registration info; use a stable incrementing identifier instead of raw wl_surface handle bits.
  • Add safety logging when removing a surface that was never registered in ForeignToplevelV1.
src/modules/foreign-toplevel/foreigntoplevelmanagerv1.cpp
src/modules/foreign-toplevel/foreigntoplevelmanagerv1.h
Introduce a unified close API on SurfaceWrapper and use it to make splash screens closable from the dock while tracking closed splash appIds to cancel subsequent real windows.
  • Add SurfaceWrapper::close that emits requestCloseSplash for Type::SplashScreen and calls shellSurface->close() for normal toplevels, plus a requestCloseSplash signal in the header.
  • In ShellHandler::createPrelaunchSplash, connect requestCloseSplash to logic that logs the close, inserts the appId into m_closedSplashAppIds, removes the wrapper from m_prelaunchWrappers, and destroys the splash surface.
  • Augment onXdgToplevelSurfaceAdded/onXWaylandSurfaceAdded to trigger async appId resolve when either prelaunch wrappers or closed splash appIds are present, and in ensureXdgWrapper/ensureXwaylandWrapper, immediately close new surfaces whose resolved appId matches a closed splash (removing the appId from the set).
src/core/shellhandler.cpp
src/core/shellhandler.h
src/surface/surfacewrapper.cpp
src/surface/surfacewrapper.h

Possibly linked issues

  • #N/A: PR implements dock-visible, dock-closable splash screens, directly addressing the issue’s “taskbar cannot close splash” item.
  • #[Bug]: dock 预览功能失效: PR reworks ForeignToplevelV1 surface registration and dock preview handlers, directly addressing incorrect dock preview protocol data.
  • #[Bug]: 通过dock preview 关闭应用崩溃: PR changes dock preview close and foreign-toplevel handling, likely fixing the crash when closing apps from dock preview

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • The new SurfaceWrapper::requestCloseSplash is declared as a slot but used as a signal (e.g. connect(wrapper, &SurfaceWrapper::requestCloseSplash, ...) and Q_EMIT requestCloseSplash()), which will not compile with the new connect syntax; move it to the signals section instead of public Q_SLOTS.
  • In ForeignToplevelV1::addSurface, the set_identifier now uses a static int counter instead of something tied to the underlying surface/handle; consider whether this needs to be stable/unique across the compositor lifetime and make the identifier generation more robust (and thread‑safe) if clients rely on it.
  • The m_closedSplashAppIds set is only pruned when a matching window appears; if an app never creates a window after its splash is closed, the appId will remain in the set indefinitely—consider adding a timeout or cleanup path to avoid unbounded growth over long sessions.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `SurfaceWrapper::requestCloseSplash` is declared as a slot but used as a signal (e.g. `connect(wrapper, &SurfaceWrapper::requestCloseSplash, ...)` and `Q_EMIT requestCloseSplash()`), which will not compile with the new connect syntax; move it to the `signals` section instead of `public Q_SLOTS`.
- In `ForeignToplevelV1::addSurface`, the `set_identifier` now uses a `static int counter` instead of something tied to the underlying surface/handle; consider whether this needs to be stable/unique across the compositor lifetime and make the identifier generation more robust (and thread‑safe) if clients rely on it.
- The `m_closedSplashAppIds` set is only pruned when a matching window appears; if an app never creates a window after its splash is closed, the appId will remain in the set indefinitely—consider adding a timeout or cleanup path to avoid unbounded growth over long sessions.

## Individual Comments

### Comment 1
<location> `src/surface/surfacewrapper.h:330` </location>
<code_context>
     void showOnAllWorkspaceChanged();
     void requestActive();
     void requestInactive();
+    void requestCloseSplash();
     void skipSwitcherChanged();
     void skipDockPreViewChanged();
</code_context>

<issue_to_address>
**issue (bug_risk):** requestCloseSplash should be declared as a signal, not a slot, to match its usage.

`requestCloseSplash` is currently under `public Q_SLOTS`, but in `surfacewrapper.cpp` you use `Q_EMIT requestCloseSplash();` and in `ShellHandler::createPrelaunchSplash` you connect with `&SurfaceWrapper::requestCloseSplash` as if it were a signal. Because it’s not declared under `signals:`, there will be no meta-object entry, so this pointer-to-member connection will fail at runtime (usually with `QObject::connect: No such signal ...`) and the handler won’t be invoked. Please move `requestCloseSplash` to the `signals:` section (or add one) and keep the implementation the same.
</issue_to_address>

### Comment 2
<location> `src/core/shellhandler.h:137` </location>
<code_context>
     WAYLIB_SERVER_NAMESPACE::WLayerShell *m_layerShell = nullptr;
     WAYLIB_SERVER_NAMESPACE::WInputMethodHelper *m_inputMethodHelper = nullptr;
     QList<WAYLIB_SERVER_NAMESPACE::WXWayland *> m_xwaylands;
+    ForeignToplevelV1 *m_treelandForeignToplevel = nullptr;

     QPointer<RootSurfaceContainer> m_rootSurfaceContainer;
</code_context>

<issue_to_address>
**issue (bug_risk):** m_treelandForeignToplevel is used from Helper but declared private, which will not compile.

In `Helper::init` you connect directly to `m_shellHandler->m_treelandForeignToplevel`, but this member is private in `ShellHandler` and `Helper` is not a friend, so this will not compile. Please either add a public accessor (e.g. `ForeignToplevelV1 *treelandForeignToplevel() const`) or route these connections via `ShellHandler` signals instead of accessing its internals directly.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR integrates prelaunch splash screens into Treeland’s ForeignToplevelV1 (dock/preview) so they appear in the dock and can be closed from it, and moves Treeland foreign-toplevel registration responsibilities from Helper into ShellHandler for tighter lifecycle integration.

Changes:

  • Register splash SurfaceWrapper instances with ForeignToplevelV1, including basic metadata and close handling.
  • Centralize Treeland foreign-toplevel surface registration in ShellHandler, including reacting to skipDockPreView changes.
  • Track appIds for splash screens closed from the dock and close the matching real toplevel when it appears.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/surface/surfacewrapper.h Adds a unified close() API and a splash-close request signal hook.
src/surface/surfacewrapper.cpp Implements SurfaceWrapper::close() and adjusts skipDockPreView teardown behavior and validation.
src/seat/helper.h Removes stored Treeland foreign-toplevel manager pointer from Helper.
src/seat/helper.cpp Constructs ShellHandler with WServer and reroutes dock-preview connections to the manager owned by ShellHandler.
src/modules/foreign-toplevel/foreigntoplevelmanagerv1.h Extracts toplevel-handle initialization into a helper method.
src/modules/foreign-toplevel/foreigntoplevelmanagerv1.cpp Extends Treeland foreign-toplevel handling for splash screens and refactors handle initialization.
src/core/shellhandler.h Stores Treeland foreign-toplevel manager and adds tracking for dock-closed splash appIds.
src/core/shellhandler.cpp Registers wrappers (including splash) with Treeland foreign-toplevel and enforces “closed splash cancels real window” behavior.

(中文)
本 PR 将预启动闪屏接入 Treeland 的 ForeignToplevelV1(dock/preview 协议)以便在 dock 中可见并可关闭,并将 Treeland foreign-toplevel 的管理从 Helper 迁移到 ShellHandler,以获得更一致的生命周期与状态联动。

主要改动:

  • 将闪屏 SurfaceWrapper 注册到 ForeignToplevelV1,并支持从 dock 发起关闭。
  • ShellHandler 中集中处理 Treeland foreign-toplevel 的注册/反注册(随 skipDockPreView 动态变化)。
  • 记录从 dock 关闭的闪屏 appId,并在真实窗口出现时自动关闭匹配窗口。

@wineee wineee marked this pull request as draft February 26, 2026 03:26
@wineee wineee force-pushed the titlebar branch 3 times, most recently from d26e0f9 to eaefd9e Compare February 26, 2026 09:06
@wineee wineee requested a review from Copilot February 26, 2026 09:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

1. Moved dock preview functionality from Helper class to ShellHandler
for better code organization
2. Dock preview creation and signal connections are now handled in
ShellHandler::createComponent
3. Added setupDockPreview method to connect foreign toplevel signals
4. Removed dock preview related code from Helper class including
onDockPreview and onDockPreviewTooltip methods
5. Updated ShellHandler::createComponent to accept parentItem parameter
for dock preview creation
6. Adjusted initialization order in Helper::init to pass correct parent
item

1. 将 dock 预览功能从 Helper 类移动到 ShellHandler 以实现更好的代码组织
2. Dock 预览创建和信号连接现在在 ShellHandler::createComponent 中处理
3. 添加 setupDockPreview 方法用于连接 foreign toplevel 信号
4. 从 Helper 类中移除 dock 预览相关代码,包括 onDockPreview 和
onDockPreviewTooltip 方法
5. 更新 ShellHandler::createComponent 以接受 parentItem 参数用于 dock 预
览创建
6. 调整 Helper::init 中的初始化顺序以传递正确的父项
@wineee wineee marked this pull request as ready for review February 26, 2026 09:34
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: wineee, zccrs

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@zccrs zccrs merged commit a9eb979 into linuxdeepin:master Feb 26, 2026
7 of 8 checks passed
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • The new SurfaceWrapper::requestCloseSplash is declared as a slot but used with Q_EMIT and in connect as if it were a signal; this should be declared in the signals section (or split into a dedicated signal and slot) to avoid Qt meta-object issues.
  • ShellHandler declares void setupDockPreview(QObject *dockPreview); in the header but only defines a parameterless setupDockPreview() in the cpp and calls it without arguments; either remove the unused declaration or align the signature and call sites to prevent compilation or ODR problems.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `SurfaceWrapper::requestCloseSplash` is declared as a slot but used with `Q_EMIT` and in `connect` as if it were a signal; this should be declared in the `signals` section (or split into a dedicated signal and slot) to avoid Qt meta-object issues.
- `ShellHandler` declares `void setupDockPreview(QObject *dockPreview);` in the header but only defines a parameterless `setupDockPreview()` in the cpp and calls it without arguments; either remove the unused declaration or align the signature and call sites to prevent compilation or ODR problems.

## Individual Comments

### Comment 1
<location path="src/surface/surfacewrapper.h" line_range="330" />
<code_context>
     void showOnAllWorkspaceChanged();
     void requestActive();
     void requestInactive();
+    void requestCloseSplash();
     void skipSwitcherChanged();
     void skipDockPreViewChanged();
</code_context>
<issue_to_address>
**issue (bug_risk):** requestCloseSplash is declared but not defined, and is used like a signal, which will currently fail to link/work correctly.

In `SurfaceWrapper`, `requestCloseSplash` is declared as a slot in the header but never defined in the `.cpp`, while `ShellHandler::createPrelaunchSplash` connects to `&SurfaceWrapper::requestCloseSplash` and `SurfaceWrapper::close()` emits it. This will cause a linker error and, since it’s in `public Q_SLOTS` instead of `signals`, moc won’t treat it as a signal. If this is meant to be a signal, move it to the `signals` section and let Qt handle it as a signal (no manual implementation needed). If it’s meant to be a slot callable from QML, add a definition and consider renaming to clearly distinguish the signal from the slot.
</issue_to_address>

### Comment 2
<location path="src/core/shellhandler.h" line_range="88-92" />
<code_context>
                                WAYLIB_SERVER_NAMESPACE::WSeat *seat);

     WAYLIB_SERVER_NAMESPACE::WXWayland *defaultXWaylandSocket() const;
+    void setupDockPreview(QObject *dockPreview);
+
 Q_SIGNALS:
</code_context>
<issue_to_address>
**issue (bug_risk):** setupDockPreview is declared with an argument in the header but implemented without one, creating an API mismatch.

In the header, `ShellHandler` declares `void setupDockPreview(QObject *dockPreview);`, but `shellhandler.cpp` only defines `void ShellHandler::setupDockPreview()` (no parameter) and uses `m_dockPreview`. This API mismatch will either produce a linker error if `setupDockPreview(QObject*)` is called, or indicates a stale declaration.

Please either remove the parameterized declaration and keep the no-arg version as a private helper/slot, or update the implementation to take the `QObject *dockPreview` parameter and pass it from callers instead of using `m_dockPreview` directly.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

void showOnAllWorkspaceChanged();
void requestActive();
void requestInactive();
void requestCloseSplash();
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): requestCloseSplash is declared but not defined, and is used like a signal, which will currently fail to link/work correctly.

In SurfaceWrapper, requestCloseSplash is declared as a slot in the header but never defined in the .cpp, while ShellHandler::createPrelaunchSplash connects to &SurfaceWrapper::requestCloseSplash and SurfaceWrapper::close() emits it. This will cause a linker error and, since it’s in public Q_SLOTS instead of signals, moc won’t treat it as a signal. If this is meant to be a signal, move it to the signals section and let Qt handle it as a signal (no manual implementation needed). If it’s meant to be a slot callable from QML, add a definition and consider renaming to clearly distinguish the signal from the slot.

Comment on lines +88 to 92
void setupDockPreview(QObject *dockPreview);

Q_SIGNALS:
void surfaceWrapperAdded(SurfaceWrapper *wrapper);
void surfaceWrapperAboutToRemove(SurfaceWrapper *wrapper);
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): setupDockPreview is declared with an argument in the header but implemented without one, creating an API mismatch.

In the header, ShellHandler declares void setupDockPreview(QObject *dockPreview);, but shellhandler.cpp only defines void ShellHandler::setupDockPreview() (no parameter) and uses m_dockPreview. This API mismatch will either produce a linker error if setupDockPreview(QObject*) is called, or indicates a stale declaration.

Please either remove the parameterized declaration and keep the no-arg version as a private helper/slot, or update the implementation to take the QObject *dockPreview parameter and pass it from callers instead of using m_dockPreview directly.

@wineee wineee deleted the titlebar branch February 26, 2026 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants