26 个版本 (12 个重大更新)
使用旧的 Rust 2015
0.13.3 | 2018 年 3 月 26 日 |
---|---|
0.13.2 | 2017 年 11 月 5 日 |
0.12.0 | 2017 年 10 月 29 日 |
0.7.0 | 2017 年 7 月 5 日 |
0.2.0 | 2015 年 11 月 30 日 |
#1138 在 GUI 中
7,911 每月下载量
52KB
1K SLoC
wayland-window
基于 wayland-client 的简单窗口装饰库。
它在一个给定的 wayland 表面周围绘制简约的装饰,并注册回调以允许使用边框调整大小和移动表面。
目前它更注重可用性而不是设计质量,因此绘制的边框是纯灰色且不可自定义。我可能在未来的版本中对其进行改进。
用法
使用说明在文档的主页上,可在 docs.rs 上阅读。
主分支的文档也在线上可用: https://smithay.github.io/wayland-window
lib.rs
:
Wayland Window,为 wayland 应用程序提供的简约装饰绘制库。
此软件包只能在 wayland-client
软件包的同时使用。
创建带装饰的窗口
创建带装饰的窗口框架非常简单,只需使用提供的初始化函数即可完成
use wayland_window::create_frame;
// if using the legacy wl_shell global
let shell = Shell::Wl(my_wl_shell);
// if using the new not-yet-stable xdg_shell
let shell = Shell::Xdg(my_xdh_shell);
let frame = create_frame(
&mut event_queue, my_implementation, my_implementation_data,
&my_surface, width, height, &compositor, &subcompositor, &shm, &shell, Some(seat)
).unwrap(); // creation can fail
如你所见,你需要传递几个全局对象的引用以及一个 WlSeat
。这对于库能够创建绘制边框的表面、在边框中响应用户输入、调整大小和移动是必需的。它将使用你传递的参数 seat 上提供的事件。(所以如果你在一个有多个指针的设置中,只有与这个 seat 关联的指针才能调整窗口的大小)。
下一节将展示 my_implementation
和 my_implementation_data
参数的示例用法。
配置事件
Frame
对象不会自己调整你的窗口大小,因为它不能做到。
当用户点击边框并开始调整大小时,服务器将在 shell 表面开始生成一系列 configure
事件。你需要处理由表面生成的这些事件。
Wayland服务器在用户正在调整窗口大小时,可能会(并且确实会)在单个WlDisplay::dispatch()
过程中生成大量的configure
事件。您只需要处理最后一个事件,如果尝试处理所有事件,您的应用程序将会非常卡顿。
正确的方法是将它们累积在您的子处理器中,每次都覆盖上一个事件,并在程序的主循环中手动检查是否收到了事件。例如,可以这样操作
use wayland_window::{Frame, create_frame, FrameImplementation};
// define a state to accumulate sizes
struct ConfigureState {
new_size: Option<(i32,i32)>
}
// insert it in your event queue state
let configure_token = event_queue.state().insert(ConfigureState { new_size: None });
// use it in your implementation:
let my_implementation = FrameImplementation {
configure: |evqh, token, _, newsize| {
let configure_state: &mut ConfigureState = evqh.state().get_mut(token);
configure_state.new_size = newsize;
},
close: |_, _| { /* ... */ },
refresh: |_, _| { /* ... */ }
};
// create the decorated surface:
let frame = create_frame(
&mut event_queue, // the event queue
my_implementation, // our implementation
configure_token.clone(), // the implementation data
&my_surface, width, height, &compositor, &subcompositor, &shm, &shell, Some(seat)
).unwrap();
// then, while running your event loop
loop {
display.flush().unwrap();
event_queue.dispatch().unwrap();
// check if a resize is needed
let mut configure_state = event_queue.state().get_mut(&configure_token);
if let Some((w, h)) = configure_state.new_size.take() {
// The compositor suggests we take a new size of (w, h)
// Handle it as needed (see next section)
}
}
调整表面大小
在调整主表面大小时,您需要通知Frame
它必须更新其尺寸。这非常简单
// update your contents size (here by attaching a new buffer)
surface.attach(Some(&new_buffer));
surface.commit();
// update the borders size
frame.resize(width, height);
// refresh the frame so that it actually draws the new size
frame.refresh();
如果您将此作为响应configure
事件来执行,请注意以下要点
- 您不必严格遵守由合成器提供的精确尺寸,这只是一个提示。如果您不希望调整窗口大小,甚至可以忽略它。
- 如果您选择忽略调整大小,仍然可以将窗口调整到当前大小(更新缓冲区到合成器),因为合成器可能已经调整了您的窗口大小而没有通知您。
- 提供给您的尺寸提示是窗口内部的尺寸提示:合成器给出的提示中已经减去了边框的尺寸。如果您需要考虑边框尺寸来计算尺寸,可以使用
add_borders
和subtract_borders
函数。
依赖项
~2–11MB
~115K SLoC