diff --git a/CMakeLists.txt b/CMakeLists.txt
index 53ddf82..c182621 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,7 +29,9 @@ set(TREELAND_PROTOCOL_DDE_XML_FILES
dde/treeland-shortcut-manager-unstable-v3.xml
dde/treeland-compositor-action-unstable-v1.xml
dde/treeland-appearance-manager-unstable-v1.xml
- dde/treeland-virtual-output-manager-v1.xml
+ dde/treeland-output-group-manager-unstable-v1.xml
+ dde/treeland-output-uuid-unstable-v1.xml
+ dde/treeland-output-uuid-head-unstable-v1.xml
dde/treeland-wallpaper-manager-unstable-v1.xml
dde/treeland-layer-shell-extension-unstable-v1.xml
dde/treeland-xwindow-control-unstable-v1.xml
@@ -68,6 +70,7 @@ set(TREELAND_PROTOCOL_DEPRECATED_XML_FILES
deprecated/treeland-wallpaper-color-v1.xml
deprecated/treeland-window-management-v1.xml
deprecated/treeland-foreign-toplevel-manager-v1.xml
+ deprecated/treeland-virtual-output-manager-v1.xml
)
option(TREELAND_PROTOCOLS_INSTALL_DEPRECATED "Install deprecated protocol files" ON)
diff --git a/dde/README.md b/dde/README.md
index db7176a..50b396d 100644
--- a/dde/README.md
+++ b/dde/README.md
@@ -7,11 +7,13 @@ For DDE desktop components. Installed via `TREELAND_PROTOCOL_DDE_XML_FILES`.
| `treeland-foreign-toplevel-manager-unstable-v2.xml` | `treeland_foreign_toplevel_manager_unstable_v2` | `treeland_foreign_toplevel_manager_v2`, `treeland_foreign_toplevel_handle_v2`, `treeland_dock_preview_context_v2` | Redesigned toplevel observation and dock preview; fixes naming, member ordering, destroy placement, and description quality relative to v1 |
| `treeland-input-manager-unstable-v1.xml` | `treeland_input_manager_unstable_v1` | `treeland_input_manager_v1`, `treeland_pointer_device_configuration_v1`, `treeland_mouse_settings_v1`, `treeland_touchpad_settings_v1`, `treeland_keyboard_settings_v1` | Per-device input configuration: pointer acceleration, send-events mode, keyboard toggle state, and XKB keymap settings |
| `treeland-keyboard-state-notify-unstable-v1.xml` | `treeland_keyboard_state_notify_unstable_v1` | `treeland_keyboard_state_notify_manager_v1`, `treeland_keyboard_state_watcher_v1` | Watch keyboard modifier (caps/num lock) state changes |
-| `treeland-output-manager-unstable-v2.xml` | `treeland_output_manager_unstable_v2` | `treeland_output_manager_v2`, `treeland_output_picture_control_v2` | Primary output designation, per-output color temperature and brightness control |
+| `treeland-output-manager-unstable-v2.xml` | `treeland_output_manager_unstable_v2` | `treeland_output_manager_v2`, `treeland_output_picture_control_v2` | Primary output designation, per-output color temperature and brightness control; outputs addressed by uuid |
| `treeland-shortcut-manager-unstable-v3.xml` | `treeland_shortcut_manager_unstable_v3` | `treeland_shortcut_manager_v3`, `treeland_shortcut_capture_v3` | Global keyboard shortcut binding with key/touch/multi-touch gesture support and one-shot shortcut capture |
| `treeland-compositor-action-unstable-v1.xml` | `treeland_compositor_action_unstable_v1` | `treeland_compositor_action_v1` | One-shot privileged triggering of window-independent compositor actions: workspace switching, show-desktop, multitask overview, screen zoom, FPS overlay, lockscreen, shutdown menu, user switch; window-level and task-switch actions are intentionally excluded and remain only as shortcuts in `treeland_shortcut_manager_v3` |
| `treeland-appearance-manager-unstable-v1.xml` | `treeland_appearance_manager_unstable_v1` | `treeland_appearance_manager_v1` | Privileged user-level appearance configuration: cursor theme/size, global font, icon theme, accent color, window opacity, color scheme, titlebar height, global corner radius |
-| `treeland-virtual-output-manager-v1.xml` | `treeland_virtual_output_manager_v1` | `treeland_virtual_output_manager_v1`, `treeland_virtual_output_v1` | Virtual (mirrored) output creation and management |
+| `treeland-output-uuid-unstable-v1.xml` | `treeland_output_uuid_unstable_v1` | `treeland_output_uuid_manager_v1`, `treeland_output_uuid_v1` (frozen) | Stable opaque uuid identity for `wl_output` objects; the uuid is shared with the head variant and consumed by other output protocols |
+| `treeland-output-uuid-head-unstable-v1.xml` | `treeland_output_uuid_head_unstable_v1` | `treeland_output_uuid_head_manager_v1` | Companion to `treeland-output-uuid-unstable-v1`: obtain the same `treeland_output_uuid_v1` object from a `zwlr_output_head_v1` (wlr-output-management), including disabled outputs with no live `wl_output` |
+| `treeland-output-group-manager-unstable-v1.xml` | `treeland_output_group_manager_unstable_v1` | `treeland_output_group_manager_v1`, `treeland_output_group_v1` | Output mirroring (copy mode) groups: designate a source output mirrored to one or more mirror outputs, addressed by uuid, with registry-pattern enumeration |
| `treeland-wallpaper-manager-unstable-v1.xml` | `treeland_wallpaper_manager_unstable_v1` | `treeland_wallpaper_manager_v1`, `treeland_wallpaper_v1` | Per-output wallpaper configuration with image/video sources |
| `treeland-layer-shell-extension-unstable-v1.xml` | `treeland_layer_shell_extension_unstable_v1` | `treeland_layer_shell_extension_manager_v1`, `treeland_layer_shell_extension_object_v1` | Compositor-driven interactive resize for layer-shell surfaces (dock / side bar / status bar): begin_resize with seat+serial, per-resize size limits, and rejection reasons |
| `treeland-xwindow-control-unstable-v1.xml` | `treeland_xwindow_control_unstable_v1` | `treeland_xwindow_control_v1` | XWayland window placement: move an XWayland window (by X11 window ID) to a position relative to another surface, with wl_callback result feedback |
@@ -48,20 +50,34 @@ The DDE-shell protocol interfaces consumed by DDE components are split into dedi
- `treeland_multitaskview_v1` and `treeland_lockscreen_v1` (with their creating requests) are superseded by the corresponding actions (`toggle_multitask_view`/`open_multitask_view`/`close_multitask_view` and `lockscreen`/`shutdown_menu`/`show_user_switch`) of `treeland-compositor-action-unstable-v1.xml` (`treeland_compositor_action_v1`).
- `treeland_dde_shell_surface_v1` (and its `get_shell_surface` manager request) is superseded by `treeland-dde-shell-unstable-v2.xml` (`treeland_dde_shell_manager_v2` / `treeland_dde_shell_surface_v2`), in `dde/`; the surface role is carried over with a `role` enum that adds `normal` (0) while keeping `overlay` (1), and a merged `set_skip_flags` bitfield.
-### 0.6.0
-
#### `treeland-output-manager-v1.xml`
-Superseded by `treeland-output-manager-unstable-v2.xml`; the old v1 file moved to `deprecated/` unchanged. The v2 protocol renames both interfaces, normalizes member ordering, and switches primary-output identification from output names to `wl_output` objects. Wire-level differences:
+Superseded by `treeland-output-manager-unstable-v2.xml`; the old v1 file moved to `deprecated/` unchanged. The v2 protocol renames both interfaces, normalizes member ordering, and addresses outputs by opaque uuid strings from the new `treeland-output-uuid-unstable-v1` protocol instead of output names or `wl_output` objects. Wire-level differences:
-1. Interfaces renamed: `treeland_output_manager_v1` → `treeland_output_manager_v2` and `treeland_output_color_control_v1` → `treeland_output_picture_control_v2`; interface versions reset to 1 and the `since="2"` markers were removed.
+1. Interfaces renamed: `treeland_output_manager_v1` → `treeland_output_manager_v2` and `treeland_output_color_control_v1` → `treeland_output_picture_control_v2`; interface versions reset to 1.
2. `destroy` moved to the first request on both interfaces, shifting the opcodes of all other requests by one.
-3. `set_primary_output` now takes a non-null, enabled `wl_output` object instead of an output name `string`; passing a disabled or destroyed output is rejected via a `primary_output_failed` event rather than a protocol error. The compositor no longer supports clearing the primary designation via a null argument.
-4. The `primary_output` event now carries a `wl_output` object (null only when no output is available) instead of an output name `string`, is emitted once immediately after bind, and confirms every `set_primary_output` request. When the designated primary output is disconnected or disabled, the compositor automatically selects another available output as the new primary and emits this event.
-5. The `result` event argument changed from a plain `uint` flag (1 = success, 0 = failure) to the new `commit_result` enum (`success = 0`, `failed = 1`, `unsupported = 2`, `invalid_output = 3`), so the wire values are inverted.
-6. The picture control `error` enum is retained on the renamed `treeland_output_picture_control_v2` interface; its `invalid_color_temperature`/`invalid_brightness` entries keep the same names but their values reset from 1/2 to 0/1 following the interface version reset, and the fatal-protocol-error behavior on out-of-range `set_*` values is unchanged. `commit_result` therefore carries only success and output-related failure causes (no range entries); enums moved before requests, and a `primary_output_failed_reason` enum backs the new `primary_output_failed` event. `get_picture_control` accepts any valid `wl_output` regardless of state — invalid object ids remain a core protocol error; output validity is reported at commit time through the `result` event.
+3. `set_primary_output` takes a `string uuid` instead of an output name or `wl_output` object; an empty uuid is a fatal `error.invalid_uuid`, and a uuid with no connected enabled output is rejected via the `primary_output_failed` event (reason `invalid_output`).
+4. The `primary_output` event carries a `string uuid` (empty when no primary output is designated) instead of an output name or `wl_output` object, is emitted once on bind, and confirms every `set_primary_output` request.
+5. `get_picture_control` takes a `string uuid`; an empty uuid, or a uuid with no recognized connected output, is a fatal `error.invalid_uuid` (the object is not created, so the initial-state contract holds).
+6. The `result` event argument changed from a plain `uint` flag (1 = success, 0 = failure) to the `commit_result` enum (`success = 0`, `failed = 1`, `unsupported = 2`, `invalid_output = 3`), so the wire values are inverted.
+
+Consumers should rebind the global as `treeland_output_manager_v2`, obtain output uuids from `treeland_output_uuid_manager_v1.get_uuid`, pass uuid strings instead of output names or `wl_output` objects, and interpret `result` values via the `commit_result` enum.
+
+#### `treeland-virtual-output-manager-v1.xml`
-Consumers should rebind the global as `treeland_output_manager_v2`, pass `wl_output` objects instead of output names, and interpret `result` values via the `commit_result` enum; the old v1 XML is kept installed during migration but must not be used in new code.
+Superseded by `treeland-output-group-manager-unstable-v1.xml`; the old v1 file moved to `deprecated/` unchanged. The protocol was redesigned around uuid-based output identity instead of output-name strings, with explicit source/mirror separation, a registry-pattern enumeration model, and fully specified object lifecycles. Wire-level differences:
+
+1. Protocol and interfaces renamed: `treeland_virtual_output_manager_v1` → `treeland_output_group_manager_unstable_v1`, with interfaces `treeland_virtual_output_manager_v1` → `treeland_output_group_manager_v1` and `treeland_virtual_output_v1` → `treeland_output_group_v1`; interface versions reset to 1.
+2. Output identity switched from name strings to uuids: the `name`/`outputs` `string`/`array` arguments of `create_virtual_output`, the `names` `array` argument of the `virtual_output_list` event, and the `outputs` `array` argument of the `outputs` event are all removed. The new `create_group` request takes a group `name` `string` and an initial `source` uuid `string` (empty for no source), so a group is created with its source already set and observers never see an empty-source group; mirrors are added with `add_output` and the source changed with `set_source`. Outputs are referenced by uuid strings on the group's `set_source`, `add_output`, and `remove_output` requests and on its `source`, `output_added`, and `output_removed` events. The old `outputs[0] = source, outputs[1..] = mirrors` positional convention is replaced by an explicit `set_source` request and an ordered `add_output`/`remove_output` mirror list, with the `source` event reporting the current source uuid (empty when the group has no source). A non-empty source that does not identify a connected enabled output is rejected with the new fatal manager error `invalid_source`.
+3. Enumeration replaced by a registry push model: the `get_virtual_output_list` request and the `virtual_output_list` snapshot event are removed. On binding the manager the compositor emits one `group_added` event (carrying a fresh group object) per existing group, and again whenever a group is created; `group_removed` is emitted when a group is dissolved. This removes the list-then-lookup TOCTOU window.
+4. The `get_virtual_output` request is removed; clients obtain handles to existing groups from the bind-time `group_added` dump or from later `group_added` events, so the unknown-name fatal-error path no longer exists.
+5. The per-group `error` event is removed. Failures are split by severity: manager errors `invalid_name` (empty, non-UTF-8, or NUL-containing name) and `name_exists` (duplicate) are fatal protocol errors; group business failures — `invalid_output`, `duplicate_output`, `output_in_use`, `not_in_group` — are non-fatal and reported via the new `operation_failed` event (code + uuid), so transient output state like an unplug between `get_uuid` and the request does not terminate the connection. Only `already_dissolved` (any request other than `destroy` on a dissolved group) remains a fatal group protocol error. The old codes `invalid_group_name` (0), `invalid_screen_number` (1), and `invalid_output` (2) no longer exist.
+6. Object lifecycle redefined: destroying a group object (`destroy`) now only releases that client's handle and does not dissolve the group or affect other clients; a separate `dissolve` request tears down the group, emitting `removed` to all bound group objects and `group_removed` on the manager. The old behavior, where any client destroying its `treeland_virtual_output_v1` object (including one obtained via `get_virtual_output`) dissolved the group, is removed. Initial state is now pushed: a `source` event (empty uuid when no source) followed by one `output_added` per mirror is emitted immediately on every group object's creation, so clients no longer start with unknown state.
+7. Source-successor behavior on hardware removal is retained and made explicit: when the source output is unplugged or disabled and mirrors remain, the first remaining mirror becomes the new source (the compositor emits `output_removed` then `source` for it); client-driven `remove_output` of the source instead clears it (emits `source` with an empty uuid) and does not auto-select a successor.
+
+Consumers should rebind the global as `treeland_output_group_manager_v1`, obtain `treeland_output_group_v1` objects from the `group_added` event (or as the return value of `create_group`), reference outputs by uuid via `set_source`/`add_output`/`remove_output`, and dissolve groups with `dissolve` rather than by destroying a group object; the old v1 XML is kept installed during migration but must not be used in new code.
+
+### 0.6.0
#### `treeland-personalization-manager-v1.xml`
diff --git a/dde/README.zh_CN.md b/dde/README.zh_CN.md
index 1a1702a..6024c82 100644
--- a/dde/README.zh_CN.md
+++ b/dde/README.zh_CN.md
@@ -7,11 +7,13 @@
| `treeland-foreign-toplevel-manager-unstable-v2.xml` | `treeland_foreign_toplevel_manager_unstable_v2` | `treeland_foreign_toplevel_manager_v2`, `treeland_foreign_toplevel_handle_v2`, `treeland_dock_preview_context_v2` | 重新设计的顶层窗口观察和 Dock 预览;修正了命名、成员顺序、destroy 位置和描述质量 |
| `treeland-input-manager-unstable-v1.xml` | `treeland_input_manager_unstable_v1` | `treeland_input_manager_v1`, `treeland_pointer_device_configuration_v1`, `treeland_mouse_settings_v1`, `treeland_touchpad_settings_v1`, `treeland_keyboard_settings_v1` | 逐设备输入配置:指针加速、发送事件模式、键盘切换状态与 XKB 键盘映射设置 |
| `treeland-keyboard-state-notify-unstable-v1.xml` | `treeland_keyboard_state_notify_unstable_v1` | `treeland_keyboard_state_notify_manager_v1`, `treeland_keyboard_state_watcher_v1` | 监听键盘修饰键(Caps/Num Lock)状态变化 |
-| `treeland-output-manager-unstable-v2.xml` | `treeland_output_manager_unstable_v2` | `treeland_output_manager_v2`, `treeland_output_picture_control_v2` | 指定主屏、逐输出色温和亮度控制 |
+| `treeland-output-manager-unstable-v2.xml` | `treeland_output_manager_unstable_v2` | `treeland_output_manager_v2`, `treeland_output_picture_control_v2` | 指定主屏、逐输出色温和亮度控制;输出按 uuid 寻址 |
| `treeland-shortcut-manager-unstable-v3.xml` | `treeland_shortcut_manager_unstable_v3` | `treeland_shortcut_manager_v3`, `treeland_shortcut_capture_v3` | 全局键盘快捷键绑定,支持按键/触摸/多点触摸手势及一次性快捷键捕获 |
| `treeland-compositor-action-unstable-v1.xml` | `treeland_compositor_action_unstable_v1` | `treeland_compositor_action_v1` | 特权客户端一次性触发与当前窗口无关的合成器动作:工作区切换、显示桌面、多任务视图、屏幕缩放、FPS 覆盖层、锁屏、关机菜单、用户切换;窗口级与任务切换动作被有意排除,仅作为 `treeland_shortcut_manager_v3` 中的快捷键保留 |
| `treeland-appearance-manager-unstable-v1.xml` | `treeland_appearance_manager_unstable_v1` | `treeland_appearance_manager_v1` | 特权用户级外观配置:光标主题/大小、全局字体、图标主题、强调色、窗口不透明度、配色方案、标题栏高度、全局圆角 |
-| `treeland-virtual-output-manager-v1.xml` | `treeland_virtual_output_manager_v1` | `treeland_virtual_output_manager_v1`, `treeland_virtual_output_v1` | 虚拟(镜像)输出创建和管理 |
+| `treeland-output-uuid-unstable-v1.xml` | `treeland_output_uuid_unstable_v1` | `treeland_output_uuid_manager_v1`、`treeland_output_uuid_v1`(frozen) | `wl_output` 的稳定不透明 uuid 身份;该 uuid 与 head 变体共享,供其他输出协议消费 |
+| `treeland-output-uuid-head-unstable-v1.xml` | `treeland_output_uuid_head_unstable_v1` | `treeland_output_uuid_head_manager_v1` | `treeland-output-uuid-unstable-v1` 的配套协议:从 `zwlr_output_head_v1`(wlr-output-management)获取同一个 `treeland_output_uuid_v1` 对象,涵盖无存活 `wl_output` 的禁用输出 |
+| `treeland-output-group-manager-unstable-v1.xml` | `treeland_output_group_manager_unstable_v1` | `treeland_output_group_manager_v1`, `treeland_output_group_v1` | 输出镜像(复制模式)分组管理:指定一个源输出并镜像到一个或多个镜像输出,按 uuid 寻址,采用 registry 模式枚举 |
| `treeland-wallpaper-manager-unstable-v1.xml` | `treeland_wallpaper_manager_unstable_v1` | `treeland_wallpaper_manager_v1`, `treeland_wallpaper_v1` | 逐输出壁纸配置,支持图片/视频来源 |
| `treeland-layer-shell-extension-unstable-v1.xml` | `treeland_layer_shell_extension_unstable_v1` | `treeland_layer_shell_extension_manager_v1`, `treeland_layer_shell_extension_object_v1` | 合成器驱动的 layer-shell 表面交互式缩放(dock / 侧边栏 / 状态栏):begin_resize 携带 seat+serial 与单次尺寸限制,及拒绝原因 |
| `treeland-xwindow-control-unstable-v1.xml` | `treeland_xwindow_control_unstable_v1` | `treeland_xwindow_control_v1` | XWayland 窗口定位:将 XWayland 窗口(按 X11 窗口 ID)移动到相对另一 surface 的位置,结果经 wl_callback 回报 |
@@ -48,20 +50,34 @@ DDE-shell 协议中被 DDE 组件消费的接口拆分为 `dde/` 下的专用协
- `treeland_multitaskview_v1` 和 `treeland_lockscreen_v1`(含其创建请求)由 `treeland-compositor-action-unstable-v1.xml`(`treeland_compositor_action_v1`)的对应动作取代(`toggle_multitask_view`/`open_multitask_view`/`close_multitask_view` 与 `lockscreen`/`shutdown_menu`/`show_user_switch`)。
- `treeland_dde_shell_surface_v1`(含其创建请求 `get_shell_surface`)由 `treeland-dde-shell-unstable-v2.xml`(`treeland_dde_shell_manager_v2` / `treeland_dde_shell_surface_v2`)取代,后者位于 `dde/`;surface 角色得以保留,`role` 枚举新增 `normal`(0)并保留 `overlay`(1),skip 请求合并为 `set_skip_flags` 位域。
-### 0.6.0
-
#### `treeland-output-manager-v1.xml`
-被 `treeland-output-manager-unstable-v2.xml` 取代;旧 v1 文件原样移至 `deprecated/`。v2 协议重命名了两个接口,规范了成员排序,并将主屏标识从输出名称改为 `wl_output` 对象。线缆级差异:
+被 `treeland-output-manager-unstable-v2.xml` 取代;旧 v1 文件原样移至 `deprecated/`。v2 协议重命名两个接口、规范成员排序,并改用来自新增 `treeland-output-uuid-unstable-v1` 协议的不透明 uuid 字符串寻址输出,替代输出名称或 `wl_output` 对象。线缆级差异:
-1. 接口重命名:`treeland_output_manager_v1` → `treeland_output_manager_v2`,`treeland_output_color_control_v1` → `treeland_output_picture_control_v2`;接口版本重置为 1,移除了 `since="2"` 标记。
+1. 接口重命名:`treeland_output_manager_v1` → `treeland_output_manager_v2`,`treeland_output_color_control_v1` → `treeland_output_picture_control_v2`;接口版本重置为 1。
2. 两个接口的 `destroy` 移至首个请求,其余请求的操作码整体后移一位。
-3. `set_primary_output` 参数由输出名称 `string` 改为不可为 null 且已启用的 `wl_output` 对象;传已禁用或已销毁的输出将通过 `primary_output_failed` 事件拒绝而非协议错误。不再支持通过传 null 清除主屏指定。
-4. `primary_output` 事件参数由输出名称 `string` 改为 `wl_output` 对象(仅当无可用输出时为 null),绑定时立即发送一次,并确认每一次 `set_primary_output` 请求。当被指定的主屏被拔出或禁用时,合成器自动选择另一个可用输出作为新主屏并发送该事件。
-5. `result` 事件参数由普通 `uint` 标志(1 = 成功,0 = 失败)改为新增的 `commit_result` 枚举(`success = 0`,`failed = 1`,`unsupported = 2`,`invalid_output = 3`),线缆取值因此反转。
-6. picture control 的 `error` 枚举在重命名后的 `treeland_output_picture_control_v2` 接口上保留;其 `invalid_color_temperature`/`invalid_brightness` 项名称不变,但因接口版本重置,值由 1/2 重置为 0/1,`set_*` 越界即致命协议错误的行为不变。`commit_result` 因此只承载成功与输出相关的失败原因(不含范围校验项);枚举移至 requests 之前,`primary_output_failed_reason` 枚举供新增的 `primary_output_failed` 事件使用。`get_picture_control` 接受任何状态的合法 `wl_output`——无效对象 ID 仍属核心协议错误;输出有效性在 commit 时通过 `result` 事件反馈。
+3. `set_primary_output` 参数改为 `string uuid`(替代输出名称或 `wl_output` 对象);空 uuid 为致命错误 `error.invalid_uuid`,无已连接已启用输出的 uuid 以 `primary_output_failed` 事件拒绝(原因 `invalid_output`)。
+4. `primary_output` 事件携带 `string uuid`(无主屏时为空),替代输出名称或 `wl_output` 对象,绑定时发送一次,并确认每一次 `set_primary_output` 请求。
+5. `get_picture_control` 参数改为 `string uuid`;空 uuid 或无合成器已识别的已连接输出的 uuid 为致命错误 `error.invalid_uuid`(不创建对象,故初始状态契约成立)。
+6. `result` 事件参数由普通 `uint` 标志(1 = 成功,0 = 失败)改为 `commit_result` 枚举(`success = 0`,`failed = 1`,`unsupported = 2`,`invalid_output = 3`),线缆取值反转。
+
+消费者应将全局对象重新绑定为 `treeland_output_manager_v2`,从 `treeland_output_uuid_manager_v1.get_uuid` 获取输出 uuid,改传 uuid 字符串而非输出名称或 `wl_output` 对象,并按 `commit_result` 枚举解释 `result` 值。
+
+#### `treeland-virtual-output-manager-v1.xml`
-消费者应将全局对象重新绑定为 `treeland_output_manager_v2`,改传 `wl_output` 对象而非输出名称,并按 `commit_result` 枚举解释 `result` 值;旧 v1 XML 在迁移期间仍会安装,但不得用于新代码。
+被 `treeland-output-group-manager-unstable-v1.xml` 取代;旧 v1 文件原样移至 `deprecated/`。协议围绕基于 uuid 的输出身份(而非输出名字符串)重新设计,显式区分源/镜像,采用 registry 模式枚举,并完整定义了对象生命周期。线缆级差异:
+
+1. 协议与接口重命名:`treeland_virtual_output_manager_v1` → `treeland_output_group_manager_unstable_v1`,接口 `treeland_virtual_output_manager_v1` → `treeland_output_group_manager_v1`、`treeland_virtual_output_v1` → `treeland_output_group_v1`;接口版本重置为 1。
+2. 输出身份由名称改为 uuid:移除 `create_virtual_output` 的 `name`、`outputs` `string`/`array` 参数、`virtual_output_list` 事件的 `names` `array` 参数以及 `outputs` 事件的 `outputs` `array` 参数。新 `create_group` 请求接收组名 `name` `string` 与初始源 uuid `string`(空表示无源),因此组创建时即已设置源,观察者不会看到空源组;镜像通过 `add_output` 添加,源通过 `set_source` 更改。输出在组的 `set_source`、`add_output`、`remove_output` 请求及 `source`、`output_added`、`output_removed` 事件中均以 uuid 字符串引用。旧的 `outputs[0] = 源,outputs[1..] = 镜像` 位置约定改为显式的 `set_source` 请求与有序的 `add_output`/`remove_output` 镜像列表,并以 `source` 事件上报当前源 uuid(无源时为空)。不标识已连接已启用输出的非空源以新增致命管理器错误 `invalid_source` 拒绝。
+3. 枚举改为 registry 推送模型:移除 `get_virtual_output_list` 请求与 `virtual_output_list` 快照事件。绑定管理器时,合成器为每个已存在的组发送一个 `group_added` 事件(携带一个新的组对象),并在任意组创建时再次发送;组解散时发送 `group_removed`。由此消除了“先列表、再查找”的 TOCTOU 窗口。
+4. 移除 `get_virtual_output` 请求;客户端从绑定时的 `group_added` 推送或后续 `group_added` 事件获取已存在组的句柄,因此不再存在未知名称的致命错误路径。
+5. 移除逐组的 `error` 事件。失败按严重程度划分:管理器错误 `invalid_name`(空、非 UTF-8 或含 NUL 的名称)、`name_exists`(重名)为致命协议错误;组业务失败——`invalid_output`、`duplicate_output`、`output_in_use`、`not_in_group`——为非致命,通过新增的 `operation_failed` 事件(code + uuid)报告,因此 `get_uuid` 与请求之间的拔出等瞬态输出状态不会终止连接。仅 `already_dissolved`(对已解散组发送除 `destroy` 外的任何请求)仍为致命组协议错误。旧码值 `invalid_group_name`(0)、`invalid_screen_number`(1)、`invalid_output`(2)不复存在。
+6. 对象生命周期重新定义:销毁组对象(`destroy`)现在仅释放该客户端的句柄,不会解散组也不影响其他客户端;新增 `dissolve` 请求才解散组,并向所有绑定的组对象发送 `removed`、在管理器上发送 `group_removed`。旧“任意客户端销毁其 `treeland_virtual_output_v1` 对象(含经 `get_virtual_output` 获取者)即解散组”的行为已移除。初始状态现改为推送:每个组对象创建后立即发送一次 `source` 事件(无源时为空 uuid)及逐个镜像的 `output_added` 事件,客户端不再以未知状态开始。
+7. 源拔出后的后继行为保留并明确化:当源输出被拔出或禁用且仍有镜像时,第一个剩余镜像成为新源(合成器依次发送该输出的 `output_removed` 与 `source`);而客户端主动 `remove_output` 源则清除源(发送携带空 uuid 的 `source`),不自动选择后继。
+
+消费者应将全局对象重新绑定为 `treeland_output_group_manager_v1`,从 `group_added` 事件(或 `create_group` 的返回值)获取 `treeland_output_group_v1` 对象,以 uuid 通过 `set_source`/`add_output`/`remove_output` 引用输出,并用 `dissolve` 而非销毁组对象来解散组;旧 v1 XML 在迁移期间仍会安装,但不得用于新代码。
+
+### 0.6.0
#### `treeland-personalization-manager-v1.xml`
diff --git a/dde/treeland-output-group-manager-unstable-v1.xml b/dde/treeland-output-group-manager-unstable-v1.xml
new file mode 100644
index 0000000..125cf70
--- /dev/null
+++ b/dde/treeland-output-group-manager-unstable-v1.xml
@@ -0,0 +1,486 @@
+
+
+
+
+
+ This protocol lets a privileged client such as the DDE display settings
+ panel organize physical outputs into mirroring groups: one source
+ output whose rendered content is duplicated to one or more mirror
+ outputs, so that several screens show the same desktop. This is the
+ "copy mode" of the compositor, as opposed to the default "extension"
+ mode where each output shows an independent desktop region.
+
+ The protocol exposes a singleton manager global that creates and
+ tracks treeland_output_group_v1 objects. Each group designates
+ a single source output and an ordered list of mirror outputs, all
+ addressed by opaque uuid strings. While copy mode is engaged the
+ compositor exposes a wl_output global only for the source output;
+ mirror outputs have no wl_output, so their uuids must be obtained
+ from the treeland-output-uuid-head-unstable-v1 protocol rather than
+ treeland-output-uuid-unstable-v1 (see treeland_output_group_v1 for
+ details). An output may belong to at most one group at a time. A
+ group drives copy mode while it has both a source and at least one
+ mirror; a group with no source or no mirrors is inert, the affected
+ outputs get their wl_output back, and they behave as normal
+ extension outputs. An empty uuid represents the absence of a
+ source; output uuids are never empty.
+
+ The compositor persists the set of groups and their configuration
+ (name, configured source uuid, and configured mirror uuid list)
+ across compositor restarts and restores them on startup, so groups
+ survive reboots and reappear as group_added events on bind; this
+ lets a privileged client configure mirroring once and have it
+ reapply automatically later. An output must be connected and
+ enabled when it is first added to a group (via create_group,
+ set_source, or add_output); once configured it is kept across
+ unplug/replug and compositor restart and auto-resumes when the
+ output returns. The name never changes; the configured source and
+ mirror list persist until a client changes them with set_source,
+ add_output, remove_output, or dissolve.
+
+ The terms "must", "must not", "should", and "may" in this document are
+ to be interpreted as described in RFC 2119.
+
+ Warning! This protocol is EXPERIMENTAL and under active development.
+ It may change at any time, including in backward-incompatible ways,
+ without incrementing the interface major version and without prior
+ notice. No compatibility guarantees of any kind are provided. Clients
+ and compositors must track the upstream definition in treeland-protocols
+ and must not rely on the current interface names, requests, events, or
+ semantics remaining stable across releases.
+
+
+
+
+ A singleton global that creates treeland_output_group_v1
+ objects and broadcasts the set of existing groups to bound clients.
+
+ On bind the compositor emits one group_added event per existing
+ group, followed by a single groups_done event, so the client can
+ distinguish the initial dump of pre-existing groups from later
+ group_added events for groups created after the bind. When any
+ client creates a group every other bound client receives
+ group_added for it, and when a group is dissolved every bound
+ client receives group_removed. Clients therefore never poll for
+ the group set; they may also obtain a group object for a known
+ name at any time with the get_group request.
+
+ Multiple privileged clients such as the DDE display settings
+ panel may bind and use the protocol concurrently. Requests from
+ all clients are applied in arrival order; an output claimed by
+ one group is rejected for another with the non-fatal
+ output_in_use failure, so concurrent edits never terminate a
+ connection and clients may retry or adjust.
+
+
+
+
+ Raised as fatal protocol errors on the manager object.
+
+
+
+
+
+
+
+ Destroy the treeland_output_group_manager_v1 object and
+ release the client's binding to the manager global.
+
+ Existing treeland_output_group_v1 objects are not
+ affected and remain valid until they are destroyed or the
+ compositor dissolves the group. The client must destroy each
+ group object separately; the compositor does not cascade
+ destruction from the manager.
+
+
+
+
+
+ Create a new treeland_output_group_v1 object with the
+ given initial source output. An empty source creates
+ a group with no source; the client adds mirrors afterwards
+ with add_output and may change the source with set_source.
+ Copy mode engages once the group has both a source and at
+ least one mirror.
+
+ The compositor assigns a unique name to the new group; names
+ are chosen by the compositor, not by clients. The client
+ learns the name from the name event, which the compositor
+ emits on the new group object before any other event. The
+ name identifies the group in the manager's group_removed
+ event. A non-empty source that does not identify a connected
+ enabled output is rejected with the invalid_source fatal
+ error. This check is deterministic, so the compositor raises
+ it on the manager object and does not create the group.
+
+ On success the compositor broadcasts a group_added event
+ carrying a new group object to every other bound client; the
+ caller receives its group object only as the new_id return
+ value and does not get a group_added event for it.
+
+
+
+
+
+
+
+ Create a new treeland_output_group_v1 object bound to the
+ existing group with the given name, for example a group
+ created by another client or one whose object the client
+ has since destroyed. On success the compositor sends the initial state of
+ the group on the new object: one name event, then one source
+ event, followed by one outputs event carrying the full
+ mirror list in list order.
+
+ The name is the compositor-assigned name reported by the
+ name event on group objects. An empty name, or a name that
+ does not identify an existing group at the time the request
+ is processed, is rejected with the invalid_name fatal error
+ and no object is created; note that a group may have been
+ dissolved between the group_removed event and this request.
+ This lookup is deterministic, so the compositor raises the
+ error on the manager object.
+
+ The returned object is an independent handle: destroying it
+ does not dissolve the group, and several clients may hold
+ objects bound to the same group at the same time.
+
+
+
+
+
+
+
+ Emitted when an output group is created by any client. Each
+ bound client receives this event once per existing group on
+ bind, and again whenever a new group is created — except for
+ the client that created the group, which receives the group
+ object as the new_id return value of create_group instead.
+
+ The id argument is a fresh group object; the compositor sends
+ the initial name, source, and outputs state of the group
+ on it immediately after this event. The client may destroy the
+ object if it does not need to observe that group; doing so
+ does not dissolve the group.
+
+
+
+
+
+
+ Emitted exactly once, after the compositor has finished
+ sending the bind-time group_added events, and the initial
+ state on each group object they carry, for all groups that
+ existed when the client bound. A client receiving this event
+ knows it has seen the complete initial set and that any
+ later group_added is for a group created after the bind.
+
+
+
+
+
+ Emitted when an output group is dissolved, whether because a
+ client sent the dissolve request or because the compositor
+ removed it as a whole. Every bound client receives this event
+ for the group; any group objects that client holds for it
+ receive a removed event and must be destroyed afterwards.
+
+
+
+
+
+
+
+ Represents one mirroring group: a source output, identified by
+ its uuid, whose content is duplicated to an ordered list of
+ mirror outputs, each identified by its uuid. Output uuids are
+ never empty; an empty uuid in events represents the absence of
+ a source.
+
+ While the group has both a source and at least one mirror, the
+ compositor exposes a wl_output global only for the source
+ output. Mirror outputs have no wl_output while copy mode is
+ engaged, so clients cannot use wl_output-based protocols
+ (including treeland-output-uuid-unstable-v1, which requires a
+ wl_output) to identify them; they must instead obtain mirror
+ uuids from the treeland-output-uuid-head-unstable-v1 protocol,
+ which resolves a zwlr_output_head_v1 to the same uuid. A
+ configured mirror only loses its wl_output while copy mode is
+ actually engaged; while the group is inert (no effective source
+ or no effective mirrors) the mirror retains its wl_output and
+ behaves as a normal extension output. When copy mode exits —
+ the last mirror is removed, the source is cleared, or the group
+ is dissolved — the affected outputs become normal extension
+ outputs again and their wl_output globals come back.
+
+ The group keeps a configured source (zero or one) and a
+ configured mirror list (zero or more), set by the client with
+ set_source, add_output, and remove_output. The source and outputs
+ events report the effective runtime state, not the configured
+ state: a configured source or mirror whose output is currently
+ unplugged or disabled is absent from those events but remains in
+ the persisted configuration, so copy mode auto-resumes when the
+ output comes back. An output may belong to at most one group at
+ a time; one already in another group fails with the
+ output_in_use failure. Copy mode is engaged while the group has
+ both an effective source and at least one effective mirror;
+ otherwise the group is inert and the affected outputs behave as
+ normal extension outputs.
+
+ Requests that cannot be applied because of transient output state
+ (e.g. an output unplugged between get_uuid and the request) are
+ reported via a non-fatal operation_failed event; the group is
+ unchanged and the client may retry. Only already_dissolved —
+ sending any request other than destroy on a dissolved group — is
+ a fatal protocol error.
+
+ On creation the compositor sends the current state: one name
+ event carrying the compositor-assigned group name, then one
+ source event (empty uuid if no source), followed by one outputs
+ event carrying the full mirror list. Later changes are
+ reported by further source and outputs events; the name never
+ changes.
+
+ Several group objects may be bound to the same group, for example
+ one from create_group, one from get_group, and others from
+ group_added; they all observe the same state. Destroying one
+ object only releases that client's handle. The dissolve request tears down the group as a
+ whole, emitting removed to every bound group object and
+ group_removed on the manager. After removed the object is inert:
+ only destroy is valid, and anything else is rejected with the
+ already_dissolved error.
+
+ When a member output is unplugged or disabled the compositor
+ updates the effective runtime state without dissolving the group
+ and without changing the persisted configuration: an unavailable
+ mirror is dropped from the outputs event, and if the source
+ becomes unavailable its source event is emitted with an empty
+ uuid — unavailable outputs cannot serve as source, so the
+ compositor does not auto-promote a mirror. When the output comes
+ back (replugged or re-enabled) the compositor re-evaluates and
+ resumes automatically: the source event regains its configured
+ uuid and the outputs event regains the mirror, without any client
+ action. If all of a group's outputs are unavailable the source
+ event is empty and the outputs count is zero, but the group
+ remains and is restored once any output returns. Client-driven
+ remove_output, by contrast, removes the output from the
+ persisted configuration.
+
+
+
+
+ Raised as fatal protocol errors on the group object.
+
+
+
+
+
+
+ Returned by the operation_failed event when a set_source,
+ add_output, or remove_output request cannot be applied.
+ These reflect transient or dynamic output state (e.g. an
+ output unplugged between get_uuid and the request), not a
+ protocol violation; the client may retry or adjust and the
+ connection is not terminated.
+
+
+
+
+
+
+
+
+
+ Destroy this group object and release the client's handle.
+ The group itself is not affected: copy mode continues, other
+ handles remain valid, and the compositor does not emit
+ group_removed. Use dissolve to tear down the group as a whole.
+ It is safe to destroy an object that has already received the
+ removed event.
+
+
+
+
+
+ Set the output identified by the given uuid as the configured
+ source of the group, replacing any current configured source.
+ The previous source, if available, becomes a normal extension
+ output again.
+
+ If the request cannot be applied, the compositor emits an
+ operation_failed event and the group is unchanged:
+ invalid_output if the uuid does not identify a connected
+ enabled output, duplicate_output if the output is already
+ in this group (to promote a current mirror to the source,
+ remove it first with remove_output), or output_in_use if the
+ output belongs to another group.
+
+ If the group already has mirrors, this engages or updates copy
+ mode immediately. The compositor confirms the new source by
+ emitting a source event.
+
+
+
+
+
+
+ Append the output identified by the given uuid to the end of
+ the group's mirror list.
+
+ If the request cannot be applied, the compositor emits an
+ operation_failed event and the group is unchanged:
+ invalid_output if the uuid does not identify a connected
+ enabled output, duplicate_output if the output is already in
+ this group, or output_in_use if it belongs to another group.
+
+ If the group already has a source, this engages or extends
+ copy mode immediately, confirmed by an outputs event carrying
+ the updated mirror list. Sources and mirrors may be set in
+ any order; copy mode engages once both are present.
+
+
+
+
+
+
+ Remove the output identified by the given uuid from the
+ configured membership of the group. If the output is not a
+ configured member, the compositor emits an operation_failed
+ event with not_in_group and the group is unchanged; this
+ covers an output that was never added as well as one whose
+ configuration was already removed.
+
+ If the output is a configured mirror (whether currently
+ available or not), an outputs event carrying the updated
+ effective mirror list is emitted; if the group then has an
+ effective source but no effective mirrors, copy mode exits
+ while the source remains set.
+
+ If the output is the configured source (whether currently
+ available or not), the configured source is cleared and a
+ source event with an empty uuid is emitted; the mirrors are
+ unchanged and copy mode exits. This does not auto-select a
+ successor; to promote a mirror, call set_source on it.
+
+
+
+
+
+
+ Tear down the group: exit copy mode, remove it from the
+ manager, and release the affected outputs. The configured
+ source and mirror list are discarded and the group is not
+ restored on compositor restart. The compositor emits removed
+ to every group object bound to this group and group_removed
+ on the manager. After removed the object is inert; only
+ destroy is valid, and anything else — including dissolve
+ again — is rejected with already_dissolved.
+
+
+
+
+
+ Reports the name the compositor assigned to this group.
+ Emitted exactly once on each group object, before any other
+ event, so the creator of the group learns its name without a
+ group_added event. The name is unique among existing groups
+ and never changes; it identifies the group in the manager's
+ group_removed event and is the name accepted by the
+ manager's get_group request.
+
+
+
+
+
+
+ Reports the uuid of the current effective source output:
+ the configured source if its output is currently connected
+ and enabled, or an empty uuid when the configured source is
+ unavailable (unplugged or disabled) or when no source is
+ configured. Emitted once on creation and again whenever the
+ effective source changes, including when an unavailable
+ source comes back or an available one goes away; the
+ configured source is restored automatically on return.
+
+
+
+
+
+
+ Reports the complete ordered list of effective mirror
+ outputs of the group: the configured mirrors whose outputs
+ are currently connected and enabled. Emitted once on
+ creation with the current effective mirror list, and again
+ whenever that list changes: after a successful add_output
+ or remove_output of a mirror, when a mirror is unplugged,
+ disabled, re-enabled, or replugged. Each emission carries the
+ full effective list, replacing any previously known list, so
+ the client replaces its state instead of applying deltas.
+
+ The uuids argument contains the concatenation of count
+ uuids, one per mirror, in list order. All output uuids have
+ the same length, so each uuid is the array size in bytes
+ divided by count, and parsing needs no separators: the
+ client reads count fixed-length uuids back to back. The
+ count argument always matches the number of uuids in the
+ array; a client may use it to validate the array size. The
+ list order follows the order in which mirrors were added;
+ unavailable mirrors are filtered out without shifting the
+ relative order of the others. The source output, if any, is
+ not part of the list and is reported separately by the source
+ event; a count of zero means the group currently has no
+ effective mirrors.
+
+
+
+
+
+
+
+ Emitted to every group object bound to the group when the
+ group is dissolved. After this event the object is inert and
+ the client must destroy it.
+
+
+
+
+
+ Emitted when a set_source, add_output, or remove_output
+ request cannot be applied because of a transient or dynamic
+ output state, such as an output being unplugged between
+ get_uuid and the request. The code identifies the failure
+ cause; the uuid is the output the client passed to the
+ failing request. The group state is unchanged and the client
+ may retry or adjust. This is not a protocol error and the
+ connection is not terminated.
+
+
+
+
+
+
diff --git a/dde/treeland-output-manager-unstable-v2.xml b/dde/treeland-output-manager-unstable-v2.xml
index 5d6259d..e086c99 100644
--- a/dde/treeland-output-manager-unstable-v2.xml
+++ b/dde/treeland-output-manager-unstable-v2.xml
@@ -24,6 +24,14 @@
2. Adjusting the color temperature and brightness of individual outputs
via a double-buffered pending/commit model.
+ Outputs in this protocol are addressed by opaque uuid strings instead
+ of wl_output objects. Clients obtain the uuid of an output from the
+ treeland-output-uuid-unstable-v1 protocol. A uuid remains stable
+ across sessions and output reconnections, which lets clients and the
+ compositor persist per-output settings and restore them after a
+ restart. In the primary_output event an empty uuid means that no
+ primary output is currently designated.
+
The terms "must", "must not", "should", and "may" in this document are
to be interpreted as described in RFC 2119.
@@ -38,8 +46,8 @@
requests from them, while a binding is already active.
On binding, the compositor immediately emits a primary_output event
- carrying the currently designated primary output, or null if no
- primary output has been designated.
+ carrying the uuid of the currently designated primary output, or
+ an empty uuid if no primary output has been designated.
@@ -47,7 +55,15 @@
Reasons returned by the primary_output_failed event.
+ summary="no enabled output with the provided uuid is currently connected" />
+
+
+
+
+ Raised as fatal protocol errors on the manager object.
+
+
@@ -62,37 +78,45 @@
- Designate the given output as the primary output. The compositor
- uses the primary output as a hint for panel placement, initial
- window positioning, and other compositor-defined policies.
-
- The output must be a currently enabled, available wl_output.
- If the output is disabled or no longer available, the compositor
- rejects the request and emits a primary_output_failed event;
- the primary output designation is unchanged.
+ Designate the output identified by the given uuid as the
+ primary output. The compositor uses the primary output as a
+ hint for panel placement, initial window positioning, and
+ other compositor-defined policies.
+
+ The uuid must identify a currently connected, enabled output.
+ If no enabled output with this uuid is currently connected,
+ the compositor rejects the request and emits a
+ primary_output_failed event with the invalid_output reason;
+ the primary output designation is unchanged. An empty uuid is
+ a client error and is rejected with the invalid_uuid fatal
+ protocol error.
The compositor applies a successful change immediately and
confirms it by emitting a primary_output event carrying the
- newly designated primary output.
+ uuid of the newly designated primary output.
-
+
- Create a treeland_output_picture_control_v2 object bound to the
- given output. The returned object allows the client to adjust
- the color temperature and brightness of that output.
-
- For any live wl_output resource this request always succeeds
- without a protocol error, regardless of the output state —
- enabled, disabled, or no longer present in the configuration.
- An invalid or destroyed object id, or an object of another
- type, is still rejected by the core protocol
- (wl_display.invalid_object). If the bound output is later
- destroyed or not recognized by the compositor, subsequent
- commits fail with the invalid_output result.
+ Create a treeland_output_picture_control_v2 object for the
+ output identified by the given uuid. The returned object
+ allows the client to adjust the color temperature and
+ brightness of that output.
+
+ The uuid must identify a currently connected output, in any
+ state (enabled or disabled). An empty uuid, or a uuid that
+ does not identify a connected output the compositor
+ recognizes, is rejected with the invalid_uuid fatal error.
+ This check is deterministic at request time, so the compositor
+ raises it on the manager object and does not create the
+ picture control object.
+
+ For an output that was valid at creation but later becomes
+ unavailable, subsequent commits fail with the invalid_output
+ result.
Multiple picture control objects may exist for the same output at
the same time; each object reports value changes independently.
@@ -104,34 +128,35 @@
-
+
- Emitted by the compositor to report the current primary output.
- This event is sent once immediately after the client binds this
- interface, and again whenever the primary output designation
- changes — whether in response to a set_primary_output request
- or through a compositor-driven fallback.
+ Emitted by the compositor to report the uuid of the current
+ primary output. This event is sent once immediately after the
+ client binds this interface, and again whenever the primary
+ output designation changes — whether in response to a
+ set_primary_output request or through a compositor-driven
+ fallback.
When the designated primary output is disconnected or disabled,
the compositor automatically selects another available output as
- the new primary and emits this event with it. When no output is
- currently available, the event is emitted with a null output.
+ the new primary and emits this event with its uuid. When no
+ output is currently available, the event is emitted with an
+ empty uuid.
-
+
Emitted when a set_primary_output request cannot be applied,
indicating that the primary output designation is unchanged.
- The reason identifies why the request was rejected: the
- provided output was disabled or no longer available.
+ The reason identifies why the request was rejected: no enabled
+ output with the provided uuid is currently connected.
@@ -140,8 +165,9 @@
- Represents a picture control session bound to a specific output,
- created by treeland_output_manager_v2.get_picture_control.
+ Represents a picture control session bound to the output
+ identified by its uuid, created by
+ treeland_output_manager_v2.get_picture_control.
Color temperature and brightness are managed via a double-buffered
pending/commit model. The client accumulates changes with
@@ -154,9 +180,10 @@
events to report the current values of the output before the client
has made any changes.
- Clients should destroy this object when the associated wl_output
- is destroyed; otherwise subsequent commits fail with the
- invalid_output result.
+ Clients should destroy this object when the output identified
+ by its uuid is removed; otherwise subsequent commits fail with
+ the invalid_output result. (A uuid rejected at creation never
+ produces a picture control object; see get_picture_control.)
@@ -187,7 +214,7 @@
+ summary="the uuid does not identify a live enabled output; settings remain unchanged" />
@@ -254,8 +281,8 @@
time and never reaches a commit; a commit therefore only
fails because of the output: it does not support the requested
adjustment (unsupported, retrying the same settings is unlikely
- to succeed), it has been destroyed or is no longer recognized
- (invalid_output), or the commit could not be applied for a
+ to succeed), the uuid no longer identifies a live enabled
+ output (invalid_output), or the commit could not be applied for a
transient or unknown reason (failed). In every failure case the
applied settings remain unchanged.
diff --git a/dde/treeland-output-uuid-head-unstable-v1.xml b/dde/treeland-output-uuid-head-unstable-v1.xml
new file mode 100644
index 0000000..3a5629b
--- /dev/null
+++ b/dde/treeland-output-uuid-head-unstable-v1.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+ Companion of treeland-output-uuid-unstable-v1 for clients that
+ identify outputs through wlr-output-management. It lets a client
+ obtain the same stable treeland_output_uuid_v1 object from a
+ zwlr_output_head_v1 instead of a wl_output, so it can identify an
+ output that is disabled and has no live wl_output global, or an
+ output used as a mirror in a copy mode group of the
+ treeland-output-group-manager-unstable-v1 protocol, which likewise
+ has no wl_output. The uuid
+ returned for a head is the same uuid that
+ treeland_output_uuid_manager_v1.get_uuid returns for the wl_output
+ of the same physical output device.
+
+ The treeland_output_uuid_v1 interface, including the meaning and
+ stability of the uuid, is defined by
+ treeland-output-uuid-unstable-v1 and is not duplicated here; this
+ protocol only adds a second factory that creates the same object.
+
+ The terms "must", "must not", "should", and "may" in this document are
+ to be interpreted as described in RFC 2119.
+
+ Warning! This protocol is EXPERIMENTAL and under active development.
+ It may change at any time, including in backward-incompatible ways,
+ without incrementing the interface major version and without prior
+ notice. No compatibility guarantees of any kind are provided. Clients
+ and compositors must track the upstream definition in treeland-protocols
+ and must not rely on the current interface names, requests, events, or
+ semantics remaining stable across releases.
+
+
+
+
+ A singleton global that creates treeland_output_uuid_v1 objects
+ from zwlr_output_head_v1 objects. The client calls get_uuid for
+ each head it wants to identify; the compositor reports the uuid in
+ the initial uuid event on the returned object. Multiple uuid
+ objects may be created for the same output, whether through this
+ manager or through treeland_output_uuid_manager_v1; each reports
+ independently.
+
+
+
+
+ Destroy the treeland_output_uuid_head_manager_v1 object and
+ release the client's binding to the manager global.
+
+ Existing treeland_output_uuid_v1 objects created through
+ this manager are not affected and must be destroyed
+ separately by the client.
+
+
+
+
+
+ Create a treeland_output_uuid_v1 object for the output
+ represented by the given zwlr_output_head_v1. The head may be
+ in any state, including disabled: a wlr_output_head is
+ advertised even when the output is turned off, so this request
+ can identify an output with no live wl_output global.
+
+
+
+
+
+
diff --git a/dde/treeland-output-uuid-unstable-v1.xml b/dde/treeland-output-uuid-unstable-v1.xml
new file mode 100644
index 0000000..cb4288d
--- /dev/null
+++ b/dde/treeland-output-uuid-unstable-v1.xml
@@ -0,0 +1,134 @@
+
+
+
+
+
+ This protocol lets clients obtain a stable uuid for each output,
+ identifying the physical output device behind it. The uuid is an
+ opaque, non-empty UTF-8 string that remains stable across sessions
+ and output reconnections, so clients and the compositor can persist
+ per-output settings and restore them after a restart. Other
+ treeland protocols, such as treeland_output_manager_v2 and
+ treeland_output_group_v1, address outputs by these uuids.
+
+ The uuid is unique among the currently connected outputs: the
+ compositor must ensure that no two connected outputs report the
+ same uuid at the same time. The compositor derives the uuid from
+ the persistent identity of the device, for example the make, model,
+ and serial reported in its EDID. When no persistent device identity
+ is available, the compositor may derive the uuid from the connector;
+ such a uuid is only stable while the device remains connected to
+ the same connector.
+
+ Clients obtain a uuid for a wl_output via get_uuid on this
+ protocol, or for a zwlr_output_head_v1 via the companion
+ treeland-output-uuid-head-unstable-v1 protocol; both entry points
+ return the same uuid for the same physical output device. The head
+ variant can identify an output that is disabled and has no live
+ wl_output global.
+
+ Clients must treat the uuid as opaque: they must not parse it,
+ derive meaning from its contents, or present it to users.
+
+ The terms "must", "must not", "should", and "may" in this document are
+ to be interpreted as described in RFC 2119.
+
+ Warning! This protocol is EXPERIMENTAL and under active development.
+ It may change at any time, including in backward-incompatible ways,
+ without incrementing the interface major version and without prior
+ notice. No compatibility guarantees of any kind are provided. Clients
+ and compositors must track the upstream definition in treeland-protocols
+ and must not rely on the current interface names, requests, events, or
+ semantics remaining stable across releases.
+
+
+
+
+ A singleton global that creates treeland_output_uuid_v1 objects
+ from wl_output objects. The client calls get_uuid for each output
+ it wants to identify; the compositor reports the uuid in the
+ initial uuid event on the returned object. Multiple uuid objects
+ may be created for the same output; each reports independently.
+
+
+
+
+ Destroy the treeland_output_uuid_manager_v1 object and
+ release the client's binding to the manager global.
+
+ Existing treeland_output_uuid_v1 objects created through
+ this manager are not affected and must be destroyed
+ separately by the client.
+
+
+
+
+
+ Create a treeland_output_uuid_v1 object for the given
+ wl_output. The output may be in any state, including disabled:
+ the uuid identifies the physical device regardless of its
+ enabled state.
+
+ For an output that is currently disabled and has no live
+ wl_output global, the client should use the companion
+ treeland-output-uuid-head-unstable-v1 protocol with the
+ corresponding zwlr_output_head_v1 instead.
+
+
+
+
+
+
+
+
+ Represents the uuid identity of the output it was created for,
+ obtained from treeland_output_uuid_manager_v1.get_uuid or from
+ the companion treeland-output-uuid-head-unstable-v1 protocol.
+ The compositor emits the uuid event once immediately after the
+ object is created, and again whenever the uuid of the output
+ changes, for example when a persistent device identity becomes
+ available after an initial connector-based fallback.
+
+ The object is not tied to the lifetime of the wl_output global:
+ when the output is unplugged and its wl_output global is
+ destroyed, this object remains valid and the last reported uuid
+ remains the identity of the physical device, which may
+ reappear later with the same uuid. The client should destroy
+ this object when it no longer needs the mapping.
+
+ Note, because treeland_output_uuid_v1 objects are created from
+ multiple independent factory interfaces —
+ treeland_output_uuid_manager_v1 on this protocol and
+ treeland_output_uuid_head_manager_v1 on the companion
+ treeland-output-uuid-head-unstable-v1 protocol — the
+ treeland_output_uuid_v1 interface is frozen at version 1.
+
+
+
+
+ Destroy this object. Only this object is affected; the uuid
+ of the output and other uuid objects for the same output
+ are unchanged.
+
+
+
+
+
+ Reports the current uuid of the output. It is emitted once
+ immediately after the object is created, and again whenever
+ the compositor determines a different uuid for the output.
+ All uuids have the same fixed length, so consumers may rely
+ on the byte length of one uuid to parse concatenations of
+ several, for example in the outputs event of the
+ treeland-output-group-manager-unstable-v1 protocol.
+
+
+
+
+
diff --git a/dde/treeland-virtual-output-manager-v1.xml b/deprecated/treeland-virtual-output-manager-v1.xml
similarity index 100%
rename from dde/treeland-virtual-output-manager-v1.xml
rename to deprecated/treeland-virtual-output-manager-v1.xml