1#![deny(missing_docs)]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![doc = include_str!("../README.md")]
4
5use terminput::{
6 Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, MouseButton, MouseEvent,
7 MouseEventKind, ScrollDirection, UnsupportedEvent,
8};
9
10pub fn to_terminput(value: egui::Event) -> Result<Event, UnsupportedEvent> {
12 match value {
13 egui::Event::Paste(text) => Ok(Event::Paste(text)),
14 egui::Event::Text(_) => Err(UnsupportedEvent(format!("{value:?}"))),
15 egui::Event::Key {
16 key,
17 physical_key: _,
18 pressed,
19 repeat,
20 modifiers,
21 } => Ok(Event::Key(KeyEvent {
22 code: key_code_to_terminput(key)?,
23 modifiers: key_modifiers_to_terminput(modifiers),
24 kind: if repeat {
25 KeyEventKind::Repeat
26 } else if pressed {
27 KeyEventKind::Press
28 } else {
29 KeyEventKind::Release
30 },
31 state: KeyEventState::empty(),
32 })),
33 egui::Event::PointerMoved(pos) => Ok(Event::Mouse(MouseEvent {
34 kind: MouseEventKind::Moved,
35 column: pos.x as u16,
36 row: pos.y as u16,
37 modifiers: KeyModifiers::empty(),
38 })),
39
40 egui::Event::PointerButton {
41 pos,
42 button,
43 pressed,
44 modifiers,
45 } => Ok(Event::Mouse(MouseEvent {
46 kind: if pressed {
47 MouseEventKind::Down(mouse_button_to_terminput(button))
48 } else {
49 MouseEventKind::Up(mouse_button_to_terminput(button))
50 },
51 column: pos.x as u16,
52 row: pos.y as u16,
53 modifiers: key_modifiers_to_terminput(modifiers),
54 })),
55 egui::Event::MouseWheel {
56 unit: _,
57 delta,
58 modifiers,
59 } => Ok(Event::Mouse(MouseEvent {
60 kind: MouseEventKind::Scroll(if delta.y < 0.0 {
61 ScrollDirection::Down
62 } else if delta.y > 0.0 {
63 ScrollDirection::Up
64 } else if delta.x < 0.0 {
65 ScrollDirection::Left
66 } else {
67 ScrollDirection::Right
68 }),
69 column: 0,
70 row: 0,
71 modifiers: key_modifiers_to_terminput(modifiers),
72 })),
73 egui::Event::WindowFocused(true) => Ok(Event::FocusGained),
74 egui::Event::WindowFocused(false) => Ok(Event::FocusLost),
75 egui::Event::Copy
76 | egui::Event::Cut
77 | egui::Event::MouseMoved(_)
78 | egui::Event::Ime(_)
79 | egui::Event::PointerGone
80 | egui::Event::Zoom(_)
81 | egui::Event::Touch { .. }
82 | egui::Event::Screenshot { .. } => Err(UnsupportedEvent(format!("{value:?}"))),
83 }
84}
85
86pub fn to_egui(value: Event) -> Result<egui::Event, UnsupportedEvent> {
88 Ok(match value {
89 Event::Key(key_event) => egui::Event::Key {
90 key: key_code_to_egui(key_event.code)?,
91 physical_key: None,
92 pressed: key_event.kind != KeyEventKind::Release,
93 repeat: key_event.kind == KeyEventKind::Repeat,
94 modifiers: key_modifiers_to_egui(key_event.modifiers),
95 },
96 Event::Mouse(mouse_event) => match mouse_event.kind {
97 MouseEventKind::Down(mouse_button) | MouseEventKind::Drag(mouse_button) => {
98 egui::Event::PointerButton {
99 pos: egui::Pos2 {
100 x: mouse_event.column as f32,
101 y: mouse_event.row as f32,
102 },
103 button: mouse_button_to_egui(mouse_button),
104 pressed: true,
105 modifiers: key_modifiers_to_egui(mouse_event.modifiers),
106 }
107 }
108 MouseEventKind::Up(mouse_button) => egui::Event::PointerButton {
109 pos: egui::Pos2 {
110 x: mouse_event.column as f32,
111 y: mouse_event.row as f32,
112 },
113 button: mouse_button_to_egui(mouse_button),
114 pressed: false,
115 modifiers: key_modifiers_to_egui(mouse_event.modifiers),
116 },
117 MouseEventKind::Moved => egui::Event::PointerMoved(egui::Pos2 {
118 x: mouse_event.column as f32,
119 y: mouse_event.row as f32,
120 }),
121 MouseEventKind::Scroll(scroll_direction) => egui::Event::MouseWheel {
122 unit: egui::MouseWheelUnit::Line,
123 delta: egui::Vec2 {
124 x: scroll_direction.delta().x as f32,
125 y: scroll_direction.delta().y as f32,
126 },
127 modifiers: key_modifiers_to_egui(mouse_event.modifiers),
128 },
129 },
130 Event::Paste(text) => egui::Event::Paste(text),
131 Event::FocusGained => egui::Event::WindowFocused(true),
132 Event::FocusLost => egui::Event::WindowFocused(false),
133 Event::Resize { .. } => Err(UnsupportedEvent(format!("{value:?}")))?,
134 })
135}
136
137fn key_code_to_terminput(value: egui::Key) -> Result<KeyCode, UnsupportedEvent> {
138 match value {
139 egui::Key::ArrowDown => Ok(KeyCode::Down),
140 egui::Key::ArrowLeft => Ok(KeyCode::Left),
141 egui::Key::ArrowRight => Ok(KeyCode::Right),
142 egui::Key::ArrowUp => Ok(KeyCode::Up),
143 egui::Key::Escape => Ok(KeyCode::Esc),
144 egui::Key::Tab => Ok(KeyCode::Tab),
145 egui::Key::Backspace => Ok(KeyCode::Backspace),
146 egui::Key::Enter => Ok(KeyCode::Enter),
147 egui::Key::Space => Ok(KeyCode::Char(' ')),
148 egui::Key::Insert => Ok(KeyCode::Insert),
149 egui::Key::Delete => Ok(KeyCode::Delete),
150 egui::Key::Home => Ok(KeyCode::Home),
151 egui::Key::End => Ok(KeyCode::End),
152 egui::Key::PageUp => Ok(KeyCode::PageUp),
153 egui::Key::PageDown => Ok(KeyCode::PageDown),
154 egui::Key::Colon => Ok(KeyCode::Char(':')),
155 egui::Key::Comma => Ok(KeyCode::Char(',')),
156 egui::Key::Backslash => Ok(KeyCode::Char('\\')),
157 egui::Key::Slash => Ok(KeyCode::Char('/')),
158 egui::Key::Pipe => Ok(KeyCode::Char('|')),
159 egui::Key::Questionmark => Ok(KeyCode::Char('?')),
160 egui::Key::Exclamationmark => Ok(KeyCode::Char('!')),
161 egui::Key::OpenBracket => Ok(KeyCode::Char('[')),
162 egui::Key::CloseBracket => Ok(KeyCode::Char(']')),
163 egui::Key::OpenCurlyBracket => Ok(KeyCode::Char('{')),
164 egui::Key::CloseCurlyBracket => Ok(KeyCode::Char('}')),
165 egui::Key::Backtick => Ok(KeyCode::Char('`')),
166 egui::Key::Minus => Ok(KeyCode::Char('-')),
167 egui::Key::Period => Ok(KeyCode::Char('.')),
168 egui::Key::Plus => Ok(KeyCode::Char('+')),
169 egui::Key::Equals => Ok(KeyCode::Char('=')),
170 egui::Key::Semicolon => Ok(KeyCode::Char(';')),
171 egui::Key::Quote => Ok(KeyCode::Char('\'')),
172 egui::Key::Num0 => Ok(KeyCode::Char('0')),
173 egui::Key::Num1 => Ok(KeyCode::Char('1')),
174 egui::Key::Num2 => Ok(KeyCode::Char('2')),
175 egui::Key::Num3 => Ok(KeyCode::Char('3')),
176 egui::Key::Num4 => Ok(KeyCode::Char('4')),
177 egui::Key::Num5 => Ok(KeyCode::Char('5')),
178 egui::Key::Num6 => Ok(KeyCode::Char('6')),
179 egui::Key::Num7 => Ok(KeyCode::Char('7')),
180 egui::Key::Num8 => Ok(KeyCode::Char('8')),
181 egui::Key::Num9 => Ok(KeyCode::Char('9')),
182 egui::Key::A => Ok(KeyCode::Char('a')),
183 egui::Key::B => Ok(KeyCode::Char('b')),
184 egui::Key::C => Ok(KeyCode::Char('c')),
185 egui::Key::D => Ok(KeyCode::Char('d')),
186 egui::Key::E => Ok(KeyCode::Char('e')),
187 egui::Key::F => Ok(KeyCode::Char('f')),
188 egui::Key::G => Ok(KeyCode::Char('g')),
189 egui::Key::H => Ok(KeyCode::Char('h')),
190 egui::Key::I => Ok(KeyCode::Char('i')),
191 egui::Key::J => Ok(KeyCode::Char('j')),
192 egui::Key::K => Ok(KeyCode::Char('k')),
193 egui::Key::L => Ok(KeyCode::Char('l')),
194 egui::Key::M => Ok(KeyCode::Char('m')),
195 egui::Key::N => Ok(KeyCode::Char('n')),
196 egui::Key::O => Ok(KeyCode::Char('o')),
197 egui::Key::P => Ok(KeyCode::Char('p')),
198 egui::Key::Q => Ok(KeyCode::Char('q')),
199 egui::Key::R => Ok(KeyCode::Char('r')),
200 egui::Key::S => Ok(KeyCode::Char('s')),
201 egui::Key::T => Ok(KeyCode::Char('t')),
202 egui::Key::U => Ok(KeyCode::Char('u')),
203 egui::Key::V => Ok(KeyCode::Char('v')),
204 egui::Key::W => Ok(KeyCode::Char('w')),
205 egui::Key::X => Ok(KeyCode::Char('x')),
206 egui::Key::Y => Ok(KeyCode::Char('y')),
207 egui::Key::Z => Ok(KeyCode::Char('z')),
208 egui::Key::F1 => Ok(KeyCode::F(1)),
209 egui::Key::F2 => Ok(KeyCode::F(2)),
210 egui::Key::F3 => Ok(KeyCode::F(3)),
211 egui::Key::F4 => Ok(KeyCode::F(4)),
212 egui::Key::F5 => Ok(KeyCode::F(5)),
213 egui::Key::F6 => Ok(KeyCode::F(6)),
214 egui::Key::F7 => Ok(KeyCode::F(7)),
215 egui::Key::F8 => Ok(KeyCode::F(8)),
216 egui::Key::F9 => Ok(KeyCode::F(9)),
217 egui::Key::F10 => Ok(KeyCode::F(10)),
218 egui::Key::F11 => Ok(KeyCode::F(11)),
219 egui::Key::F12 => Ok(KeyCode::F(12)),
220 egui::Key::F13 => Ok(KeyCode::F(13)),
221 egui::Key::F14 => Ok(KeyCode::F(14)),
222 egui::Key::F15 => Ok(KeyCode::F(15)),
223 egui::Key::F16 => Ok(KeyCode::F(16)),
224 egui::Key::F17 => Ok(KeyCode::F(17)),
225 egui::Key::F18 => Ok(KeyCode::F(18)),
226 egui::Key::F19 => Ok(KeyCode::F(19)),
227 egui::Key::F20 => Ok(KeyCode::F(20)),
228 egui::Key::F21 => Ok(KeyCode::F(21)),
229 egui::Key::F22 => Ok(KeyCode::F(22)),
230 egui::Key::F23 => Ok(KeyCode::F(23)),
231 egui::Key::F24 => Ok(KeyCode::F(24)),
232 egui::Key::F25 => Ok(KeyCode::F(25)),
233 egui::Key::F26 => Ok(KeyCode::F(26)),
234 egui::Key::F27 => Ok(KeyCode::F(27)),
235 egui::Key::F28 => Ok(KeyCode::F(28)),
236 egui::Key::F29 => Ok(KeyCode::F(29)),
237 egui::Key::F30 => Ok(KeyCode::F(30)),
238 egui::Key::F31 => Ok(KeyCode::F(31)),
239 egui::Key::F32 => Ok(KeyCode::F(32)),
240 egui::Key::F33 => Ok(KeyCode::F(33)),
241 egui::Key::F34 => Ok(KeyCode::F(34)),
242 egui::Key::F35 => Ok(KeyCode::F(35)),
243 egui::Key::Copy | egui::Key::Cut | egui::Key::Paste | egui::Key::BrowserBack => {
244 Err(UnsupportedEvent(format!("{value:?}")))
245 }
246 }
247}
248
249fn key_code_to_egui(value: KeyCode) -> Result<egui::Key, UnsupportedEvent> {
250 Ok(match value {
251 KeyCode::Backspace => egui::Key::Backspace,
252 KeyCode::Enter => egui::Key::Enter,
253 KeyCode::Left => egui::Key::ArrowLeft,
254 KeyCode::Right => egui::Key::ArrowRight,
255 KeyCode::Up => egui::Key::ArrowUp,
256 KeyCode::Down => egui::Key::ArrowDown,
257 KeyCode::Home => egui::Key::Home,
258 KeyCode::End => egui::Key::End,
259 KeyCode::PageUp => egui::Key::PageUp,
260 KeyCode::PageDown => egui::Key::PageDown,
261 KeyCode::Tab => egui::Key::Tab,
262 KeyCode::Delete => egui::Key::Delete,
263 KeyCode::Insert => egui::Key::Insert,
264 KeyCode::F(1) => egui::Key::F1,
265 KeyCode::F(2) => egui::Key::F2,
266 KeyCode::F(3) => egui::Key::F3,
267 KeyCode::F(4) => egui::Key::F4,
268 KeyCode::F(5) => egui::Key::F5,
269 KeyCode::F(6) => egui::Key::F6,
270 KeyCode::F(7) => egui::Key::F7,
271 KeyCode::F(8) => egui::Key::F8,
272 KeyCode::F(9) => egui::Key::F9,
273 KeyCode::F(10) => egui::Key::F10,
274 KeyCode::F(11) => egui::Key::F11,
275 KeyCode::F(12) => egui::Key::F12,
276 KeyCode::F(13) => egui::Key::F13,
277 KeyCode::F(14) => egui::Key::F14,
278 KeyCode::F(15) => egui::Key::F15,
279 KeyCode::F(16) => egui::Key::F16,
280 KeyCode::F(17) => egui::Key::F17,
281 KeyCode::F(18) => egui::Key::F18,
282 KeyCode::F(19) => egui::Key::F19,
283 KeyCode::F(20) => egui::Key::F20,
284 KeyCode::F(21) => egui::Key::F21,
285 KeyCode::F(22) => egui::Key::F22,
286 KeyCode::F(23) => egui::Key::F23,
287 KeyCode::F(24) => egui::Key::F24,
288 KeyCode::F(25) => egui::Key::F25,
289 KeyCode::F(26) => egui::Key::F26,
290 KeyCode::F(27) => egui::Key::F27,
291 KeyCode::F(28) => egui::Key::F28,
292 KeyCode::F(29) => egui::Key::F29,
293 KeyCode::F(30) => egui::Key::F30,
294 KeyCode::F(31) => egui::Key::F31,
295 KeyCode::F(32) => egui::Key::F32,
296 KeyCode::F(33) => egui::Key::F33,
297 KeyCode::F(34) => egui::Key::F34,
298 KeyCode::F(35) => egui::Key::F35,
299 KeyCode::F(_) => Err(UnsupportedEvent(format!("{value:?}")))?,
300 KeyCode::Char('a' | 'A') => egui::Key::A,
301 KeyCode::Char('b' | 'B') => egui::Key::B,
302 KeyCode::Char('c' | 'C') => egui::Key::C,
303 KeyCode::Char('d' | 'D') => egui::Key::D,
304 KeyCode::Char('e' | 'E') => egui::Key::E,
305 KeyCode::Char('f' | 'F') => egui::Key::F,
306 KeyCode::Char('g' | 'G') => egui::Key::G,
307 KeyCode::Char('h' | 'H') => egui::Key::H,
308 KeyCode::Char('i' | 'I') => egui::Key::I,
309 KeyCode::Char('j' | 'J') => egui::Key::J,
310 KeyCode::Char('k' | 'K') => egui::Key::K,
311 KeyCode::Char('l' | 'L') => egui::Key::L,
312 KeyCode::Char('m' | 'M') => egui::Key::M,
313 KeyCode::Char('n' | 'N') => egui::Key::N,
314 KeyCode::Char('o' | 'O') => egui::Key::O,
315 KeyCode::Char('p' | 'P') => egui::Key::P,
316 KeyCode::Char('q' | 'Q') => egui::Key::Q,
317 KeyCode::Char('r' | 'R') => egui::Key::R,
318 KeyCode::Char('s' | 'S') => egui::Key::S,
319 KeyCode::Char('t' | 'T') => egui::Key::T,
320 KeyCode::Char('u' | 'U') => egui::Key::U,
321 KeyCode::Char('v' | 'V') => egui::Key::V,
322 KeyCode::Char('w' | 'W') => egui::Key::W,
323 KeyCode::Char('x' | 'X') => egui::Key::X,
324 KeyCode::Char('y' | 'Y') => egui::Key::Y,
325 KeyCode::Char('z' | 'Z') => egui::Key::Z,
326 KeyCode::Char('0') => egui::Key::Num0,
327 KeyCode::Char('1') => egui::Key::Num1,
328 KeyCode::Char('2') => egui::Key::Num2,
329 KeyCode::Char('3') => egui::Key::Num3,
330 KeyCode::Char('4') => egui::Key::Num4,
331 KeyCode::Char('5') => egui::Key::Num5,
332 KeyCode::Char('6') => egui::Key::Num6,
333 KeyCode::Char('7') => egui::Key::Num7,
334 KeyCode::Char('8') => egui::Key::Num8,
335 KeyCode::Char('9') => egui::Key::Num9,
336 KeyCode::Char(' ') => egui::Key::Space,
337 KeyCode::Char(':') => egui::Key::Colon,
338 KeyCode::Char(',') => egui::Key::Comma,
339 KeyCode::Char('\\') => egui::Key::Backslash,
340 KeyCode::Char('/') => egui::Key::Slash,
341 KeyCode::Char('|') => egui::Key::Pipe,
342 KeyCode::Char('?') => egui::Key::Questionmark,
343 KeyCode::Char('[') => egui::Key::OpenBracket,
344 KeyCode::Char(']') => egui::Key::CloseBracket,
345 KeyCode::Char('`') => egui::Key::Backtick,
346 KeyCode::Char('-') => egui::Key::Minus,
347 KeyCode::Char('.') => egui::Key::Period,
348 KeyCode::Char('+') => egui::Key::Plus,
349 KeyCode::Char('=') => egui::Key::Equals,
350 KeyCode::Char(';') => egui::Key::Semicolon,
351 KeyCode::Char('\'') => egui::Key::Quote,
352 KeyCode::Char(_) => Err(UnsupportedEvent(format!("{value:?}")))?,
353 KeyCode::Esc => egui::Key::Escape,
354 KeyCode::CapsLock
355 | KeyCode::ScrollLock
356 | KeyCode::NumLock
357 | KeyCode::PrintScreen
358 | KeyCode::Pause
359 | KeyCode::Menu
360 | KeyCode::KeypadBegin
361 | KeyCode::Media(_)
362 | KeyCode::Modifier(_, _) => Err(UnsupportedEvent(format!("{value:?}")))?,
363 })
364}
365
366fn key_modifiers_to_terminput(value: egui::Modifiers) -> KeyModifiers {
367 let mut mapped = KeyModifiers::empty();
368 if value.alt {
369 mapped |= KeyModifiers::ALT;
370 }
371 if value.shift {
372 mapped |= KeyModifiers::SHIFT;
373 }
374 if value.command | value.ctrl | value.mac_cmd {
375 mapped |= KeyModifiers::CTRL;
376 }
377 mapped
378}
379
380fn key_modifiers_to_egui(value: KeyModifiers) -> egui::Modifiers {
381 egui::Modifiers {
382 alt: value.intersects(KeyModifiers::ALT),
383 ctrl: value.intersects(KeyModifiers::CTRL),
384 shift: value.intersects(KeyModifiers::SHIFT),
385 mac_cmd: false,
386 command: false,
387 }
388}
389
390fn mouse_button_to_terminput(value: egui::PointerButton) -> MouseButton {
391 match value {
392 egui::PointerButton::Primary => MouseButton::Left,
393 egui::PointerButton::Secondary => MouseButton::Right,
394 egui::PointerButton::Middle => MouseButton::Middle,
395 egui::PointerButton::Extra1 | egui::PointerButton::Extra2 => MouseButton::Unknown,
396 }
397}
398
399fn mouse_button_to_egui(value: MouseButton) -> egui::PointerButton {
400 match value {
401 MouseButton::Left | MouseButton::Unknown => egui::PointerButton::Primary,
402 MouseButton::Right => egui::PointerButton::Secondary,
403 MouseButton::Middle => egui::PointerButton::Middle,
404 }
405}