1use crate::app::strategies::framebuffer::{AutoRepeatContext, AutoRepeatTimer};
6use crate::app::Config;
7use crate::drawing::DisplayRotation;
8use crate::geometry::{IntVector, LimitToBounds};
9use crate::input::{
10 consumer_control, input3_key_to_hid_usage, keyboard, mouse, touch, Button, ButtonSet, DeviceId,
11 Event, EventType, Modifiers,
12};
13use crate::{IntPoint, IntRect, IntSize};
14use euclid::{point2, size2, vec2};
15use fidl_fuchsia_input_report as hid_input_report;
16use keymaps::Keymap;
17use std::collections::HashSet;
18
19#[derive(Debug)]
20pub struct TouchScale {
21 pub target_size: IntSize,
22 pub x: hid_input_report::Range,
23 pub x_span: f32,
24 pub y: hid_input_report::Range,
25 pub y_span: f32,
26}
27
28fn restrict_to_range(value: i64, range: &hid_input_report::Range) -> i64 {
29 if value < range.min {
30 range.min
31 } else if value > range.max {
32 range.max
33 } else {
34 value
35 }
36}
37
38fn scale_value(value: i64, span: f32, range: &hid_input_report::Range, value_max: i32) -> i32 {
39 let value = restrict_to_range(value, range) - range.min;
40 let value_fraction = value as f32 / span;
41 (value_fraction * value_max as f32) as i32
42}
43
44impl TouchScale {
45 fn calculate_span(range: &hid_input_report::Range) -> f32 {
46 if range.max <= range.min {
47 1.0
48 } else {
49 (range.max - range.min) as f32
50 }
51 }
52
53 pub fn new(
54 target_size: &IntSize,
55 x: &hid_input_report::Range,
56 y: &hid_input_report::Range,
57 ) -> Self {
58 Self {
59 target_size: *target_size,
60 x: *x,
61 x_span: Self::calculate_span(x),
62 y: *y,
63 y_span: Self::calculate_span(y),
64 }
65 }
66
67 pub fn scale(&self, pt: &IntPoint) -> IntPoint {
68 let x = scale_value(pt.x as i64, self.x_span, &self.x, self.target_size.width);
69 let y = scale_value(pt.y as i64, self.y_span, &self.y, self.target_size.height);
70 point2(x, y)
71 }
72}
73
74fn create_keyboard_event(
75 event_time: u64,
76 device_id: &DeviceId,
77 phase: keyboard::Phase,
78 key: fidl_fuchsia_input::Key,
79 modifiers: &Modifiers,
80 keymap: &Keymap<'_>,
81) -> Event {
82 let hid_usage = input3_key_to_hid_usage(key);
83 let code_point =
84 keymap.hid_usage_to_code_point_for_mods(hid_usage, modifiers.shift, modifiers.caps_lock);
85 let keyboard_event = keyboard::Event { phase, code_point, hid_usage, modifiers: *modifiers };
86 Event {
87 event_time,
88 device_id: device_id.clone(),
89 event_type: EventType::Keyboard(keyboard_event),
90 }
91}
92
93pub(crate) struct InputReportHandler<'a> {
94 device_id: DeviceId,
95 view_size: IntSize,
96 display_rotation: DisplayRotation,
97 touch_scale: Option<TouchScale>,
98 keymap: &'a Keymap<'a>,
99 repeating: Option<fidl_fuchsia_input::Key>,
100 cursor_position: IntPoint,
101 pressed_mouse_buttons: HashSet<u8>,
102 pressed_keys: HashSet<fidl_fuchsia_input::Key>,
103 raw_contacts: HashSet<touch::RawContact>,
104 pressed_consumer_control_buttons: HashSet<hid_input_report::ConsumerControlButton>,
105}
106
107impl<'a> InputReportHandler<'a> {
108 pub fn new(
109 device_id: DeviceId,
110 size: IntSize,
111 display_rotation: DisplayRotation,
112 device_descriptor: &hid_input_report::DeviceDescriptor,
113 keymap: &'a Keymap<'a>,
114 ) -> Self {
115 let touch_scale = device_descriptor
116 .touch
117 .as_ref()
118 .and_then(|touch| touch.input.as_ref())
119 .and_then(|input_descriptor| input_descriptor.contacts.as_ref())
120 .and_then(|contacts| contacts.first())
121 .and_then(|contact_input_descriptor| {
122 if contact_input_descriptor.position_x.is_some()
123 && contact_input_descriptor.position_y.is_some()
124 {
125 Some(TouchScale::new(
126 &size,
127 &contact_input_descriptor.position_x.as_ref().expect("position_x").range,
128 &contact_input_descriptor.position_y.as_ref().expect("position_y").range,
129 ))
130 } else {
131 None
132 }
133 });
134 Self::new_with_scale(device_id, size, display_rotation, touch_scale, keymap)
135 }
136
137 pub fn new_with_scale(
138 device_id: DeviceId,
139 size: IntSize,
140 display_rotation: DisplayRotation,
141 touch_scale: Option<TouchScale>,
142 keymap: &'a Keymap<'a>,
143 ) -> Self {
144 Self {
145 device_id: device_id,
146 view_size: size,
147 display_rotation,
148 keymap,
149 repeating: None,
150 touch_scale,
151 cursor_position: IntPoint::zero(),
152 pressed_mouse_buttons: HashSet::new(),
153 pressed_keys: HashSet::new(),
154 raw_contacts: HashSet::new(),
155 pressed_consumer_control_buttons: HashSet::new(),
156 }
157 }
158
159 fn handle_mouse_input_report(
160 &mut self,
161 event_time: u64,
162 device_id: &DeviceId,
163 mouse: &hid_input_report::MouseInputReport,
164 ) -> Vec<Event> {
165 let transform = self.display_rotation.inv_transform(&self.view_size.to_f32());
166 let new_cursor_position = self.cursor_position
167 + vec2(mouse.movement_x.unwrap_or(0) as i32, mouse.movement_y.unwrap_or(0) as i32);
168 let m = self.view_size;
169 let bounds = IntRect::new(IntPoint::zero(), m);
170 let new_cursor_position = bounds.limit_to_bounds(new_cursor_position);
171 let pressed_buttons: HashSet<u8> = if let Some(ref pressed_buttons) = mouse.pressed_buttons
172 {
173 let pressed_buttons_set = pressed_buttons.iter().cloned().collect();
174 pressed_buttons_set
175 } else {
176 HashSet::new()
177 };
178
179 let button_set = ButtonSet::new(&pressed_buttons);
180
181 let move_event = if new_cursor_position != self.cursor_position {
182 let event = mouse::create_event(
183 event_time,
184 device_id,
185 &button_set,
186 new_cursor_position,
187 &transform,
188 mouse::Phase::Moved,
189 );
190 Some(event)
191 } else {
192 None
193 };
194
195 self.cursor_position = new_cursor_position;
196
197 let newly_pressed = pressed_buttons.difference(&self.pressed_mouse_buttons).map(|button| {
198 mouse::create_event(
199 event_time,
200 device_id,
201 &button_set,
202 new_cursor_position,
203 &transform,
204 mouse::Phase::Down(Button(*button)),
205 )
206 });
207
208 let released = self.pressed_mouse_buttons.difference(&pressed_buttons).map(|button| {
209 mouse::create_event(
210 event_time,
211 device_id,
212 &button_set,
213 new_cursor_position,
214 &transform,
215 mouse::Phase::Up(Button(*button)),
216 )
217 });
218
219 let wheel_v = mouse.scroll_v.unwrap_or(0) as i32;
220 let wheel_h = mouse.scroll_h.unwrap_or(0) as i32;
221 let wheel = if wheel_v != 0 || wheel_h != 0 {
222 Some(mouse::create_event(
223 event_time,
224 device_id,
225 &button_set,
226 new_cursor_position,
227 &transform,
228 mouse::Phase::Wheel(IntVector::new(wheel_h, wheel_v)),
229 ))
230 } else {
231 None
232 };
233
234 let events = newly_pressed.chain(move_event).chain(wheel).chain(released).collect();
235 self.pressed_mouse_buttons = pressed_buttons;
236 events
237 }
238
239 fn handle_keyboard_input_report(
240 &mut self,
241 event_time: u64,
242 device_id: &DeviceId,
243 keyboard: &hid_input_report::KeyboardInputReport,
244 context: &mut dyn AutoRepeatTimer,
245 ) -> Vec<Event> {
246 let pressed_keys: HashSet<fidl_fuchsia_input::Key> =
247 if let Some(ref pressed_keys) = keyboard.pressed_keys3 {
248 HashSet::from_iter(pressed_keys.iter().map(|key| *key))
249 } else {
250 HashSet::new()
251 };
252
253 let modifiers = Modifiers::from_pressed_keys_3(&pressed_keys);
254
255 let mut first_non_modifier: Option<fidl_fuchsia_input::Key> = None;
256
257 let newly_pressed = pressed_keys.difference(&self.pressed_keys).map(|key| {
258 if first_non_modifier.is_none() && !Modifiers::is_modifier(key) {
259 first_non_modifier = Some(*key);
260 }
261 create_keyboard_event(
262 event_time,
263 device_id,
264 keyboard::Phase::Pressed,
265 *key,
266 &modifiers,
267 self.keymap,
268 )
269 });
270
271 let mut repeating: Option<fidl_fuchsia_input::Key> = self.repeating.clone();
272
273 let released = self.pressed_keys.difference(&pressed_keys).map(|key| {
274 if repeating.as_ref() == Some(key) {
275 repeating = None;
276 }
277
278 create_keyboard_event(
279 event_time,
280 device_id,
281 keyboard::Phase::Released,
282 *key,
283 &modifiers,
284 self.keymap,
285 )
286 });
287
288 let events = newly_pressed.chain(released).collect();
289 self.pressed_keys = pressed_keys;
290 self.repeating = first_non_modifier.or(repeating);
291 if Config::get().keyboard_autorepeat && self.repeating.is_some() {
292 context.schedule_autorepeat_timer(&self.device_id);
293 }
294 events
295 }
296
297 pub fn handle_keyboard_autorepeat(
298 &mut self,
299 device_id: &DeviceId,
300 context: &mut AutoRepeatContext,
301 ) -> Vec<Event> {
302 if let Some(key) = self.repeating.as_ref() {
303 let repeat_time = zx::MonotonicInstant::get();
304 let modifiers = Modifiers::from_pressed_keys_3(&self.pressed_keys);
305 context.continue_autorepeat_timer(&self.device_id);
306 let repeat = create_keyboard_event(
307 repeat_time.into_nanos() as u64,
308 device_id,
309 keyboard::Phase::Repeat,
310 *key,
311 &modifiers,
312 self.keymap,
313 );
314 vec![repeat]
315 } else {
316 context.cancel_autorepeat_timer();
317 Vec::new()
318 }
319 }
320
321 fn handle_touch_input_report(
322 &mut self,
323 event_time: u64,
324 device_id: &DeviceId,
325 touch: &hid_input_report::TouchInputReport,
326 ) -> Vec<Event> {
327 if self.touch_scale.is_none() {
328 return Vec::new();
329 }
330
331 let pressed_buttons: HashSet<u8> = if let Some(ref pressed_buttons) = touch.pressed_buttons
332 {
333 let pressed_buttons_set = pressed_buttons.iter().cloned().collect();
334 pressed_buttons_set
335 } else {
336 HashSet::new()
337 };
338
339 let button_set = ButtonSet::new(&pressed_buttons);
340
341 let raw_contacts: HashSet<touch::RawContact> = if let Some(ref contacts) = touch.contacts {
342 let id_iter = contacts.iter().filter_map(|contact| {
343 if contact.position_x.is_none() || contact.position_y.is_none() {
344 return None;
345 }
346 let contact_id = contact.contact_id.expect("contact_id");
347 let contact_size =
348 if contact.contact_width.is_none() || contact.contact_height.is_none() {
349 None
350 } else {
351 Some(size2(
352 contact.contact_width.expect("contact_width") as i32,
353 contact.contact_height.expect("contact_height") as i32,
354 ))
355 };
356 Some(touch::RawContact {
357 contact_id,
358 position: point2(
359 contact.position_x.expect("position_x") as i32,
360 contact.position_y.expect("position_y") as i32,
361 ),
362 contact_size,
363 pressure: contact.pressure,
364 })
365 });
366 HashSet::from_iter(id_iter)
367 } else {
368 HashSet::new()
369 };
370
371 let transform = self.display_rotation.inv_transform(&self.view_size.to_f32());
372 let touch_scale = self.touch_scale.as_ref().expect("touch_scale");
373
374 let t = |point: IntPoint| transform.transform_point(point.to_f32()).to_i32();
375
376 let maintained_contacts =
377 self.raw_contacts.intersection(&raw_contacts).map(|raw_contact| touch::Contact {
378 contact_id: touch::ContactId(raw_contact.contact_id),
379 phase: touch::Phase::Moved(
380 t(touch_scale.scale(&raw_contact.position)),
381 raw_contact.contact_size.unwrap_or_else(|| IntSize::zero()),
382 ),
383 });
384
385 let new_contacts =
386 raw_contacts.difference(&self.raw_contacts).map(|raw_contact| touch::Contact {
387 contact_id: touch::ContactId(raw_contact.contact_id),
388 phase: touch::Phase::Down(
389 t(touch_scale.scale(&raw_contact.position)),
390 raw_contact.contact_size.unwrap_or_else(|| IntSize::zero()),
391 ),
392 });
393
394 let ended_contacts =
395 self.raw_contacts.difference(&raw_contacts).map(|raw_contact| touch::Contact {
396 contact_id: touch::ContactId(raw_contact.contact_id),
397 phase: touch::Phase::Up,
398 });
399
400 let contacts: Vec<touch::Contact> =
401 new_contacts.chain(maintained_contacts).chain(ended_contacts).collect();
402
403 self.raw_contacts = raw_contacts;
404
405 let touch_event = touch::Event { contacts: contacts, buttons: button_set };
406 let event = Event {
407 event_time,
408 device_id: device_id.clone(),
409 event_type: EventType::Touch(touch_event),
410 };
411 vec![event]
412 }
413
414 fn handle_consumer_control_report(
415 &mut self,
416 event_time: u64,
417 device_id: &DeviceId,
418 consumer_control: &hid_input_report::ConsumerControlInputReport,
419 ) -> Vec<Event> {
420 fn create_consumer_control_event(
421 event_time: u64,
422 device_id: &DeviceId,
423 phase: consumer_control::Phase,
424 button: hid_input_report::ConsumerControlButton,
425 ) -> Event {
426 let consumer_control_event = consumer_control::Event { phase, button };
427 Event {
428 event_time,
429 device_id: device_id.clone(),
430 event_type: EventType::ConsumerControl(consumer_control_event),
431 }
432 }
433
434 let pressed_consumer_control_buttons: HashSet<hid_input_report::ConsumerControlButton> =
435 if let Some(ref pressed_buttons) = consumer_control.pressed_buttons {
436 let pressed_buttons_set = pressed_buttons.iter().cloned().collect();
437 pressed_buttons_set
438 } else {
439 HashSet::new()
440 };
441 let newly_pressed = pressed_consumer_control_buttons
442 .difference(&self.pressed_consumer_control_buttons)
443 .map(|button| {
444 create_consumer_control_event(
445 event_time,
446 device_id,
447 consumer_control::Phase::Down,
448 *button,
449 )
450 });
451
452 let released = self
453 .pressed_consumer_control_buttons
454 .difference(&pressed_consumer_control_buttons)
455 .map(|button| {
456 create_consumer_control_event(
457 event_time,
458 device_id,
459 consumer_control::Phase::Up,
460 *button,
461 )
462 });
463 let events = newly_pressed.chain(released).collect();
464 self.pressed_consumer_control_buttons = pressed_consumer_control_buttons;
465 events
466 }
467
468 pub fn handle_input_report(
469 &mut self,
470 device_id: &DeviceId,
471 input_report: &hid_input_report::InputReport,
472 context: &mut dyn AutoRepeatTimer,
473 ) -> Vec<Event> {
474 let mut events = Vec::new();
475 let event_time = input_report.event_time.unwrap_or(0) as u64;
476 if let Some(mouse) = input_report.mouse.as_ref() {
477 events.extend(self.handle_mouse_input_report(event_time, device_id, mouse));
478 }
479 if let Some(keyboard) = input_report.keyboard.as_ref() {
480 events.extend(
481 self.handle_keyboard_input_report(event_time, &device_id, keyboard, context),
482 );
483 }
484 if let Some(touch) = input_report.touch.as_ref() {
485 events.extend(self.handle_touch_input_report(event_time, &device_id, touch));
486 }
487 if let Some(consumer_control) = input_report.consumer_control.as_ref() {
488 events.extend(self.handle_consumer_control_report(
489 event_time,
490 &device_id,
491 consumer_control,
492 ));
493 }
494 events
495 }
496}