Files
zed/crates/gpui/examples/layer_shell.rs
Hilmar Wiegand b92664c52d gpui: Implement support for wlr layer shell (#35610)
This reintroduces `layer_shell` support after #32651 was reverted. On
top of that, it allows setting options for the created surface,
restricts the enum variant to the `wayland` feature, and adds an example
that renders a clock widget using the protocol.

I've renamed the `WindowKind` variant to `LayerShell` from `Overlay`,
since the protocol can also be used to render wallpapers and such, which
doesn't really fit with the word.

Things I'm still unsure of:
- We need to get the layer options types to the user somehow, but
nothing from the `platform::linux` crate was exported, I'm assuming
intentionally. I've kept the types inside the module (instead of doing
`pub use layer_shell::*` to not pollute the global namespace with
generic words like `Anchor` or `Layer` Let me know if you want to do
this differently.
- I've added the options to the `WindowKind` variant. That's the only
clean way I see to supply them when the window is created. This makes
the kind no longer implement `Copy`.
- The options don't have setter methods yet and can only be defined on
window creation. We'd have to make fallible functions for setting them,
which only work if the underlying surface is a `layer_shell` surface.
That feels un-rust-y.

CC @zeroeightysix  
Thanks to @wuliuqii, whose layer-shell implementation I've also looked
at while putting this together.

Release Notes:

- Add support for the `layer_shell` protocol on wayland

---------

Co-authored-by: Ridan Vandenbergh <ridanvandenbergh@gmail.com>
2025-10-29 11:32:01 -04:00

88 lines
3.0 KiB
Rust

fn main() {
#[cfg(all(target_os = "linux", feature = "wayland"))]
example::main();
#[cfg(not(all(target_os = "linux", feature = "wayland")))]
panic!("This example requires the `wayland` feature and a linux system.");
}
#[cfg(all(target_os = "linux", feature = "wayland"))]
mod example {
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use gpui::{
App, Application, Bounds, Context, FontWeight, Size, Window, WindowBackgroundAppearance,
WindowBounds, WindowKind, WindowOptions, div, layer_shell::*, point, prelude::*, px, rems,
rgba, white,
};
struct LayerShellExample;
impl LayerShellExample {
fn new(cx: &mut Context<Self>) -> Self {
cx.spawn(async move |this, cx| {
loop {
let _ = this.update(cx, |_, cx| cx.notify());
cx.background_executor()
.timer(Duration::from_millis(500))
.await;
}
})
.detach();
LayerShellExample
}
}
impl Render for LayerShellExample {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
let hours = (now / 3600) % 24;
let minutes = (now / 60) % 60;
let seconds = now % 60;
div()
.size_full()
.flex()
.items_center()
.justify_center()
.text_size(rems(4.5))
.font_weight(FontWeight::EXTRA_BOLD)
.text_color(white())
.bg(rgba(0x0000044))
.rounded_xl()
.child(format!("{:02}:{:02}:{:02}", hours, minutes, seconds))
}
}
pub fn main() {
Application::new().run(|cx: &mut App| {
cx.open_window(
WindowOptions {
titlebar: None,
window_bounds: Some(WindowBounds::Windowed(Bounds {
origin: point(px(0.), px(0.)),
size: Size::new(px(500.), px(200.)),
})),
app_id: Some("gpui-layer-shell-example".to_string()),
window_background: WindowBackgroundAppearance::Transparent,
kind: WindowKind::LayerShell(LayerShellOptions {
namespace: "gpui".to_string(),
anchor: Anchor::LEFT | Anchor::RIGHT | Anchor::BOTTOM,
margin: Some((px(0.), px(0.), px(40.), px(0.))),
keyboard_interactivity: KeyboardInteractivity::None,
..Default::default()
}),
..Default::default()
},
|_, cx| cx.new(LayerShellExample::new),
)
.unwrap();
});
}
}