Skip to content

treeland-snap - #1307

Open
glyvut wants to merge 2 commits into
linuxdeepin:masterfrom
glyvut:s4
Open

glyvut wants to merge 2 commits into
linuxdeepin:masterfrom
glyvut:s4

Conversation

@glyvut

@glyvut glyvut commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

前置:linuxdeepin/treeland-protocols#87

Summary by Sourcery

Implement snap-target selection support in the compositor and provide a multi-output demonstration client.

New Features:

  • Add a snap-target Wayland protocol implementation that reports the surface or output under the pointer, including optional owning-process pidfds.
  • Add a multi-output Qt Quick snap-target demo with selectable regions, optional per-output background capture, and confirmation UI.

Bug Fixes:

  • Prevent snap-mask windows from being treated as snap targets, moved or resized, maximized, tiled, or exposed to window-management previews.

Enhancements:

  • Introduce a dedicated high-priority compositor layer and surface classification for snap-mask windows.

Build:

  • Register the snap-target compositor module and example, including generated Wayland protocol sources and required Qt components.

@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: glyvut

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 Aug 20, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

This PR removes the legacy screenshot integration in favor of a compositor-provided snap-target protocol, adds snap-mask-specific layering and window-management exclusions, and ships a multi-output interactive example with optional pre-captured screen backgrounds. Review the protocol lifecycle and single-session semantics, target ordering/hit testing, pidfd ownership, mask-surface state transitions, and the example’s Wayland capture/resource cleanup paths.

Sequence diagram for snap-target pointer selection

sequenceDiagram
    participant Client as SnapTargetClient
    participant Protocol as SnapTargetV1
    participant Detector as SnapDetector
    participant Cursor as WCursor
    participant Surface as WToplevelSurface

    Client->>Protocol: start(seat, events)
    Protocol->>Detector: collect(renderWindow, excludeSurfaces)
    Protocol->>Cursor: positionChanged
    Cursor-->>Protocol: onCursorMoved()
    Protocol->>Detector: hitTest(cursorPos, snapshot)
    Detector-->>Protocol: SnapTarget
    alt target has owning process and pidfd requested
        Protocol->>Surface: pidFD()
        Surface-->>Protocol: pidfd
        Protocol-->>Client: sendPidfd(pidfd)
    end
    Protocol-->>Client: sendSnapRegion(x, y, width, height)
    Client->>Protocol: stop()
    Protocol->>Protocol: stopSnapping()
Loading

Flow diagram for snap-mask surface handling

flowchart TD
    TaggedSurface["Surface tagged org.deepin.treeland.snap-mask"] --> Apply["applySnapMask(wrapper)"]
    Apply --> State["setSnapMask(true)"]
    Apply --> Layer["Add to snapMaskContainer"]
    Apply --> Exclude["addSnapMaskSurface(surface)"]
    Apply --> WindowRules["Disable animation and window-management views"]
    Exclude --> Detect["SnapDetector.collect(renderWindow, excludeSurfaces)"]
    Detect --> HitTest["SnapDetector.hitTest(cursorPos, snapshot)"]
    State --> Capabilities["Reject resize, maximize, and tiling capabilities"]
    SurfaceRemoved["XDG surface removed"] --> Remove["removeSnapMaskSurface(surface)"]
Loading

File-Level Changes

Change Details Files
Replaced the legacy capture-oriented integration with a compositor-side snap-target protocol and server module.
  • Added the unstable protocol implementation and generated server bindings.
  • Registered the protocol with the compositor and connected it to the shell handler and render window.
  • Implemented single-client session handling, cursor tracking, target hit testing, stop/failure handling, and optional pidfd reporting.
src/modules/CMakeLists.txt
src/modules/snap-target/CMakeLists.txt
src/modules/snap-target/impl/snapv1impl.cpp
src/modules/snap-target/impl/snapv1impl.h
src/modules/snap-target/snapdetector.cpp
src/modules/snap-target/snapdetector.h
src/modules/snap-target/snaphandler.cpp
src/modules/snap-target/snaphandler.h
src/seat/helper.cpp
src/core/shellhandler.cpp
src/core/shellhandler.h
Introduced snap-mask surface classification and compositor-layer isolation to keep selection overlays out of normal window management and target detection.
  • Recognized surfaces tagged as org.deepin.treeland.snap-mask and moved them to a dedicated high-priority container.
  • Excluded mask surfaces from snap-target hit testing and removed them from tracking when destroyed.
  • Disabled movement, resizing, maximization, tiling, animations, task-switcher presentation, and workspace restrictions for mask surfaces.
