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