Skip to main content

spell_framework/wayland_adapter/
win_impl.rs

1use crate::wayland_adapter::{SpellWin, way_helper::get_string};
2use slint::{
3    SharedString,
4    platform::{PointerEventButton, WindowEvent},
5};
6use smithay_client_toolkit::{
7    output::OutputState,
8    reexports::client::{
9        Connection, QueueHandle,
10        protocol::{wl_pointer, wl_seat},
11    },
12    registry::{ProvidesRegistryState, RegistryState},
13    registry_handlers,
14    seat::{
15        Capability, SeatHandler, SeatState,
16        keyboard::KeyboardHandler,
17        pointer::{PointerData, PointerEvent, PointerEventKind, PointerHandler},
18        touch::TouchHandler,
19    },
20    shell::WaylandSurface,
21};
22use tracing::{info, trace, warn};
23
24// Slint doesn't hve very specific
25// APIs for touch support (I think). I am talking with them on what
26// can be done so that things like multi-touch support, gestures etc
27// can be made possible. For now I am going to place empty value in here.
28impl TouchHandler for SpellWin {
29    fn up(
30        &mut self,
31        _conn: &Connection,
32        _qh: &QueueHandle<Self>,
33        _touch: &smithay_client_toolkit::reexports::client::protocol::wl_touch::WlTouch,
34        _serial: u32,
35        _time: u32,
36        _id: i32,
37    ) {
38        info!("Up event from touch");
39    }
40    fn down(
41        &mut self,
42        _conn: &Connection,
43        _qh: &QueueHandle<Self>,
44        _touch: &smithay_client_toolkit::reexports::client::protocol::wl_touch::WlTouch,
45        _serial: u32,
46        _time: u32,
47        _surface: smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface,
48        _id: i32,
49        position: (f64, f64),
50    ) {
51        info!("Down event produced with posaition: {position:?}");
52    }
53
54    fn motion(
55        &mut self,
56        _conn: &Connection,
57        _qh: &QueueHandle<Self>,
58        _touch: &smithay_client_toolkit::reexports::client::protocol::wl_touch::WlTouch,
59        _time: u32,
60        _id: i32,
61        position: (f64, f64),
62    ) {
63        self.adapter
64            .try_dispatch_event(WindowEvent::PointerMoved {
65                position: slint::LogicalPosition {
66                    x: position.0 as f32,
67                    y: position.1 as f32,
68                },
69            })
70            .unwrap_or_else(|err| warn!("Touch move event failed with error: {:?}", err));
71    }
72
73    fn shape(
74        &mut self,
75        _conn: &Connection,
76        _qh: &QueueHandle<Self>,
77        _touch: &smithay_client_toolkit::reexports::client::protocol::wl_touch::WlTouch,
78        _id: i32,
79        major: f64,
80        minor: f64,
81    ) {
82        info!("Shape data released. Major: {major}, Minor: {minor}");
83    }
84    fn orientation(
85        &mut self,
86        _conn: &Connection,
87        _qh: &QueueHandle<Self>,
88        _touch: &smithay_client_toolkit::reexports::client::protocol::wl_touch::WlTouch,
89        _id: i32,
90        orientation: f64,
91    ) {
92        info!("Orientation data released: {orientation}.")
93    }
94    fn cancel(
95        &mut self,
96        _conn: &Connection,
97        _qh: &QueueHandle<Self>,
98        _touch: &smithay_client_toolkit::reexports::client::protocol::wl_touch::WlTouch,
99    ) {
100        info!("Active touch sequence cancelled");
101    }
102}
103
104impl KeyboardHandler for SpellWin {
105    fn enter(
106        &mut self,
107        _conn: &Connection,
108        _qh: &QueueHandle<Self>,
109        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
110        _surface: &smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface,
111        _serial: u32,
112        _raw: &[u32],
113        _keysyms: &[smithay_client_toolkit::seat::keyboard::Keysym],
114    ) {
115        info!("Keyboard focus entered");
116    }
117
118    fn leave(
119        &mut self,
120        _conn: &Connection,
121        _qh: &QueueHandle<Self>,
122        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
123        _surface: &smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface,
124        _serial: u32,
125    ) {
126        info!("Keyboard focus left");
127    }
128
129    fn press_key(
130        &mut self,
131        _conn: &Connection,
132        _qh: &QueueHandle<Self>,
133        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
134        _serial: u32,
135        event: smithay_client_toolkit::seat::keyboard::KeyEvent,
136    ) {
137        trace!("Key pressed");
138        let string_val: SharedString = get_string(event);
139        // if string_val == <slint::platform::Key as Into<SharedString>>::into(Key::Backspace) {
140        //     self.loop_handle.enable(&self.backspace).unwrap();
141        //     self.adapter
142        //         .try_dispatch_event(WindowEvent::KeyPressed { text: string_val })
143        //         .unwrap();
144        // } else {
145        self.adapter
146            .try_dispatch_event(WindowEvent::KeyPressed { text: string_val })
147            .unwrap_or_else(|err| warn!("Key press event failed with error: {:?}", err));
148        // }
149    }
150
151    fn release_key(
152        &mut self,
153        _conn: &Connection,
154        _qh: &QueueHandle<Self>,
155        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
156        _serial: u32,
157        /*mut*/ event: smithay_client_toolkit::seat::keyboard::KeyEvent,
158    ) {
159        trace!("Key released");
160        // if let Err(err) = self.loop_handle.disable(&self.backspace) {
161        //     warn!("{}", err);
162        // }
163        // let key_sym = Keysym::new(event.raw_code);
164        // event.keysym = key_sym;
165        let string_val: SharedString = get_string(event);
166        self.adapter
167            .try_dispatch_event(WindowEvent::KeyReleased { text: string_val })
168            .unwrap_or_else(|err| warn!("Key release event failed with error: {:?}", err));
169    }
170
171    // TODO needs to be implemented to enable functionalities of ctl, shift, alt etc.
172    fn update_modifiers(
173        &mut self,
174        _conn: &Connection,
175        _qh: &QueueHandle<Self>,
176        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
177        _serial: u32,
178        _modifiers: smithay_client_toolkit::seat::keyboard::Modifiers,
179        _raw_modifiers: smithay_client_toolkit::seat::keyboard::RawModifiers,
180        _layout: u32,
181    ) {
182    }
183    // TODO This method needs to be implemented after the looping mecha is changed to calloop.
184    fn update_repeat_info(
185        &mut self,
186        _conn: &Connection,
187        _qh: &QueueHandle<Self>,
188        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
189        _info: smithay_client_toolkit::seat::keyboard::RepeatInfo,
190    ) {
191        trace!("Key repeat info updated");
192    }
193
194    fn repeat_key(
195        &mut self,
196        _conn: &Connection,
197        _qh: &QueueHandle<Self>,
198        _keyboard: &smithay_client_toolkit::reexports::client::protocol::wl_keyboard::WlKeyboard,
199        _serial: u32,
200        _event: smithay_client_toolkit::seat::keyboard::KeyEvent,
201    ) {
202        trace!("Repeat key called");
203    }
204}
205
206impl SeatHandler for SpellWin {
207    fn seat_state(&mut self) -> &mut SeatState {
208        &mut self.states.seat_state
209    }
210
211    fn new_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
212
213    fn new_capability(
214        &mut self,
215        _conn: &Connection,
216        qh: &QueueHandle<Self>,
217        seat: wl_seat::WlSeat,
218        capability: Capability,
219    ) {
220        if capability == Capability::Keyboard && self.states.keyboard_state.is_none() {
221            info!("Setting keyboard capability");
222            let keyboard = self
223                .states
224                .seat_state
225                .get_keyboard(qh, &seat, None)
226                .expect("Failed to create keyboard");
227            self.states.keyboard_state = Some(keyboard);
228        }
229        if capability == Capability::Touch && self.states.touch_state.is_none() {
230            info!("Setting touch Capability");
231            let touch = self
232                .states
233                .seat_state
234                .get_touch(qh, &seat)
235                .expect("Failed to create touch");
236            self.states.touch_state = Some(touch);
237        }
238        if capability == Capability::Pointer && self.states.pointer_state.pointer.is_none() {
239            info!("Setting pointer capability");
240            let pointer = self
241                .states
242                .seat_state
243                .get_pointer(qh, &seat)
244                .expect("Failed to create pointer");
245            let pointer_data = PointerData::new(seat);
246            self.states.pointer_state.pointer = Some(pointer);
247            self.states.pointer_state.pointer_data = Some(pointer_data);
248        }
249    }
250
251    fn remove_capability(
252        &mut self,
253        _conn: &Connection,
254        _: &QueueHandle<Self>,
255        _: wl_seat::WlSeat,
256        capability: Capability,
257    ) {
258        if capability == Capability::Keyboard && self.states.keyboard_state.is_some() {
259            info!("Unsetting keyboard capability");
260            self.states.keyboard_state.take().unwrap().release();
261        }
262
263        if capability == Capability::Pointer && self.states.pointer_state.pointer.is_some() {
264            info!("Unsetting pointer capability");
265            self.states.pointer_state.pointer.take().unwrap().release();
266        }
267        if capability == Capability::Touch && self.states.touch_state.is_some() {
268            info!("Unsetting pointer capability");
269            self.states.touch_state.take().unwrap().release();
270        }
271    }
272
273    fn remove_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
274}
275
276impl PointerHandler for SpellWin {
277    fn pointer_frame(
278        &mut self,
279        _conn: &Connection,
280        _qh: &QueueHandle<Self>,
281        _pointer: &wl_pointer::WlPointer,
282        events: &[PointerEvent],
283    ) {
284        use PointerEventKind::*;
285        for event in events {
286            // Ignore events for other surfaces
287            if &event.surface != self.layer.as_ref().unwrap().wl_surface() {
288                continue;
289            }
290            match event.kind {
291                Enter { serial } => {
292                    trace!(
293                        "Pointer entered with serial {:?} at: {:?}",
294                        serial, event.position
295                    );
296
297                    self.states.pointer_state.last_cursor_enter_serial = Some(serial);
298                }
299                Leave { .. } => {
300                    info!("Pointer left: {:?}", event.position);
301                    self.adapter
302                        .try_dispatch_event(WindowEvent::PointerExited)
303                        .unwrap_or_else(|err| {
304                            warn!("Pointer exit event failed with error: {:?}", err)
305                        });
306                }
307                Motion { .. } => {
308                    // debug!("Pointer entered @{:?}", event.position);
309                    self.adapter
310                        .try_dispatch_event(WindowEvent::PointerMoved {
311                            position: slint::LogicalPosition {
312                                x: event.position.0 as f32,
313                                y: event.position.1 as f32,
314                            },
315                        })
316                        .unwrap_or_else(|err| {
317                            warn!("Pointer move event failed with error: {:?}", err)
318                        });
319                }
320                Press { button, .. } => {
321                    trace!("Press {:x} @ {:?}", button, event.position);
322                    self.adapter
323                        .try_dispatch_event(WindowEvent::PointerPressed {
324                            position: slint::LogicalPosition {
325                                x: event.position.0 as f32,
326                                y: event.position.1 as f32,
327                            },
328                            button: PointerEventButton::Left,
329                        })
330                        .unwrap_or_else(|err| {
331                            warn!("Pointer press event failed with error: {:?}", err)
332                        });
333                }
334                Release { button, .. } => {
335                    trace!("Release {:x} @ {:?}", button, event.position);
336                    self.adapter
337                        .try_dispatch_event(WindowEvent::PointerReleased {
338                            position: slint::LogicalPosition {
339                                x: event.position.0 as f32,
340                                y: event.position.1 as f32,
341                            },
342                            button: PointerEventButton::Left,
343                        })
344                        .unwrap_or_else(|err| {
345                            warn!("Pointer release event failed with error: {:?}", err)
346                        });
347                }
348                Axis {
349                    horizontal,
350                    vertical,
351                    ..
352                } => {
353                    trace!("Scroll H:{horizontal:?}, V:{vertical:?}");
354                    if !self.natural_scroll {
355                        self.adapter
356                            .try_dispatch_event(WindowEvent::PointerScrolled {
357                                position: slint::LogicalPosition {
358                                    x: event.position.0 as f32,
359                                    y: event.position.1 as f32,
360                                },
361                                delta_x: horizontal.absolute as f32,
362                                delta_y: vertical.absolute as f32,
363                            })
364                            .unwrap_or_else(|err| {
365                                warn!("Pointer scroll event failed with error: {:?}", err)
366                            });
367                    } else {
368                        self.adapter
369                            .try_dispatch_event(WindowEvent::PointerScrolled {
370                                position: slint::LogicalPosition {
371                                    x: event.position.0 as f32,
372                                    y: event.position.1 as f32,
373                                },
374                                delta_x: -horizontal.absolute as f32,
375                                delta_y: -vertical.absolute as f32,
376                            })
377                            .unwrap_or_else(|err| {
378                                warn!("Pointer scroll event failed with error: {:?}", err)
379                            });
380                    }
381                }
382            }
383        }
384    }
385}
386
387// TODO FIND What is the use of registery_handlers here?
388impl ProvidesRegistryState for SpellWin {
389    fn registry(&mut self) -> &mut RegistryState {
390        &mut self.states.registry_state
391    }
392    registry_handlers![OutputState, SeatState];
393}