Skip to content

protocols: add treeland-cross-subsurface-unstable-v1 - #56

Open
wineee wants to merge 1 commit into
linuxdeepin:masterfrom
wineee:subsurface
Open

protocols: add treeland-cross-subsurface-unstable-v1#56
wineee wants to merge 1 commit into
linuxdeepin:masterfrom
wineee:subsurface

Conversation

@wineee

@wineee wineee commented May 12, 2026

Copy link
Copy Markdown
Member

treeland_cross_subsurface_unstable_v1 设计文档

1. 背景与问题

1.1 Wayland 的进程隔离限制

标准 wl_subcompositor 要求 parent 和 child 的 wl_surface 来自同一个 wl_compositor(即同一个客户端连接)。这意味着跨进程的 subsurface 关系在标准协议下是不可能的。

1.2 X11 的做法

X11 中 XReparentWindow() 是服务端操作,任何 X 客户端都可以把窗口 reparent 到另一个 X 窗口下,没有进程隔离限制。所有 Wine 进程共享同一个 gdi_display,跨进程父子窗口关系天然支持。

X11 驱动中 attach_client_window()winex11.drv/window.c:2309)通过 XReparentWindow() 将 client window 嵌入 parent 的 whole_window,即使 parent 属于另一个进程也能正常工作。当跨进程 parent 查找失败时(get_win_data(toplevel) 返回 NULL),X11 只是跳过坐标偏移修正,client window 仍然正常存在和渲染。

1.3 Wine Wayland 后端的现状

Wine 的 winewayland.drv 中有两类 subsurface:

  1. wayland_surface 的 wl_subsurfacewayland_surface.c:305):WS_CHILD 窗口作为 toplevel 的 subsurface
  2. wayland_client_surface 的 wl_subsurfacewayland_surface.c:1179):OpenGL/Vulkan 渲染区域作为 toplevel 的 subsurface

两者都通过 wl_subcompositor_get_subsurface() 创建,必须在同一进程内。

wayland_client_surface_attach()wayland_surface.c:1150)中,当 toplevel 属于另一个进程时:

if (!(toplevel_data = wayland_win_data_get_nolock(toplevel)) || !(surface = toplevel_data->wayland_surface))
{
    wayland_client_surface_attach(client, NULL);  // 直接 detach,渲染丢失
    return;
}

wayland_win_data_get_nolock() 只能查找当前进程的红黑树,跨进程查找返回 NULL,导致 client_surface 被 detach。

1.4 触发场景

