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