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<hid_input_report::TouchButton> =
332 if let Some(ref pressed_buttons) = touch.pressed_buttons {
333 let pressed_buttons_set = pressed_buttons.iter().cloned().collect();
334 pressed_buttons_set
335 } else {
336 HashSet::new()
337 };
338
339 let raw_contacts: HashSet<touch::RawContact> = if let Some(ref contacts) = touch.contacts {
340 let id_iter = contacts.iter().filter_map(|contact| {
341 if contact.position_x.is_none() || contact.position_y.is_none() {
342 return None;
343 }
344 let contact_id = contact.contact_id.expect("contact_id");
345 let contact_size =
346 if contact.contact_width.is_none() || contact.contact_height.is_none() {
347 None
348 } else {
349 Some(size2(
350 contact.contact_width.expect("contact_width") as i32,
351 contact.contact_height.expect("contact_height") as i32,
352 ))
353 };
354 Some(touch::RawContact {
355 contact_id,
356 position: point2(
357 contact.position_x.expect("position_x") as i32,
358 contact.position_y.expect("position_y") as i32,
359 ),
360 contact_size,
361 pressure: contact.pressure,
362 })
363 });
364 HashSet::from_iter(id_iter)
365 } else {
366 HashSet::new()
367 };
368
369 let transform = self.display_rotation.inv_transform(&self.view_size.to_f32());
370 let touch_scale = self.touch_scale.as_ref().expect("touch_scale");
371
372 let t = |point: IntPoint| transform.transform_point(point.to_f32()).to_i32();
373
374 let maintained_contacts =
375 self.raw_contacts.intersection(&raw_contacts).map(|raw_contact| touch::Contact {
376 contact_id: touch::ContactId(raw_contact.contact_id),
377 phase: touch::Phase::Moved(
378 t(touch_scale.scale(&raw_contact.position)),
379 raw_contact.contact_size.unwrap_or_else(|| IntSize::zero()),
380 ),
381 });
382
383 let new_contacts =
384 raw_contacts.difference(&self.raw_contacts).map(|raw_contact| touch::Contact {
385 contact_id: touch::ContactId(raw_contact.contact_id),
386 phase: touch::Phase::Down(
387 t(touch_scale.scale(&raw_contact.position)),
388 raw_contact.contact_size.unwrap_or_else(|| IntSize::zero()),
389 ),
390 });
391
392 let ended_contacts =
393 self.raw_contacts.difference(&raw_contacts).map(|raw_contact| touch::Contact {
394 contact_id: touch::ContactId(raw_contact.contact_id),
395 phase: touch::Phase::Up,
396 });
397
398 let contacts: Vec<touch::Contact> =
399 new_contacts.chain(maintained_contacts).chain(ended_contacts).collect();
400
401 self.raw_contacts = raw_contacts;
402
403 let touch_event = touch::Event { contacts: contacts, buttons: pressed_buttons };
404 let event = Event {
405 event_time,
406 device_id: device_id.clone(),
407 event_type: EventType::Touch(touch_event),
408 };
409 vec![event]
410 }
411
412 fn handle_consumer_control_report(
413 &mut self,
414 event_time: u64,
415 device_id: &DeviceId,
416 consumer_control: &hid_input_report::ConsumerControlInputReport,
417 ) -> Vec<Event> {
418 fn create_consumer_control_event(
419 event_time: u64,
420 device_id: &DeviceId,
421 phase: consumer_control::Phase,
422 button: hid_input_report::ConsumerControlButton,
423 ) -> Event {
424 let consumer_control_event = consumer_control::Event { phase, button };
425 Event {
426 event_time,
427 device_id: device_id.clone(),
428 event_type: EventType::ConsumerControl(consumer_control_event),
429 }
430 }
431
432 let pressed_consumer_control_buttons: HashSet<hid_input_report::ConsumerControlButton> =
433 if let Some(ref pressed_buttons) = consumer_control.pressed_buttons {
434 let pressed_buttons_set = pressed_buttons.iter().cloned().collect();
435 pressed_buttons_set
436 } else {
437 HashSet::new()
438 };
439 let newly_pressed = pressed_consumer_control_buttons
440 .difference(&self.pressed_consumer_control_buttons)
441 .map(|button| {
442 create_consumer_control_event(
443 event_time,
444 device_id,
445 consumer_control::Phase::Down,
446 *button,
447 )
448 });
449
450 let released = self
451 .pressed_consumer_control_buttons
452 .difference(&pressed_consumer_control_buttons)
453 .map(|button| {
454 create_consumer_control_event(
455 event_time,
456 device_id,
457 consumer_control::Phase::Up,
458 *button,
459 )
460 });
461 let events = newly_pressed.chain(released).collect();
462 self.pressed_consumer_control_buttons = pressed_consumer_control_buttons;
463 events
464 }
465
466 pub fn handle_input_report(
467 &mut self,
468 device_id: &DeviceId,
469 input_report: &hid_input_report::InputReport,
470 context: &mut dyn AutoRepeatTimer,
471 ) -> Vec<Event> {
472 let mut events = Vec::new();
473 let event_time = input_report.event_time.unwrap_or(0) as u64;
474 if let Some(mouse) = input_report.mouse.as_ref() {
475 events.extend(self.handle_mouse_input_report(event_time, device_id, mouse));
476 }
477 if let Some(keyboard) = input_report.keyboard.as_ref() {
478 events.extend(
479 self.handle_keyboard_input_report(event_time, &device_id, keyboard, context),
480 );
481 }
482 if let Some(touch) = input_report.touch.as_ref() {
483 events.extend(self.handle_touch_input_report(event_time, &device_id, touch));
484 }
485 if let Some(consumer_control) = input_report.consumer_control.as_ref() {
486 events.extend(self.handle_consumer_control_report(
487 event_time,
488 &device_id,
489 consumer_control,
490 ));
491 }
492 events
493 }
494}