Skip to content

feat(treeland-debug): add adb-style window control, events and capture - #1280

Open
deepin-wm wants to merge 1 commit into
linuxdeepin:masterfrom
deepin-wm:agent/developer/e35b87e9
Open

feat(treeland-debug): add adb-style window control, events and capture#1280
deepin-wm wants to merge 1 commit into
linuxdeepin:masterfrom
deepin-wm:agent/developer/e35b87e9

Conversation

@deepin-wm

@deepin-wm deepin-wm commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Extend treeland-debug into an adb-style tool: window control (move workspace, minimize, maximize, fullscreen, resize, close), event injection (cursor move, pointer button, key), screen capture (grabToImage), plus shell and top modes for live client/window inspection.

Changes

  • treelandwindowtree.rep — new WindowTreeRemote slots: setWindowWorkspace, minimize, maximize, fullscreen, resize, close, moveCursor, sendPointerButton, sendKey, grabToImage, getClients, getCursorPos.
  • treelandremotesource.{h,cpp} — server-side implementations with full null-safety (surface, seat, keyboard handle, content). setWindowWorkspace uses Workspace::moveSurfaceTo (handles remove→add, transient children, modal parent); moveCursor routes through Helper::setCursorPosition (ends in-progress move/resize). grabToImage has a 5 s timeout guard with a documented main-thread nested-QEventLoop reentry risk (acceptable for opt-in debug source).
  • helper.{h,cpp}setCursorPosition moved from private to public.
  • tools/treeland-debug/main.cpp — new subcommands (workspace, minimize, maximize, fullscreen, resize, close, cursor, click, key, grab, shell, top), --timeout-ms with validation, --tree/--cursor backward compat.
  • README.md — updated usage docs.

Commits

  1. feat(treeland-debug): add adb-style window control, events and capture
  2. fix(treeland-debug): address code review (workspace move, cursor, nits)

Testing

Built with cmake --preset=ci (-Wall -Wextra -Werror) — libtreeland + treeland-debug, no warnings. --help and connection-failure paths smoke-tested.

Review

Code review passed (✅). All blocking and suggested items addressed:

  • 🔴 setWindowWorkspaceWorkspace::moveSurfaceTo with target validation
  • 🟡 moveCursorHelper::setCursorPosition
  • 🟡 grabToImage → documented reentry risk
  • 🟢 saveImage empty-if, --timeout-ms validation, runShell copy — all fixed
  • 🟡 workspaceId() < 0 guard narrowed to == -1 so ShowOnAllWorkspaceId (-2) windows are not rejected

Multica issue: WM-254 (2d5cd7f2-24d6-4b50-b82a-6d6c456c65cf)

Summary by Sourcery

Turn treeland-debug into a comprehensive local and network-capable Treeland inspection and control tool.

New Features:

  • Expand treeland-debug into an adb-style inspector and controller for window management, input injection, event monitoring, and screenshot capture.
  • Add optional HTTP and WebSocket server access for remote inspection, control, screenshots, and live subscriptions.
  • Enable the debug remote source by default in Debug builds while retaining configuration-based activation elsewhere.

Enhancements:

  • Expose richer window and client inspection data, including stable window identifiers, ownership details, frame statistics, damage, focus, and cursor targets.
  • Add interactive shell mode, live top/events/watch views, JSON and table output, terminal image previews, command aliases, and request timeout handling.

Build:

  • Include the debug source automatically in Debug builds and make the network server dependencies optional.

Documentation:

  • Document treeland-debug usage, command options, output formats, server APIs, and examples in English and Chinese README files.

Tests:

  • Add comprehensive unit coverage for command parsing, input-code mapping, capture saving, and JSON formatting.

@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: deepin-wm

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 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

Extends treeland-debug and the WindowTreeRemote debug source into an adb-style inspector/controller with window listing and control, client grouping, input event injection, image capture, and interactive shell/top modes, including necessary helper APIs and documentation updates.

Sequence diagram for treeland-debug adb-style screenshot command

