Skip to content

feat(dde-shell): adapt to dde-shell-unstable-v2 protocol - #1447

Open
wineee wants to merge 1 commit into
linuxdeepin:masterfrom
wineee:dde-shell-v2
Open

wineee wants to merge 1 commit into
linuxdeepin:masterfrom
wineee:dde-shell-v2

Conversation

@wineee

@wineee wineee commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Implement treeland_dde_shell_manager_v2 and
treeland_dde_shell_surface_v2 (treeland-protocols 0.7.0) and register the v2 global alongside the deprecated v1 one for the migration period. v2 brings a 0-based overlay default role, a set_skip_flags bitfield, mutually exclusive position/cursor placement hints resolved to global coordinates on request, an already_shell_surface error on duplicate creation, destroy as the first request, and auto-destroy of the surface resource when the wl_surface is destroyed.

Make (0,0) a valid fixed position: track position-request presence with an explicit hasClientRequstPos flag instead of the QPoint::isNull() sentinel, and re-apply placement immediately when the placement mode switches at runtime.

Raise the treeland-protocols build dependency to >= 0.7.0.

v1 behavior changes: set_surface_position/set_auto_placement now take effect immediately at runtime instead of on the next arrange pass; set_surface_position(0,0) pins the surface to the anchor origin instead of falling back to auto placement.

Log: v1 set_surface_position applies immediately; (0,0) pins to origin

Influence:

  1. Run the v2 protocol suite (test_treeland_dde_shell_v2, 14 cases) and the v1 regression suite (28 cases)
  2. With a v2 client, verify position hints land at the resolved global position, including (0,0) on multi-screen setups
  3. Verify runtime switches between position hint and cursor placement re-place the surface immediately
  4. Regression-test v1 windows: set_surface_position(0,0) now pins to the origin instead of reverting to auto layout

feat(dde-shell): 适配 dde-shell-unstable-v2 协议

实现 treeland_dde_shell_manager_v2 与 treeland_dde_shell_surface_v2 (treeland-protocols 0.7.0),迁移期将 v2 全局对象与已废弃的 v1 并行 注册。v2 采用 0 基 overlay 默认 role、set_skip_flags 位域、互斥的 position/cursor 定位 hint(请求时解析为全局坐标)、重复创建报
already_shell_surface 错误、destroy 位于首请求位,且 wl_surface 销毁 时自动销毁 surface 资源。

使 (0,0) 成为合法固定位置:以显式 hasClientRequstPos 标志替代
QPoint::isNull() 哨兵,运行时切换定位模式时立即重新摆放。

v1 行为变化:set_surface_position/set_auto_placement 运行时立即生效 (此前延迟到下次 arrange);set_surface_position(0,0) 固定到锚点原点 而非退回自动布局。

close: #1419

Summary by Sourcery

Adapt DDE shell handling to the unstable v2 protocol while preserving v1 compatibility and correcting placement state management.

New Features:

  • Add the treeland DDE shell v2 manager and surface protocol alongside the deprecated v1 interface during migration.
  • Provide mutually exclusive fixed-position and cursor-placement hints, skip-flag bitfields, overlay roles, keyboard-focus control, duplicate-surface errors, and automatic resource cleanup.
  • Update the super-overlay example to exercise the v2 protocol through an interactive placement and metadata UI.

Bug Fixes:

  • Treat (0,0) as a valid fixed position instead of using it as an unset sentinel.
  • Ensure placement mode changes and v1 placement requests are applied immediately and that surfaces are cleaned up when their wl_surface is destroyed.

Enhancements:

  • Prefer v2 DDE shell surfaces when both protocol versions are available and support global-coordinate resolution for output-relative position hints.

Build:

  • Generate server and client bindings for the v2 protocol and require treeland-protocols 0.7.0 or newer.

Documentation:

  • Document the v2 protocol behavior, coverage, lifecycle guarantees, and remaining test boundaries.

