34个版本 (8个稳定版)
1.4.0 | 2024年4月23日 |
---|---|
1.3.0 | 2023年12月9日 |
1.2.2 | 2023年7月22日 |
1.2.0 | 2022年11月3日 |
0.7.1 | 2016年3月29日 |
#58 in Unix API
每月下载量32,058
在 311 个crate中使用 (直接使用65个)
565KB
13K SLoC
Rust XCB
Rust-XCB是XCB的Rust安全接口。Rust-XCB使用底层的核心XCB函数来连接和与X服务器通信。
文档: https://rust-x-bindings.github.io/rust-xcb/xcb/
Rust-XCB由以下组件组成
- 核心库
- X协议及其扩展(从XML生成)
有关贡献,请参阅CONTRIBUTING.md。
核心库
主要组件是用于连接和与X服务器通信的Connection
类。该Connection
类将C XCB函数的调用封装在一个安全可用的接口中。
在新API(v1.0+
)中,Rust-XCB负责处理所有事件和错误解决的重负载,包括处理不同类型的事件(常规事件、“GeGeneric”事件,Xkb的具体信息等),并以统一且安全的方式使用enum
展示,而不是像C库那样要求用户进行不安全的转换。
核心库还提供许多在协议实现中使用的特性。例如,BaseEvent
和BaseError
特性,Reply
特性... 还提供了Raw
特性,用于将C事件或错误类型转换为Rust类型。
协议实现
核心X协议以及XCB中存在的所有扩展都是从(几乎精确地)与XCB C绑定相同的XML生成的。生成是通过构建脚本完成的,构建脚本完全用Rust编写。构建脚本不会生成对C协议扩展的绑定,而是直接生成一个安全的Rust协议实现。
- 与C具有相同内存布局的简单结构可以直接在Rust中转换(例如点等)。
- 更复杂的结构封装了一块原始数据切片,并提供访问器方法(
Debug
仍然可以正确打印所有成员)。 - 掩码使用
bitflags
crate宏。 - 枚举就是枚举!
- 联合也是携带数据的枚举。
- Xids(窗口、位图等的句柄)是
Xid
特质的类型安全实现。 - 请求是在传递给
Connection
时序列化的结构。- 每个请求有两种类型的cookie,用于检查和非检查请求。这允许类型安全的回复获取和错误检查。
- 协议以及每个扩展都提供了一个
Event
和一个Error
枚举,这些枚举由核心库统一。
API
以下是API的一些亮点。
模块
在xcb
crate下面直接是手写的核心库。核心协议在x
模块中生成,每个扩展协议也在其自己的模块中生成。
窗口创建请求
let window: x::Window = conn.generate_id();
conn.send_request(&x::CreateWindow {
depth: x::COPY_FROM_PARENT as u8,
wid: window,
parent: screen.root(),
x: 0,
y: 0,
width: 150,
height: 150,
border_width: 10,
class: x::WindowClass::InputOutput,
visual: screen.root_visual(),
value_list: &[
x::Cw::BackPixel(screen.white_pixel()),
x::Cw::EventMask(x::EventMask::EXPOSURE | x::EventMask::KEY_PRESS),
],
});
检查空请求
// specific cookie type for the checked request
// code would not compile with `conn.send_request(..)`
let cookie = conn.send_request_checked(&x::MapWindow {window});
// reports `Ok` or a resolved error enum (e.g. x::Error::Drawable(..))
conn.check_request(cookie)?;
事件和错误处理
核心协议和每个激活扩展的事件在xcb::Event
枚举中统一。因此,所有事件都可以在单个匹配表达式中处理。许多函数(如wait_for_event
)返回一个xcb::Result
,这允许惯用的错误处理。
fn main() -> xcb::Result<()> {
// ...
loop {
match conn.wait_for_event()? {
xcb::Event::X(x::Event::KeyPress(key_press)) => {
// do stuff
}
xcb::Event::Xkb(xkb::Event::MapNotify(ev)) => {
// do other stuff (pass data to xkbcommon for example)
}
_ => {}
}
}
}
调试
Rust XCB中所有类型都实现了Debug
,允许递归调试打印。例如,迭代器不会打印无用的指针值,而是递归到每个元素。
此外,还有一个可选的"debug_atom_names"
cargo功能,在某种情况下,每个原子都会打印其名称,以便更容易调试。例如,Xinput提供有关输入设备的原子标识符的信息。这允许您快速查找需要内部化和查找的原子。例如,功能将
Atom {
res_id: 303,
}
变成
Atom("Abs Pressure" ; 303)
该功能将全局变量设置为在Debug::fmt
调用中访问连接,因此它仅在需要时激活。