1#![allow(dead_code)]
8
9extern crate alloc;
10use alloc::string::String;
11
12use crate::kernel::config::{self, KeyboardLayout};
13use crate::kernel::draw::{Color, Screen};
14use crate::kernel::window_mgr::App;
15
16pub struct KeymapApp {
17 last_keycode: u8,
18 last_ascii: Option<char>,
19 is_pressed: bool,
20 history: alloc::vec::Vec<String>,
21}
22
23impl Default for KeymapApp {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl KeymapApp {
30 pub fn new() -> Self {
31 Self {
32 last_keycode: 0,
33 last_ascii: None,
34 is_pressed: false,
35 history: alloc::vec::Vec::new(),
36 }
37 }
38
39 fn push_history(&mut self, ev_str: String) {
40 self.history.push(ev_str);
41 if self.history.len() > 10 {
42 self.history.remove(0);
43 }
44 }
45}
46
47fn keycode_to_name(keycode: u8, ascii: Option<char>) -> String {
48 match keycode {
49 0x01 => String::from("Esc"),
50 0x0E => String::from("Backspace"),
51 0x0F => String::from("Tab"),
52 0x1C => String::from("Enter"),
53 0x1D => String::from("LCtrl"),
54 0x2A => String::from("LShift"),
55 0x36 => String::from("RShift"),
56 0x38 => String::from("Alt/Option"),
57 0x5B => String::from("Command"),
58 0x39 => String::from("Space"),
59 0x3A => String::from("CapsLock"),
60 0x3B => String::from("F1"),
61 0x3C => String::from("F2"),
62 0x3D => String::from("F3"),
63 0x3E => String::from("F4"),
64 0x3F => String::from("F5"),
65 0x40 => String::from("F6"),
66 0x41 => String::from("F7"),
67 0x42 => String::from("F8"),
68 0x43 => String::from("F9"),
69 0x44 => String::from("F10"),
70 0x57 => String::from("F11"),
71 0x58 => String::from("F12"),
72 0x47 => String::from("Home"),
73 0x48 => String::from("Up"),
74 0x4B => String::from("Left"),
75 0x4D => String::from("Right"),
76 0x4F => String::from("End"),
77 0x50 => String::from("Down"),
78 0x53 => String::from("Delete"),
79 _ => {
80 if let Some(c) = ascii {
81 match c {
83 '\t' => String::from("Tab"),
84 '\n' => String::from("Enter"),
85 '\x08' => String::from("Backspace"),
86 ' ' => String::from("Space"),
87 _ => alloc::format!("'{}'", c),
88 }
89 } else {
90 String::from("None")
91 }
92 }
93 }
94}
95
96impl App for KeymapApp {
97 fn name(&self) -> &str {
98 "Keymap & Checker"
99 }
100
101 fn draw(&mut self, screen: &Screen, win_x: u32, win_y: u32, win_w: u32, win_h: u32) {
102 let config = config::get_config();
103
104 screen.boxfill(
106 win_x,
107 win_y,
108 win_x + win_w,
109 win_y + win_h,
110 Color(config.theme.terminal_bg),
111 );
112
113 screen.draw_string_vector(
115 win_x + 15,
116 win_y + 15,
117 "KEYBOARD CHECKER",
118 Color(config.theme.success_fg),
119 18,
120 );
121 screen.boxfill(
122 win_x + 15,
123 win_y + 38,
124 win_x + win_w - 15,
125 win_y + 39,
126 Color(config.theme.tab_area_border),
127 );
128
129 let layout_str = match config.keyboard_layout {
131 KeyboardLayout::Jis => "JIS (106/109)",
132 KeyboardLayout::Us => "US (101/104)",
133 };
134 let caps_str = if config.swap_caps_ctrl {
135 "Ctrl"
136 } else {
137 "CapsLock"
138 };
139
140 screen.draw_string_vector(
141 win_x + 15,
142 win_y + 55,
143 "Current Layout:",
144 Color(config.theme.fn_bar_key_fg),
145 14,
146 );
147 screen.draw_string_vector(win_x + 150, win_y + 55, layout_str, Color(config.theme.terminal_fg), 14);
148
149 screen.draw_string_vector(
150 win_x + 15,
151 win_y + 80,
152 "CapsLock as:",
153 Color(config.theme.fn_bar_key_fg),
154 14,
155 );
156 screen.draw_string_vector(win_x + 150, win_y + 80, caps_str, Color(config.theme.terminal_fg), 14);
157
158 screen.draw_string_vector(
160 win_x + 15,
161 win_y + 120,
162 "Live Keyboard Event:",
163 Color(config.theme.warning_fg),
164 16,
165 );
166
167 let box_y = win_y + 145;
169 screen.boxfill(
170 win_x + 15,
171 box_y,
172 win_x + win_w - 15,
173 box_y + 100,
174 Color(config.theme.ui_overlay_bg),
175 );
176 screen.boxfill(
177 win_x + 15,
178 box_y,
179 win_x + win_w - 15,
180 box_y + 2,
181 Color(config.theme.sysmon_accent),
182 ); if self.last_keycode != 0 {
185 let state_str = if self.is_pressed {
186 "PRESSED "
187 } else {
188 "RELEASED"
189 };
190 let state_color = if self.is_pressed {
191 Color(config.theme.error_fg)
192 } else {
193 Color(config.theme.fn_bar_key_fg)
194 };
195
196 screen.draw_string_vector(win_x + 30, box_y + 25, "State:", Color(config.theme.fn_bar_dim_fg), 14);
197 screen.draw_string_vector(win_x + 90, box_y + 25, state_str, state_color, 14);
198
199 let code_str = alloc::format!("0x{:02X} ({})", self.last_keycode, self.last_keycode);
200 screen.draw_string_vector(win_x + 30, box_y + 50, "Code:", Color(config.theme.fn_bar_dim_fg), 14);
201 screen.draw_string_vector(win_x + 90, box_y + 50, &code_str, Color(config.theme.terminal_fg), 14);
202
203 let char_str = keycode_to_name(self.last_keycode, self.last_ascii);
204 screen.draw_string_vector(win_x + 200, box_y + 50, "Key:", Color(config.theme.fn_bar_dim_fg), 14);
205 screen.draw_string_vector(win_x + 240, box_y + 50, &char_str, Color(config.theme.tab_active_fg), 14);
206 } else {
207 screen.draw_string_vector(
208 win_x + 30,
209 box_y + 40,
210 "Press any key to test...",
211 Color(config.theme.fn_bar_dim_fg),
212 14,
213 );
214 }
215
216 screen.draw_string_vector(
218 win_x + 15,
219 win_y + 270,
220 "Event History:",
221 Color(config.theme.success_fg),
222 14,
223 );
224 let mut hist_y = win_y + 295;
225 for hist in self.history.iter().rev() {
226 screen.draw_string_vector(win_x + 25, hist_y, hist, Color(config.theme.terminal_fg), 12);
227 hist_y += 18;
228 }
229 }
230
231 fn on_mouse(
232 &mut self,
233 _local_x: i32,
234 _local_y: i32,
235 _btn_left: bool,
236 _btn_right: bool,
237 _wheel: i32,
238 ) {
239 }
241
242 fn on_key(&mut self, keycode: u8, pressed: bool, ascii: Option<char>) {
243 self.last_keycode = keycode;
244 self.is_pressed = pressed;
245 self.last_ascii = ascii;
246
247 let state_str = if pressed { "DOWN" } else { "UP " };
248 let char_str = keycode_to_name(keycode, ascii);
249 let hist_str = alloc::format!(
250 "[{}] Code: 0x{:02X} | Key: {}",
251 state_str,
252 keycode,
253 char_str
254 );
255 self.push_history(hist_str);
256 }
257}