docs(list_globals): 中文注释 Wayland globals 示例

This commit is contained in:
dailz
2026-06-22 18:10:03 +08:00
parent b2ba34ef04
commit e6b5a5dc36
+47
View File
@@ -1,11 +1,43 @@
//! 列出当前 Wayland 桌面广播的全部全局对象(registry globals)。
//!
//! Wayland 协议采用"客户端发现"模型:客户端连接到 compositor 后,第一件事是从
//! registry 中枚举所有被广播的 interface(如 `wl_compositor`、`wl_shm`、
//! `zwlr_screencopy_manager_v1`、`zxdg_portal_screencast` 等),每个 global 带有
//! 唯一数字 name、interface 名字符串、最高支持版本号。本示例即打印这三元组。
//!
//! 类比 Go 的 `xcursor` / wayland-client 示例:用最小可运行代码确认运行环境。
//!
//! 运行(参见 AGENTS.md "Useful manual commands"):
//! ```sh
//! cargo run --example list_globals
//! ```
//!
//! 该示例也是 `src/backend_detect.rs` 中检测 `zwlr_screencopy_manager_v1` 是否存在的
//! 同款机制(参见 `check_screencopy_available`),用于决定走 wlr-screencopy 还是 Portal。
// 引入 wayland-client 的快捷初始化辅助函数:内部完成 connect + registry bind + 同步枚举。
use wayland_client::globals::registry_queue_init; use wayland_client::globals::registry_queue_init;
// GlobalListContents 是 registry_queue_init 返回的"已收集好的 global 列表"句柄类型。
use wayland_client::globals::GlobalListContents; use wayland_client::globals::GlobalListContents;
// WlRegistry 是 Wayland 协议对象;Event 是其产生的枚举事件(global/global_remove)。
use wayland_client::protocol::wl_registry::{Event, WlRegistry}; use wayland_client::protocol::wl_registry::{Event, WlRegistry};
// Connection 表示与 compositor 的 socket 连接;QueueHandle 是事件队列句柄;
// Dispatch 是 trait,用户必须为关心的协议对象实现它以接收事件回调。
use wayland_client::{Connection, Dispatch, QueueHandle}; use wayland_client::{Connection, Dispatch, QueueHandle};
// 示例用的极简 state:无字段。Wayland 客户端需要至少一个 state 类型作为
// Dispatch trait 的 `Self`,这里就用零大小类型 `Ls`list globals 的缩写)。
struct Ls; struct Ls;
// 为 Ls 实现 WlRegistry 的 Dispatch:本示例只需枚举 globals,不需要响应任何
// registry 事件,因此 event 函数留空。wayland-client 要求即便不处理事件也必须
// 实现 Dispatchtrait contract 强制),否则 `registry_queue_init::<Ls>` 无法编译。
//
// Go 类比:类似 `type Ls struct{}` + `func (Ls) HandleEvent(...) {}`——
// 显式声明"我接收事件但不响应"。
impl Dispatch<WlRegistry, GlobalListContents> for Ls { impl Dispatch<WlRegistry, GlobalListContents> for Ls {
// 所有参数加 `_` 前缀表示本实现不读取任何参数(Rust 中 `_x` 与 `x` 区分:
// 前者显式标记未使用,避免 dead_code 警告)。
fn event( fn event(
_state: &mut Self, _state: &mut Self,
_registry: &WlRegistry, _registry: &WlRegistry,
@@ -17,10 +49,25 @@ impl Dispatch<WlRegistry, GlobalListContents> for Ls {
} }
} }
// 程序入口。Rust 的 `fn main()` 不能返回 `Result`(标准约定),故用 `.unwrap()`
// 简单 panic;示例程序通常省略错误处理以突出主线逻辑。
fn main() { fn main() {
// 从 `WAYLAND_DISPLAY` / `XDG_RUNTIME_DIR` 环境变量建立与 compositor 的 socket 连接。
// 类比 Go 的 `net.Dial("unix", path)`。`.unwrap()` 在连接失败时 panic(示例代码约定)。
let conn = Connection::connect_to_env().unwrap(); let conn = Connection::connect_to_env().unwrap();
// registry_queue_init 是 wayland-client 的高层辅助:内部发送 sync request 并阻塞
// 直到 registry 全部 global 事件到达。返回 (GlobalList, EventQueue)。
// `::<Ls>` 是 turbofish 显式指定 state 类型,对应上面 `impl Dispatch for Ls`。
// 类比 Go 的 `globals, queue := wayland.RegistryQueueInit[Ls](conn)`(泛型实例化)。
let (globals, _queue) = registry_queue_init::<Ls>(&conn).unwrap(); let (globals, _queue) = registry_queue_init::<Ls>(&conn).unwrap();
// 遍历所有已收集的 globals。`globals.contents()` 返回内部快照引用,
// `.clone_list()` 复制成 `Vec<GlobalListEntry>`(每个 entry 含 name/interface/version)。
// 类比 Go `for _, g := range globals { ... }`——Rust 的 `for ... in` 直接消费迭代器。
for g in globals.contents().clone_list() { for g in globals.contents().clone_list() {
// `println!` 是 Rust 标准宏(不是函数),类比 Go `fmt.Printf("%d: %s v%d\n", ...)`。
// `{}` 自动调用参数的 `Display` traitname 是 u32、interface 是 String、version 是 u32。
println!("{}: {} v{}", g.name, g.interface, g.version); println!("{}: {} v{}", g.name, g.interface, g.version);
} }
} }