1use std::collections::VecDeque;
7
8use dais_core::keybindings::{KeyCombo, KeybindingMap};
9
10const MAX_EVENTS: usize = 20;
12
13struct KeyEvent {
15 key_name: String,
16 modifiers: String,
17 action: String,
18}
19
20pub struct TestInputApp {
22 keybindings: KeybindingMap,
23 events: VecDeque<KeyEvent>,
24}
25
26impl TestInputApp {
27 pub fn new(keybindings: KeybindingMap) -> Self {
28 Self { keybindings, events: VecDeque::with_capacity(MAX_EVENTS + 1) }
29 }
30}
31
32impl eframe::App for TestInputApp {
33 fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
34 let raw_events: Vec<egui::Event> = ctx.input(|i| i.events.clone());
36
37 for event in &raw_events {
38 if let egui::Event::Key { key, pressed: true, modifiers, .. } = event {
39 let key_name = crate::input::egui_key_name_public(*key);
40 let combo = KeyCombo {
41 key: key_name.clone(),
42 shift: modifiers.shift,
43 ctrl: modifiers.ctrl || modifiers.command,
44 alt: modifiers.alt,
45 };
46
47 let mod_str = format_modifiers(*modifiers);
48 let action = match self.keybindings.lookup(&combo) {
49 Some(a) => a.config_name().to_string(),
50 None => "(none)".to_string(),
51 };
52
53 tracing::info!(
54 key = %key_name,
55 modifiers = %mod_str,
56 action = %action,
57 "Key event captured"
58 );
59
60 self.events.push_front(KeyEvent { key_name, modifiers: mod_str, action });
61 if self.events.len() > MAX_EVENTS {
62 self.events.pop_back();
63 }
64 }
65 }
66
67 let wants_exit = ctx.input(|i| i.key_pressed(egui::Key::Escape));
69
70 egui::CentralPanel::default().show(ctx, |ui| {
71 ui.heading("Test Input Mode — Press keys to see events");
72 ui.separator();
73
74 if self.events.is_empty() {
75 ui.label("No key events yet. Press any key on your clicker or keyboard.");
76 } else {
77 egui::ScrollArea::vertical().max_height(ui.available_height() - 40.0).show(
78 ui,
79 |ui| {
80 egui::Grid::new("key_events")
81 .num_columns(3)
82 .striped(true)
83 .spacing([20.0, 4.0])
84 .show(ui, |ui| {
85 ui.strong("Key");
86 ui.strong("Modifiers");
87 ui.strong("Action");
88 ui.end_row();
89
90 for ev in &self.events {
91 ui.monospace(&ev.key_name);
92 ui.monospace(&ev.modifiers);
93 ui.monospace(&ev.action);
94 ui.end_row();
95 }
96 });
97 },
98 );
99 }
100
101 ui.separator();
102 if ui.button("Exit").clicked() || wants_exit {
103 ctx.send_viewport_cmd(egui::ViewportCommand::Close);
104 }
105 });
106 }
107}
108
109fn format_modifiers(m: egui::Modifiers) -> String {
111 let mut parts = Vec::new();
112 if m.ctrl || m.command {
113 parts.push("Ctrl");
114 }
115 if m.shift {
116 parts.push("Shift");
117 }
118 if m.alt {
119 parts.push("Alt");
120 }
121 if parts.is_empty() { "(none)".to_string() } else { parts.join("+") }
122}