src/core/rootsurfacecontainer.h
src/core/shellhandler.cpp
src/core/shellhandler.h
src/seat/helper.cpp
src/surface/seatsurfacemanager.cpp
src/surface/surfacewrapper.cpp
src/surface/surfacewrapper.h
src/modules/snap-target/snapdetector.cpp
src/modules/snap-target/snaphandler.cpp
Added a multi-output interactive snap-target example with optional pre-captured backgrounds.
  • Created one full-screen QML mask window and controller per output while sharing one snap session.
  • Rendered hover and confirmed selection regions, process name/debug state, and a post-confirmation demo toolbar.
  • Added optional ext-image-copy-capture screen snapshots using shared-memory buffers and per-output image providers.
  • Generated client bindings for the snap-target, capture, foreign-toplevel, xdg-toplevel-tag, and xdg-shell protocols.
examples/CMakeLists.txt
examples/test_snap_target/CMakeLists.txt
examples/test_snap_target/Main.qml
examples/test_snap_target/main.cpp
examples/test_snap_target/screencapture.cpp
examples/test_snap_target/screencapture.h
examples/test_snap_target/snapproxy.cpp
examples/test_snap_target/snapproxy.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

@deepin-bot

deepin-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.9.0
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1312

@deepin-bot

deepin-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.9.1
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1348

@deepin-bot

deepin-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.10.0
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1392

@glyvut
glyvut force-pushed the s4 branch 6 times, most recently from d99b852 to c02cb85 Compare September 17, 2026 03:17
@glyvut
glyvut force-pushed the s4 branch 5 times, most recently from b590482 to 201787f Compare September 28, 2026 03:06
@glyvut
glyvut marked this pull request as ready for review September 28, 2026 03:13
@glyvut glyvut changed the title 移除旧截图,引入 treeland-capture-snap treeland-snap Sep 28, 2026

@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

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

## Individual Comments

### Comment 1
<location path="examples/test_snap_target/screencapture.cpp" line_range="189-190" />
<code_context>
+    static int serial = 0;
+    int framesSent = 0;
+    for (Output *output : std::as_const(m_outputs)) {
+        if (!output->constraintsDone || output->imageFormat == QImage::Format_Invalid)
+            continue;
+
+        const int stride = output->bufferW * 4;
</code_context>
<issue_to_address>
**issue (bug_risk):** When any output does not complete capture constraints or does not advertise a supported shared-memory format, that output is skipped without setting `captureReady` or `captureFailed`. If another output has a frame in flight, the dispatch loop waits forever because it continues treating the skipped output as pending, so the example hangs before showing its UI.

**Triggers:** When background capture is enabled and at least one output cannot be captured while another output is capture-capable.

**Suggested fix:** Track only outputs for which a frame was submitted in the pending loop, or mark skipped outputs as failed before entering the loop.

```suggestion
        if (!output->constraintsDone || output->imageFormat == QImage::Format_Invalid) {
            output->captureFailed = true;
            continue;
        }
```
</issue_to_address>

### Comment 2
<location path="examples/test_snap_target/CMakeLists.txt" line_range="52" />
<code_context>
+        Qt6::Core
+        Qt6::Gui
+        Qt6::WaylandClient
+        Qt6::WaylandClientPrivate
+        Qt6::Quick
+)
</code_context>
<issue_to_address>
**issue (bug_risk):** The example links `Qt6::WaylandClientPrivate` unconditionally even though the corresponding package component is found only for Qt versions greater than or equal to 6.10. On supported older Qt versions where that imported target is unavailable, CMake configuration fails with an unknown target error.

**Triggers:** When building with Qt 6 before 6.10.

**Suggested fix:** Link `Qt6::WaylandClientPrivate` only under the same Qt-version condition, or require Qt 6.10 explicitly for this example.
</issue_to_address>

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

Comment thread examples/test_snap_target/screencapture.cpp
Comment thread examples/test_snap_target/CMakeLists.txt
Comment thread src/core/shellhandler.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

Unresolved critical protocol resource validation and undefined-slot link issues remain, along with additional correctness fixes.

Review effort: Lite
Findings: 2 High severity · 2 Medium severity

Open (4)
What changed in this PR

Adds snap-target Wayland protocol support, snap-mask handling, and a multi-output Qt/QML demonstration client.

