1use crate::input_device::{Handled, InputDeviceEvent, InputEvent, UnhandledInputEvent};
6use crate::input_handler::{InputHandlerStatus, UnhandledInputHandler};
7use async_trait::async_trait;
8use fidl_fuchsia_ui_input3::{KeyMeaning, Modifiers, NonPrintableKey};
9use fuchsia_inspect::health::Reporter;
10use keymaps::{LockStateKeys, ModifierState};
11use std::cell::RefCell;
12use std::rc::Rc;
13
14#[derive(Debug)]
24pub struct ModifierHandler {
25 modifier_state: RefCell<ModifierState>,
27
28 lock_state: RefCell<LockStateKeys>,
30
31 pub inspect_status: InputHandlerStatus,
33}
34
35#[async_trait(?Send)]
36impl UnhandledInputHandler for ModifierHandler {
37 async fn handle_unhandled_input_event(
38 self: Rc<Self>,
39 unhandled_input_event: UnhandledInputEvent,
40 ) -> Vec<InputEvent> {
41 match unhandled_input_event.clone() {
42 UnhandledInputEvent {
43 device_event: InputDeviceEvent::Keyboard(mut event),
44 device_descriptor,
45 event_time,
46 trace_id,
47 } => {
48 fuchsia_trace::duration!(c"input", c"modifier_handler");
49 if let Some(trace_id) = trace_id {
50 fuchsia_trace::flow_step!(
51 c"input",
52 c"event_in_input_pipeline",
53 trace_id.into()
54 );
55 }
56
57 self.inspect_status.count_received_event(InputEvent::from(unhandled_input_event));
58 self.modifier_state.borrow_mut().update(event.get_event_type(), event.get_key());
59 self.lock_state.borrow_mut().update(event.get_event_type(), event.get_key());
60 event = event
61 .into_with_lock_state(Some(self.lock_state.borrow().get_state()))
62 .into_with_modifiers(Some(self.modifier_state.borrow().get_state()));
63 log::debug!("modifiers and lock state applied: {:?}", &event);
64 vec![InputEvent {
65 device_event: InputDeviceEvent::Keyboard(event),
66 device_descriptor,
67 event_time,
68 handled: Handled::No,
69 trace_id,
70 }]
71 }
72 _ => vec![InputEvent::from(unhandled_input_event)],
74 }
75 }
76
77 fn set_handler_healthy(self: std::rc::Rc<Self>) {
78 self.inspect_status.health_node.borrow_mut().set_ok();
79 }
80
81 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
82 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
83 }
84}
85
86impl ModifierHandler {
87 pub fn new(input_handlers_node: &fuchsia_inspect::Node) -> Rc<Self> {
89 let inspect_status = InputHandlerStatus::new(
90 input_handlers_node,
91 "modifier_handler",
92 false,
93 );
94 Rc::new(Self {
95 modifier_state: RefCell::new(ModifierState::new()),
96 lock_state: RefCell::new(LockStateKeys::new()),
97 inspect_status,
98 })
99 }
100}
101
102#[derive(Debug)]
105pub struct ModifierMeaningHandler {
106 modifier_state: RefCell<ModifierState>,
108
109 pub inspect_status: InputHandlerStatus,
111}
112
113impl ModifierMeaningHandler {
114 pub fn new(input_handlers_node: &fuchsia_inspect::Node) -> Rc<Self> {
116 let inspect_status = InputHandlerStatus::new(
117 input_handlers_node,
118 "modifier_meaning_handler",
119 false,
120 );
121 Rc::new(Self { modifier_state: RefCell::new(ModifierState::new()), inspect_status })
122 }
123}
124
125#[async_trait(?Send)]
126impl UnhandledInputHandler for ModifierMeaningHandler {
127 async fn handle_unhandled_input_event(
128 self: Rc<Self>,
129 unhandled_input_event: UnhandledInputEvent,
130 ) -> Vec<InputEvent> {
131 match unhandled_input_event.clone() {
132 UnhandledInputEvent {
133 device_event: InputDeviceEvent::Keyboard(mut event),
134 device_descriptor,
135 event_time,
136 trace_id,
137 } if event.get_key_meaning()
138 == Some(KeyMeaning::NonPrintableKey(NonPrintableKey::AltGraph)) =>
139 {
140 self.inspect_status.count_received_event(InputEvent::from(unhandled_input_event));
141 if let Some(key_meaning) = event.get_key_meaning() {
144 self.modifier_state
145 .borrow_mut()
146 .update_with_key_meaning(event.get_event_type(), key_meaning);
147 let new_modifier = event.get_modifiers().unwrap_or(Modifiers::empty())
148 | self.modifier_state.borrow().get_state();
149 event = event.into_with_modifiers(Some(new_modifier));
150 log::debug!("additinal modifiers and lock state applied: {:?}", &event);
151 }
152 vec![InputEvent {
153 device_event: InputDeviceEvent::Keyboard(event),
154 device_descriptor,
155 event_time,
156 handled: Handled::No,
157 trace_id,
158 }]
159 }
160 _ => vec![InputEvent::from(unhandled_input_event)],
162 }
163 }
164
165 fn set_handler_healthy(self: std::rc::Rc<Self>) {
166 self.inspect_status.health_node.borrow_mut().set_ok();
167 }
168
169 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
170 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177 use crate::input_device::InputDeviceDescriptor;
178 use crate::input_handler::InputHandler;
179 use crate::keyboard_binding::{self, KeyboardEvent};
180 use crate::testing_utilities;
181 use fidl_fuchsia_input::Key;
182 use fidl_fuchsia_ui_input3::{KeyEventType, LockState};
183 use fuchsia_async as fasync;
184 use pretty_assertions::assert_eq;
185
186 fn get_unhandled_input_event(event: KeyboardEvent) -> UnhandledInputEvent {
187 UnhandledInputEvent {
188 device_event: InputDeviceEvent::Keyboard(event),
189 event_time: zx::MonotonicInstant::from_nanos(42),
190 device_descriptor: InputDeviceDescriptor::Fake,
191 trace_id: None,
192 }
193 }
194
195 #[fasync::run_singlethreaded(test)]
196 async fn test_decoration() {
197 let inspector = fuchsia_inspect::Inspector::default();
198 let test_node = inspector.root().create_child("test_node");
199 let handler = ModifierHandler::new(&test_node);
200 let input_event =
201 get_unhandled_input_event(KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed));
202 let result = handler.handle_unhandled_input_event(input_event.clone()).await;
203
204 let expected = InputEvent::from(get_unhandled_input_event(
207 KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed)
208 .into_with_modifiers(Some(Modifiers::CAPS_LOCK))
209 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
210 ));
211 assert_eq!(vec![expected], result);
212 }
213
214 #[fasync::run_singlethreaded(test)]
215 async fn test_key_meaning_decoration() {
216 let inspector = fuchsia_inspect::Inspector::default();
217 let test_node = inspector.root().create_child("test_node");
218 let handler = ModifierMeaningHandler::new(&test_node);
219 {
220 let input_event = get_unhandled_input_event(
221 KeyboardEvent::new(Key::RightAlt, KeyEventType::Pressed)
222 .into_with_key_meaning(Some(KeyMeaning::NonPrintableKey(
223 NonPrintableKey::AltGraph,
224 )))
225 .into_with_modifiers(Some(Modifiers::CAPS_LOCK)),
226 );
227 let result = handler.clone().handle_unhandled_input_event(input_event.clone()).await;
228 let expected = InputEvent::from(get_unhandled_input_event(
229 KeyboardEvent::new(Key::RightAlt, KeyEventType::Pressed)
230 .into_with_key_meaning(Some(KeyMeaning::NonPrintableKey(
231 NonPrintableKey::AltGraph,
232 )))
233 .into_with_modifiers(Some(Modifiers::ALT_GRAPH | Modifiers::CAPS_LOCK)),
234 ));
235 assert_eq!(vec![expected], result);
236 }
237 {
238 let input_event = get_unhandled_input_event(
239 KeyboardEvent::new(Key::RightAlt, KeyEventType::Released)
240 .into_with_key_meaning(Some(KeyMeaning::NonPrintableKey(
241 NonPrintableKey::AltGraph,
242 )))
243 .into_with_modifiers(Some(Modifiers::CAPS_LOCK)),
244 );
245 let handler = handler.clone();
246 let result = handler.handle_unhandled_input_event(input_event.clone()).await;
247 let expected = InputEvent::from(get_unhandled_input_event(
248 KeyboardEvent::new(Key::RightAlt, KeyEventType::Released)
249 .into_with_key_meaning(Some(KeyMeaning::NonPrintableKey(
250 NonPrintableKey::AltGraph,
251 )))
252 .into_with_modifiers(Some(Modifiers::CAPS_LOCK)),
253 ));
254 assert_eq!(vec![expected], result);
255 }
256 }
257
258 #[fasync::run_singlethreaded(test)]
264 async fn test_modifier_press_lock_release() {
265 let input_events = vec![
266 get_unhandled_input_event(KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed)),
267 get_unhandled_input_event(KeyboardEvent::new(Key::CapsLock, KeyEventType::Released)),
268 get_unhandled_input_event(KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed)),
269 get_unhandled_input_event(KeyboardEvent::new(Key::CapsLock, KeyEventType::Released)),
270 ];
271
272 let inspector = fuchsia_inspect::Inspector::default();
273 let test_node = inspector.root().create_child("test_node");
274 let handler = ModifierHandler::new(&test_node);
275 let clone_handler = move || handler.clone();
276 let result = futures::future::join_all(
277 input_events
278 .into_iter()
279 .map(|e| async { clone_handler().handle_unhandled_input_event(e).await }),
280 )
281 .await
282 .into_iter()
283 .flatten()
284 .collect::<Vec<InputEvent>>();
285
286 let expected = IntoIterator::into_iter([
287 get_unhandled_input_event(
288 KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed)
289 .into_with_modifiers(Some(Modifiers::CAPS_LOCK))
290 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
291 ),
292 get_unhandled_input_event(
293 KeyboardEvent::new(Key::CapsLock, KeyEventType::Released)
294 .into_with_modifiers(Some(Modifiers::from_bits_allow_unknown(0)))
295 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
296 ),
297 get_unhandled_input_event(
298 KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed)
299 .into_with_modifiers(Some(Modifiers::CAPS_LOCK))
300 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
301 ),
302 get_unhandled_input_event(
303 KeyboardEvent::new(Key::CapsLock, KeyEventType::Released)
304 .into_with_modifiers(Some(Modifiers::from_bits_allow_unknown(0)))
305 .into_with_lock_state(Some(LockState::from_bits_allow_unknown(0))),
306 ),
307 ])
308 .map(InputEvent::from)
309 .collect::<Vec<_>>();
310
311 assert_eq!(expected, result);
312 }
313
314 #[fasync::run_singlethreaded(test)]
321 async fn repeated_modifier_key() {
322 let input_events = vec![
323 get_unhandled_input_event(KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed)),
324 get_unhandled_input_event(KeyboardEvent::new(Key::CapsLock, KeyEventType::Released)),
325 get_unhandled_input_event(KeyboardEvent::new(Key::A, KeyEventType::Pressed)),
326 get_unhandled_input_event(KeyboardEvent::new(Key::A, KeyEventType::Released)),
327 ];
328
329 let inspector = fuchsia_inspect::Inspector::default();
330 let test_node = inspector.root().create_child("test_node");
331 let handler = ModifierHandler::new(&test_node);
332 let clone_handler = move || handler.clone();
333 let result = futures::future::join_all(
334 input_events
335 .into_iter()
336 .map(|e| async { clone_handler().handle_unhandled_input_event(e).await }),
337 )
338 .await
339 .into_iter()
340 .flatten()
341 .collect::<Vec<InputEvent>>();
342
343 let expected = IntoIterator::into_iter([
344 get_unhandled_input_event(
345 KeyboardEvent::new(Key::CapsLock, KeyEventType::Pressed)
346 .into_with_modifiers(Some(Modifiers::CAPS_LOCK))
347 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
348 ),
349 get_unhandled_input_event(
350 KeyboardEvent::new(Key::CapsLock, KeyEventType::Released)
351 .into_with_modifiers(Some(Modifiers::from_bits_allow_unknown(0)))
352 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
353 ),
354 get_unhandled_input_event(
355 KeyboardEvent::new(Key::A, KeyEventType::Pressed)
356 .into_with_modifiers(Some(Modifiers::from_bits_allow_unknown(0)))
357 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
358 ),
359 get_unhandled_input_event(
360 KeyboardEvent::new(Key::A, KeyEventType::Released)
361 .into_with_modifiers(Some(Modifiers::from_bits_allow_unknown(0)))
362 .into_with_lock_state(Some(LockState::CAPS_LOCK)),
363 ),
364 ])
365 .map(InputEvent::from)
366 .collect::<Vec<_>>();
367 assert_eq!(expected, result);
368 }
369
370 #[fuchsia::test]
371 fn modifier_handlers_initialized_with_inspect_node() {
372 let inspector = fuchsia_inspect::Inspector::default();
373 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
374 let _modifier_handler = ModifierHandler::new(&fake_handlers_node);
375 let _modifier_meaning_handler = ModifierMeaningHandler::new(&fake_handlers_node);
376 diagnostics_assertions::assert_data_tree!(inspector, root: {
377 input_handlers_node: {
378 modifier_handler: {
379 events_received_count: 0u64,
380 events_handled_count: 0u64,
381 last_received_timestamp_ns: 0u64,
382 "fuchsia.inspect.Health": {
383 status: "STARTING_UP",
384 start_timestamp_nanos: diagnostics_assertions::AnyProperty
387 },
388 },
389 modifier_meaning_handler: {
390 events_received_count: 0u64,
391 events_handled_count: 0u64,
392 last_received_timestamp_ns: 0u64,
393 "fuchsia.inspect.Health": {
394 status: "STARTING_UP",
395 start_timestamp_nanos: diagnostics_assertions::AnyProperty
398 },
399 }
400 }
401 });
402 }
403
404 #[fasync::run_singlethreaded(test)]
405 async fn modifier_handler_inspect_counts_events() {
406 let inspector = fuchsia_inspect::Inspector::default();
407 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
408 let modifier_handler = ModifierHandler::new(&fake_handlers_node);
409 let modifier_meaning_handler = ModifierMeaningHandler::new(&fake_handlers_node);
410 let device_descriptor =
411 InputDeviceDescriptor::Keyboard(keyboard_binding::KeyboardDeviceDescriptor {
412 keys: vec![Key::A, Key::B, Key::RightAlt],
413 ..Default::default()
414 });
415 let (_, event_time_u64) = testing_utilities::event_times();
416 let input_events = vec![
417 testing_utilities::create_keyboard_event_with_time(
418 Key::A,
419 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
420 None,
421 event_time_u64,
422 &device_descriptor,
423 None,
424 ),
425 testing_utilities::create_keyboard_event_with_handled(
427 Key::B,
428 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
429 None,
430 event_time_u64,
431 &device_descriptor,
432 None,
433 None,
434 Handled::Yes,
435 ),
436 testing_utilities::create_keyboard_event_with_time(
437 Key::A,
438 fidl_fuchsia_ui_input3::KeyEventType::Released,
439 None,
440 event_time_u64,
441 &device_descriptor,
442 None,
443 ),
444 testing_utilities::create_fake_input_event(event_time_u64),
446 testing_utilities::create_keyboard_event_with_key_meaning(
448 Key::RightAlt,
449 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
450 None,
451 event_time_u64,
452 &device_descriptor,
453 None,
454 Some(KeyMeaning::NonPrintableKey(NonPrintableKey::AltGraph)),
456 ),
457 ];
458
459 for input_event in input_events {
460 let _ = modifier_handler.clone().handle_input_event(input_event.clone()).await;
461 let _ = modifier_meaning_handler.clone().handle_input_event(input_event).await;
462 }
463
464 let last_event_timestamp: u64 = event_time_u64.into_nanos().try_into().unwrap();
465
466 diagnostics_assertions::assert_data_tree!(inspector, root: {
467 input_handlers_node: {
468 modifier_handler: {
469 events_received_count: 3u64,
470 events_handled_count: 0u64,
471 last_received_timestamp_ns: last_event_timestamp,
472 "fuchsia.inspect.Health": {
473 status: "STARTING_UP",
474 start_timestamp_nanos: diagnostics_assertions::AnyProperty
477 },
478 },
479 modifier_meaning_handler: {
480 events_received_count: 1u64,
481 events_handled_count: 0u64,
482 last_received_timestamp_ns: last_event_timestamp,
483 "fuchsia.inspect.Health": {
484 status: "STARTING_UP",
485 start_timestamp_nanos: diagnostics_assertions::AnyProperty
488 },
489 }
490 }
491 });
492 }
493}