实际触发跨进程失败需要同时满足三个条件:

  1. 窗口使用 OpenGL/Vulkan 渲染(有 wayland_client_surface
  2. 窗口 !managed(无 caption/thickframe/sysmenu/WS_EX_APPWINDOW)
  3. owner_hint(来自 GW_OWNERNtUserWindowFromPoint)指向另一个进程

这在真实应用中极为罕见,因为使用 GPU 渲染的窗口几乎总是有 caption 或 thickframe,会被判为 managed。但协议设计应覆盖这类场景以保证完整性。

1.5 place_above 的实际使用模式

Wine 中 place_above 只引用两种目标(wayland_surface.c:611-694):

  • parent 的 wl_surface(toplevel 窗口表面本身)
  • parent 的 client_surface->wl_surface(OpenGL/Vulkan 渲染区域)

并且只在 if/else 分支中使用,不需要引用任意中间 subsurface。

2. 设计目标

  1. 通用性:协议不耦合 Wine,任何 Wayland 客户端都可以使用
  2. 兼容性:语义尽可能对齐 wl_subcompositor,减少客户端适配成本
  3. 统一 ID 空间:parent、sibling(标准 + 跨进程)共用一个 uint32 命名空间
  4. compositor 透明:标准 wl_subcompositor 创建的 subsurface 也能被自动纳入 ID 管理

3. 协议设计

3.1 整体架构

treeland_subsurface_manager_v1 (global)
├── export_surface(surface) → treeland_exported_surface_v1
│   ├── surface_id 事件:分配 parent ID
│   ├── child_entered 事件:标准 wl_subsurface 进入时分配 sibling ID
│   └── child_left 事件:标准 wl_subsurface 离开时回收 ID
│
└── create_remote_subsurface(surface, parent_id) → treeland_remote_subsurface_v1
    ├── subsurface_id 事件:分配跨进程 subsurface 的 sibling ID
    ├── parent_geometry 事件:parent 几何信息(坐标换算用)
    └── parent_destroyed 事件:parent 销毁通知

3.2 ID 命名空间

所有 ID(surface_id 和 subsurface_id)在同一个 uint32 命名空间中:

值范围              | 含义
[1, 0xFFFFFFFE]    | compositor 分配的有效 ID
0                  | 保留(无效值,触发 bad_sibling 错误)
0xFFFFFFFF         | 保留(sibling_ref.top,放到 sibling 栈顶)

ID 来源有三个:

来源 接口 分配时机
exported surface treeland_exported_surface_v1.surface_id export_surface 后立即
standard subsurface treeland_exported_surface_v1.child_entered wl_subcompositor.get_subsurface 时自动
remote subsurface treeland_remote_subsurface_v1.subsurface_id create_remote_subsurface 后立即

compositor 内部维护一个全局 ID 分配器,保证三个来源不重复。

3.3 核心机制:标准 subsurface 的自动发现

compositor 在以下时机自动追踪标准 wl_subcompositor subsurface:

  1. 监听 wl_subcompositor.get_subsurface(surface, parent) 请求
  2. 如果 parent 是一个已 export 的 surface,为其 child 分配 subsurface_id
  3. 通过 child_entered 事件通知 export owner
  4. 通过 child_left 事件通知 export owner(wl_subsurface 销毁时)

这个机制不需要改动标准 wl_subcompositor 协议,完全在 compositor 侧实现。

3.4 与 wl_subcompositor 的对应关系

wl_subcompositor treeland_cross_subsurface 变化
get_subsurface(id, surface, parent) create_remote_subsurface(id, surface, parent_id) parent: wl_surface → uint32
set_position(x, y) set_position(x, y) 不变
place_above(sibling: wl_surface) place_above(sibling_ref: uint32) sibling: wl_surface → uint32
place_below(sibling: wl_surface) place_below(sibling_ref: uint32) 同上
set_sync() set_sync() 不变
set_desync() set_desync() 不变
(无) subsurface_id 事件 新增:跨进程标识
(无) parent_geometry 事件 新增:坐标换算依据
(无) parent_destroyed 事件 新增:生命周期通知
(无) export_surface + surface_id 新增:parent export 机制
(无) child_entered / child_left 新增:标准 subsurface 自动发现

3.5 place_above / place_below 的 sibling_ref 语义

<!-- sibling_ref 值 -->  <!-- 含义 -->
parent_id             <!-- parent surface 自身 -->
sibling_subsurface_id <!-- 任意 sibling(标准或跨进程) -->
0xFFFFFFFF            <!-- 栈顶 -->
0                     <!-- 无效,触发 bad_sibling 错误 -->

示例:place_above(sibling_ref = parent_id) 等价于标准协议中的
place_above(parent_wl_surface)

3.6 parent_geometry 事件

跨进程后,子进程没有 parent 的 wl_surface proxy,无法直接获取 parent 的
buffer_scale 和 buffer_transform。parent_geometry 事件提供这些信息:

  • x, y:parent 在 compositor 全局逻辑坐标系中的原点位置
  • scale:parent 的 wl_surface.buffer_scale
  • transform:parent 的 wl_surface.buffer_transform(遵循 wl_output.transform 语义)

子进程使用这些值将自身逻辑坐标转换为 parent 的 surface-local 坐标后传给 set_position()

4. Compositor 侧实现要点

4.1 ID 管理

class SubsurfaceIdAllocator {
    uint32_t next_id = 1;

    uint32_t allocate() {
        // 跳过 0 和 0xFFFFFFFF
        uint32_t id = next_id++;
        if (id == 0) id = next_id++;
        if (id == 0xFFFFFFFF) id = next_id++;
        return id;
    }
};

所有 ID(exported surface、standard subsurface、remote subsurface)通过同一个分配器管理。

4.2 标准 subsurface 监听

compositor 在处理 wl_subcompositor.get_subsurface 时:

void on_subcompositor_get_subsurface(wl_subcompositor *subcompositor,
                                     wl_surface *surface,
                                     wl_surface *parent)
{
    // 检查 parent 是否是已 export 的 surface
    auto export = find_export(parent);
    if (!export) return;  // 标准 subsurface,不干预

    // 分配 subsurface_id,通知 export owner
    uint32_t id = allocator.allocate();
    export->send_child_entered(id, surface);
    track_standard_subsurface(surface, export, id);
}

4.3 place_above / place_below 处理

void on_place_above(RemoteSubsurface *self, uint32_t sibling_ref)
{
    Surface *sibling;

    if (sibling_ref == 0) {
        // 错误:无效值
        self->send_bad_sibling();
        return;
    }

    if (sibling_ref == 0xFFFFFFFF) {
        // 栈顶
        restack_to_top(self);
        return;
    }

    // 在 parent 的所有 subsurface(标准 + 跨进程)中查找
    sibling = find_surface_by_id(self->parent, sibling_ref);
    if (!sibling || !is_sibling_of(self, sibling)) {
        self->send_bad_sibling();
        return;
    }

    restack_above(self, sibling);
}

4.4 安全策略

compositor 应通过以下机制限制访问:

  1. 绑定控制:只允许受信任的客户端绑定 treeland_subsurface_manager_v1(通过 app-id 或 PID 白名单)
  2. parent_id 验证create_remote_subsurface 时验证 parent_id 对应的 export 属于受信任的客户端
  3. 进程隔离:child_entered 事件中的 wl_surface 参数只在 export owner 的连接中有效,其他客户端无法通过这个 proxy 操作 surface

5. Wine 集成方案

5.1 与现有 wine_window_management 的关系

treeland_wine_window_management_v1window_id 和本协议的 surface_id
是两个独立系统,各自有独立的命名空间。Wine driver 需要在 wineserver 共享内存
中同时维护两套映射:

wineserver 共享内存布局:
{
    HWND -> {
        window_id,       // 来自 wine_window_management(z-order 用)
        surface_id,      // 来自 cross_subsurface(subsurface parent/sibling 用)
    }
}

5.2 集成流程

进程 A (parent):
  1. wine_window_management.get_window_control(toplevel)
     → window_id = 42
  2. cross_subsurface.export_surface(toplevel)
     → surface_id = 100
  3. wl_subcompositor.get_subsurface(client_surface, toplevel)
     → compositor 自动触发 child_entered(subsurface_id=200, client_surface)
  4. wineserver 共享: {toplevel: surface_id=100, client_surface: subsurface_id=200}

进程 B (child):
  1. wineserver 查表 → parent surface_id = 100, sibling client_surface subsurface_id = 200
  2. cross_subsurface.create_remote_subsurface(my_surface, parent_id=100)
     → subsurface_id = 300
  3. set_desync()
  4. set_position(x, y)              // 用 parent_geometry 事件算坐标
  5. place_above(sibling_ref=200)    // above parent 的 OpenGL 渲染区
  6. place_above(sibling_ref=100)    // above parent 自身(window frame)
  7. place_above(0xFFFFFFFF)         // 栈顶

5.3 修改点(winewayland.drv)

需要修改的函数:

函数 文件:行 当前行为 修改后
wayland_client_surface_attach() wayland_surface.c:1169 找不到 toplevel 时 detach 尝试通过 surface_id 创建 remote_subsurface
wayland_surface_make_subsurface() wayland_surface.c:294 只找本进程 toplevel_surface 跨进程时使用 create_remote_subsurface
wayland_surface_reconfigure_subsurface() wayland_surface.c:673 调用 wl_subsurface_set_position 跨进程时使用 remote_subsurface.set_position
wayland_surface_reconfigure_client() wayland_surface.c:588 调用 wl_subsurface_place_above 跨进程时使用 remote_subsurface.place_above

6. 与 xdg-foreign-v2 的对比

特性 xdg-foreign-v2 treeland_cross_subsurface
目标 窗口间 stacking(类似 X11 transient) 完整的 subsurface 语义
导出粒度 仅 xdg_toplevel 任意 wl_surface
子 surface 的位置控制 无(依赖 WM) set_position
同步/异步模式 set_sync/set_desync
sibling 排序 place_above/place_below
内容渲染 子进程独立渲染 子进程独立渲染
适用场景 对话框、弹出菜单 嵌入式渲染、子窗口

xdg-foreign-v2 只解决了 "把我的窗口放在另一个窗口上面" 的问题,而
treeland_cross_subsurface 解决的是 "把我的 surface 作为另一个 surface 的子 surface"
——包括定位、同步、排序在内的完整 subsurface 语义。

Summary by Sourcery

Introduce a new treeland cross-process subsurface Wayland protocol and register it in the build system.

New Features:

  • Add treeland_cross_subsurface_unstable_v1 protocol XML defining cross-process subsurface management and geometry/stacking semantics.
  • Register the new cross-subsurface protocol XML in CMake so it is installed with other treeland protocols.

@deepin-ci-robot

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: wineee

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

@deepin-bot

deepin-bot Bot commented May 22, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.5.7
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #60

@deepin-bot

deepin-bot Bot commented Jun 4, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.5.8
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #71

@deepin-bot

deepin-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.5.9
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #74

Comment thread xml/treeland-cross-subsurface-unstable-v1.xml Outdated
@wineee
wineee force-pushed the subsurface branch 2 times, most recently from b9942be to 7939e38 Compare August 3, 2026 07:40
@wineee
wineee requested a review from Copilot August 3, 2026 07:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Treeland Wayland protocol XML specification to support cross-process subsurface relationships, and wires it into the build/install list so it ships with the rest of the protocol set.

Changes:

  • Introduces treeland_cross_subsurface_unstable_v1 protocol with manager/export/remote-subsurface interfaces and token-based parenting/sibling references.
  • Adds the new XML to the top-level CMakeLists.txt XML install list.

Reviewed changes

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

File Description
xml/treeland-cross-subsurface-unstable-v1.xml New protocol specification for exporting surfaces and creating cross-process subsurfaces, including sibling restacking and parent geometry events.
CMakeLists.txt Installs the new protocol XML alongside existing Treeland protocols.
Suppressed comments (3)

xml/treeland-cross-subsurface-unstable-v1.xml:339

  • The place_above description contradicts itself: it says using an empty string causes bad_sibling, but later lists "" as a valid sentinel for "top". This should be consistent so clients/implementations don’t diverge.
                of the sub-surfaces.  The reference surface must be
                identified by a valid sibling_token, or the parent's
                surface_token.  Using an empty string or any
                unrecognized token will cause a bad_sibling protocol
                error.

xml/treeland-cross-subsurface-unstable-v1.xml:223

  • surface_destroyed does not explicitly say what happens to surface_token / subsurface_token validity. Since create_remote_subsurface requires a live exported surface, it should be explicit that tokens are revoked once the underlying wl_surface is destroyed.
                The underlying wl_surface was destroyed.  This
                treeland_exported_surface_v1 object is now inert.
                No further events will be emitted.  The client
                should destroy this object.
            </description>

xml/treeland-cross-subsurface-unstable-v1.xml:40

  • PR description explicitly includes set_sync/set_desync behavior aligned with wl_subcompositor, but the XML states synchronized mode is not supported and treeland_remote_subsurface_v1 has no set_sync/set_desync requests. Please reconcile the design doc and the protocol surface so clients know which behavior is actually supported.
        sub-surfaces are always in desynchronized mode; synchronized
        mode is not supported.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread xml/treeland-cross-subsurface-unstable-v1.xml Outdated
Comment thread xml/treeland-cross-subsurface-unstable-v1.xml Outdated
Comment thread xml/treeland-cross-subsurface-unstable-v1.xml Outdated
Comment thread xml/treeland-cross-subsurface-unstable-v1.xml Outdated
Comment thread xml/treeland-cross-subsurface-unstable-v1.xml Outdated
@wineee
wineee force-pushed the subsurface branch 5 times, most recently from f16f0b3 to 285d462 Compare August 3, 2026 09:54
@wineee
wineee requested a review from Copilot August 3, 2026 09:55

Copilot AI left a comment

Copy link
Copy Markdown

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 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (3)

xml/treeland-cross-subsurface-unstable-v1.xml:25

  • The protocol description and API use UUID string tokens (surface_token/subsurface_token, empty-string sentinel for top), but the PR description/design doc describes a uint32 ID namespace (including reserved values 0 and 0xFFFFFFFF) plus automatic discovery of standard wl_subsurface children (child_entered/child_left). Please reconcile the spec and the PR description so clients have one authoritative contract (either update this XML to match the uint32-based design, or update the PR description to reflect the token-based protocol actually being added).
        client.  This protocol removes that restriction by using
        UUID-based tokens exchanged out-of-band:

        1. A client exports a wl_surface and receives a surface_token.

        2. Another client provides that surface_token with its own
           local wl_surface to create a cross-process sub-surface.

        3. Each cross-process sub-surface receives a subsurface_token
           that can be used as a sibling reference in place_above
           and place_below.

xml/treeland-cross-subsurface-unstable-v1.xml:131

  • This text makes destruction ordering a hard "must" but does not define what happens if the wl_surface is destroyed first (and there is no specific protocol error for this case). Other Treeland protocols either enforce ordering with an explicit protocol error or document inert behavior. Consider relaxing this to "should" and documenting compositor behavior when the wl_surface is destroyed first.
                The client must destroy this object before
                destroying the associated wl_surface.

xml/treeland-cross-subsurface-unstable-v1.xml:215

  • place_above's description currently says that using an empty string or an unrecognized token in place_below is a bad_sibling error, which is both confusing (wrong request name) and contradicts the earlier statement that empty string is a valid sentinel for place_above. This should describe place_above's own error behavior (unrecognized sibling_token) and leave place_below rules to the place_below section.
                - An empty string (""), a sentinel meaning
                  "place at the very top of the sibling stack".

                Using an empty string or any unrecognized token in
                place_below results in a bad_sibling protocol error.

@wineee
wineee marked this pull request as ready for review August 4, 2026 02:28
@sourcery-ai

sourcery-ai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a new Wayland protocol XML definition for cross-process sub-surface compositing (treeland-cross-subsurface-unstable-v1) and wires it into the build/install, defining manager, exported-surface, and remote-subsurface interfaces with token-based cross-client parenting and stacking semantics.

Sequence diagram for cross-process remote subsurface creation and stacking

sequenceDiagram
    participant Client_A
    participant Client_B
    participant Compositor
    participant treeland_subsurface_manager_v1

    Client_A->>treeland_subsurface_manager_v1: export_surface(id, surface)
    treeland_subsurface_manager_v1->>Client_A: surface_token(token)

    Client_B->>treeland_subsurface_manager_v1: export_surface(id, surface)
    treeland_subsurface_manager_v1->>Client_B: surface_token(child_token)

    Client_B->>Compositor: create_remote_subsurface(id, parent_token)
    Compositor->>Client_B: parent_geometry(x, y, scale, transform)

    Client_B->>Compositor: set_position(x, y)
    Client_B->>Compositor: place_above(sibling_token)
Loading

File-Level Changes

Change Details Files
Introduce treeland_cross_subsurface_unstable_v1 protocol and register it in the CMake XML list so it is generated and installed with other treeland protocols.
  • Extend top-level CMakeLists.txt XML list to include the new treeland-cross-subsurface-unstable-v1.xml protocol file so it participates in code generation and installation.
  • Define treeland_subsurface_manager_v1 interface as a global factory for exporting wl_surface objects and emitting treeland_exported_surface_v1, with error handling for duplicate exports.
  • Define treeland_exported_surface_v1 interface that assigns a UUID surface_token to a wl_surface, supports revocation via destroy, and allows creation of treeland_remote_subsurface_v1 given a parent_token.
  • Define treeland_remote_subsurface_v1 interface that attaches a wl_surface as a cross-process sub-surface with set_position, place_above/place_below using token-based sibling references, and lifecycle/geometry events such as parent_geometry and parent_destroyed.
  • Specify protocol semantics and constraints: cross-process subsurfaces are always desynchronized, keyboard focus rules, error enums (bad_surface, bad_parent_token, bad_sibling), and use of UUID strings as tokens for parent and sibling identification.
CMakeLists.txt
xml/treeland-cross-subsurface-unstable-v1.xml

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

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

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 protocol XML diverges significantly from the accompanying design document (UUID tokens vs uint32 IDs, no automatic tracking of standard wl_subsurface children, no set_sync/set_desync, different place_above semantics); consider aligning the implementation with the documented design or updating the design doc to match the actual protocol.
  • Error handling and role constraints around export_surface/create_remote_subsurface are a bit unclear (two different bad_surface meanings, parent_token errors placed on treeland_exported_surface rather than the manager); tightening and documenting the exact role compatibility and where each error is raised would make the protocol semantics easier to implement correctly.
  • The sibling reference model only allows siblings identified via shared UUID tokens and does not integrate standard wl_subcompositor subsurfaces as siblings under the same parent; if you intend to support mixed standard and cross-process subsurface trees as in the design doc, you may want to introduce events or IDs that expose compositor-tracked standard subsurfaces.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The protocol XML diverges significantly from the accompanying design document (UUID tokens vs uint32 IDs, no automatic tracking of standard wl_subsurface children, no set_sync/set_desync, different place_above semantics); consider aligning the implementation with the documented design or updating the design doc to match the actual protocol.
- Error handling and role constraints around export_surface/create_remote_subsurface are a bit unclear (two different bad_surface meanings, parent_token errors placed on treeland_exported_surface rather than the manager); tightening and documenting the exact role compatibility and where each error is raised would make the protocol semantics easier to implement correctly.
- The sibling reference model only allows siblings identified via shared UUID tokens and does not integrate standard wl_subcompositor subsurfaces as siblings under the same parent; if you intend to support mixed standard and cross-process subsurface trees as in the design doc, you may want to introduce events or IDs that expose compositor-tracked standard subsurfaces.

## Individual Comments

### Comment 1
<location path="xml/treeland-cross-subsurface-unstable-v1.xml" line_range="112-121" />
<code_context>
+        <request name="create_remote_subsurface">
</code_context>
<issue_to_address>
**question:** Specify whether a surface can be its own parent via parent_token to avoid undefined self-parenting.

The spec says the exported surface "may act as a parent" and that `create_remote_subsurface` attaches "this surface" to the `parent_token`, but it’s unclear whether passing this surface’s own `surface_token` as `parent_token` is allowed. Self-parenting could lead to ambiguous stacking and mapping behavior. Please either explicitly forbid using the same exported surface as both parent and child, or clearly define the semantics if self-parenting is supported.
</issue_to_address>

### Comment 2
<location path="xml/treeland-cross-subsurface-unstable-v1.xml" line_range="207-216" />
<code_context>
+        <request name="place_above">
</code_context>
<issue_to_address>
**suggestion:** Define behavior when sibling_token refers to this sub-surface itself to avoid ambiguous restacking.

The protocol should define what happens if `sibling_token` refers to this sub-surface itself, since valid values include the parent and sibling cross-process sub-surfaces. Without a specified behavior (e.g., explicit no-op vs. `bad_sibling`), implementations may diverge, leading to inconsistent restacking semantics.
</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.

Comment thread xml/treeland-cross-subsurface-unstable-v1.xml
Comment thread xml/treeland-cross-subsurface-unstable-v1.xml
@wineee
wineee force-pushed the subsurface branch 2 times, most recently from dae4078 to da27f83 Compare August 4, 2026 03:04
Add a new protocol and its design document for cross-process
sub-surface compositing.

treeland_cross_subsurface_unstable_v1 extends wl_subcompositor
semantics to surfaces belonging to different client connections.
Surfaces are exported via treeland_exported_surface_v1, receiving
a numeric surface_id that can be shared out-of-band.  A remote
client attaches its own wl_surface as a sub-surface by passing the
parent's surface_id to create_remote_subsurface, obtaining a
treeland_remote_subsurface_v1 that mirrors the full wl_subsurface
API (set_position, place_above/below, set_sync/desync).

Standard wl_subcompositor sub-surfaces created under an exported
surface are automatically tracked by the compositor and reported
via child_entered / child_left, assigning them a subsurface_id
that participates in the same numeric namespace.

The primary motivation is Wine's winewayland.drv, where GPU-rendered
child windows belonging to a different Wine process cannot attach
their wl_surface as a sub-surface of the parent's surface today.

docs/cross-subsurface-design.md documents the background, design
rationale, compositor implementation notes, Wine integration plan,
and a comparison with xdg-foreign-v2.
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:100分

■ 【总体评价】

代码实现了跨进程子表面的Wayland协议定义,结构清晰且无安全漏洞
逻辑完全正确且符合Wayland协议规范,无需扣分

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

XML格式及Wayland协议语法完全正确,接口定义、请求、事件和枚举的结构均符合Wayland协议标准。transform参数正确引用了wl_output.transform枚举,place_aboveplace_below对空字符串的处理逻辑差异合理。
潜在问题:版权年份标注为2026年,可能为笔误
建议:核实并修正版权年份为当前实际年份

  • 2.代码质量(优秀)✓

接口命名严格遵循Wayland协议命名规范,错误枚举定义详尽且覆盖了重复导出、无效令牌、循环依赖等异常场景。对双缓冲状态、坐标系统、同步与异步模式等关键语义的描述非常清晰完整。
建议:无

  • 3.代码性能(无性能问题)✓

纯XML协议声明文件,不涉及运行时计算、资源分配或系统调用,无性能开销。
建议:无

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
协议设计充分考虑了跨进程交互的安全边界,明确要求compositor将绑定权限限制在受信任客户端,要求令牌生成必须密码学安全,并强制要求实现检测子表面树中的循环依赖。XML文件使用CDATA包裹文本且未引入外部DTD,无外部实体注入风险。

  • 建议:在后续C++实现该协议时,务必使用密码学安全的随机数生成器生成令牌,并严格按规范实现权限校验和环检测逻辑

■ 【改进建议代码示例】

<?xml version="1.0" encoding="UTF-8"?>
<protocol name="treeland_cross_subsurface_unstable_v1">

    <copyright><![CDATA[
    SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
    SPDX-License-Identifier: MIT
    ]]></copyright>

    <description summary="cross-process sub-surface compositing">
        Extends wl_subcompositor to support sub-surface relationships
        between surfaces belonging to different client connections.
        <!-- 其余协议内容保持不变 -->
    </description>

</protocol>

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.

3 participants