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

Download history 8753/week @ 2024-05-03 10456/week @ 2024-05-10 13955/week @ 2024-05-17 10501/week @ 2024-05-24 7339/week @ 2024-05-31 5681/week @ 2024-06-07 6524/week @ 2024-06-14 6996/week @ 2024-06-21 6510/week @ 2024-06-28 5370/week @ 2024-07-05 7171/week @ 2024-07-12 6967/week @ 2024-07-19 6464/week @ 2024-07-26 7301/week @ 2024-08-02 10309/week @ 2024-08-09 6923/week @ 2024-08-16

每月下载量32,058
311 个crate中使用 (直接使用65个)

MIT 许可证

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库那样要求用户进行不安全的转换。

核心库还提供许多在协议实现中使用的特性。例如,BaseEventBaseError特性,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调用中访问连接,因此它仅在需要时激活。

依赖关系