Skip to main content

spell_framework/wayland_adapter/
win_impl.rs

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