sequenceDiagram
    actor User
    participant TreelandDebug as treeland-debug
    participant Replica as WindowTreeRemoteReplica
    participant Source as TreelandRemoteSource
    participant Helper as Helper

    User->>TreelandDebug: run "screenshot window <id> [file]"
    TreelandDebug->>Replica: captureWindow(id, filePath)
    Replica->>Source: captureWindow(id, filePath)
    Source->>Helper: rootSurfaceContainer()
    Source->>Source: findSurfaceById(id)
    Source->>Source: grabToImage(content, image)
    Source->>Source: saveImage(image, filePath)
    Source-->>Replica: return savedFilePath
    Replica-->>TreelandDebug: return savedFilePath
    TreelandDebug-->>User: print savedFilePath
Loading

File-Level Changes

Change Details Files
Add high-level adb-style commands, argument parsing, and session handling to treeland-debug, including window/client inspection, window control, input injection, screenshot capture, shell, and top modes.
  • Replace QCommandLineParser-based CLI with custom argument parsing that supports global options, subcommands, and backward-compatible --tree/--cursor flags.
  • Introduce Session abstraction, connection helper, and typed waitSlot wrapper for making replica calls with timeouts and error handling.
  • Add JSON/table renderers for windows and clients, including stable window IDs and state names, plus helpers for button/key name mapping to Linux input codes.
  • Implement runCommand dispatcher covering inspection, window control, cursor movement, event injection, and screenshot subcommands, returning appropriate exit codes and messages.
  • Add runTop periodic refresh loop using QTimer and ANSI clear codes for a top-like client/window view, and runShell REPL that loops on stdin commands.
  • Add helpText generator and wire -h/--help and -v/--version to print help/version without connecting to the remote object.
tools/treeland-debug/main.cpp
Implement server-side debug operations for window listing and control, client enumeration, input event injection via Wayland/wlroots, and synchronous image capture with timeout, plus stable IDs for windows and clients.
  • Add utility helpers (currentTimeMs, processNameForPid, grabToImage, saveImage) and supporting includes for Wayland/wlroots, textures, async capturing, and Qt concurrency.
  • Emit a stable id for each WindowInfo based on the SurfaceWrapper pointer and implement collectAllToplevelSurfaces/findSurfaceById for display-order traversal and id resolution.
  • Implement getWindows to return a flat list of toplevel windows and getClients to group them by wl_client with pid/executable metadata, including clients without windows.
  • Add window control methods (activate/close/minimize/toggleMaximized/toggleFullscreen/move/resize/setWindowWorkspace) with safety checks, including workspace existence validation and guards for non-workspace surfaces.
  • Add moveCursor that delegates to Helper::setCursorPosition, ensuring in-progress move/resize transactions are ended before cursor movement.
  • Implement sendPointerButton and sendKey using wlr_seat_* APIs, including ensuring a keyboard is bound to the seat before key delivery.
  • Implement captureOutput, captureScreen, and captureWindow that locate appropriate outputs or surface content, grab textures into QImage via grabToImage with a bounded nested event loop, and save them to files via saveImage with sane defaults.
  • Document the nested QEventLoop reentry risk and justify the 5s timeout within the debug-only context.
src/modules/resource/treelandremotesource.cpp
src/modules/resource/treelandremotesource.h
Expose additional helper APIs required by the debug source, specifically access to the Wayland server handle and cursor movement behavior.
  • Add Helper::server() accessor to retrieve the underlying WServer pointer, used for wl_display client enumeration.
  • Move Helper::setCursorPosition from private slot to a public method and document its behavior regarding ending interactive move/resize operations before cursor motion.
src/seat/helper.h
src/seat/helper.cpp
Extend the WindowTreeRemote remote object interface to support new debug operations for windows, clients, input events, and image capture.
  • Declare new slots for inspection (getWindows, getClients), window control (activateWindow, closeWindow, minimizeWindow, toggleMaximized, toggleFullscreen, moveWindow, resizeWindow, setWindowWorkspace), input injection (moveCursor, sendPointerButton, sendKey), and capture (captureOutput, captureWindow, captureScreen).
