1use uefi::{Char16, Status, Result};
8use uefi::boot::ScopedProtocol;
9use uefi::proto::console::text::Key;
10use uefi_raw::protocol::console::InputKey;
11use crate::input::Input;
12use crate::simple_text_input_ex::*;
13
14#[derive(Debug, Copy, Clone)]
16pub struct KeyData {
17 pub key: Key,
18 pub key_state: KeyState,
19}
20
21impl From<KeyData> for RawKeyData {
23 fn from(value: KeyData) -> Self {
24 let input_key = match value.key {
25 Key::Printable(c) => InputKey {
26 scan_code: 0,
27 unicode_char: u16::from(c),
28 },
29 Key::Special(code) => InputKey {
30 scan_code: code.0,
31 unicode_char: 0,
32 },
33 };
34
35 Self {
36 key: input_key,
37 key_state: value.key_state,
38 }
39 }
40}
41
42impl From<RawKeyData> for KeyData {
44 fn from(raw: RawKeyData) -> Self {
45 Self {
46 key: Key::from(raw.key),
47 key_state: raw.key_state,
48 }
49 }
50}
51
52impl KeyData {
53 pub fn new(c: char) -> Result<Self> {
55 let c = Char16::try_from(c).map_err(|_| Status::INVALID_PARAMETER)?;
56
57 Ok(Self {
58 key: Key::Printable(c),
59 key_state: KeyState::default(),
60 })
61 }
62
63 #[inline(always)]
65 pub fn supports_modifiers(&self) -> bool {
66 (self.key_state.key_shift_state & SHIFT_STATE_VALID) != 0
67 }
68
69 #[inline(always)]
71 pub fn r_shift(&self) -> bool { (self.key_state.key_shift_state & RIGHT_SHIFT_PRESSED) != 0 }
72
73 #[inline(always)]
75 pub fn l_shift(&self) -> bool { (self.key_state.key_shift_state & LEFT_SHIFT_PRESSED) != 0 }
76
77 #[inline(always)]
79 pub fn shift(&self) -> bool {
80 const SHIFT_MASK: u32 = LEFT_SHIFT_PRESSED | RIGHT_SHIFT_PRESSED;
81 (self.key_state.key_shift_state & SHIFT_MASK) != 0
82 }
83
84 #[inline(always)]
86 pub fn r_ctrl(&self) -> bool { (self.key_state.key_shift_state & RIGHT_CONTROL_PRESSED) != 0 }
87
88 #[inline(always)]
90 pub fn l_ctrl(&self) -> bool { (self.key_state.key_shift_state & LEFT_CONTROL_PRESSED) != 0 }
91
92 #[inline(always)]
94 pub fn ctrl(&self) -> bool {
95 const CTRL_MASK: u32 = LEFT_CONTROL_PRESSED | RIGHT_CONTROL_PRESSED;
96 (self.key_state.key_shift_state & CTRL_MASK) != 0
97 }
98
99 #[inline(always)]
101 pub fn r_alt(&self) -> bool { (self.key_state.key_shift_state & RIGHT_ALT_PRESSED) != 0 }
102
103 #[inline(always)]
105 pub fn l_alt(&self) -> bool { (self.key_state.key_shift_state & LEFT_ALT_PRESSED) != 0 }
106
107 #[inline(always)]
109 pub fn alt(&self) -> bool {
110 const ALT_MASK: u32 = LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED;
111 (self.key_state.key_shift_state & ALT_MASK) != 0
112 }
113
114 #[inline(always)]
116 pub fn r_logo(&self) -> bool { (self.key_state.key_shift_state & RIGHT_LOGO_PRESSED) != 0 }
117
118 #[inline(always)]
120 pub fn l_logo(&self) -> bool { (self.key_state.key_shift_state & LEFT_LOGO_PRESSED) != 0 }
121
122 #[inline(always)]
124 pub fn logo(&self) -> bool {
125 const LOGO_MASK: u32 = LEFT_LOGO_PRESSED | RIGHT_LOGO_PRESSED;
126 (self.key_state.key_shift_state & LOGO_MASK) != 0
127 }
128
129 #[inline(always)]
131 pub fn menu(&self) -> bool { (self.key_state.key_shift_state & MENU_KEY_PRESSED) != 0 }
132
133 #[inline(always)]
135 pub fn sys_req(&self) -> bool { (self.key_state.key_shift_state & SYS_REQ_PRESSED) != 0 }
136
137 #[inline(always)]
139 pub fn supports_toggles(&self) -> bool {
140 (self.key_state.key_toggle_state & TOGGLE_STATE_VALID) != 0
141 }
142
143 #[inline(always)]
146 pub fn is_realtime_mode(&self) -> bool {
147 (self.key_state.key_toggle_state & KEY_STATE_EXPOSED) != 0
148 }
149
150 #[inline(always)]
152 pub fn scroll_lock(&self) -> bool {
153 (self.key_state.key_toggle_state & SCROLL_LOCK_ACTIVE) != 0
154 }
155
156 #[inline(always)]
158 pub fn num_lock(&self) -> bool { (self.key_state.key_toggle_state & NUM_LOCK_ACTIVE) != 0 }
159
160 #[inline(always)]
162 pub fn caps_lock(&self) -> bool { (self.key_state.key_toggle_state & CAPS_LOCK_ACTIVE) != 0 }
163
164 #[inline]
168 pub fn realtime_init(stdin: &mut ScopedProtocol<Input>, enable: bool) -> Result {
169 let state_bits = TOGGLE_STATE_VALID | ((enable as u8) << 6);
171 stdin.set_state(state_bits)
172 }
173}