terminput_egui/
lib.rs

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
10/// Converts the egui [`Event`](egui::Event) to a terminput [`Event`].
11pub 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
86/// Converts the terminput [`Event`] to an egui [`Event`](egui::Event).
87pub 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 => {
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}