1use crate::input_device::{self, Handled, InputDeviceBinding, InputDeviceStatus, InputEvent};
6use crate::{Transport, metrics, utils};
7use anyhow::{Error, Result, format_err};
8use async_trait::async_trait;
9use fidl_fuchsia_ui_input3 as fidl_ui_input3;
10use fidl_fuchsia_ui_input3::{KeyEventType, Modifiers};
11use fuchsia_inspect::health::Reporter;
12use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
13use metrics_registry::*;
14
15#[derive(Clone, Debug, PartialEq)]
31pub struct KeyboardEvent {
32 key: fidl_fuchsia_input::Key,
34
35 event_type: KeyEventType,
37
38 modifiers: Option<fidl_ui_input3::Modifiers>,
40
41 lock_state: Option<fidl_ui_input3::LockState>,
43
44 keymap: Option<String>,
47
48 key_meaning: Option<fidl_fuchsia_ui_input3::KeyMeaning>,
53
54 repeat_sequence: u32,
60}
61
62impl KeyboardEvent {
63 pub fn new(key: fidl_fuchsia_input::Key, event_type: KeyEventType) -> Self {
66 KeyboardEvent {
67 key,
68 event_type,
69 modifiers: None,
70 lock_state: None,
71 keymap: None,
72 key_meaning: None,
73 repeat_sequence: 0,
74 }
75 }
76
77 pub fn get_key(&self) -> fidl_fuchsia_input::Key {
78 self.key
79 }
80
81 pub fn into_with_key(self, key: fidl_fuchsia_input::Key) -> Self {
83 Self { key, ..self }
84 }
85
86 pub fn get_event_type(&self) -> KeyEventType {
87 self.event_type
88 }
89
90 pub fn into_with_event_type(self, event_type: KeyEventType) -> Self {
92 Self { event_type, ..self }
93 }
94
95 pub fn into_with_folded_event(self) -> Self {
97 Self { event_type: self.get_event_type_folded(), ..self }
98 }
99
100 pub fn get_event_type_folded(&self) -> KeyEventType {
102 match self.event_type {
103 KeyEventType::Pressed | KeyEventType::Sync => KeyEventType::Pressed,
104 KeyEventType::Released | KeyEventType::Cancel => KeyEventType::Released,
105 }
106 }
107
108 pub fn into_with_modifiers(self, modifiers: Option<fidl_ui_input3::Modifiers>) -> Self {
110 Self { modifiers, ..self }
111 }
112
113 pub fn get_modifiers(&self) -> Option<fidl_ui_input3::Modifiers> {
115 self.modifiers
116 }
117
118 pub fn get_unsided_modifiers(&self) -> Modifiers {
122 let mut modifiers = self.modifiers.unwrap_or(Modifiers::empty());
123 modifiers.set(
124 Modifiers::LEFT_ALT
125 | Modifiers::LEFT_CTRL
126 | Modifiers::LEFT_SHIFT
127 | Modifiers::LEFT_META
128 | Modifiers::RIGHT_ALT
129 | Modifiers::RIGHT_CTRL
130 | Modifiers::RIGHT_SHIFT
131 | Modifiers::RIGHT_META,
132 false,
133 );
134 modifiers
135 }
136
137 pub fn into_with_lock_state(self, lock_state: Option<fidl_ui_input3::LockState>) -> Self {
139 Self { lock_state, ..self }
140 }
141
142 pub fn get_lock_state(&self) -> Option<fidl_ui_input3::LockState> {
144 self.lock_state
145 }
146
147 pub fn into_with_keymap(self, keymap: Option<String>) -> Self {
150 Self { keymap, ..self }
151 }
152
153 pub fn get_keymap(&self) -> Option<String> {
155 self.keymap.clone()
156 }
157
158 pub fn into_with_key_meaning(
160 self,
161 key_meaning: Option<fidl_fuchsia_ui_input3::KeyMeaning>,
162 ) -> Self {
163 Self { key_meaning, ..self }
164 }
165
166 pub fn get_key_meaning(&self) -> Option<fidl_fuchsia_ui_input3::KeyMeaning> {
168 self.key_meaning
169 }
170
171 pub fn get_repeat_sequence(&self) -> u32 {
175 self.repeat_sequence
176 }
177
178 pub fn into_with_repeat_sequence(self, repeat_sequence: u32) -> Self {
181 Self { repeat_sequence, ..self }
182 }
183
184 #[cfg(test)]
186 pub(crate) fn from_key_event_at_time(
187 &self,
188 event_time: zx::MonotonicInstant,
189 ) -> fidl_ui_input3::KeyEvent {
190 fidl_ui_input3::KeyEvent {
191 timestamp: Some(event_time.into_nanos()),
192 type_: Some(self.event_type),
193 key: Some(self.key),
194 modifiers: self.modifiers,
195 lock_state: self.lock_state,
196 repeat_sequence: Some(self.repeat_sequence),
197 key_meaning: self.key_meaning,
198 ..Default::default()
199 }
200 }
201}
202
203impl KeyboardEvent {
204 pub fn same_key(this: &KeyboardEvent, that: &KeyboardEvent) -> bool {
206 this.get_key() == that.get_key()
207 }
208}
209
210#[derive(Clone, Debug, PartialEq)]
212pub struct KeyboardDeviceDescriptor {
213 pub keys: Vec<fidl_fuchsia_input::Key>,
215
216 pub device_information: fidl_fuchsia_input_report::DeviceInformation,
218
219 pub device_id: u32,
221}
222
223#[cfg(test)]
224impl Default for KeyboardDeviceDescriptor {
225 fn default() -> Self {
226 KeyboardDeviceDescriptor {
227 keys: vec![],
228 device_information: fidl_fuchsia_input_report::DeviceInformation {
229 vendor_id: Some(0),
230 product_id: Some(0),
231 version: Some(0),
232 polling_rate: Some(0),
233 ..Default::default()
234 },
235 device_id: 0,
236 }
237 }
238}
239
240pub struct KeyboardBinding {
246 event_sender: UnboundedSender<Vec<InputEvent>>,
248
249 device_descriptor: KeyboardDeviceDescriptor,
251}
252
253#[async_trait]
254impl input_device::InputDeviceBinding for KeyboardBinding {
255 fn input_event_sender(&self) -> UnboundedSender<Vec<InputEvent>> {
256 self.event_sender.clone()
257 }
258
259 fn get_device_descriptor(&self) -> input_device::InputDeviceDescriptor {
260 input_device::InputDeviceDescriptor::Keyboard(self.device_descriptor.clone())
261 }
262}
263
264impl KeyboardBinding {
265 pub async fn new(
280 device_proxy: fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
281 device_id: u32,
282 input_event_sender: UnboundedSender<Vec<InputEvent>>,
283 device_node: fuchsia_inspect::Node,
284 feature_flags: input_device::InputPipelineFeatureFlags,
285 metrics_logger: metrics::MetricsLogger,
286 ) -> Result<Self, Error> {
287 let (device_binding, mut inspect_status) = Self::bind_device(
288 &device_proxy,
289 input_event_sender,
290 device_id,
291 device_node,
292 metrics_logger.clone(),
293 )
294 .await?;
295 inspect_status.health_node.set_ok();
296 input_device::initialize_report_stream(
297 device_proxy,
298 device_binding.get_device_descriptor(),
299 device_binding.input_event_sender(),
300 inspect_status,
301 metrics_logger.clone(),
302 feature_flags,
303 Self::process_reports,
304 );
305
306 Ok(device_binding)
307 }
308
309 pub fn to_modifiers(keys: &[&fidl_fuchsia_input::Key]) -> Option<fidl_ui_input3::Modifiers> {
320 let mut modifiers = fidl_ui_input3::Modifiers::empty();
321 for key in keys {
322 let modifier = match key {
323 fidl_fuchsia_input::Key::CapsLock => Some(fidl_ui_input3::Modifiers::CAPS_LOCK),
324 fidl_fuchsia_input::Key::NumLock => Some(fidl_ui_input3::Modifiers::NUM_LOCK),
325 fidl_fuchsia_input::Key::ScrollLock => Some(fidl_ui_input3::Modifiers::SCROLL_LOCK),
326 _ => None,
327 };
328 if let Some(modifier) = modifier {
329 modifiers.insert(modifier);
330 };
331 }
332 if modifiers.is_empty() {
333 return None;
334 }
335 Some(modifiers)
336 }
337
338 async fn bind_device(
350 device: &fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
351 input_event_sender: UnboundedSender<Vec<InputEvent>>,
352 device_id: u32,
353 device_node: fuchsia_inspect::Node,
354 metrics_logger: metrics::MetricsLogger,
355 ) -> Result<(Self, InputDeviceStatus), Error> {
356 let mut input_device_status = InputDeviceStatus::new(device_node);
357 let descriptor = match device.get_descriptor().await {
358 Ok(descriptor) => descriptor.descriptor,
359 Err(_) => {
360 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
361 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
362 }
363 };
364
365 let device_info = descriptor.device_information.ok_or_else(|| {
366 input_device_status.health_node.set_unhealthy("Empty device_information in descriptor");
367 metrics_logger.log_error(
370 InputPipelineErrorMetricDimensionEvent::KeyboardEmptyDeviceInfo,
371 std::format!("DRIVER BUG: empty device_information for device_id: {}", device_id),
372 );
373 format_err!("empty device info for device_id: {}", device_id)
374 })?;
375 match descriptor.keyboard {
376 Some(fidl_next_fuchsia_input_report::KeyboardDescriptor {
377 input: Some(fidl_next_fuchsia_input_report::KeyboardInputDescriptor { keys3, .. }),
378 output: _,
379 ..
380 }) => Ok((
381 KeyboardBinding {
382 event_sender: input_event_sender,
383 device_descriptor: KeyboardDeviceDescriptor {
384 keys: keys3
385 .unwrap_or_default()
386 .into_iter()
387 .map(|k| utils::key_to_old(&k))
388 .collect(),
389 device_information: fidl_fuchsia_input_report::DeviceInformation {
390 vendor_id: device_info.vendor_id,
391 product_id: device_info.product_id,
392 version: device_info.version,
393 polling_rate: device_info.polling_rate,
394 ..Default::default()
395 },
396 device_id,
397 },
398 },
399 input_device_status,
400 )),
401 device_descriptor => {
402 input_device_status
403 .health_node
404 .set_unhealthy("Keyboard Device Descriptor failed to parse.");
405 Err(format_err!(
406 "Keyboard Device Descriptor failed to parse: \n {:?}",
407 device_descriptor
408 ))
409 }
410 }
411 }
412
413 fn process_reports(
435 reports: &[fidl_next_fuchsia_input_report::wire::InputReport<'_>],
436 mut previous_state: Option<input_device::PreviousDeviceState>,
437 device_descriptor: &input_device::InputDeviceDescriptor,
438 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
439 inspect_status: &InputDeviceStatus,
440 metrics_logger: &metrics::MetricsLogger,
441 _feature_flags: &input_device::InputPipelineFeatureFlags,
442 ) -> (Option<input_device::PreviousDeviceState>, Option<UnboundedReceiver<InputEvent>>) {
443 fuchsia_trace::duration!("input", "keyboard-binding-process-report", "num_reports" => reports.len());
444 let (inspect_sender, inspect_receiver) = futures::channel::mpsc::unbounded();
445
446 for report in reports {
447 previous_state = Self::process_report(
448 report,
449 previous_state,
450 device_descriptor,
451 input_event_sender,
452 inspect_status,
453 metrics_logger,
454 inspect_sender.clone(),
455 );
456 }
457 (previous_state, Some(inspect_receiver))
458 }
459
460 fn process_report(
461 report: &fidl_next_fuchsia_input_report::wire::InputReport<'_>,
462 previous_state: Option<input_device::PreviousDeviceState>,
463 device_descriptor: &input_device::InputDeviceDescriptor,
464 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
465 inspect_status: &InputDeviceStatus,
466 metrics_logger: &metrics::MetricsLogger,
467 inspect_sender: UnboundedSender<InputEvent>,
468 ) -> Option<input_device::PreviousDeviceState> {
469 if let Some(trace_id) = report.trace_id() {
470 fuchsia_trace::flow_end!("input", "input_report", trace_id.0.into());
471 }
472
473 let tracing_id = fuchsia_trace::Id::new();
474 fuchsia_trace::flow_begin!("input", "key_event_thread", tracing_id);
475
476 inspect_status.count_received_report_wire(report);
477 match report.keyboard() {
479 None => {
480 inspect_status.count_filtered_report();
481 return previous_state;
482 }
483 _ => (),
484 };
485
486 let new_keys = match KeyboardBinding::parse_pressed_keys_wire(report) {
487 Some(keys) => keys,
488 None => {
489 metrics_logger.log_error(
495 InputPipelineErrorMetricDimensionEvent::KeyboardFailedToParse,
496 std::format!("Failed to parse keyboard keys: {:?}", report),
497 );
498 inspect_status.count_filtered_report();
499 return previous_state;
500 }
501 };
502
503 let previous_keys: Vec<fidl_fuchsia_input::Key> = match previous_state {
504 Some(input_device::PreviousDeviceState::Keyboard { pressed_keys }) => pressed_keys,
505 _ => vec![],
506 };
507
508 KeyboardBinding::send_key_events(
509 &new_keys,
510 &previous_keys,
511 device_descriptor.clone(),
512 zx::MonotonicInstant::get(),
513 input_event_sender.clone(),
514 inspect_sender,
515 metrics_logger,
516 tracing_id,
517 );
518
519 Some(input_device::PreviousDeviceState::Keyboard { pressed_keys: new_keys })
520 }
521
522 fn parse_pressed_keys_wire(
523 input_report: &fidl_next_fuchsia_input_report::wire::InputReport<'_>,
524 ) -> Option<Vec<fidl_fuchsia_input::Key>> {
525 input_report
526 .keyboard()
527 .and_then(|unwrapped_keyboard| unwrapped_keyboard.pressed_keys3())
528 .map(|unwrapped_keys| {
529 unwrapped_keys
530 .iter()
531 .map(|&k| {
532 let natural_key = fidl_next::FromWire::from_wire(k);
533 utils::key_to_old(&natural_key)
534 })
535 .collect()
536 })
537 }
538
539 fn send_key_events(
548 new_keys: &Vec<fidl_fuchsia_input::Key>,
549 previous_keys: &Vec<fidl_fuchsia_input::Key>,
550 device_descriptor: input_device::InputDeviceDescriptor,
551 event_time: zx::MonotonicInstant,
552 input_event_sender: UnboundedSender<Vec<InputEvent>>,
553 inspect_sender: UnboundedSender<input_device::InputEvent>,
554 metrics_logger: &metrics::MetricsLogger,
555 tracing_id: fuchsia_trace::Id,
556 ) {
557 fn dispatch_events(
560 key_events: Vec<(fidl_fuchsia_input::Key, fidl_fuchsia_ui_input3::KeyEventType)>,
561 device_descriptor: input_device::InputDeviceDescriptor,
562 event_time: zx::MonotonicInstant,
563 input_event_sender: UnboundedSender<Vec<input_device::InputEvent>>,
564 inspect_sender: UnboundedSender<input_device::InputEvent>,
565 metrics_logger: metrics::MetricsLogger,
566 tracing_id: fuchsia_trace::Id,
567 ) {
568 fuchsia_trace::duration!("input", "key_event_thread");
569 fuchsia_trace::flow_end!("input", "key_event_thread", tracing_id);
570
571 let mut event_time = event_time;
572 for (key, event_type) in key_events.into_iter() {
573 let trace_id = fuchsia_trace::Id::new();
574 fuchsia_trace::duration!("input", "keyboard_event_in_binding");
575 fuchsia_trace::flow_begin!("input", "event_in_input_pipeline", trace_id);
576
577 let event = input_device::InputEvent {
578 device_event: input_device::InputDeviceEvent::Keyboard(KeyboardEvent::new(
579 key, event_type,
580 )),
581 device_descriptor: device_descriptor.clone(),
582 event_time,
583 handled: Handled::No,
584 trace_id: Some(trace_id),
585 };
586 match input_event_sender.unbounded_send(vec![event.clone()]) {
587 Err(error) => {
588 metrics_logger.log_error(
589 InputPipelineErrorMetricDimensionEvent::KeyboardFailedToSendKeyboardEvent,
590 std::format!(
591 "Failed to send KeyboardEvent for key: {:?}, event_type: {:?}: {:?}",
592 key,
593 event_type,
594 error));
595 }
596 _ => {
597 let _ = inspect_sender.unbounded_send(event).expect("Failed to count generated KeyboardEvent in Input Pipeline Inspect tree.");
598 }
599 }
600 event_time = event_time + zx::MonotonicDuration::from_nanos(1);
605 }
606 }
607
608 let pressed_keys = new_keys
611 .iter()
612 .cloned()
613 .filter(|key| !previous_keys.contains(key))
614 .map(|k| (k, fidl_fuchsia_ui_input3::KeyEventType::Pressed));
615
616 let released_keys = previous_keys
619 .iter()
620 .cloned()
621 .filter(|key| !new_keys.contains(key))
622 .map(|k| (k, fidl_fuchsia_ui_input3::KeyEventType::Released));
623
624 let all_keys = released_keys.chain(pressed_keys).collect::<Vec<_>>();
628
629 dispatch_events(
630 all_keys,
631 device_descriptor,
632 event_time,
633 input_event_sender,
634 inspect_sender,
635 metrics_logger.clone(),
636 tracing_id,
637 );
638 }
639}
640
641#[cfg(test)]
642mod tests {
643 use super::*;
644 use crate::testing_utilities;
645 use fuchsia_async as fasync;
646 use futures::StreamExt;
647
648 #[fasync::run_singlethreaded(test)]
651 async fn pressed_key() {
652 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
653 keys: vec![fidl_fuchsia_input::Key::A],
654 ..Default::default()
655 });
656 let (event_time_i64, _) = testing_utilities::event_times();
657
658 let reports = vec![testing_utilities::create_keyboard_input_report(
659 vec![fidl_fuchsia_input::Key::A],
660 event_time_i64,
661 )];
662 let expected_events = vec![testing_utilities::create_keyboard_event(
663 fidl_fuchsia_input::Key::A,
664 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
665 None,
666 &descriptor,
667 None,
668 )];
669
670 assert_input_report_sequence_generates_events!(
671 input_reports: reports,
672 expected_events: expected_events,
673 device_descriptor: descriptor,
674 device_type: KeyboardBinding,
675 );
676 }
677
678 #[fasync::run_singlethreaded(test)]
681 async fn released_key() {
682 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
683 keys: vec![fidl_fuchsia_input::Key::A],
684 ..Default::default()
685 });
686 let (event_time_i64, _) = testing_utilities::event_times();
687
688 let reports = vec![
689 testing_utilities::create_keyboard_input_report(
690 vec![fidl_fuchsia_input::Key::A],
691 event_time_i64,
692 ),
693 testing_utilities::create_keyboard_input_report(vec![], event_time_i64),
694 ];
695
696 let expected_events = vec![
697 testing_utilities::create_keyboard_event(
698 fidl_fuchsia_input::Key::A,
699 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
700 None,
701 &descriptor,
702 None,
703 ),
704 testing_utilities::create_keyboard_event(
705 fidl_fuchsia_input::Key::A,
706 fidl_fuchsia_ui_input3::KeyEventType::Released,
707 None,
708 &descriptor,
709 None,
710 ),
711 ];
712
713 assert_input_report_sequence_generates_events!(
714 input_reports: reports,
715 expected_events: expected_events,
716 device_descriptor: descriptor.clone(),
717 device_type: KeyboardBinding,
718 );
719 }
720
721 #[fasync::run_singlethreaded(test)]
724 async fn multiple_pressed_event_filtering() {
725 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
726 keys: vec![fidl_fuchsia_input::Key::A],
727 ..Default::default()
728 });
729 let (event_time_i64, _) = testing_utilities::event_times();
730
731 let reports = vec![
732 testing_utilities::create_keyboard_input_report(
733 vec![fidl_fuchsia_input::Key::A],
734 event_time_i64,
735 ),
736 testing_utilities::create_keyboard_input_report(
737 vec![fidl_fuchsia_input::Key::A],
738 event_time_i64,
739 ),
740 ];
741
742 let expected_events = vec![testing_utilities::create_keyboard_event(
743 fidl_fuchsia_input::Key::A,
744 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
745 None,
746 &descriptor,
747 None,
748 )];
749
750 assert_input_report_sequence_generates_events!(
751 input_reports: reports,
752 expected_events: expected_events,
753 device_descriptor: descriptor,
754 device_type: KeyboardBinding,
755 );
756 }
757
758 #[fasync::run_singlethreaded(test)]
760 async fn pressed_and_released_keys() {
761 let descriptor = input_device::InputDeviceDescriptor::Keyboard(KeyboardDeviceDescriptor {
762 keys: vec![fidl_fuchsia_input::Key::A, fidl_fuchsia_input::Key::B],
763 ..Default::default()
764 });
765 let (event_time_i64, _) = testing_utilities::event_times();
766
767 let reports = vec![
768 testing_utilities::create_keyboard_input_report(
769 vec![fidl_fuchsia_input::Key::A],
770 event_time_i64,
771 ),
772 testing_utilities::create_keyboard_input_report(
773 vec![fidl_fuchsia_input::Key::B],
774 event_time_i64,
775 ),
776 ];
777
778 let expected_events = vec![
779 testing_utilities::create_keyboard_event(
780 fidl_fuchsia_input::Key::A,
781 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
782 None,
783 &descriptor,
784 None,
785 ),
786 testing_utilities::create_keyboard_event(
787 fidl_fuchsia_input::Key::A,
788 fidl_fuchsia_ui_input3::KeyEventType::Released,
789 None,
790 &descriptor,
791 None,
792 ),
793 testing_utilities::create_keyboard_event(
794 fidl_fuchsia_input::Key::B,
795 fidl_fuchsia_ui_input3::KeyEventType::Pressed,
796 None,
797 &descriptor,
798 None,
799 ),
800 ];
801
802 assert_input_report_sequence_generates_events!(
803 input_reports: reports,
804 expected_events: expected_events,
805 device_descriptor: descriptor,
806 device_type: KeyboardBinding,
807 );
808 }
809
810 #[fuchsia::test]
811 fn get_unsided_modifiers() {
812 use fidl_ui_input3::Modifiers;
813 let event = KeyboardEvent::new(fidl_fuchsia_input::Key::A, KeyEventType::Pressed)
814 .into_with_modifiers(Some(Modifiers::all()));
815 assert_eq!(
816 event.get_unsided_modifiers(),
817 Modifiers::CAPS_LOCK
818 | Modifiers::NUM_LOCK
819 | Modifiers::SCROLL_LOCK
820 | Modifiers::FUNCTION
821 | Modifiers::SYMBOL
822 | Modifiers::SHIFT
823 | Modifiers::ALT
824 | Modifiers::ALT_GRAPH
825 | Modifiers::META
826 | Modifiers::CTRL
827 )
828 }
829
830 #[fuchsia::test]
831 fn conversion_fills_out_all_fields() {
832 use fidl_fuchsia_input::Key;
833 use fidl_ui_input3::{KeyMeaning, LockState, Modifiers, NonPrintableKey};
834 let event = KeyboardEvent::new(Key::A, KeyEventType::Pressed)
835 .into_with_modifiers(Some(Modifiers::all()))
836 .into_with_lock_state(Some(LockState::all()))
837 .into_with_repeat_sequence(42)
838 .into_with_key_meaning(Some(KeyMeaning::NonPrintableKey(NonPrintableKey::Tab)));
839
840 let actual = event.from_key_event_at_time(zx::MonotonicInstant::from_nanos(42));
841 assert_eq!(
842 actual,
843 fidl_fuchsia_ui_input3::KeyEvent {
844 timestamp: Some(42),
845 type_: Some(KeyEventType::Pressed),
846 key: Some(Key::A),
847 modifiers: Some(Modifiers::all()),
848 key_meaning: Some(KeyMeaning::NonPrintableKey(NonPrintableKey::Tab)),
849 repeat_sequence: Some(42),
850 lock_state: Some(LockState::all()),
851 ..Default::default()
852 }
853 );
854 }
855}