1use crate::app::{InternalSender, MessageInternal};
6use crate::geometry::{IntPoint, IntSize};
7use anyhow::{Error, format_err};
8use euclid::default::Transform2D;
9use fidl::endpoints::create_proxy;
10use fidl_fuchsia_input_report as fidl_input_report;
11use fuchsia_async::{self as fasync, MonotonicInstant, TimeoutExt};
12use fuchsia_component::client::Service;
13use futures::{StreamExt, TryFutureExt};
14use keymaps::usages::input3_key_to_hid_usage;
15use std::collections::HashSet;
16use std::hash::{Hash, Hasher};
17use zx::{self as zx, MonotonicDuration};
18
19#[derive(Debug)]
20pub(crate) enum UserInputMessage {
21 ScenicKeyEvent(fidl_fuchsia_ui_input3::KeyEvent),
22 FlatlandMouseEvents(Vec<fidl_fuchsia_ui_pointer::MouseEvent>),
23 FlatlandTouchEvents(Vec<fidl_fuchsia_ui_pointer::TouchEvent>),
24}
25
26#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
28pub struct Button(pub u8);
29
30const PRIMARY_BUTTON: u8 = 1;
31
32impl Button {
33 pub fn is_primary(&self) -> bool {
36 self.0 == PRIMARY_BUTTON
37 }
38}
39
40#[derive(Clone, Debug, Default, PartialEq)]
42pub struct ButtonSet {
43 buttons: HashSet<Button>,
44}
45
46impl ButtonSet {
47 pub fn new(buttons: &HashSet<u8>) -> ButtonSet {
49 ButtonSet { buttons: buttons.iter().map(|button| Button(*button)).collect() }
50 }
51
52 pub fn new_from_flags(flags: u32) -> ButtonSet {
54 let buttons: HashSet<u8> = (0..2)
55 .filter_map(|index| {
56 let mask = 1 << index;
57 if flags & mask != 0 { Some(index + 1) } else { None }
58 })
59 .collect();
60 ButtonSet::new(&buttons)
61 }
62
63 pub fn primary_button_is_down(&self) -> bool {
65 self.buttons.contains(&Button(PRIMARY_BUTTON))
66 }
67}
68
69#[derive(Debug, Default, PartialEq, Clone, Copy)]
71pub struct Modifiers {
72 pub shift: bool,
74 pub alt: bool,
76 pub control: bool,
78 pub caps_lock: bool,
80}
81
82impl Modifiers {
83 pub(crate) fn from_pressed_keys_3(pressed_keys: &HashSet<fidl_fuchsia_input::Key>) -> Self {
84 Self {
85 shift: pressed_keys.contains(&fidl_fuchsia_input::Key::LeftShift)
86 || pressed_keys.contains(&fidl_fuchsia_input::Key::RightShift),
87 alt: pressed_keys.contains(&fidl_fuchsia_input::Key::LeftAlt)
88 || pressed_keys.contains(&fidl_fuchsia_input::Key::RightAlt),
89 control: pressed_keys.contains(&fidl_fuchsia_input::Key::LeftCtrl)
90 || pressed_keys.contains(&fidl_fuchsia_input::Key::RightCtrl),
91 caps_lock: pressed_keys.contains(&fidl_fuchsia_input::Key::CapsLock),
92 }
93 }
94
95 pub(crate) fn is_modifier(key: &fidl_fuchsia_input::Key) -> bool {
96 match key {
97 fidl_fuchsia_input::Key::LeftShift
98 | fidl_fuchsia_input::Key::RightShift
99 | fidl_fuchsia_input::Key::LeftAlt
100 | fidl_fuchsia_input::Key::RightAlt
101 | fidl_fuchsia_input::Key::LeftCtrl
102 | fidl_fuchsia_input::Key::RightCtrl
103 | fidl_fuchsia_input::Key::CapsLock => true,
104 _ => false,
105 }
106 }
107}
108
109pub mod mouse {
111 use super::*;
112 use crate::geometry::IntVector;
113
114 #[derive(Debug, PartialEq, Clone)]
116 pub enum Phase {
117 Down(Button),
119 Up(Button),
121 Moved,
123 Wheel(IntVector),
125 }
126
127 #[derive(Debug, PartialEq, Clone)]
129 pub struct Event {
130 pub buttons: ButtonSet,
132 pub phase: Phase,
134 pub location: IntPoint,
136 }
137
138 pub(crate) fn create_event(
139 event_time: u64,
140 device_id: &DeviceId,
141 button_set: &ButtonSet,
142 cursor_position: IntPoint,
143 transform: &Transform2D<f32>,
144 phase: mouse::Phase,
145 ) -> super::Event {
146 let cursor_position = transform.transform_point(cursor_position.to_f32()).to_i32();
147 let mouse_event =
148 mouse::Event { buttons: button_set.clone(), phase, location: cursor_position };
149 super::Event {
150 event_time,
151 device_id: device_id.clone(),
152 event_type: EventType::Mouse(mouse_event),
153 }
154 }
155}
156
157pub mod keyboard {
159 use super::*;
160
161 #[derive(Clone, Copy, Debug, PartialEq)]
163 pub enum Phase {
164 Pressed,
166 Released,
168 Cancelled,
170 Repeat,
172 }
173
174 #[derive(Debug, PartialEq, Clone)]
176 pub struct Event {
177 pub phase: Phase,
179 pub code_point: Option<u32>,
181 pub hid_usage: u32,
183 pub modifiers: Modifiers,
186 }
187}
188
189pub mod touch {
191 use super::*;
192
193 #[derive(Debug, Eq)]
194 pub(crate) struct RawContact {
195 pub contact_id: u32,
196 pub position: IntPoint,
197 #[allow(unused)]
199 pub pressure: Option<i64>,
200 pub contact_size: Option<IntSize>,
201 }
202
203 impl PartialEq for RawContact {
204 fn eq(&self, rhs: &Self) -> bool {
205 self.contact_id == rhs.contact_id
206 }
207 }
208
209 impl Hash for RawContact {
210 fn hash<H: Hasher>(&self, state: &mut H) {
211 self.contact_id.hash(state);
212 }
213 }
214
215 #[derive(Clone, Copy, Debug, Eq, Ord, PartialOrd, PartialEq, Hash)]
217 pub struct ContactId(pub u32);
218
219 #[derive(Debug, PartialEq, Clone)]
221 pub enum Phase {
222 Down(IntPoint, IntSize),
224 Moved(IntPoint, IntSize),
226 Up,
228 Remove,
230 Cancel,
232 }
233
234 #[derive(Debug, Clone, PartialEq)]
236 pub struct Contact {
237 pub contact_id: ContactId,
239 pub phase: Phase,
241 }
242
243 #[derive(Debug, PartialEq, Clone)]
245 pub struct Event {
246 pub contacts: Vec<Contact>,
248 pub buttons: HashSet<fidl_input_report::TouchButton>,
251 }
252}
253
254pub mod pointer {
259 use super::*;
260
261 #[derive(Debug, PartialEq, Clone)]
263 pub enum Phase {
264 Down(IntPoint),
266 Moved(IntPoint),
268 Up,
270 Remove,
272 Cancel,
274 }
275
276 #[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, Hash)]
278 pub enum PointerId {
279 Mouse(DeviceId),
281 Contact(touch::ContactId),
283 }
284
285 #[derive(Debug, PartialEq, Clone)]
287 pub struct Event {
288 pub phase: Phase,
290 pub pointer_id: PointerId,
292 }
293
294 impl Event {
295 pub fn new_from_mouse_event(
297 device_id: &DeviceId,
298 mouse_event: &mouse::Event,
299 ) -> Option<Self> {
300 match &mouse_event.phase {
301 mouse::Phase::Down(button) => {
302 if button.is_primary() {
303 Some(pointer::Phase::Down(mouse_event.location))
304 } else {
305 None
306 }
307 }
308 mouse::Phase::Moved => {
309 if mouse_event.buttons.primary_button_is_down() {
310 Some(pointer::Phase::Moved(mouse_event.location))
311 } else {
312 None
313 }
314 }
315 mouse::Phase::Up(button) => {
316 if button.is_primary() {
317 Some(pointer::Phase::Up)
318 } else {
319 None
320 }
321 }
322 mouse::Phase::Wheel(_) => None,
323 }
324 .and_then(|phase| Some(Self { phase, pointer_id: PointerId::Mouse(device_id.clone()) }))
325 }
326
327 pub fn new_from_contact(contact: &touch::Contact) -> Self {
329 let phase = match contact.phase {
330 touch::Phase::Down(location, ..) => pointer::Phase::Down(location),
331 touch::Phase::Moved(location, ..) => pointer::Phase::Moved(location),
332 touch::Phase::Up => pointer::Phase::Up,
333 touch::Phase::Remove => pointer::Phase::Remove,
334 touch::Phase::Cancel => pointer::Phase::Cancel,
335 };
336 Self { phase, pointer_id: PointerId::Contact(contact.contact_id) }
337 }
338 }
339}
340
341pub mod consumer_control {
346 use super::*;
347
348 #[derive(Debug, PartialEq, Clone, Copy)]
350 pub enum Phase {
351 Down,
353 Up,
355 }
356
357 #[derive(Debug, PartialEq, Clone)]
359 pub struct Event {
360 pub phase: Phase,
362 pub button: fidl_input_report::ConsumerControlButton,
364 }
365}
366
367#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, PartialOrd, Ord)]
369pub struct DeviceId(pub String);
370
371#[derive(Debug, PartialEq, Clone)]
373pub enum EventType {
374 Mouse(mouse::Event),
376 Keyboard(keyboard::Event),
378 Touch(touch::Event),
380 ConsumerControl(consumer_control::Event),
382}
383
384#[derive(Debug, PartialEq, Clone)]
386pub struct Event {
387 pub event_time: u64,
389 pub device_id: DeviceId,
391 pub event_type: EventType,
393}
394
395async fn listen_to_instance(
396 instance: &fidl_input_report::ServiceProxy,
397 internal_sender: &InternalSender,
398) -> Result<(), Error> {
399 let device = instance.connect_to_input_device()?;
400 let descriptor = device
401 .get_descriptor()
402 .map_err(|err| format_err!("FIDL error on get_descriptor: {:?}", err))
403 .on_timeout(MonotonicInstant::after(MonotonicDuration::from_millis(200)), || {
404 Err(format_err!("FIDL timeout on get_descriptor"))
405 })
406 .await?;
407
408 let device_id = instance.instance_name().to_string();
409 internal_sender
410 .unbounded_send(MessageInternal::RegisterDevice(
411 DeviceId(device_id.clone()),
412 Box::new(descriptor),
413 ))
414 .expect("unbounded_send");
415 let input_report_sender = internal_sender.clone();
416 let (input_reports_reader_proxy, input_reports_reader_request) = create_proxy();
417 device.get_input_reports_reader(input_reports_reader_request)?;
418 fasync::Task::local(async move {
419 let _device = device;
420 loop {
421 let reports_res = input_reports_reader_proxy.read_input_reports().await;
422 match reports_res {
423 Ok(r) => match r {
424 Ok(reports) => {
425 for report in reports {
426 input_report_sender
427 .unbounded_send(MessageInternal::InputReport(
428 DeviceId(device_id.clone()),
429 report,
430 ))
431 .expect("unbounded_send");
432 }
433 }
434 Err(err) => {
435 eprintln!("Error report from read_input_reports: {}: {}", device_id, err);
436 break;
437 }
438 },
439 Err(err) => {
440 eprintln!("Error report from read_input_reports: {}: {}", device_id, err);
441 break;
442 }
443 }
444 }
445 })
446 .detach();
447 Ok(())
448}
449
450pub(crate) async fn listen_for_user_input(internal_sender: InternalSender) -> Result<(), Error> {
451 let watcher_sender = internal_sender.clone();
452
453 let service = Service::open(fidl_input_report::ServiceMarker)
454 .map_err(|err| format_err!("failed to open fuchsia.input.report.Service: {:?}", err))?;
455 let mut watcher = service
456 .watch()
457 .await
458 .map_err(|err| format_err!("failed to watch fuchsia.input.report.Service: {:?}", err))?;
459
460 fasync::Task::local(async move {
461 while let Some(instance) = watcher.next().await {
462 match instance {
463 Ok(instance) => {
464 match listen_to_instance(&instance, &watcher_sender).await {
465 Err(err) => {
466 eprintln!("Error: {}: {}", instance.instance_name(), err)
467 }
468 _ => (),
469 };
470 }
471 Err(err) => {
472 eprintln!("Error watching input report service: {}", err);
473 break;
474 }
475 }
476 }
477 })
478 .detach();
479
480 Ok(())
481}
482
483pub(crate) mod flatland;
484pub(crate) mod key3;
485pub(crate) mod report;
486
487#[cfg(test)]
488mod tests;