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