Tests:

  • Add a 15-case v2 protocol suite covering roles, placement hints, skip flags, focus, recreation, lifecycle cleanup, and duplicate creation errors.

Chores:

  • Mark the v1 DDE shell implementation as deprecated while retaining it for the migration period.

@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

@sourcery-ai

sourcery-ai Bot commented Sep 28, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR introduces the dde-shell unstable v2 server protocol and registers it beside v1, integrates its metadata and placement hints into shell surfaces, fixes explicit (0,0) placement and immediate runtime re-placement, and adds CI/build adjustments plus protocol lifecycle and behavior tests.

Sequence diagram for v2 shell surface creation and placement hints

sequenceDiagram
    participant Client
    participant Manager as DDEShellManagerInterfaceV2
    participant Surface as DDEShellSurfaceV2
    participant Handler as ShellHandler
    participant Wrapper as SurfaceWrapper
    participant Output

    Client->>Manager: get_shell_surface(id, wl_surface)
    Manager->>Manager: getByWlrSurface(wl_surface)
    Manager-->>Client: already_shell_surface error [duplicate]
    Manager->>Surface: create
    Manager-->>Handler: surfaceCreated(Surface)
    Handler->>Wrapper: setSurfaceRole(Overlay)
    Client->>Surface: set_position_hint(output, x, y)
    Surface->>Surface: resolve global position
    Surface-->>Handler: positionHintChanged(globalPos)
    Handler->>Wrapper: setClientRequstPos(globalPos)
    Wrapper-->>Output: clientRequstPosChanged()
    Output->>Output: placeClientRequstPos(surface, globalPos)
    Client->>Surface: set_cursor_placement_hint(x_offset, y_offset)
    Surface-->>Handler: cursorPlacementHintChanged(offset)
    Handler->>Wrapper: setCursorPlacement(true)
    Wrapper-->>Output: cursorPlacementChanged()
    Output->>Output: placeUnderCursor(surface)
Loading

State diagram for mutually exclusive v2 placement modes

stateDiagram-v2
    [*] --> Automatic
    Automatic --> FixedPosition: set_position_hint
    Automatic --> CursorPlacement: set_cursor_placement_hint
    FixedPosition --> FixedPosition: set_position_hint
    FixedPosition --> CursorPlacement: set_cursor_placement_hint
    CursorPlacement --> CursorPlacement: set_cursor_placement_hint
    CursorPlacement --> FixedPosition: set_position_hint
    FixedPosition --> Automatic: set_auto_placement
    CursorPlacement --> Automatic: set_auto_placement
    FixedPosition: global position including (0,0)
    CursorPlacement: cursor offsets x and y
Loading

File-Level Changes

Change Details Files
Adds the dde-shell unstable v2 Wayland protocol implementation while retaining v1 during migration.
  • Generates and registers the v2 manager/surface interfaces alongside v1.
  • Implements overlay role handling, mutually exclusive position/cursor hints, skip flags, keyboard-focus state, duplicate-surface validation, destroy-first semantics, and wl_surface-driven resource cleanup.
  • Integrates v2 shell surfaces with XDG wrappers and shell metadata/placement updates.
src/modules/dde-shell/CMakeLists.txt
src/modules/dde-shell/ddeshellmanagerinterfacev2.h
src/modules/dde-shell/ddeshellmanagerinterfacev2.cpp
src/core/shellhandler.h
src/core/shellhandler.cpp
src/seat/helper.h
src/seat/helper.cpp
Reworks surface placement state so explicit fixed coordinates and runtime placement-mode changes are handled immediately.
  • Tracks fixed-position request presence independently from QPoint nullness, making (0,0) valid for v1 and v2.
  • Adds cursor placement with x/y offsets and applies position/cursor mode switches immediately.
  • Changes v1 position and auto-placement requests to take effect immediately, including pinning set_surface_position(0,0) to the anchor origin.
  • Clamps v1 unsigned y offsets before converting to signed placement offsets.