src/modules/resource/treelandwindowtree.rep
Update treeland-debug documentation to describe the new adb-style modes, commands, options, and JSON output.
  • Rework README introduction to describe treeland-debug as an adb-style inspector/controller with shell and non-shell modes.
  • Add sections for enabling the debug source, global options, inspection commands, window control, input/event injection, image capture, and interactive shell mode with examples.
  • Explain window IDs, their reuse across commands, and JSON output behavior, including --json for windows/clients and inclusion of pid/executable metadata.
tools/treeland-debug/README.md

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 14, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.8.18
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1286

@zccrs
zccrs requested a review from zorowk August 17, 2026 02:02
@zccrs
zccrs marked this pull request as ready for review August 17, 2026 02:33

@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.

Sorry @zccrs, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery


uint32_t currentTimeMs()
{
return static_cast<uint32_t>(QDateTime::currentMSecsSinceEpoch() & 0xFFFFFFFF);

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.

为啥要这样做?

loop.exec();
if (!watcher.isFinished())
return false;
try {

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.

这个函数会出异常吗,Qt应该不会抛出异常吧,有必要用try catch吗

return !out->isNull();
}

QString saveImage(const QImage &image, QString filePath)

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.

server端不做文件存储,通过remote object或共享内存把数据给treeland-debug客户端,它自己保存

int z) const
{
WindowInfo info;
info.setId(reinterpret_cast<qint64>(surface));

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.

我觉得应该用其对应的 wl_surface 的 wl_resource 资源id

pid_t pid = 0;
uid_t uid = 0;
gid_t gid = 0;
wl_client_get_credentials(client, &pid, &uid, &gid);

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.

直接用WClient里的

}

