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