src/surface/surfacewrapper.h
src/surface/surfacewrapper.cpp
src/output/output.h
src/output/output.cpp
src/core/shellhandler.cpp
Updates build and protocol-test coverage for the new protocol.
  • Synchronizes the locally built treeland-protocols package version with its CMake source version in CI.
  • Generates the v2 protocol bindings and adds a 15-case protocol test covering metadata, placement hints, skip flags, lifecycle, automatic wl_surface cleanup, and duplicate creation errors.
  • Documents the v2 test scope and current wrapper-integration boundary.
.github/workflows/treeland-deepin-build.yml
tests/protocols/CMakeLists.txt
tests/protocols/INDEX.md
tests/protocols/treeland-dde-shell-v2/CMakeLists.txt
tests/protocols/treeland-dde-shell-v2/README.md
tests/protocols/treeland-dde-shell-v2/setup.cpp
tests/protocols/treeland-dde-shell-v2/treeland-dde-shell-v2.c
tests/protocols/treeland-dde-shell-v2/treeland-dde-shell-v2.h

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 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/surface/surfacewrapper.cpp" line_range="2878-2888" />
<code_context>
+void SurfaceWrapper::setAutoPlaceYOffset(int offset)
 {
-    if (m_autoPlaceYOffset == offset)
+    const bool wantCursor = offset != 0;
+    // The offset also derives the placement mode and the fixed-request state,
+    // so an unchanged value may still need to apply them (e.g. v1
+    // set_auto_placement(0) releasing a fixed-position request).
+    if (m_autoPlaceYOffset == offset && m_cursorPlacement == wantCursor
+        && (wantCursor || (!m_hasClientRequstPos && positionAutomatic())))
         return;

     m_autoPlaceYOffset = offset;
-    setPositionAutomatic(offset == 0);
+    // Entering cursor placement supersedes a stale fixed-position request;
+    // leaving it (offset 0) returns the surface to automatic placement.
+    setCursorPlacement(wantCursor);
+    if (wantCursor) {
</code_context>
<issue_to_address>
**issue (broader_impact):** Nonzero v1 `set_auto_placement` y-offsets are interpreted as cursor-placement requests, so v1 surfaces with an ordinary edge-clamping offset are placed under the pointer instead of using the v1 automatic layout.

**Triggers:** When a v1 client calls `set_auto_placement` with a nonzero y offset.

**Suggested fix:** Keep v1 y-offset handling separate from the v2 cursor-placement mode, or set `cursorPlacement` only from v2 requests.
</issue_to_address>

### Comment 2
<location path="src/modules/dde-shell/CMakeLists.txt" line_range="3-7" />
<code_context>
 find_package(TreelandProtocols REQUIRED)

+# NOTE: the v2 XML (treeland-dde-shell-unstable-v2.xml) only exists in
+# treeland-protocols master / 0.7.0 sources, which are not tagged or
+# released yet. The debian build-dependency stays at >= 0.6.0 and the
+# build environment must provide the 0.7.0 XML (e.g. the CI workflow
+# builds it from the protocols master source).
+
+# --- Deprecated v1 protocol (kept for transition until dde-shell migrates) ---
</code_context>
<issue_to_address>
**issue (bug_risk):** The module now unconditionally generates code from `treeland-dde-shell-unstable-v2.xml`, but the build dependency remains documented and configured at >= 0.6.0, where that XML is absent; builds using the released 0.6.0 protocol package fail during CMake configuration.

**Triggers:** When the build environment installs treeland-protocols 0.6.x instead of building protocols master.

**Suggested fix:** Raise the package/build dependency to >= 0.7.0 and ensure the v2 XML is provided by that dependency.
</issue_to_address>

### Comment 3
<location path="tests/protocols/treeland-dde-shell-v2/treeland-dde-shell-v2.c" line_range="210-227" />
<code_context>
+// v2 protocol requires the compositor to destroy the object automatically.
+static int surface_destroy_releases_shell_surface(struct test_ctx *ctx)
+{
+    struct wl_surface *surface = wl_compositor_create_surface(ctx->compositor);
+    if (!surface)
+        return 0;
+    struct treeland_dde_shell_surface_v2 *shell =
+        treeland_dde_shell_manager_v2_get_shell_surface(ctx->manager, surface);
+    if (!shell || wl_display_roundtrip(ctx->display) < 0)
+        return 0;
+
+    wl_surface_destroy(surface);
+    if (wl_display_roundtrip(ctx->display) < 0)
+        return 0;
+
+    // The server-side test bridge resets its tracked object on destruction,
+    // so the state query must come back empty afterwards.
+    struct dde_shell_surface_v2_state state;
+    if (!invoke_on_server_thread(dde_shell_v2_query_surface_state, &state))
+        return 0;
+    return !state.position_set && !state.cursor_set && !state.role_overlay
+           && state.skip_flags == 0;
+}
</code_context>
<issue_to_address>
**nitpick (bug_risk):** The lifecycle test creates a second shell-surface proxy and never destroys the client-side `shell` proxy after destroying its wl_surface, leaking that proxy until connection teardown and masking whether the protocol correctly cleans up both sides of the resource relationship.

**Triggers:** When the surface-destruction test runs repeatedly in the same client connection.

**Suggested fix:** Destroy the local shell proxy after the roundtrip, or explicitly assert that its client-side destruction callback ran.
</issue_to_address>

### Comment 4
<location path="src/modules/dde-shell/ddeshellmanagerinterfacev2.cpp" line_range="346" />
<code_context>
+    return d->acceptKeyboardFocus;
+}
+
+DDEShellSurfaceV2 *DDEShellSurfaceV2::get(wl_resource *native)
+{
+    WSurface *surface = WSurface::fromHandle(wlr_surface_from_resource(native));
+    if (surface) {
+        return DDEShellSurfaceV2::get(surface);
+    }
+
+    return nullptr;
+}
+
</code_context>
<issue_to_address>
**issue (bug_risk):** `DDEShellSurfaceV2::get(wl_resource *native)` calls `wlr_surface_from_resource(native)` without checking that `native` is non-null or that it is a wl_surface resource, so callers passing another resource type can trigger the wlroots assertion instead of returning null.

**Triggers:** When a caller asks `DDEShellSurfaceV2::get` to inspect a null or non-wl_surface resource.

**Suggested fix:** Validate `native` and its resource class before calling `wlr_surface_from_resource`.

```suggestion
    if (!native || strcmp(wl_resource_get_class(native), wl_surface_interface.name) != 0)
        return nullptr;

    WSurface *surface = WSurface::fromHandle(wlr_surface_from_resource(native));
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread src/surface/surfacewrapper.cpp
Comment thread src/modules/dde-shell/CMakeLists.txt Outdated
Comment thread tests/protocols/treeland-dde-shell-v2/treeland-dde-shell-v2.c
Comment thread src/modules/dde-shell/ddeshellmanagerinterfacev2.cpp

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Critical lifecycle, dependency, duplicate-surface, and privilege issues remain, along with placement and test coverage gaps.

Review effort: Lite
Findings: 4 High severity · 3 Medium severity

Open (7)
What changed in this PR

Adds dde-shell unstable v2 support alongside v1, with updated placement behavior and protocol tests.

Changes:

  • Add v2 manager/surface integration and lifecycle handling.
  • Update fixed and cursor placement behavior.
  • Add protocol fixtures, tests, documentation, and build registration.
File Description
tests/​protocols/​treeland-dde-shell-v2/​treeland-dde-shell-v2.h Test state and fixture declarations
tests/​protocols/​treeland-dde-shell-v2/​treeland-dde-shell-v2.c v2 client protocol cases
tests/​protocols/​treeland-dde-shell-v2/​setup.cpp Server-side test fixture
tests/​protocols/​treeland-dde-shell-v2/​README.md v2 coverage documentation
tests/​protocols/​treeland-dde-shell-v2/​CMakeLists.txt v2 test target
tests/​protocols/​INDEX.md Protocol test index
tests/​protocols/​CMakeLists.txt Test directory registration
src/​surface/​surfacewrapper.h Placement properties and state
src/​surface/​surfacewrapper.cpp Placement state transitions
src/​seat/​helper.h v2 manager ownership
src/​seat/​helper.cpp v2 global registration
src/​output/​output.h Placement API updates
src/​output/​output.cpp Cursor and fixed-position placement
src/​modules/​dde-shell/​ddeshellmanagerinterfacev2.h v2 public interfaces
src/​modules/​dde-shell/​ddeshellmanagerinterfacev2.cpp v2 protocol implementation
src/​modules/​dde-shell/​CMakeLists.txt Protocol generation and sources
src/​core/​shellhandler.h v2 handler declaration
src/​core/​shellhandler.cpp v2 integration and cleanup

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/core/shellhandler.cpp Outdated
Comment thread src/modules/dde-shell/CMakeLists.txt Outdated
Comment thread src/modules/dde-shell/ddeshellmanagerinterfacev2.cpp
Comment thread src/seat/helper.cpp
Comment thread src/output/output.cpp Outdated
Comment thread tests/protocols/treeland-dde-shell-v2/README.md
Comment thread tests/protocols/treeland-dde-shell-v2/treeland-dde-shell-v2.c
@wineee
wineee force-pushed the dde-shell-v2 branch 2 times, most recently from 972486e to d757c33 Compare September 29, 2026 02:14
Implement treeland_dde_shell_manager_v2 and
treeland_dde_shell_surface_v2 (treeland-protocols 0.7.0) and register
the v2 global alongside the deprecated v1 one for the migration
period. v2 brings a 0-based overlay default role, a set_skip_flags
bitfield, mutually exclusive position/cursor placement hints resolved
to global coordinates on request, an already_shell_surface error on
duplicate creation, destroy as the first request, and auto-destroy of
the surface resource when the wl_surface is destroyed.

Make (0,0) a valid fixed position: track position-request presence
with an explicit hasClientRequstPos flag instead of the
QPoint::isNull() sentinel, and re-apply placement immediately when the
placement mode switches at runtime.

Raise the treeland-protocols build dependency to >= 0.7.0.

v1 behavior changes: set_surface_position/set_auto_placement now take
effect immediately at runtime instead of on the next arrange pass;
set_surface_position(0,0) pins the surface to the anchor origin
instead of falling back to auto placement.

Log: v1 set_surface_position applies immediately; (0,0) pins to origin

Influence:
1. Run the v2 protocol suite (test_treeland_dde_shell_v2, 14 cases) and the v1 regression suite (28 cases)
2. With a v2 client, verify position hints land at the resolved global position, including (0,0) on multi-screen setups
3. Verify runtime switches between position hint and cursor placement re-place the surface immediately
4. Regression-test v1 windows: set_surface_position(0,0) now pins to the origin instead of reverting to auto layout

feat(dde-shell): 适配 dde-shell-unstable-v2 协议

实现 treeland_dde_shell_manager_v2 与 treeland_dde_shell_surface_v2
(treeland-protocols 0.7.0),迁移期将 v2 全局对象与已废弃的 v1 并行
注册。v2 采用 0 基 overlay 默认 role、set_skip_flags 位域、互斥的
position/cursor 定位 hint(请求时解析为全局坐标)、重复创建报
already_shell_surface 错误、destroy 位于首请求位,且 wl_surface 销毁
时自动销毁 surface 资源。

使 (0,0) 成为合法固定位置:以显式 hasClientRequstPos 标志替代
QPoint::isNull() 哨兵,运行时切换定位模式时立即重新摆放。

v1 行为变化:set_surface_position/set_auto_placement 运行时立即生效
(此前延迟到下次 arrange);set_surface_position(0,0) 固定到锚点原点
而非退回自动布局。
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