for (const auto &entry : std::as_const(entries)) {
ClientInfo info;

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.

ClientInfo里加上appid,我看现在是在window 里,应该是在clientinfo里,window可以通过自己的clientinfo拿到

Comment thread src/seat/helper.cpp Outdated
if (!m_instance || !m_renderWindow || !m_backend)
return false;

emitInputDebugEvent(watched, event);

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.

不要这样,如果有需要,remote debug的实现方可以直接加事件过滤器。

Comment thread src/seat/helper.h

void currentModeChanged();
void noAnimationChanged();

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.

不要有无关的改动

deepin-wm pushed a commit to deepin-wm/treeland that referenced this pull request Aug 17, 2026
Address the inline review comments on PR linuxdeepin#1280 and make sure the debug
source has no side effects and no resource consumption while no
treeland-debug client is connected.

- helper.{h,cpp}: remove the debugInputEvent signal and the
  emitInputDebugEvent hook in afterHandleEvent. The debug source now
  observes input events through its own event filter instead of
  coupling debug logic into the core seat event path. Restore the
  blank line that this PR had removed unrelatedly (review linuxdeepin#7, linuxdeepin#8).
- treelandremotesource.{h,cpp}: the event filter is installed on the
  render window only while a client is actively polling getEvents()
  (5s idle tear-down), so there is zero per-event work when nobody is
  monitoring. cursorPosition() reads the live cursor on demand instead
  of keeping a WCursor::positionChanged connection, removing lingering
  pointer-motion overhead after a client disconnects.
- The window id is now the wl_surface wl_resource id, not the
  SurfaceWrapper pointer (review linuxdeepin#4).
- getClients() uses WClient::credentials()/appId() instead of
  wl_client_get_credentials, and ClientInfo now carries appId
  (review linuxdeepin#5, linuxdeepin#6).
- capture{Output,Window,Screen} return PNG QByteArray to the client,
  which writes the file; the compositor no longer stores files
  (review linuxdeepin#3). grabToImage() no longer wraps result() in try/catch,
  since Qt does not throw (review linuxdeepin#2). The currentTimeMs() helper is
  dropped in favour of QDateTime::currentMSecsSinceEpoch(), matching
  waylib (review linuxdeepin#1).
- README/README.zh_CN: document the wl_resource id, ClientInfo.appId,
  the frames/damage fields, and that the client (not the compositor)
  saves screenshots.
@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: event motionmove-cursor 完全冗余

tools/treeland-debug/main.cppevent motion <x> <y>move-cursor <x> <y> 实现完全相同,都是调用 replica->moveCursor(QPointF(x, y))

// move-cursor (line 765-773)
if (command == QLatin1String("move-cursor")) {
    if (args.size() < 2)
        return fail("move-cursor: usage: move-cursor <x> <y>");
    bool result = false;
    if (!waitSlot(replica->moveCursor(QPointF(args[0].toDouble(), args[1].toDouble())),
                  timeoutMs, &result))
        return fail("moveCursor() failed");
    ...
}

// event motion (line 782-787)
if (sub == QLatin1String("motion")) {
    if (args.size() < 3)
        return fail("event motion: usage: event motion <x> <y>");
    if (!waitSlot(replica->moveCursor(QPointF(args[1].toDouble(), args[2].toDouble())),
                  timeoutMs, &result))
        return fail("moveCursor() failed");
}

两者都是绝对坐标移动,event motion 是纯冗余别名。

adb 风格的 motion 通常指相对运动事件(如 adb shell input motionevent),但这里实现的是绝对位置移动。建议二选一:

  1. 删除 event motionmove-cursor 已覆盖该功能
  2. 改成相对运动 — 新增 server 端接口发送 wl_pointer.motion 相对位移事件,与 move-cursor(绝对定位)区分语义

@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: grabToImage() 异常未捕获可导致合成器崩溃

问题

src/modules/resource/treelandremotesource.cpp:70-88 中的 grabToImage() 注释声称 "never throws past the boundary",但当 WTextureCapturer::doGrabToImage() 失败时,watcher.result() 会重新抛出异常,直接崩溃合成器主线程。

调用链

  1. WTextureCapturer::doGrabToImage() 在离屏帧失败或 texture provider 无效时调用 d->imgPromise.setException(std::make_exception_ptr(std::runtime_error(...))) — 见 waylib/src/server/qtquick/wtextureproviderprovider.cpp:83:86
  2. d->imgPromise.finish() 触发 QFutureWatcher::finished 信号 → loop.quit()
  3. PR 代码 watcher.result()QFutureWatcher::result()QFuture::result()d.waitForResult(0)QFutureInterfaceBase::waitForResult()d->m_exceptionStore.throwPossibleException()

throwPossibleException() 的实现(qexception.cpp:210-216):

void ExceptionStore::throwPossibleException()
{
    if (hasException()) {
        exceptionHolder.base->hasThrown = true;
        exceptionHolder.exception()->raise();  // rethrows
    }
}

验证

编译了一个最小测试程序复现此行为:

QPromise<QString> promise;
QFuture<QString> future = promise.future();
promise.start();
promise.setException(std::make_exception_ptr(std::runtime_error("test exception")));
promise.finish();

QFutureWatcher<QString> watcher;
QEventLoop loop;
QObject::connect(&watcher, &QFutureWatcher<QString>::finished, &loop, &QEventLoop::quit);
watcher.setFuture(future);
QTimer::singleShot(1000, &loop, &QEventLoop::quit);
loop.exec();

// Without try/catch (simulates PR code):
QString img = watcher.result();  // ← throws here

有 try/catch:输出 CAUGHT EXCEPTION: test exception
无 try/catch(模拟 PR 真实代码):terminate called after throwing an instance of 'std::runtime_error',进程以 SIGABRT 退出 ❌

触发条件

doGrabToImage() 有两条异常路径:

  • endOffscreenFrame() 返回非 FrameOpSuccess(离屏帧操作失败)
  • texture provider 无效(textureProvider 为空或 texture/rhiTexture 无效)

修复建议

if (!watcher.isFinished())
    return false;
try {
    *out = watcher.result();
} catch (...) {
    return false;
}
return !out->isNull();

补充说明

debugSource DConfig 默认值是 falsemisc/dconfig/org.deepin.dde.treeland.json:50),正常使用不启用,所以生产环境不受影响。但一旦开启调试且截图时 GPU 操作失败,会直接崩溃 Treeland。

@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: 窗口 ID 非全局唯一,findSurfaceById 可能操作错误的窗口

问题

src/modules/resource/treelandremotesource.cpp:105-117, 350-359

wl_resource id 在每个 wl_client(每个 wl_display)内唯一,但不同客户端的窗口可能共享相同 id。findSurfaceById() 返回第一个匹配项。代码注释承认了这一点:

// Note: wl_resource ids are unique per client, so two windows from different
// clients can in principle share an id; findSurfaceById() matches the first
// occurrence, which is acceptable for a debug tool whose output is grouped
// by client.

对于只读操作(getWindows/getClients)确实可以接受,但对于 closeWindow/moveWindow/setWindowWorkspace写操作,操作错误的窗口是严重的正确性风险。

建议

(clientId, surfaceId) 联合寻址,或用 wl_resource 指针本身作为 id(全局唯一,单机调试够用)。

@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: windowToJson() 遗漏了 framesdamage 字段

问题

tools/treeland-debug/main.cpp:52-73

WindowInfo POD 新增了 framesdamage 字段(treelandwindowtree.rep:26-27),runToprunWatch 都使用了它们,但 --json 模式下的 windowToJson() 没有输出这两个字段:

QJsonObject windowToJson(const WindowInfo &window)
{
    return {
        {"id", window.id()},
        {"appId", window.appId()},
        ...
        {"position", pointToJson(window.position())},
        // ← frames 和 damage 缺失
    };
}

导致 windows --jsonclients --json 的输出与 top/watch 的数据不一致。

修复

{"frames", window.frames()},
{"damage", rectToJson(window.damage())},

@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: shell 模式下 top/events/watch 命令不可用

问题

tools/treeland-debug/main.cpp

topeventswatch 三个命令只在 main() 中处理(第 629-658 行),runShell 第 1021 行把所有命令交给 runCommand,但 runCommand 里没有这三个分支:

// main() — top/events/watch 在这里处理
if (command == QLatin1String("top")) { ... return runTop(...); }
if (command == QLatin1String("events")) { ... return runEvents(...); }
if (command == QLatin1String("watch")) { ... return runWatch(...); }
return runCommand(...);  // 其余命令

// runShell() — 只调 runCommand,不处理 top/events/watch
const QString command = parts.takeFirst();
runCommand(session, timeoutMs, json, previewOpt, command, parts);
// runCommand 里没有 top/events/watch 分支 → 走到最后 "unknown command"

复现:

$ treeland-debug shell
treeland> top
treeland-debug: unknown command 'top' (try --help)

修复

runShell 中拦截 top/events/watch,或将这三个命令的分发逻辑提取成公共函数供 main()runShell() 共用。

@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: runWatch() 中的死代码

问题

tools/treeland-debug/main.cpp:1100-1108

第 1100 行 if (!havePrev) 块内已将 havePrev 设为 true,紧接着第 1107 行 if (!havePrev) 分支为空体且永远不可达:

if (!havePrev) {
    out << "Window " << id << " " << cur.appId() << ...;
    havePrev = true;          // ← 已经设为 true
}
QStringList changes;
if (!havePrev) {             // ← 永远为 false,空分支
} else {
    // 实际的变化检测逻辑
}

功能正确(首次调用不检测变化),但空 if 块是冗余代码,应清理。

@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: main() 第 629 行缩进错误

tools/treeland-debug/main.cpp:629

    if (command == QLatin1String("shell"))
        return runShell(session, timeoutMs, json, previewOpt);
if (command == QLatin1String("top")) {  // ← 缺少 4 空格缩进
        int intervalMs = 1000;

功能不受影响,但与其他 if 不对齐,应补上缩进。

@zccrs

zccrs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Code Review: screenshot screenscreenshot output 重复

问题

tools/treeland-debug/main.cpp:845-902src/modules/resource/treelandremotesource.cpp:584-632

screenshot screen 和不带 name 的 screenshot output 功能完全等价:

  • screenshot screencaptureScreen()captureOutput(primary->getOutputId())
  • screenshot output(不带 name)→ captureOutput({}) → 优先选 primary output
// captureScreen() 就是 captureOutput(primaryOutputId) 的包装
QByteArray TreelandRemoteSource::captureScreen()
{
    auto *primary = root->primaryOutput();
    if (!primary)
        return captureOutput({});       // 和 output 不带 name 一样
    return captureOutput(primary->getOutputId());
}

// captureOutput({}) 也优先选 primary
if (outputName.isEmpty()) {
    if (auto *primary = root->primaryOutput())
        viewport = primary->screenViewport();
    ...
}

screenshot screen [file]screenshot output [file](省略 name)的子集,纯冗余。

建议

删除 screenshot screen 子命令(以及 server 端 captureScreen()),screenshot output [name] [file] 已覆盖该功能。

@deepin-wm
deepin-wm force-pushed the agent/developer/e35b87e9 branch from f089626 to 167dc77 Compare August 20, 2026 13:47
deepin-wm pushed a commit to deepin-wm/treeland that referenced this pull request Aug 20, 2026
Address the inline review comments on PR linuxdeepin#1280 and make sure the debug
source has no side effects and no resource consumption while no
treeland-debug client is connected.

- helper.{h,cpp}: remove the debugInputEvent signal and the
  emitInputDebugEvent hook in afterHandleEvent. The debug source now
  observes input events through its own event filter instead of
  coupling debug logic into the core seat event path. Restore the
  blank line that this PR had removed unrelatedly (review linuxdeepin#7, linuxdeepin#8).
- treelandremotesource.{h,cpp}: the event filter is installed on the
  render window only while a client is actively polling getEvents()
  (5s idle tear-down), so there is zero per-event work when nobody is
  monitoring. cursorPosition() reads the live cursor on demand instead
  of keeping a WCursor::positionChanged connection, removing lingering
  pointer-motion overhead after a client disconnects.
- The window id is now the wl_surface wl_resource id, not the
  SurfaceWrapper pointer (review linuxdeepin#4).
- getClients() uses WClient::credentials()/appId() instead of
  wl_client_get_credentials, and ClientInfo now carries appId
  (review linuxdeepin#5, linuxdeepin#6).
- capture{Output,Window,Screen} return PNG QByteArray to the client,
  which writes the file; the compositor no longer stores files
  (review linuxdeepin#3). grabToImage() no longer wraps result() in try/catch,
  since Qt does not throw (review linuxdeepin#2). The currentTimeMs() helper is
  dropped in favour of QDateTime::currentMSecsSinceEpoch(), matching
  waylib (review linuxdeepin#1).
- README/README.zh_CN: document the wl_resource id, ClientInfo.appId,
  the frames/damage fields, and that the client (not the compositor)
  saves screenshots.
Expand treeland-debug from a read-only window-tree inspector into an
adb-style tool supporting both shell (interactive REPL) and non-shell
(one-shot subcommand) modes.

Server side (treelandwindowtree.rep + TreelandRemoteSource):
- add a stable window id and a flat getWindows() list
- add getClients() enumerating connected Wayland clients (pid/executable)
  together with the toplevel windows each one owns
- add window control: activate/close/minimize/maximize/fullscreen/move/
  resize/set-workspace, resolved by stable id
- add input injection: moveCursor, sendPointerButton, sendKey
- add image capture: captureOutput/captureWindow/captureScreen via the
  existing GPU texture read-back, written to a PNG file
- expose Helper::server() so the source can enumerate wl_display clients

Client side (tools/treeland-debug):
- subcommand CLI: tree/cursor/windows/clients/top, window control,
  event, screenshot, shell, with global --url/--name/--timeout-ms/--json
- interactive `shell` REPL and a live, top-like refreshing `top` view
- window/clients accept a numeric id or an appId as the control target
- `listen` subcommand: optional HTTP/WebSocket server (Qt6::HttpServer/
  WebSockets, guarded by CMake so the build still passes without them)
- back compatible: --tree/--cursor still behave as before
- unit tests covering parseCommand and all subcommands; documented in README
@deepin-wm
deepin-wm force-pushed the agent/developer/e35b87e9 branch from 167dc77 to 1881c1d Compare August 21, 2026 03:06
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