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 日

#1138GUI

Download history 2063/week @ 2024-03-14 2619/week @ 2024-03-21 2620/week @ 2024-03-28 2092/week @ 2024-04-04 2447/week @ 2024-04-11 2666/week @ 2024-04-18 2802/week @ 2024-04-25 2351/week @ 2024-05-02 2313/week @ 2024-05-09 2421/week @ 2024-05-16 2418/week @ 2024-05-23 2508/week @ 2024-05-30 1913/week @ 2024-06-06 1921/week @ 2024-06-13 2134/week @ 2024-06-20 1666/week @ 2024-06-27

7,911 每月下载量

MIT 许可证

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_implementationmy_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_borderssubtract_borders函数。

依赖项

~2–11MB
~115K SLoC