Skip to main content

spell_framework/wayland_adapter/
lock_impl.rs

1use slint::{
2    PhysicalSize, SharedString,
3    platform::{PointerEventButton, /*Key,*/ WindowEvent},
4};
5use smithay_client_toolkit::{
6    compositor::CompositorHandler,
7    output::{OutputHandler, OutputState},
8    reexports::{
9        client::{
10            Connection, QueueHandle,
11            protocol::{wl_output, wl_pointer, wl_seat, wl_surface},
12        },
13        protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::Shape,
14    },
15    registry::{ProvidesRegistryState, RegistryState},
16    registry_handlers,
17    seat::{
18        Capability, SeatHandler, SeatState,
19        keyboard::{KeyboardHandler /*Keysym*/},
20        pointer::{PointerData, PointerEvent, PointerEventKind, PointerHandler},
21    },
22    session_lock::{
23        SessionLock, SessionLockHandler, SessionLockSurface, SessionLockSurfaceConfigure,
24    },
25    shm::{Shm, ShmHandler, slot::Buffer},
26};
27use tracing::{info, trace, warn};
28
29use crate::{
30    slint_adapter::SpellSkiaWinAdapter,
31    wayland_adapter::{SpellLock, way_helper::get_string},
32};
33
34impl ProvidesRegistryState for SpellLock {
35    fn registry(&mut self) -> &mut RegistryState {
36        &mut self.registry_state
37    }
38    registry_handlers![OutputState, SeatState];
39}
40
41impl ShmHandler for SpellLock {
42    fn shm_state(&mut self) -> &mut Shm {
43        &mut self.shm
44    }
45}
46
47impl OutputHandler for SpellLock {
48    fn output_state(&mut self) -> &mut OutputState {
49        &mut self.output_state
50    }
51
52    fn new_output(
53        &mut self,
54        _conn: &Connection,
55        _qh: &QueueHandle<Self>,
56        _output: wl_output::WlOutput,
57    ) {
58        info!("New output source added");
59    }
60
61    fn update_output(
62        &mut self,
63        _conn: &Connection,
64        _qh: &QueueHandle<Self>,
65        _output: wl_output::WlOutput,
66    ) {
67        info!("Updated output source");
68    }
69
70    fn output_destroyed(
71        &mut self,
72        _conn: &Connection,
73        _qh: &QueueHandle<Self>,
74        _output: wl_output::WlOutput,
75    ) {
76        info!("Output is destroyed");
77    }
78}
79
80impl CompositorHandler for SpellLock {
81    fn scale_factor_changed(
82        &mut self,
83        _conn: &Connection,
84        _qh: &QueueHandle<Self>,
85        _surface: &wl_surface::WlSurface,
86        _new_factor: i32,
87    ) {
88        info!("Scale factor changed");
89    }
90
91    fn transform_changed(
92        &mut self,
93        _conn: &Connection,
94        _qh: &QueueHandle<Self>,
95        _surface: &wl_surface::WlSurface,
96        _new_transform: wl_output::Transform,
97    ) {
98        info!("Compositor transformation changed");
99    }
100
101    fn frame(
102        &mut self,
103        _conn: &Connection,
104        qh: &QueueHandle<Self>,
105        _surface: &wl_surface::WlSurface,
106        _time: u32,
107    ) {
108        self.converter_lock(qh);
109    }
110
111    fn surface_enter(
112        &mut self,
113        _conn: &Connection,
114        _qh: &QueueHandle<Self>,
115        _surface: &wl_surface::WlSurface,
116        _output: &wl_output::WlOutput,
117    ) {
118        info!("Surface entered");
119    }
120
121    fn surface_leave(
122        &mut self,
123        _conn: &Connection,
124        _qh: &QueueHandle<Self>,
125        _surface: &wl_surface::WlSurface,
126        _output: &wl_output::WlOutput,
127    ) {
128        info!("Surface left");
129    }
130}
131
132impl SessionLockHandler for SpellLock {
133    fn locked(&mut self, _conn: &Connection, _qh: &QueueHandle<Self>, _session_lock: SessionLock) {
134        info!("Session is locked");
135    }
136
137    fn finished(
138        &mut self,
139        _conn: &Connection,
140        _qh: &QueueHandle<Self>,
141        _session_lock: SessionLock,
142    ) {
143        info!("Session could not be locked");
144        self.is_locked = true;
145    }
146    fn configure(
147        &mut self,
148        _conn: &Connection,
149        qh: &QueueHandle<Self>,
150        _surface: SessionLockSurface,
151        _configure: SessionLockSurfaceConfigure,
152        _serial: u32,
153    ) {
154        self.converter_lock(qh);
155    }
156}
157
158impl KeyboardHandler for SpellLock {
159    fn enter(
160        &mut self,
161        _conn: &Connection,
162        _qh: &QueueHandle<Self>,
163        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
164        _surface: &smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface,
165        _serial: u32,
166        _raw: &[u32],
167        _keysyms: &[smithay_client_toolkit::seat::keyboard::Keysym],
168    ) {
169        info!("Keyboard focus entered");
170    }
171
172    fn leave(
173        &mut self,
174        _conn: &Connection,
175        _qh: &QueueHandle<Self>,
176        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
177        _surface: &smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface,
178        _serial: u32,
179    ) {
180        info!("Keyboard focus left");
181    }
182
183    fn press_key(
184        &mut self,
185        _conn: &Connection,
186        _qh: &QueueHandle<Self>,
187        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
188        _serial: u32,
189        event: smithay_client_toolkit::seat::keyboard::KeyEvent,
190    ) {
191        let string_val: SharedString = get_string(event);
192        // if string_val == <slint::platform::Key as Into<SharedString>>::into(Key::Backspace) {
193        //     self.loop_handle.enable(&self.backspace.unwrap()).unwrap();
194        //     self.slint_part.as_ref().unwrap().adapters[0]
195        //         .try_dispatch_event(WindowEvent::KeyPressed { text: string_val })
196        //         .unwrap();
197        // } else {
198        info!("Key pressed with value : {:?}", string_val);
199        self.slint_part.as_ref().unwrap().adapters[0]
200            .try_dispatch_event(WindowEvent::KeyPressed { text: string_val })
201            .unwrap_or_else(|err| warn!("Key press event failed with error: {:?}", err));
202        //}
203    }
204
205    fn release_key(
206        &mut self,
207        _conn: &Connection,
208        _qh: &QueueHandle<Self>,
209        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
210        _serial: u32,
211        event: smithay_client_toolkit::seat::keyboard::KeyEvent,
212    ) {
213        info!("Key is released");
214        // if let Err(err) = self.loop_handle.disable(&self.backspace.unwrap()) {
215        //     warn!("{}", err);
216        // }
217        // let key_sym = Keysym::new(event.raw_code);
218        // event.keysym = key_sym;
219        let string_val: SharedString = get_string(event);
220        self.slint_part.as_ref().unwrap().adapters[0]
221            .try_dispatch_event(WindowEvent::KeyReleased { text: string_val })
222            .unwrap_or_else(|err| warn!("Key release event failed with error: {:?}", err));
223    }
224
225    // TODO needs to be implemented to enable functionalities of ctl, shift, alt etc.
226    fn update_modifiers(
227        &mut self,
228        _conn: &Connection,
229        _qh: &QueueHandle<Self>,
230        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
231        _serial: u32,
232        _modifiers: smithay_client_toolkit::seat::keyboard::Modifiers,
233        _raw_modifiers: smithay_client_toolkit::seat::keyboard::RawModifiers,
234        _layout: u32,
235    ) {
236        trace!("Updated modifiers");
237    }
238
239    fn repeat_key(
240        &mut self,
241        _conn: &Connection,
242        _qh: &QueueHandle<Self>,
243        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
244        _serial: u32,
245        _event: smithay_client_toolkit::seat::keyboard::KeyEvent,
246    ) {
247        trace!("Repeated key entered");
248    }
249    // TODO This method needs to be implemented after the looping mecha is changed to calloop.
250    fn update_repeat_info(
251        &mut self,
252        _conn: &Connection,
253        _qh: &QueueHandle<Self>,
254        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
255        _info: smithay_client_toolkit::seat::keyboard::RepeatInfo,
256    ) {
257        trace!("Repeat info updation called");
258    }
259}
260
261impl SeatHandler for SpellLock {
262    fn seat_state(&mut self) -> &mut SeatState {
263        &mut self.seat_state
264    }
265
266    fn new_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
267
268    fn new_capability(
269        &mut self,
270        _conn: &Connection,
271        qh: &QueueHandle<Self>,
272        seat: wl_seat::WlSeat,
273        capability: Capability,
274    ) {
275        if capability == Capability::Keyboard && self.keyboard_state.board.is_none() {
276            info!("Setting keyboard capability");
277            let keyboard = self
278                .seat_state
279                .get_keyboard(qh, &seat, None)
280                .expect("Failed to create keyboard");
281            self.keyboard_state.board = Some(keyboard);
282        }
283        if capability == Capability::Pointer && self.pointer_state.pointer.is_none() {
284            info!("Setting pointer capability");
285            let pointer = self
286                .seat_state
287                .get_pointer(qh, &seat)
288                .expect("Failed to create pointer");
289            let pointer_data = PointerData::new(seat);
290            self.pointer_state.pointer = Some(pointer);
291            self.pointer_state.pointer_data = Some(pointer_data);
292        }
293    }
294
295    fn remove_capability(
296        &mut self,
297        _conn: &Connection,
298        _: &QueueHandle<Self>,
299        _: wl_seat::WlSeat,
300        capability: Capability,
301    ) {
302        if capability == Capability::Keyboard && self.keyboard_state.board.is_some() {
303            info!("Unsettting keyboard capability");
304            self.keyboard_state.board.take().unwrap().release();
305        }
306        if capability == Capability::Pointer && self.pointer_state.pointer.is_some() {
307            info!("Unsetting pointer capability");
308            self.pointer_state.pointer.take().unwrap().release();
309        }
310    }
311
312    fn remove_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
313}
314
315impl PointerHandler for SpellLock {
316    fn pointer_frame(
317        &mut self,
318        _conn: &Connection,
319        qh: &QueueHandle<Self>,
320        _pointer: &wl_pointer::WlPointer,
321        events: &[PointerEvent],
322    ) {
323        use PointerEventKind::*;
324        for event in events {
325            // Ignore events for other surfaces
326            for surface in self.lock_surfaces.iter() {
327                if event.surface != *surface.wl_surface() {
328                    continue;
329                }
330            }
331            match event.kind {
332                Enter { .. } => {
333                    info!("Pointer entered: {:?}", event.position);
334
335                    // TODO this code is redundent, as it doesn't set the cursor shape.
336                    let pointer = &self.pointer_state.pointer.as_ref().unwrap();
337                    let serial_no: Option<u32> = self
338                        .pointer_state
339                        .pointer_data
340                        .as_ref()
341                        .unwrap()
342                        .latest_enter_serial();
343                    if let Some(no) = serial_no {
344                        self.pointer_state
345                            .cursor_shape
346                            .get_shape_device(pointer, qh)
347                            .set_shape(no, Shape::Pointer);
348                    }
349                }
350                Leave { .. } => {
351                    info!("Pointer left: {:?}", event.position);
352                    self.slint_part.as_ref().unwrap().adapters[0]
353                        .try_dispatch_event(WindowEvent::PointerExited)
354                        .unwrap_or_else(|err| {
355                            warn!("Pointer left event failed with error: {:?}", err)
356                        });
357                }
358                Motion { .. } => {
359                    // debug!("Pointer entered @{:?}", event.position);
360                    self.slint_part.as_ref().unwrap().adapters[0]
361                        .try_dispatch_event(WindowEvent::PointerMoved {
362                            position: slint::LogicalPosition {
363                                x: event.position.0 as f32,
364                                y: event.position.1 as f32,
365                            },
366                        })
367                        .unwrap_or_else(|err| {
368                            warn!("Pointer move event failed with error: {:?}", err)
369                        });
370                }
371                Press { button, .. } => {
372                    trace!("Press {:x} @ {:?}", button, event.position);
373                    self.slint_part.as_ref().unwrap().adapters[0]
374                        .try_dispatch_event(WindowEvent::PointerPressed {
375                            position: slint::LogicalPosition {
376                                x: event.position.0 as f32,
377                                y: event.position.1 as f32,
378                            },
379                            button: PointerEventButton::Left,
380                        })
381                        .unwrap_or_else(|err| {
382                            warn!("Pointer press event failed with error: {:?}", err)
383                        });
384                }
385                Release { button, .. } => {
386                    trace!("Release {:x} @ {:?}", button, event.position);
387                    self.slint_part.as_ref().unwrap().adapters[0]
388                        .try_dispatch_event(WindowEvent::PointerReleased {
389                            position: slint::LogicalPosition {
390                                x: event.position.0 as f32,
391                                y: event.position.1 as f32,
392                            },
393                            button: PointerEventButton::Left,
394                        })
395                        .unwrap_or_else(|err| {
396                            warn!("Pointer release event failed with error: {:?}", err)
397                        });
398                }
399                Axis {
400                    horizontal,
401                    vertical,
402                    ..
403                } => {
404                    trace!("Scroll H:{horizontal:?}, V:{vertical:?}");
405                    self.slint_part.as_ref().unwrap().adapters[0]
406                        .try_dispatch_event(WindowEvent::PointerScrolled {
407                            position: slint::LogicalPosition {
408                                x: event.position.0 as f32,
409                                y: event.position.1 as f32,
410                            },
411                            delta_x: horizontal.absolute as f32,
412                            delta_y: vertical.absolute as f32,
413                        })
414                        .unwrap_or_else(|err| {
415                            warn!("Pointer scroll event failed with error: {:?}", err)
416                        });
417                }
418            }
419        }
420    }
421}
422/// It is an internal struct used by [`SpellLock`] internally.
423pub struct SpellSlintLock {
424    pub(crate) adapters: Vec<std::rc::Rc<SpellSkiaWinAdapter>>,
425    pub(crate) size: Vec<PhysicalSize>,
426    pub(crate) wayland_buffer: Vec<Buffer>,
427}