1use repose_app::{ReposeRuntime, TouchGestureState};
4use repose_core::Vec2;
5use repose_core::input::PointerButton;
6use repose_core::shortcuts::{Action, Gesture};
7use winit::event::{ElementState, MouseScrollDelta, Touch};
8use winit::keyboard::{KeyCode, PhysicalKey};
9
10use crate::common::{map_key, winit_key_to_repose};
11
12pub fn on_modifiers_changed(rt: &mut ReposeRuntime, state: &winit::keyboard::ModifiersState) {
14 crate::common::update_modifiers(&mut rt.modifiers, state);
15}
16
17pub fn on_cursor_moved(
19 rt: &mut ReposeRuntime,
20 pos: Vec2,
21 inspector: &mut Option<repose_devtools::Inspector>,
22) -> Option<repose_core::CursorIcon> {
23 let result = rt.handle_pointer_move(pos);
24 if let (Some(inspector), Some(f)) = (inspector, &rt.frame_cache)
25 && inspector.hud.inspector_enabled
26 {
27 let hit = f.hit_regions.iter().find(|h| h.rect.contains(pos));
28 let hover_rect = hit.map(|h| h.rect);
29 let hover_info = hit.and_then(|h| {
30 f.semantics_nodes
31 .iter()
32 .find(|s| s.id == h.id)
33 .map(|s| repose_devtools::HoveredInfo {
34 id: s.id,
35 role: format!("{:?}", s.role),
36 label: s.label.clone(),
37 })
38 });
39 inspector.hud.set_hovered(hover_rect, hover_info);
40 }
41 result.cursor
42}
43
44pub fn on_mouse_wheel(rt: &mut ReposeRuntime, delta: MouseScrollDelta, scale: f32) -> bool {
46 let (dx_px, dy_px) = match delta {
47 MouseScrollDelta::LineDelta(x, y) => {
48 let _ = scale;
49 let unit_px = repose_core::Dp(60.0).to_px().0;
50 (-(x * unit_px), -(y * unit_px))
51 }
52 MouseScrollDelta::PixelDelta(p) => (-(p.x as f32), -(p.y as f32)),
53 };
54 rt.handle_scroll(Vec2 { x: dx_px, y: dy_px })
55}
56
57pub fn map_mouse_button(btn: winit::event::MouseButton) -> Option<PointerButton> {
59 match btn {
60 winit::event::MouseButton::Left => Some(PointerButton::Primary),
61 winit::event::MouseButton::Right => Some(PointerButton::Secondary),
62 winit::event::MouseButton::Middle => Some(PointerButton::Tertiary),
63 _ => None,
64 }
65}
66
67pub struct TouchResult {
69 pub dirty: bool,
70 pub pinch: Option<(f32, Vec2)>,
71 pub pan: Option<Vec2>,
72 pub rotation: Option<(f32, Vec2)>,
73 pub swipe_right: Option<bool>,
74}
75
76pub fn handle_touch_raw(
77 rt: &mut ReposeRuntime,
78 touch_gestures: &mut TouchGestureState,
79 t: &Touch,
80 scale: f32,
81) -> TouchResult {
82 let pos_px = (t.location.x as f32, t.location.y as f32);
83 let tid = t.id;
84 match t.phase {
85 winit::event::TouchPhase::Started => {
86 touch_gestures.touch_started(rt, tid, pos_px);
87 TouchResult {
88 dirty: true,
89 pinch: None,
90 pan: None,
91 rotation: None,
92 swipe_right: None,
93 }
94 }
95 winit::event::TouchPhase::Moved => {
96 let (dirty, pinch, pan, rotation) = touch_gestures.touch_moved(rt, tid, pos_px, scale);
97 TouchResult {
98 dirty,
99 pinch,
100 pan,
101 rotation,
102 swipe_right: None,
103 }
104 }
105 winit::event::TouchPhase::Ended | winit::event::TouchPhase::Cancelled => {
106 let cancelled = t.phase == winit::event::TouchPhase::Cancelled;
107 let swipe_right = touch_gestures.touch_ended(rt, tid, pos_px, cancelled);
108 TouchResult {
109 dirty: false,
110 pinch: None,
111 pan: None,
112 rotation: None,
113 swipe_right,
114 }
115 }
116 }
117}
118
119pub fn on_touch(
122 rt: &mut ReposeRuntime,
123 touch_gestures: &mut TouchGestureState,
124 t: &Touch,
125 scale: f32,
126 mut dispatch: impl FnMut(Action) -> bool,
127) -> bool {
128 let r = handle_touch_raw(rt, touch_gestures, t, scale);
129 let mut dirty = r.dirty;
130 if let Some((delta_scale, center)) = r.pinch
131 && dispatch(Action::Gesture(Gesture::PinchWithCenter {
132 delta_scale,
133 center,
134 }))
135 {
136 dirty = true;
137 }
138 if let Some(delta) = r.pan
139 && dispatch(Action::Gesture(Gesture::Pan { delta }))
140 {
141 dirty = true;
142 }
143 if let Some((delta_rotation, center)) = r.rotation
144 && dispatch(Action::Gesture(Gesture::Rotate {
145 delta_rotation,
146 center,
147 }))
148 {
149 dirty = true;
150 }
151 if let Some(right) = r.swipe_right {
152 let g = if right {
153 Gesture::SwipeRight
154 } else {
155 Gesture::SwipeLeft
156 };
157 if dispatch(Action::Gesture(g)) {
158 dirty = true;
159 }
160 }
161 dirty
162}
163
164pub fn on_touch_with_ime(
167 rt: &mut ReposeRuntime,
168 touch_gestures: &mut TouchGestureState,
169 t: &Touch,
170 scale: f32,
171 window: &winit::window::Window,
172 dispatch: impl FnMut(Action) -> bool,
173) -> bool {
174 let pos_px = (t.location.x as f32, t.location.y as f32);
175 let tid = t.id;
176 if t.phase == winit::event::TouchPhase::Started {
177 let focused = touch_gestures.touch_started(rt, tid, pos_px);
178 if let Some(fid) = focused {
179 if rt.is_textfield(fid) {
180 let (purpose, ac, cap) = rt.focused_keyboard_hints();
181 crate::common::set_ime_for_textfield_ex(window, true, purpose, ac, cap);
182 } else {
183 crate::common::set_ime_for_textfield(window, false);
184 }
185 } else {
186 crate::common::set_ime_for_textfield(window, false);
187 }
188 return true;
189 }
190 on_touch(rt, touch_gestures, t, scale, dispatch)
191}
192
193pub fn on_keyboard_input(
196 rt: &mut ReposeRuntime,
197 key_event: &winit::event::KeyEvent,
198 inspector: &mut Option<repose_devtools::Inspector>,
199) -> bool {
200 if key_event.state == ElementState::Pressed
201 && !key_event.repeat
202 && rt.modifiers.ctrl
203 && rt.modifiers.shift
204 && key_event.physical_key == PhysicalKey::Code(KeyCode::KeyI)
205 && let Some(inspector) = inspector
206 {
207 inspector.hud.toggle_inspector();
208 return true;
209 }
210 let mapped = map_key(key_event.physical_key, &rt.modifiers);
211 let ke = winit_key_to_repose(key_event, &mapped, &rt.modifiers);
212 rt.handle_key_with_text(&ke, key_event.text.as_deref())
213}
214
215pub fn on_ime(rt: &mut ReposeRuntime, ime: &winit::event::Ime) {
217 use winit::event::Ime;
218 let ev = match ime {
219 Ime::Enabled => repose_core::input::ImeEvent::Start,
220 Ime::Preedit(text, cursor) => repose_core::input::ImeEvent::Update {
221 text: text.clone(),
222 cursor: cursor.map(|(a, b)| (a, b)),
223 },
224 Ime::Commit(text) => repose_core::input::ImeEvent::Commit(text.clone()),
225 Ime::Disabled => repose_core::input::ImeEvent::Cancel,
226 };
227 rt.handle_ime(&ev);
228}