1use std::{
2 cell::RefCell,
3 cmp::{max, min},
4 collections::HashMap,
5 num::NonZeroU32,
6 rc::Rc,
7 thread,
8 time::Duration,
9};
10
11use anyhow::{anyhow, Result};
12use smithay_client_toolkit::{
13 compositor::{CompositorHandler, CompositorState},
14 delegate_compositor, delegate_keyboard, delegate_layer, delegate_output, delegate_pointer,
15 delegate_registry, delegate_seat, delegate_shm,
16 output::{OutputHandler, OutputState},
17 registry::{ProvidesRegistryState, RegistryState},
18 registry_handlers,
19 seat::{
20 keyboard::{KeyEvent, KeyboardHandler, Keysym, Modifiers},
21 pointer::{PointerEvent, PointerEventKind, PointerHandler},
22 Capability, SeatHandler, SeatState,
23 },
24 shell::{
25 wlr_layer::{
26 Anchor, KeyboardInteractivity, Layer, LayerShell, LayerShellHandler, LayerSurface,
27 LayerSurfaceConfigure,
28 },
29 WaylandSurface,
30 },
31 shm::{Shm, ShmHandler},
32};
33use thiserror::Error;
34use wayland_client::{
35 globals::GlobalList,
36 protocol::{wl_keyboard, wl_output, wl_pointer, wl_seat, wl_surface},
37 Connection, EventQueue, QueueHandle,
38};
39
40use crate::{
41 config::Config,
42 services::{Service, ServiceError, ServiceNew},
43 util::{
44 fonts::{self, FontsError},
45 signals::{Signal, SignalNames},
46 Drawer,
47 },
48 widgets::{
49 containers::{bar::Bar, Container},
50 Widget, WidgetNew,
51 },
52};
53
54pub struct Environment {
56 pub config: Config,
57 pub drawer: RefCell<Drawer>,
58 pub signals: RefCell<HashMap<SignalNames, Signal>>,
59}
60
61#[derive(Error, Debug)]
62pub enum RootError {
63 #[error("Environment is not initialised before drawing")]
64 EnvironmentNotInit,
65}
66
67pub struct Root {
68 flag: bool,
69
70 registry_state: RegistryState,
71 seat_state: SeatState,
72 output_state: OutputState,
73 shm: Shm,
74
75 first_configure: bool,
76 width: u32,
77 height: u32,
78 shift: Option<u32>,
79 layer: LayerSurface,
80 keyboard: Option<wl_keyboard::WlKeyboard>,
81 keyboard_focus: bool,
82 pointer: Option<wl_pointer::WlPointer>,
83
84 bar: Option<Bar>,
85 services: Vec<Box<dyn Service>>,
86 env: Option<Rc<Environment>>,
87}
88
89impl CompositorHandler for Root {
90 fn scale_factor_changed(
91 &mut self,
92 _conn: &Connection,
93 _qh: &QueueHandle<Self>,
94 _surface: &wl_surface::WlSurface,
95 _new_factor: i32,
96 ) {
97 }
98
99 fn transform_changed(
100 &mut self,
101 _conn: &Connection,
102 _qh: &QueueHandle<Self>,
103 _surface: &wl_surface::WlSurface,
104 _new_transform: wl_output::Transform,
105 ) {
106 }
107
108 fn frame(
109 &mut self,
110 _conn: &Connection,
111 qh: &QueueHandle<Self>,
112 _surface: &wl_surface::WlSurface,
113 _time: u32,
114 ) {
115 if let Err(a) = self.draw(qh) {
116 println!("{a}");
117 }
118 }
119
120 fn surface_enter(
121 &mut self,
122 _conn: &Connection,
123 _qh: &QueueHandle<Self>,
124 _surface: &wl_surface::WlSurface,
125 _output: &wl_output::WlOutput,
126 ) {
127 }
128
129 fn surface_leave(
130 &mut self,
131 _conn: &Connection,
132 _qh: &QueueHandle<Self>,
133 _surface: &wl_surface::WlSurface,
134 _output: &wl_output::WlOutput,
135 ) {
136 }
137}
138
139impl OutputHandler for Root {
140 fn output_state(&mut self) -> &mut OutputState {
141 &mut self.output_state
142 }
143
144 fn new_output(
145 &mut self,
146 _conn: &Connection,
147 _qh: &QueueHandle<Self>,
148 _output: wl_output::WlOutput,
149 ) {
150 }
151
152 fn update_output(
153 &mut self,
154 _conn: &Connection,
155 _qh: &QueueHandle<Self>,
156 _output: wl_output::WlOutput,
157 ) {
158 }
159
160 fn output_destroyed(
161 &mut self,
162 _conn: &Connection,
163 _qh: &QueueHandle<Self>,
164 _output: wl_output::WlOutput,
165 ) {
166 }
167}
168
169impl LayerShellHandler for Root {
170 fn closed(&mut self, _conn: &Connection, _qh: &QueueHandle<Self>, _layer: &LayerSurface) {}
171
172 fn configure(
173 &mut self,
174 _conn: &Connection,
175 qh: &QueueHandle<Self>,
176 _layer: &LayerSurface,
177 configure: LayerSurfaceConfigure,
178 _serial: u32,
179 ) {
180 self.width = NonZeroU32::new(configure.new_size.0).map_or(256, NonZeroU32::get);
181 self.height = NonZeroU32::new(configure.new_size.1).map_or(256, NonZeroU32::get);
182
183 if self.first_configure {
184 self.first_configure = false;
185
186 if let Err(a) = self.draw(qh) {
187 println!("{a}");
188 }
189 }
190 }
191}
192
193impl SeatHandler for Root {
194 fn seat_state(&mut self) -> &mut SeatState {
195 &mut self.seat_state
196 }
197
198 fn new_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
199
200 fn new_capability(
201 &mut self,
202 _conn: &Connection,
203 qh: &QueueHandle<Self>,
204 seat: wl_seat::WlSeat,
205 capability: Capability,
206 ) {
207 if capability == Capability::Keyboard && self.keyboard.is_none() {
208 let keyboard = self
209 .seat_state
210 .get_keyboard(qh, &seat, None)
211 .expect("Failed to create keyboard");
212 self.keyboard = Some(keyboard);
213 }
214
215 if capability == Capability::Pointer && self.pointer.is_none() {
216 let pointer = self
217 .seat_state
218 .get_pointer(qh, &seat)
219 .expect("Failed to create pointer");
220 self.pointer = Some(pointer);
221 }
222 }
223
224 fn remove_capability(
225 &mut self,
226 _conn: &Connection,
227 _: &QueueHandle<Self>,
228 _: wl_seat::WlSeat,
229 capability: Capability,
230 ) {
231 if capability == Capability::Keyboard && self.keyboard.is_some() {
232 self.keyboard.take().unwrap().release();
233 }
234
235 if capability == Capability::Pointer && self.pointer.is_some() {
236 self.pointer.take().unwrap().release();
237 }
238 }
239
240 fn remove_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
241}
242
243impl KeyboardHandler for Root {
244 fn enter(
245 &mut self,
246 _: &Connection,
247 _: &QueueHandle<Self>,
248 _: &wl_keyboard::WlKeyboard,
249 surface: &wl_surface::WlSurface,
250 _: u32,
251 _: &[u32],
252 _: &[Keysym],
253 ) {
254 if self.layer.wl_surface() == surface {
255 self.keyboard_focus = true;
256 }
257 }
258
259 fn leave(
260 &mut self,
261 _: &Connection,
262 _: &QueueHandle<Self>,
263 _: &wl_keyboard::WlKeyboard,
264 surface: &wl_surface::WlSurface,
265 _: u32,
266 ) {
267 if self.layer.wl_surface() == surface {
268 self.keyboard_focus = false;
269 }
270 }
271
272 fn press_key(
273 &mut self,
274 _conn: &Connection,
275 _qh: &QueueHandle<Self>,
276 _: &wl_keyboard::WlKeyboard,
277 _: u32,
278 _: KeyEvent,
279 ) {
280 }
281
282 fn release_key(
283 &mut self,
284 _: &Connection,
285 _: &QueueHandle<Self>,
286 _: &wl_keyboard::WlKeyboard,
287 _: u32,
288 _: KeyEvent,
289 ) {
290 }
291
292 fn update_modifiers(
293 &mut self,
294 _: &Connection,
295 _: &QueueHandle<Self>,
296 _: &wl_keyboard::WlKeyboard,
297 _serial: u32,
298 _: Modifiers,
299 _layout: u32,
300 ) {
301 }
302}
303
304impl PointerHandler for Root {
305 fn pointer_frame(
306 &mut self,
307 _conn: &Connection,
308 _qh: &QueueHandle<Self>,
309 _pointer: &wl_pointer::WlPointer,
310 events: &[PointerEvent],
311 ) {
312 use PointerEventKind::*;
313 for event in events {
314 if &event.surface != self.layer.wl_surface() {
315 continue;
316 }
317 match event.kind {
318 Enter { .. } => {}
319 Leave { .. } => {}
320 Motion { .. } => {}
321 Press { .. } => {
322 self.shift = self.shift.xor(Some(0));
323 }
324 Release { .. } => {}
325 Axis { .. } => {}
326 }
327 }
328 }
329}
330
331impl ShmHandler for Root {
332 fn shm_state(&mut self) -> &mut Shm {
333 &mut self.shm
334 }
335}
336
337impl ProvidesRegistryState for Root {
338 fn registry(&mut self) -> &mut RegistryState {
339 &mut self.registry_state
340 }
341 registry_handlers![OutputState, SeatState];
342}
343
344impl Root {
345 pub fn new(
346 globals: &GlobalList,
347 event_queue: &mut EventQueue<Root>,
348 bar: Option<Bar>,
349 ) -> Result<Root> {
350 let qh = event_queue.handle();
351
352 let compositor =
353 CompositorState::bind(globals, &qh).expect("wl_compositor is not available");
354 let layer_shell = LayerShell::bind(globals, &qh).expect("layer shell is not available");
355 let shm = Shm::bind(globals, &qh).expect("wl_shm is not available");
356
357 let surface = compositor.create_surface(&qh);
358
359 let layer = layer_shell.create_layer_surface(&qh, surface, Layer::Top, Some("Bar"), None);
360
361 let root = Root {
362 flag: true,
363
364 registry_state: RegistryState::new(globals),
365 seat_state: SeatState::new(globals, &qh),
366 output_state: OutputState::new(globals, &qh),
367 shm,
368
369 first_configure: true,
370 width: 16,
371 height: 16,
372 shift: None,
373 layer,
374 keyboard: None,
375 keyboard_focus: false,
376 pointer: None,
377
378 bar,
379 services: Vec::new(),
380 env: None,
381 };
382
383 Ok(root)
384 }
385
386 pub fn apply_config(&mut self, config: Config) -> Result<()> {
387 if self.bar.is_some() {
388 return Err(anyhow!("Config can only be applied once"));
389 }
390 let mut bar = Bar::new(None, config.bar.settings)?;
391
392 for widget in config.bar.left {
393 widget.create_in_container(bar.left().get_mut())?;
394 }
395
396 for widget in config.bar.center {
397 widget.create_in_container(bar.center().get_mut())?;
398 }
399
400 for widget in config.bar.right {
401 widget.create_in_container(bar.right().get_mut())?;
402 }
403
404 self.bar = Some(bar);
405 Ok(())
406 }
407
408 fn init(&mut self) -> Result<&mut Self> {
409 if self.bar.is_none() {
410 return Err(anyhow!("Empty bar can not be created"));
411 }
412
413 self.layer.set_anchor(Anchor::TOP);
414 self.layer
415 .set_keyboard_interactivity(KeyboardInteractivity::OnDemand);
416 self.width = 1;
417 self.height = 1;
418
419 self.env = Some(Rc::new(Environment {
420 config: Config::default(),
421 drawer: RefCell::new(Drawer::new(&mut self.shm, 1, 1)),
422 signals: RefCell::new(HashMap::new()),
423 }));
424
425 for service in &mut self.services {
426 service.bind(Rc::clone(self.env.as_ref().unwrap()))?;
427
428 service.init()?;
429 }
430
431 let bar = self.bar.as_mut().unwrap();
432 bar.bind(Rc::clone(self.env.as_ref().unwrap()))?;
433 bar.init()?;
434
435 self.height = max(self.height, bar.data_mut().height as u32);
436
437 for output in self.output_state().outputs() {
438 let info = self
439 .output_state
440 .info(&output)
441 .ok_or_else(|| "output has no info".to_owned())
442 .unwrap();
443
444 if let Some((width, height)) = info.logical_size {
445 self.width = max(self.width, width as u32);
446 self.height = min(self.height, height as u32);
447 }
448 }
449
450 self.layer.set_size(self.width, self.height);
451 self.layer.set_exclusive_zone(self.height as i32);
452 self.layer.commit();
453
454 self.env.as_ref().unwrap().drawer.borrow_mut().update_sizes(
455 &mut self.shm,
456 self.width as i32,
457 self.height as i32,
458 );
459
460 Ok(self)
461 }
462
463 pub fn run(&mut self, event_queue: &mut EventQueue<Root>) -> Result<&mut Self> {
464 event_queue.blocking_dispatch(self)?;
465 self.init()?;
466
467 loop {
468 thread::sleep(Duration::from_millis(100));
469 event_queue.blocking_dispatch(self)?;
470 }
471
472 }
474
475 pub fn add_font_by_name(&mut self, name: &'static str) -> Result<(), FontsError> {
476 fonts::add_font_by_name(name)
477 }
478
479 pub fn create_service<W, F>(&mut self, f: F, settings: W::Settings) -> Result<()>
480 where
481 W: ServiceNew + Service + 'static,
482 F: FnOnce(Option<Rc<Environment>>, W::Settings) -> Result<W, ServiceError>,
483 {
484 self.services.push(Box::new(f(self.env.clone(), settings)?));
485 Ok(())
486 }
487
488 fn draw(&mut self, qh: &QueueHandle<Self>) -> Result<()> {
489 if self.env.is_none() {
490 return Err(RootError::EnvironmentNotInit.into());
491 }
492
493 for service in &mut self.services {
494 service.run()?;
495 }
496
497 self.bar.as_ref().unwrap().prepare()?;
498
499 {
500 let bar = self.bar.as_ref().unwrap().data();
501 if self.width != bar.width as u32 || self.height != bar.height as u32 {
502 self.width = bar.width as u32;
503 self.height = bar.height as u32;
504
505 self.layer.set_size(self.width, self.height);
506 self.layer.set_exclusive_zone(self.height as i32);
507
508 self.env.as_ref().unwrap().drawer.borrow_mut().update_sizes(
509 &mut self.shm,
510 self.width as i32,
511 self.height as i32,
512 );
513 }
514 }
515
516 self.layer
517 .wl_surface()
518 .damage_buffer(0, 0, self.width as i32, self.height as i32);
519
520 self.bar.as_ref().unwrap().run()?;
521 self.bar.as_ref().unwrap().draw()?;
522
523 self.layer
525 .wl_surface()
526 .frame(qh, self.layer.wl_surface().clone());
527
528 self.env
529 .as_ref()
530 .unwrap()
531 .drawer
532 .borrow_mut()
533 .commit(self.layer.wl_surface());
534
535 self.flag = false;
536 Ok(())
537 }
538
539 pub fn bar(&self) -> &Option<Bar> {
540 &self.bar
541 }
542}
543
544delegate_compositor!(Root);
545delegate_output!(Root);
546delegate_shm!(Root);
547
548delegate_seat!(Root);
549delegate_keyboard!(Root);
550delegate_pointer!(Root);
551
552delegate_layer!(Root);
553
554delegate_registry!(Root);