Changes:

  • Adds cursor-based target detection with optional pidfd reporting.
  • Integrates snap-mask layering and interaction restrictions.
  • Adds screen capture support and build integration for the demo.
File Description
src/​surface/​surfacewrapper.h Adds snap-mask API.
src/​surface/​surfacewrapper.cpp Applies snap-mask restrictions.
src/​surface/​seatsurfacemanager.cpp Blocks snap-mask move/resize operations.
src/​seat/​helper.cpp Registers the snap-target protocol.
src/​modules/​snap-target/​snaphandler.h Declares protocol session handling.
src/​modules/​snap-target/​snaphandler.cpp Implements sessions and events.
src/​modules/​snap-target/​snapdetector.h Declares target detection types.
src/​modules/​snap-target/​snapdetector.cpp Performs target collection and hit testing.
src/​modules/​snap-target/​impl/​snapv1impl.h Declares protocol resource wrappers.
src/​modules/​snap-target/​impl/​snapv1impl.cpp Implements protocol requests and events.
src/​modules/​snap-target/​CMakeLists.txt Builds and installs the module.
src/​modules/​CMakeLists.txt Registers the module.
src/​core/​shellhandler.h Adds snap-mask container APIs.
src/​core/​shellhandler.cpp Manages snap-mask lifecycle and placement.
src/​core/​rootsurfacecontainer.h Defines snap-mask layer ordering.
examples/​test_snap_target/​snapproxy.h Declares demo protocol classes.
examples/​test_snap_target/​snapproxy.cpp Implements demo client interaction.
examples/​test_snap_target/​screencapture.h Declares capture support.
examples/​test_snap_target/​screencapture.cpp Implements output capture.
examples/​test_snap_target/​Main.qml Provides the selection UI.
examples/​test_snap_target/​main.cpp Creates demo windows.
examples/​test_snap_target/​CMakeLists.txt Builds the demo client.
examples/​CMakeLists.txt Registers the example.

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

Comment thread src/core/shellhandler.h Outdated
Comment thread src/modules/snap-target/impl/snapv1impl.cpp Outdated
Comment thread examples/test_snap_target/snapproxy.cpp Outdated
Comment thread src/core/shellhandler.cpp Outdated
Comment thread src/modules/snap-target/impl/snapv1impl.h Outdated
@glyvut
glyvut force-pushed the s4 branch 2 times, most recently from 2acdcab to 80d134f Compare September 28, 2026 09:17
}
} // namespace

QList<SnapTarget> SnapDetector::collect(WOutputRenderWindow *renderWindow)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

按绘制顺序收集所有可吸附目标并整理成自顶向下的顺序的列表

Comment thread src/modules/snap-target/snapdetector.h Outdated
Comment thread src/modules/snap-target/snaphandler.cpp
Comment thread src/modules/snap-target/snaphandler.cpp Outdated
Comment thread src/modules/snap-target/snaphandler.cpp
@glyvut
glyvut force-pushed the s4 branch 2 times, most recently from 15a2a13 to 74dcd29 Compare September 29, 2026 02:45
Detect snap regions under the cursor and report them to clients, and
treat xdg-toplevel-tag surfaces tagged
org.deepin.treeland.snap-mask as overlay masks.

- Add the snap-target protocol module with detector, handler and v1 impl
- Track snap-mask surfaces in a dedicated shell container and surface
  flag, and expose them through snapMaskContainer()
- Keep the existing capture module untouched

新增 snap-target 协议模块:检测光标下的吸附区域并上报给客户端,同时将带有
org.deepin.treeland.snap-mask 标签的 xdg-toplevel-tag 表面作为覆盖遮罩处理。

Log: 新增 treeland-snap-target-unstable-v1 协议模块
PMS: TASK-395745
Influence: 新增快照/吸附目标协议与遮罩表面支持,原有截图模块不变。
Add examples/test_snap_target: a per-output mask window demo that
drives the snap-target protocol, with optional ext-image-copy-capture
backgrounds.

- Create one mask window per output sharing a single snap session
- Capture each output with ext-image-copy-capture before mapping masks
  and use the images as window backgrounds with --background
- Drive the client through a SnapProxy/SnapController layer and a QML
  selection UI

新增 test_snap_target 示例:为每个输出创建遮罩窗口并通过 snap-target 协议客户端
驱动,可选使用 ext-image-copy-capture 抓取每个输出作为窗口背景。

Log: 新增 snap-target 示例客户端
PMS: TASK-395745
Influence: 提供可手动运行的 snap-target 协议演示,便于验证相关协议行为。
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