Skip to main content

capybar/
root.rs

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
54/// Structure containing things all the widgets in capybar needs access to
55pub 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        //Ok(self)
473    }
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        // Request our next frame
524        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);