Skip to main content

spell_framework/wayland_adapter/window/
wayland.rs

1use crate::wayland_adapter::{fractional_scaling::FractionalScaleHandler, window::SpellWin};
2use slint::platform::WindowAdapter;
3use smithay_client_toolkit::{
4    compositor::CompositorHandler,
5    output::{OutputHandler, OutputState},
6    reexports::{
7        client::{
8            Connection, Dispatch, QueueHandle,
9            protocol::{wl_output, wl_seat, wl_surface},
10        },
11        protocols::xdg::shell::client::xdg_surface::XdgSurface,
12    },
13    registry::{ProvidesRegistryState, RegistryState},
14    registry_handlers,
15    seat::{Capability, SeatHandler, SeatState, pointer::PointerData},
16    shell::{
17        WaylandSurface,
18        wlr_layer::{LayerShellHandler, LayerSurface, LayerSurfaceConfigure},
19        xdg::{popup::PopupHandler, window::WindowHandler},
20    },
21    shm::{Shm, ShmHandler},
22};
23use tracing::{info, trace, warn};
24
25impl WindowHandler for SpellWin {
26    fn request_close(
27        &mut self,
28        _: &Connection,
29        _: &QueueHandle<Self>,
30        _: &smithay_client_toolkit::shell::xdg::window::Window,
31    ) {
32        todo!()
33    }
34
35    fn configure(
36        &mut self,
37        _: &Connection,
38        _: &QueueHandle<Self>,
39        _: &smithay_client_toolkit::shell::xdg::window::Window,
40        _: smithay_client_toolkit::shell::xdg::window::WindowConfigure,
41        _: u32,
42    ) {
43        todo!()
44    }
45}
46
47impl SeatHandler for SpellWin {
48    fn seat_state(&mut self) -> &mut SeatState {
49        &mut self.states.seat_state
50    }
51
52    fn new_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
53
54    fn new_capability(
55        &mut self,
56        _conn: &Connection,
57        qh: &QueueHandle<Self>,
58        seat: wl_seat::WlSeat,
59        capability: Capability,
60    ) {
61        if capability == Capability::Keyboard && self.states.keyboard_state.is_none() {
62            info!("Setting keyboard capability");
63            let keyboard = self
64                .states
65                .seat_state
66                .get_keyboard(qh, &seat, None)
67                .expect("Failed to create keyboard");
68            self.states.keyboard_state = Some(keyboard);
69        }
70        if capability == Capability::Touch && self.states.touch_state.is_none() {
71            info!("Setting touch Capability");
72            let touch = self
73                .states
74                .seat_state
75                .get_touch(qh, &seat)
76                .expect("Failed to create touch");
77            self.states.touch_state = Some(touch);
78        }
79        if capability == Capability::Pointer && self.states.pointer_state.pointer.is_none() {
80            info!("Setting pointer capability");
81            let pointer = self
82                .states
83                .seat_state
84                .get_pointer(qh, &seat)
85                .expect("Failed to create pointer");
86            let pointer_data = PointerData::new(seat);
87            self.states.pointer_state.pointer = Some(pointer);
88            self.states.pointer_state.pointer_data = Some(pointer_data);
89        }
90    }
91
92    fn remove_capability(
93        &mut self,
94        _conn: &Connection,
95        _: &QueueHandle<Self>,
96        _: wl_seat::WlSeat,
97        capability: Capability,
98    ) {
99        if capability == Capability::Keyboard && self.states.keyboard_state.is_some() {
100            info!("Unsetting keyboard capability");
101            self.states.keyboard_state.take().unwrap().release();
102        }
103
104        if capability == Capability::Pointer && self.states.pointer_state.pointer.is_some() {
105            info!("Unsetting pointer capability");
106            self.states.pointer_state.pointer.take().unwrap().release();
107        }
108        if capability == Capability::Touch && self.states.touch_state.is_some() {
109            info!("Unsetting pointer capability");
110            self.states.touch_state.take().unwrap().release();
111        }
112    }
113
114    fn remove_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
115}
116
117impl PopupHandler for SpellWin {
118    fn configure(
119        &mut self,
120        _: &Connection,
121        _: &QueueHandle<Self>,
122        popup: &smithay_client_toolkit::shell::xdg::popup::Popup,
123        _: smithay_client_toolkit::shell::xdg::popup::PopupConfigure,
124    ) {
125        let x = self.popup_manager.return_popup(popup);
126        if let Some(current_popup) = x {
127            // FIXME: Is this commit required?
128            current_popup.inner().wl_surface().commit();
129            if current_popup.first_configure() {
130                current_popup.converter_popup(current_popup.inner().wl_surface(), &self.queue);
131            }
132        } else {
133            warn!("Popup configured but not pushed to the manager");
134        }
135    }
136
137    fn done(
138        &mut self,
139        _: &Connection,
140        _: &QueueHandle<Self>,
141        _: &smithay_client_toolkit::shell::xdg::popup::Popup,
142    ) {
143        info!("[Popup Manager]: A popup is closed");
144    }
145}
146
147// TODO: FIND What is the use of registery_handlers here?
148impl ProvidesRegistryState for SpellWin {
149    fn registry(&mut self) -> &mut RegistryState {
150        &mut self.states.registry_state
151    }
152    registry_handlers![OutputState, SeatState];
153}
154
155impl ShmHandler for SpellWin {
156    fn shm_state(&mut self) -> &mut Shm {
157        &mut self.states.shm
158    }
159}
160
161impl OutputHandler for SpellWin {
162    fn output_state(&mut self) -> &mut OutputState {
163        &mut self.states.output_state
164    }
165
166    fn new_output(
167        &mut self,
168        _conn: &Connection,
169        _qh: &QueueHandle<Self>,
170        _output: wl_output::WlOutput,
171    ) {
172        trace!("New output Source Added");
173    }
174
175    fn update_output(
176        &mut self,
177        _conn: &Connection,
178        _qh: &QueueHandle<Self>,
179        _output: wl_output::WlOutput,
180    ) {
181        trace!("Existing output is updated");
182    }
183
184    fn output_destroyed(
185        &mut self,
186        _conn: &Connection,
187        _qh: &QueueHandle<Self>,
188        _output: wl_output::WlOutput,
189    ) {
190        trace!("Output is destroyed");
191    }
192}
193
194impl CompositorHandler for SpellWin {
195    fn scale_factor_changed(
196        &mut self,
197        _: &Connection,
198        _: &QueueHandle<Self>,
199        _: &wl_surface::WlSurface,
200        _: i32,
201    ) {
202        info!("Scale factor changed, compositor msg");
203    }
204
205    fn transform_changed(
206        &mut self,
207        _conn: &Connection,
208        _qh: &QueueHandle<Self>,
209        _surface: &wl_surface::WlSurface,
210        _new_transform: wl_output::Transform,
211    ) {
212        trace!("Compositor transformation changed");
213    }
214
215    fn frame(
216        &mut self,
217        _conn: &Connection,
218        qh: &QueueHandle<Self>,
219        _surface: &wl_surface::WlSurface,
220        _time: u32,
221    ) {
222        self.converter(qh);
223        self.popup_manager.redraw_popups(qh);
224    }
225
226    fn surface_enter(
227        &mut self,
228        _conn: &Connection,
229        _qh: &QueueHandle<Self>,
230        _surface: &wl_surface::WlSurface,
231        _output: &wl_output::WlOutput,
232    ) {
233        trace!("Surface entered");
234    }
235
236    fn surface_leave(
237        &mut self,
238        _conn: &Connection,
239        _qh: &QueueHandle<Self>,
240        _surface: &wl_surface::WlSurface,
241        _output: &wl_output::WlOutput,
242    ) {
243        trace!("Surface left");
244    }
245}
246
247impl FractionalScaleHandler for SpellWin {
248    fn preferred_scale(
249        &mut self,
250        _: &Connection,
251        _: &QueueHandle<Self>,
252        _: &wl_surface::WlSurface,
253        scale: u32,
254    ) {
255        info!("Scale factor changed, invoked from custom trait: {}", scale);
256        let width_old = self.adapter.as_ref().unwrap().size_original.get().width;
257        let height_old = self.adapter.as_ref().unwrap().size_original.get().height;
258        self.layer.as_ref().unwrap().wl_surface().damage_buffer(
259            0,
260            0,
261            self.adapter.as_ref().unwrap().size.get().width as i32,
262            self.adapter.as_ref().unwrap().size.get().height as i32,
263        );
264        let (buffer, width, height, scale_factor) =
265            self.adapter.as_ref().unwrap().changed_scale_factor(scale);
266        self.config.evaluated_width = width;
267        self.config.evaluated_height = height;
268        self.buffer = Some(buffer);
269        self.adapter
270            .as_ref()
271            .unwrap()
272            .try_dispatch_event(slint::platform::WindowEvent::ScaleFactorChanged { scale_factor })
273            .unwrap();
274        self.viewport.as_ref().unwrap().set_source(
275            0.,
276            0.,
277            self.adapter.as_ref().unwrap().size.get().width.into(),
278            self.adapter.as_ref().unwrap().size.get().height.into(),
279        );
280
281        self.viewport
282            .as_ref()
283            .unwrap()
284            .set_destination(width_old as i32, height_old as i32);
285        self.adapter.as_ref().unwrap().request_redraw();
286        self.layer.as_ref().unwrap().commit();
287    }
288}
289
290impl LayerShellHandler for SpellWin {
291    fn closed(&mut self, _conn: &Connection, _qh: &QueueHandle<Self>, _layer: &LayerSurface) {
292        trace!("Closure of layer called");
293    }
294
295    fn configure(
296        &mut self,
297        _conn: &Connection,
298        qh: &QueueHandle<Self>,
299        _layer: &LayerSurface,
300        _configure: LayerSurfaceConfigure,
301        _serial: u32,
302    ) {
303        self.converter(qh);
304    }
305}
306
307impl Dispatch<XdgSurface, ()> for SpellWin {
308    fn event(
309        state: &mut Self,
310        xdg_surface: &XdgSurface,
311        event: <XdgSurface as smithay_client_toolkit::reexports::client::Proxy>::Event,
312        _: &(),
313        _: &Connection,
314        _: &QueueHandle<Self>,
315    ) {
316        match event {
317            smithay_client_toolkit::reexports::protocols::xdg::shell::client::xdg_surface::Event::Configure { serial } => {
318                info!("[Popup Manager]: ack called with a serial");
319                 state.popup_manager.call_ack(xdg_surface, serial);
320            },
321            event_branch => warn!("Unprocessed event branch from popup configure: {:?}", event_branch),
322        }
323    }
324}