starnix_modules_input_event_conversion/
mouse_fuchsia_to_linux.rs1use fidl_fuchsia_ui_pointer::{MouseEvent as FidlMouseEvent, MousePointerSample};
6use starnix_types::time::timeval_from_time;
7use starnix_uapi::uapi;
8use std::collections::VecDeque;
9
10pub struct LinuxMouseEventBatch {
11 pub events: VecDeque<uapi::input_event>,
12 pub count_ignored_events: u64,
13 pub count_converted_events: u64,
14 pub count_unexpected_events: u64,
15 pub last_event_time_ns: i64,
16}
17
18pub fn parse_fidl_mouse_events(mouse_events: Vec<FidlMouseEvent>) -> LinuxMouseEventBatch {
19 let mut count_ignored_events: u64 = 0;
20 let mut count_converted_events: u64 = 0;
21 let mut count_unexpected_events: u64 = 0;
22 let mut new_events: VecDeque<uapi::input_event> = VecDeque::new();
23 let mut last_event_time_ns = zx::MonotonicInstant::get();
24
25 let mut total_ticks: i32 = 0;
26
27 for event in mouse_events {
28 match event {
29 FidlMouseEvent {
30 timestamp: Some(time),
31 pointer_sample: Some(MousePointerSample { scroll_v: Some(ticks), .. }),
32 ..
33 } => {
34 last_event_time_ns = zx::MonotonicInstant::from_nanos(time);
35 if ticks != 0 {
36 total_ticks += ticks as i32;
37 count_converted_events += 1;
38 } else {
39 count_ignored_events += 1;
40 }
41 }
42 _ => {
43 count_unexpected_events += 1;
44 }
45 }
46 }
47
48 if total_ticks != 0 {
49 new_events.push_back(uapi::input_event {
50 time: timeval_from_time(last_event_time_ns),
51 type_: uapi::EV_REL as u16,
52 code: uapi::REL_WHEEL as u16,
53 value: total_ticks,
54 });
55 }
56
57 if !new_events.is_empty() {
58 new_events.push_back(uapi::input_event {
59 time: timeval_from_time(last_event_time_ns),
60 type_: uapi::EV_SYN as u16,
61 code: uapi::SYN_REPORT as u16,
62 value: 0,
63 });
64 }
65
66 LinuxMouseEventBatch {
67 events: new_events,
68 count_ignored_events,
69 count_converted_events,
70 count_unexpected_events,
71 last_event_time_ns: last_event_time_ns.into_nanos(),
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use pretty_assertions::assert_eq;
79
80 #[test]
81 fn test_mouse_wheel_event() {
82 let fidl_event = FidlMouseEvent {
83 timestamp: Some(1000),
84 pointer_sample: Some(MousePointerSample { scroll_v: Some(1), ..Default::default() }),
85 ..Default::default()
86 };
87 let batch = parse_fidl_mouse_events(vec![fidl_event]);
88
89 assert_eq!(batch.events.len(), 2);
90 assert_eq!(batch.events[0].type_, uapi::EV_REL as u16);
91 assert_eq!(batch.events[0].code, uapi::REL_WHEEL as u16);
92 assert_eq!(batch.events[0].value, 1);
93 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
94 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
95 assert_eq!(batch.count_converted_events, 1);
96 assert_eq!(batch.count_ignored_events, 0);
97 assert_eq!(batch.count_unexpected_events, 0);
98 assert_eq!(batch.last_event_time_ns, 1000);
99 }
100
101 #[test]
102 fn test_mouse_wheel_merge() {
103 let fidl_event1 = FidlMouseEvent {
104 timestamp: Some(1000),
105 pointer_sample: Some(MousePointerSample { scroll_v: Some(1), ..Default::default() }),
106 ..Default::default()
107 };
108 let fidl_event2 = FidlMouseEvent {
109 timestamp: Some(2000),
110 pointer_sample: Some(MousePointerSample { scroll_v: Some(2), ..Default::default() }),
111 ..Default::default()
112 };
113 let batch = parse_fidl_mouse_events(vec![fidl_event1, fidl_event2]);
114
115 assert_eq!(batch.events.len(), 2);
116 assert_eq!(batch.events[0].type_, uapi::EV_REL as u16);
117 assert_eq!(batch.events[0].code, uapi::REL_WHEEL as u16);
118 assert_eq!(batch.events[0].value, 3);
119 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
120 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
121 assert_eq!(batch.count_converted_events, 2);
122 assert_eq!(batch.count_ignored_events, 0);
123 assert_eq!(batch.count_unexpected_events, 0);
124 assert_eq!(batch.last_event_time_ns, 2000);
125 }
126
127 #[test]
128 fn test_mouse_wheel_merge_to_zero() {
129 let fidl_event1 = FidlMouseEvent {
130 timestamp: Some(1000),
131 pointer_sample: Some(MousePointerSample { scroll_v: Some(1), ..Default::default() }),
132 ..Default::default()
133 };
134 let fidl_event2 = FidlMouseEvent {
135 timestamp: Some(2000),
136 pointer_sample: Some(MousePointerSample { scroll_v: Some(-1), ..Default::default() }),
137 ..Default::default()
138 };
139 let batch = parse_fidl_mouse_events(vec![fidl_event1, fidl_event2]);
140
141 assert_eq!(batch.events.len(), 0);
142 assert_eq!(batch.count_converted_events, 2);
143 assert_eq!(batch.count_ignored_events, 0);
144 assert_eq!(batch.count_unexpected_events, 0);
145 assert_eq!(batch.last_event_time_ns, 2000);
146 }
147
148 #[test]
149 fn test_mouse_wheel_zero_ticks() {
150 let fidl_event = FidlMouseEvent {
151 timestamp: Some(1000),
152 pointer_sample: Some(MousePointerSample { scroll_v: Some(0), ..Default::default() }),
153 ..Default::default()
154 };
155 let batch = parse_fidl_mouse_events(vec![fidl_event]);
156
157 assert_eq!(batch.events.len(), 0);
158 assert_eq!(batch.count_converted_events, 0);
159 assert_eq!(batch.count_ignored_events, 1);
160 assert_eq!(batch.count_unexpected_events, 0);
161 }
162
163 #[test]
164 fn test_mouse_unexpected_event() {
165 let fidl_event = FidlMouseEvent { timestamp: Some(1000), ..Default::default() };
166 let batch = parse_fidl_mouse_events(vec![fidl_event]);
167
168 assert_eq!(batch.events.len(), 0);
169 assert_eq!(batch.count_converted_events, 0);
170 assert_eq!(batch.count_ignored_events, 0);
171 assert_eq!(batch.count_unexpected_events, 1);
172 }
173}