Skip to content

Commit 1fea0fb

Browse files
committed
feat: add a layershellexample
1 parent a078c5b commit 1fea0fb

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

wayland-client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ log = { version = "0.4", optional = true }
2121

2222
[dev-dependencies]
2323
wayland-protocols = { path = "../wayland-protocols", features = ["client"] }
24+
wayland-protocols-wlr = { path = "../wayland-protocols-wlr", features = ["client"] }
2425
futures-channel = "0.3.16"
2526
futures-util = "0.3"
2627
tempfile = "3.2"
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
use std::{fs::File, os::unix::io::AsFd};
2+
use wayland_client::{
3+
delegate_noop,
4+
protocol::{
5+
wl_buffer, wl_compositor, wl_keyboard, wl_registry, wl_seat, wl_shm, wl_shm_pool,
6+
wl_surface,
7+
},
8+
Connection, Dispatch, Proxy, QueueHandle, WEnum,
9+
};
10+
11+
use wayland_protocols_wlr::layer_shell::v1::client::{
12+
zwlr_layer_shell_v1::{self, Layer},
13+
zwlr_layer_surface_v1::{self, Anchor},
14+
};
15+
16+
use wayland_protocols::xdg::shell::client::xdg_wm_base;
17+
18+
fn main() {
19+
let conn = Connection::connect_to_env().unwrap();
20+
21+
let mut event_queue = conn.new_event_queue();
22+
let qhandle = event_queue.handle();
23+
24+
let display = conn.display();
25+
display.get_registry(&qhandle, ());
26+
27+
let mut state = State {
28+
running: true,
29+
base_surface: None,
30+
layer_shell: None,
31+
layer_surface: None,
32+
buffer: None,
33+
wm_base: None,
34+
};
35+
36+
event_queue.blocking_dispatch(&mut state).unwrap();
37+
38+
if state.layer_shell.is_some() && state.wm_base.is_some() {
39+
state.init_layer_surface(&qhandle);
40+
}
41+
42+
while state.running {
43+
event_queue.blocking_dispatch(&mut state).unwrap();
44+
}
45+
}
46+
47+
struct State {
48+
running: bool,
49+
base_surface: Option<wl_surface::WlSurface>,
50+
layer_shell: Option<zwlr_layer_shell_v1::ZwlrLayerShellV1>,
51+
layer_surface: Option<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1>,
52+
buffer: Option<wl_buffer::WlBuffer>,
53+
wm_base: Option<xdg_wm_base::XdgWmBase>,
54+
}
55+
56+
impl Dispatch<wl_registry::WlRegistry, ()> for State {
57+
fn event(
58+
state: &mut Self,
59+
registry: &wl_registry::WlRegistry,
60+
event: wl_registry::Event,
61+
_: &(),
62+
_: &Connection,
63+
qh: &QueueHandle<Self>,
64+
) {
65+
if let wl_registry::Event::Global { name, interface, version } = event {
66+
if interface == zwlr_layer_shell_v1::ZwlrLayerShellV1::interface().name {
67+
let wl_layer = registry.bind::<zwlr_layer_shell_v1::ZwlrLayerShellV1, _, _>(
68+
name,
69+
version,
70+
qh,
71+
(),
72+
);
73+
state.layer_shell = Some(wl_layer);
74+
} else if interface == wl_compositor::WlCompositor::interface().name {
75+
let compositor =
76+
registry.bind::<wl_compositor::WlCompositor, _, _>(name, version, qh, ());
77+
let surface = compositor.create_surface(qh, ());
78+
state.base_surface = Some(surface);
79+
} else if interface == wl_shm::WlShm::interface().name {
80+
let shm = registry.bind::<wl_shm::WlShm, _, _>(name, version, qh, ());
81+
82+
let (init_w, init_h) = (3200, 240);
83+
84+
let mut file = tempfile::tempfile().unwrap();
85+
draw(&mut file, (init_w, init_h));
86+
let pool = shm.create_pool(file.as_fd(), (init_w * init_h * 4) as i32, qh, ());
87+
let buffer = pool.create_buffer(
88+
0,
89+
init_w as i32,
90+
init_h as i32,
91+
(init_w * 4) as i32,
92+
wl_shm::Format::Argb8888,
93+
qh,
94+
(),
95+
);
96+
state.buffer = Some(buffer.clone());
97+
} else if interface == wl_seat::WlSeat::interface().name {
98+
registry.bind::<wl_seat::WlSeat, _, _>(name, version, qh, ());
99+
} else if interface == xdg_wm_base::XdgWmBase::interface().name {
100+
let wm_base = registry.bind::<xdg_wm_base::XdgWmBase, _, _>(name, 1, qh, ());
101+
state.wm_base = Some(wm_base);
102+
}
103+
}
104+
}
105+
}
106+
107+
delegate_noop!(State: ignore wl_compositor::WlCompositor);
108+
delegate_noop!(State: ignore wl_surface::WlSurface);
109+
delegate_noop!(State: ignore wl_shm::WlShm);
110+
delegate_noop!(State: ignore wl_shm_pool::WlShmPool);
111+
delegate_noop!(State: ignore wl_buffer::WlBuffer);
112+
113+
fn draw(tmp: &mut File, (buf_x, buf_y): (u32, u32)) {
114+
use std::{cmp::min, io::Write};
115+
let mut buf = std::io::BufWriter::new(tmp);
116+
for y in 0..buf_y {
117+
for x in 0..buf_x {
118+
let a = 0xFF;
119+
let r = min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
120+
let g = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
121+
let b = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
122+
123+
let color = (a << 24) + (r << 16) + (g << 8) + b;
124+
buf.write_all(&color.to_ne_bytes()).unwrap();
125+
}
126+
}
127+
buf.flush().unwrap();
128+
}
129+
130+
impl State {
131+
fn init_layer_surface(&mut self, qh: &QueueHandle<State>) {
132+
let layer = self.layer_shell.as_ref().unwrap().get_layer_surface(
133+
self.base_surface.as_ref().unwrap(),
134+
None,
135+
Layer::Top,
136+
"precure".to_string(),
137+
qh,
138+
(),
139+
);
140+
layer.set_anchor(Anchor::Bottom | Anchor::Right | Anchor::Left);
141+
layer.set_keyboard_interactivity(zwlr_layer_surface_v1::KeyboardInteractivity::OnDemand);
142+
layer.set_size(0, 30);
143+
layer.set_exclusive_zone(30);
144+
self.base_surface.as_ref().unwrap().commit();
145+
146+
self.layer_surface = Some(layer);
147+
}
148+
}
149+
150+
impl Dispatch<xdg_wm_base::XdgWmBase, ()> for State {
151+
fn event(
152+
_: &mut Self,
153+
wm_base: &xdg_wm_base::XdgWmBase,
154+
event: xdg_wm_base::Event,
155+
_: &(),
156+
_: &Connection,
157+
_: &QueueHandle<Self>,
158+
) {
159+
if let xdg_wm_base::Event::Ping { serial } = event {
160+
wm_base.pong(serial);
161+
}
162+
}
163+
}
164+
165+
impl Dispatch<wl_seat::WlSeat, ()> for State {
166+
fn event(
167+
_: &mut Self,
168+
seat: &wl_seat::WlSeat,
169+
event: wl_seat::Event,
170+
_: &(),
171+
_: &Connection,
172+
qh: &QueueHandle<Self>,
173+
) {
174+
if let wl_seat::Event::Capabilities { capabilities: WEnum::Value(capabilities) } = event {
175+
if capabilities.contains(wl_seat::Capability::Keyboard) {
176+
seat.get_keyboard(qh, ());
177+
}
178+
}
179+
}
180+
}
181+
182+
impl Dispatch<wl_keyboard::WlKeyboard, ()> for State {
183+
fn event(
184+
state: &mut Self,
185+
_: &wl_keyboard::WlKeyboard,
186+
event: wl_keyboard::Event,
187+
_: &(),
188+
_: &Connection,
189+
_: &QueueHandle<Self>,
190+
) {
191+
if let wl_keyboard::Event::Key { key, .. } = event {
192+
println!("key it is {key}");
193+
if key == 1 {
194+
// ESC key
195+
state.running = false;
196+
}
197+
}
198+
}
199+
}
200+
201+
impl Dispatch<zwlr_layer_shell_v1::ZwlrLayerShellV1, ()> for State {
202+
fn event(
203+
_state: &mut Self,
204+
_proxy: &zwlr_layer_shell_v1::ZwlrLayerShellV1,
205+
_event: <zwlr_layer_shell_v1::ZwlrLayerShellV1 as Proxy>::Event,
206+
_data: &(),
207+
_conn: &Connection,
208+
_qhandle: &QueueHandle<Self>,
209+
) {
210+
}
211+
}
212+
213+
impl Dispatch<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, ()> for State {
214+
fn event(
215+
state: &mut Self,
216+
surface: &zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
217+
event: <zwlr_layer_surface_v1::ZwlrLayerSurfaceV1 as Proxy>::Event,
218+
_data: &(),
219+
_conn: &Connection,
220+
_qhandle: &QueueHandle<Self>,
221+
) {
222+
if let zwlr_layer_surface_v1::Event::Configure { serial, .. } = event {
223+
surface.ack_configure(serial);
224+
let surface = state.base_surface.as_ref().unwrap();
225+
if let Some(ref buffer) = state.buffer {
226+
surface.attach(Some(buffer), 0, 0);
227+
surface.commit();
228+
}
229+
}
230+
}
231+
}

0 commit comments

Comments
 (0)