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