1use egui::{Key, Modifiers, MouseWheelUnit, PointerButton, Pos2, Rect};
16use sdl2::event::WindowEvent;
17use sdl2::keyboard::Keycode;
18use sdl2::keyboard::Mod;
19use sdl2::keyboard::Scancode;
20use sdl2::mouse::{Cursor, MouseButton, SystemCursor};
21use sdl2::video::Window;
22
23#[must_use]
24#[derive(Clone, Copy, Debug, Default)]
25pub struct EventResponse {
26 pub consumed: bool,
34
35 pub repaint: bool,
37}
38
39pub struct State {
43 egui_ctx: egui::Context,
44 egui_input: egui::RawInput,
45 start_time: std::time::Instant,
46 viewport_id: egui::ViewportId,
47 pointer_pos_in_points: Option<egui::Pos2>,
48 pointer_touch_id: Option<i64>,
52 current_cursor: Option<CurrentCursor>,
53 modifiers: egui::Modifiers,
56 clipboard: sdl2::clipboard::ClipboardUtil,
57 rotation: crate::Rotation,
60 window_size: (u32, u32), drawable_size: (u32, u32),
66}
67
68#[derive(Debug)]
72struct SdlDroppedFile(std::path::PathBuf);
73
74impl egui::DroppedFile for SdlDroppedFile {
75 fn path(&self) -> &std::path::Path {
76 &self.0
77 }
78
79 fn bytes(&self) -> Result<Vec<u8>, String> {
80 std::fs::read(&self.0).map_err(|e| e.to_string())
81 }
82}
83
84struct CurrentCursor {
88 icon: egui::CursorIcon,
89 cursor: Option<sdl2::mouse::Cursor>, }
91
92impl State {
93 pub fn new(window: &Window, egui_ctx: egui::Context, viewport_id: egui::ViewportId) -> Self {
94 let screen_rect = new_screen_rect(&egui_ctx, window, crate::Rotation::None);
97 let mut egui_input = egui::RawInput {
98 focused: false, screen_rect,
100 ..Default::default()
101 };
102 egui_input
103 .viewports
104 .entry(egui::ViewportId::ROOT)
105 .or_default()
106 .native_pixels_per_point = Some(native_pixels_per_point(window));
107 let clipboard = window.subsystem().clipboard();
108 let window_size = window.size();
109 let drawable_size = window.drawable_size();
110
111 State {
112 egui_ctx,
113 viewport_id,
114 clipboard,
115 start_time: std::time::Instant::now(),
116 egui_input,
117 pointer_pos_in_points: None,
118 pointer_touch_id: None,
119 current_cursor: None,
120 modifiers: egui::Modifiers::default(),
121 rotation: crate::Rotation::None,
122 window_size,
123 drawable_size,
124 }
125 }
126
127 #[inline]
135 pub fn set_rotation(&mut self, rotation: crate::Rotation) {
136 self.rotation = rotation;
137 }
138
139 #[inline]
140 pub fn rotation(&self) -> crate::Rotation {
141 self.rotation
142 }
143
144 #[inline]
145 pub fn get_window_size(&self) -> (u32, u32) {
146 self.window_size
147 }
148
149 #[inline]
154 pub fn get_drawable_size(&self) -> (u32, u32) {
155 self.drawable_size
156 }
157
158 #[inline]
159 pub fn get_pointer_pos_in_points(&self) -> Option<egui::Pos2> {
160 self.pointer_pos_in_points
161 }
162
163 #[inline]
167 pub fn set_max_texture_side(&mut self, max_texture_side: Option<usize>) {
168 self.egui_input.max_texture_side = max_texture_side;
169 }
170
171 #[inline]
172 pub fn set_theme(&mut self, theme: egui::Theme) {
173 self.egui_input.system_theme.replace(theme);
174 }
175
176 #[inline]
184 pub fn handle_platform_output(&mut self, platform_output: egui::PlatformOutput) {
185 for command in &platform_output.commands {
186 match command {
187 egui::OutputCommand::CopyText(text) => {
188 let result = self.clipboard.set_clipboard_text(text);
189
190 if result.is_err() {
191 log::warn!("Failed to set copied text to clipboard");
192 }
193 }
194 egui::OutputCommand::CopyImage(_color_image) => {
195 log::warn!("CopyImage is not supported")
196 }
197 egui::OutputCommand::OpenUrl(_url) => {
198 #[cfg(feature = "links")]
199 if let Err(err) = webbrowser::open(&_url.url) {
200 log::warn!("Failed to open url: {}", err);
201 }
202
203 #[cfg(not(feature = "links"))]
204 {
205 log::warn!("Cannot open url - feature \"links\" not enabled.");
206 }
207 }
208 }
209 }
210
211 self.set_cursor_icon(platform_output.cursor_icon);
212 }
213
214 #[inline]
220 pub fn take_egui_input(&mut self) -> egui::RawInput {
221 self.egui_input.time = Some(self.start_time.elapsed().as_secs_f64());
222 self.egui_input.viewport_id = self.viewport_id;
224
225 let native_ppp = self
231 .egui_input
232 .viewports
233 .get(&self.viewport_id)
234 .and_then(|v| v.native_pixels_per_point)
235 .unwrap_or(1.0);
236 let ppp = self.egui_ctx.zoom_factor() * native_ppp;
237 if ppp > 0.0 {
238 let points = egui::vec2(self.drawable_size.0 as f32, self.drawable_size.1 as f32) / ppp;
239 if points.x > 0.0 && points.y > 0.0 {
240 let screen = self.rotation.screen_size(points);
243 self.egui_input.screen_rect =
244 Some(egui::Rect::from_min_size(egui::Pos2::ZERO, screen));
245 }
246 }
247
248 self.egui_input.take()
249 }
250
251 #[inline]
261 fn cached_pixels_per_point(&self) -> f32 {
262 let native_ppp = self
263 .egui_input
264 .viewports
265 .get(&self.viewport_id)
266 .and_then(|v| v.native_pixels_per_point)
267 .unwrap_or(1.0);
268 self.egui_ctx.zoom_factor() * native_ppp
269 }
270
271 #[inline]
276 fn pos_in_points(&self, x: f32, y: f32) -> egui::Pos2 {
277 let ppp = self.cached_pixels_per_point();
278 let scale = if ppp > 0.0 { ppp } else { 1.0 };
279 let window = egui::vec2(self.drawable_size.0 as f32, self.drawable_size.1 as f32) / scale;
280 self.rotation.from_window(egui::pos2(x, y) / scale, window)
281 }
282
283 pub fn on_event(
287 &mut self,
288 window: &sdl2::video::Window,
289 event: &sdl2::event::Event,
290 ) -> EventResponse {
291 use sdl2::event::Event::*;
292 match event {
293 Window { win_event, .. } => self.on_window_event(*win_event, window),
294 MouseButtonDown {
295 mouse_btn, x, y, ..
296 } => self.on_mouse_button_event(*mouse_btn, true, *x, *y),
297 MouseButtonUp {
298 mouse_btn, x, y, ..
299 } => self.on_mouse_button_event(*mouse_btn, false, *x, *y),
300 MouseMotion { x, y, .. } => {
301 let pos = self.pos_in_points(*x as f32, *y as f32);
302 self.pointer_pos_in_points = Some(pos);
303 self.egui_input.events.push(egui::Event::PointerMoved(pos));
304 EventResponse {
305 repaint: true,
306 consumed: self.egui_ctx.egui_is_using_pointer(),
307 }
308 }
309 MouseWheel { x, y, .. } => {
310 let dx = *x as f32;
311 let dy = *y as f32;
312
313 if self.modifiers.command {
314 let delta = (dy / 125.0).exp();
316 self.egui_input.events.push(egui::Event::Zoom(delta));
317 } else if self.modifiers.shift {
318 self.egui_input.events.push(egui::Event::MouseWheel {
320 unit: MouseWheelUnit::Line,
321 delta: egui::vec2(dx + dy, 0.0),
322 phase: egui::TouchPhase::Move,
323 modifiers: self.modifiers,
324 });
325 } else {
326 self.egui_input.events.push(egui::Event::MouseWheel {
328 unit: MouseWheelUnit::Line,
329 delta: egui::vec2(dx, dy),
330 phase: egui::TouchPhase::Move,
331 modifiers: self.modifiers,
332 });
333 }
334 EventResponse {
335 repaint: true,
336 consumed: self.egui_ctx.egui_wants_pointer_input(),
337 }
338 }
339 KeyUp {
340 keycode: Some(kc),
341 scancode: Some(sc),
342 keymod,
343 repeat,
344 ..
345 } => self.on_keyboard_event(*kc, *sc, *keymod, false, *repeat),
346 KeyDown {
347 keycode: Some(kc),
348 scancode: Some(sc),
349 keymod,
350 repeat,
351 ..
352 } => {
353 let resp = self.on_keyboard_event(*kc, *sc, *keymod, true, *repeat);
354
355 if self.modifiers.command && *kc == Keycode::C {
356 self.egui_input.events.push(egui::Event::Copy);
357 } else if self.modifiers.command && *kc == Keycode::X {
358 self.egui_input.events.push(egui::Event::Cut);
359 } else if self.modifiers.command && *kc == Keycode::V {
360 if let Ok(contents) = self.clipboard.clipboard_text() {
361 self.egui_input.events.push(egui::Event::Text(contents));
362 }
363 }
364
365 resp
366 }
367 TextInput { text, .. } => {
368 let mut resp = EventResponse {
369 consumed: true,
370 repaint: false,
371 };
372 if !text.is_empty() {
373 let is_cmd =
376 self.modifiers.ctrl || self.modifiers.command || self.modifiers.mac_cmd;
377
378 if !is_cmd {
379 self.egui_input
380 .events
381 .push(egui::Event::Text(text.to_owned()));
382
383 resp.repaint = true;
384 }
385 }
386
387 resp
388 }
389 DropFile { filename, .. } => {
390 self.egui_input
391 .dropped_files
392 .push(std::sync::Arc::new(SdlDroppedFile(
393 std::path::PathBuf::from(filename),
394 )));
395 EventResponse {
396 repaint: true,
397 consumed: false,
398 }
399 }
400 FingerDown {
401 touch_id,
402 finger_id,
403 x,
404 y,
405 pressure,
406 ..
407 } => self.on_touch(TouchInfo {
408 phase: egui::TouchPhase::Start,
409 touch_id: *touch_id,
410 finger_id: *finger_id,
411 x: *x,
412 y: *y,
413 pressure: *pressure,
414 }),
415 FingerUp {
416 touch_id,
417 finger_id,
418 x,
419 y,
420 pressure,
421 ..
422 } => self.on_touch(TouchInfo {
423 phase: egui::TouchPhase::End,
424 touch_id: *touch_id,
425 finger_id: *finger_id,
426 x: *x,
427 y: *y,
428 pressure: *pressure,
429 }),
430 FingerMotion {
431 touch_id,
432 finger_id,
433 x,
434 y,
435 pressure,
436 ..
437 } => self.on_touch(TouchInfo {
438 phase: egui::TouchPhase::Move,
439 touch_id: *touch_id,
440 finger_id: *finger_id,
441 x: *x,
442 y: *y,
443 pressure: *pressure,
444 }),
445 _ => EventResponse::default(),
446 }
447 }
448
449 #[inline]
450 fn on_touch(&mut self, info: TouchInfo) -> EventResponse {
451 let consumed = match info.phase {
452 egui::TouchPhase::Start | egui::TouchPhase::End | egui::TouchPhase::Cancel => {
453 self.egui_ctx.egui_wants_pointer_input()
454 }
455 egui::TouchPhase::Move => self.egui_ctx.egui_is_using_pointer(),
456 };
457
458 let (win_w, win_h) = self.window_size;
466 let pixel_x = info.x * win_w as f32;
467 let pixel_y = info.y * win_h as f32;
468 let pos = self.pos_in_points(pixel_x, pixel_y);
469 self.egui_input.events.push(egui::Event::Touch {
470 device_id: egui::TouchDeviceId(info.touch_id as u64),
471 id: egui::TouchId::from(info.finger_id as u64),
472 phase: info.phase,
473 pos,
474 force: Some(info.pressure),
475 });
476
477 match info.phase {
484 egui::TouchPhase::Start if self.pointer_touch_id.is_none() => {
485 self.pointer_touch_id = Some(info.finger_id);
486 self.pointer_pos_in_points = Some(pos);
487 self.egui_input.events.push(egui::Event::PointerMoved(pos));
489 self.egui_input.events.push(egui::Event::PointerButton {
490 pos,
491 button: egui::PointerButton::Primary,
492 pressed: true,
493 modifiers: self.modifiers,
494 });
495 }
496 egui::TouchPhase::Move if self.pointer_touch_id == Some(info.finger_id) => {
497 self.pointer_pos_in_points = Some(pos);
498 self.egui_input.events.push(egui::Event::PointerMoved(pos));
499 }
500 egui::TouchPhase::End | egui::TouchPhase::Cancel
501 if self.pointer_touch_id == Some(info.finger_id) =>
502 {
503 self.pointer_touch_id = None;
504 if info.phase == egui::TouchPhase::End {
505 self.egui_input.events.push(egui::Event::PointerButton {
506 pos,
507 button: egui::PointerButton::Primary,
508 pressed: false,
509 modifiers: self.modifiers,
510 });
511 }
512 self.egui_input.events.push(egui::Event::PointerGone);
515 self.pointer_pos_in_points = None;
516 }
517 _ => {}
518 }
519
520 EventResponse {
521 repaint: true,
522 consumed,
523 }
524 }
525
526 fn on_window_event(&mut self, event: WindowEvent, window: &Window) -> EventResponse {
527 match event {
528 WindowEvent::Minimized
529 | WindowEvent::Maximized
530 | WindowEvent::Resized(_, _)
531 | WindowEvent::SizeChanged(_, _) => {
532 self.on_size_chage(window);
533 EventResponse {
534 repaint: true,
535 consumed: false,
536 }
537 }
538 WindowEvent::Shown
539 | WindowEvent::Hidden
540 | WindowEvent::Exposed
541 | WindowEvent::Moved(_, _)
542 | WindowEvent::Restored
543 | WindowEvent::Enter
544 | WindowEvent::Close => EventResponse {
545 consumed: false,
546 repaint: true,
547 },
548 WindowEvent::Leave => {
549 self.pointer_pos_in_points = None;
550 self.egui_input.events.push(egui::Event::PointerGone);
551 EventResponse {
552 repaint: true,
553 consumed: false,
554 }
555 }
556 WindowEvent::TakeFocus | WindowEvent::FocusGained => {
557 self.egui_input.focused = true;
558 self.egui_input
559 .events
560 .push(egui::Event::WindowFocused(true));
561 EventResponse {
562 repaint: true,
563 consumed: false,
564 }
565 }
566 WindowEvent::FocusLost => {
567 self.egui_input.focused = false;
568 self.egui_input
569 .events
570 .push(egui::Event::WindowFocused(false));
571 EventResponse {
572 repaint: true,
573 consumed: false,
574 }
575 }
576 WindowEvent::HitTest
577 | WindowEvent::ICCProfChanged
578 | WindowEvent::DisplayChanged(_)
579 | WindowEvent::None => EventResponse::default(),
580 }
581 }
582
583 fn on_mouse_button_event(
584 &mut self,
585 button: MouseButton,
586 pressed: bool,
587 x: i32,
588 y: i32,
589 ) -> EventResponse {
590 let Some(button) = into_egui_button(button) else {
591 return EventResponse::default();
592 };
593
594 let pos = self.pos_in_points(x as f32, y as f32);
595 self.pointer_pos_in_points = Some(pos);
596 self.egui_input.events.push(egui::Event::PointerButton {
597 pos,
598 button,
599 pressed,
600 modifiers: self.modifiers,
601 });
602 EventResponse {
603 repaint: true,
604 consumed: self.egui_ctx.egui_wants_pointer_input(),
605 }
606 }
607
608 fn on_keyboard_event(
609 &mut self,
610 keycode: Keycode,
611 scancode: Scancode,
612 keymod: Mod,
613 pressed: bool,
614 repeat: bool,
615 ) -> EventResponse {
616 let Some(key) = into_egui_key(keycode) else {
617 return EventResponse::default();
618 };
619
620 let modifiers = into_egui_modifiers(keymod);
621 if modifiers != self.modifiers {
622 self.modifiers = modifiers;
623 self.egui_input
625 .events
626 .push(egui::Event::ModifiersChanged(modifiers));
627 }
628 self.egui_input.events.push(egui::Event::Key {
629 key,
630 physical_key: into_egui_physical_key(scancode),
631 pressed,
632 repeat,
633 modifiers: self.modifiers,
634 });
635 let consumed = self.egui_ctx.egui_wants_keyboard_input() || key == Key::Tab;
637 EventResponse {
638 repaint: true,
639 consumed,
640 }
641 }
642
643 #[inline]
648 pub fn sync_window_size(&mut self, window: &Window) {
649 self.on_size_chage(window);
650 }
651
652 #[inline]
653 fn on_size_chage(&mut self, window: &Window) {
654 self.window_size = window.size();
655 self.drawable_size = window.drawable_size();
656 self.egui_input.screen_rect = new_screen_rect(&self.egui_ctx, window, self.rotation);
657 self.egui_input
658 .viewports
659 .entry(self.viewport_id)
660 .or_default()
661 .native_pixels_per_point = Some(native_pixels_per_point(window));
662 }
663
664 #[inline]
665 fn set_cursor_icon(&mut self, cursor_icon: egui::CursorIcon) {
666 if let Some(cursor) = &self.current_cursor {
667 if cursor.icon == cursor_icon {
668 return;
669 }
670 }
671
672 if self.pointer_pos_in_points.is_some() {
673 let system_cursor = into_sdl2_cursor(cursor_icon);
674 let mut current_cursor = CurrentCursor {
675 icon: cursor_icon,
676 cursor: None,
677 };
678
679 match Cursor::from_system(system_cursor) {
680 Ok(cursor) => {
681 cursor.set();
682 current_cursor.cursor = Some(cursor);
683 }
684 Err(e) => {
685 log::warn!("Failed to set cursor: {e}")
686 }
687 }
688 self.current_cursor.replace(current_cursor);
689 } else {
690 self.current_cursor = None;
691 }
692 }
693}
694
695#[inline]
696pub fn poiner_pos_in_points(
697 egui_ctx: &egui::Context,
698 window: &Window,
699 x: f32,
700 y: f32,
701) -> egui::Pos2 {
702 let pixels_per_point = pixels_per_point(egui_ctx, window);
703 egui::pos2(x, y) / pixels_per_point
704}
705
706#[inline]
707pub fn into_egui_modifiers(m: Mod) -> Modifiers {
708 let mut mods = Modifiers::NONE;
709
710 if m.intersects(Mod::LCTRLMOD | Mod::RCTRLMOD) {
711 mods.ctrl = true;
712 mods.command = true;
713 }
714
715 if m.intersects(Mod::LSHIFTMOD | Mod::RSHIFTMOD) {
716 mods.shift = true;
717 }
718
719 if m.intersects(Mod::LALTMOD | Mod::RALTMOD) {
720 mods.alt = true;
721 }
722
723 if m.intersects(Mod::LGUIMOD | Mod::RGUIMOD) {
724 mods.mac_cmd = true;
725 mods.command = true;
726 }
727
728 mods
729}
730
731#[inline]
732fn into_sdl2_cursor(cursor_icon: egui::CursorIcon) -> SystemCursor {
733 match cursor_icon {
734 egui::CursorIcon::Crosshair => SystemCursor::Crosshair,
735 egui::CursorIcon::Default => SystemCursor::Arrow,
736 egui::CursorIcon::Grab => SystemCursor::Hand,
737 egui::CursorIcon::Grabbing => SystemCursor::SizeAll,
738 egui::CursorIcon::Move => SystemCursor::SizeAll,
739 egui::CursorIcon::PointingHand => SystemCursor::Hand,
740 egui::CursorIcon::ResizeHorizontal => SystemCursor::SizeWE,
741 egui::CursorIcon::ResizeNeSw => SystemCursor::SizeNESW,
742 egui::CursorIcon::ResizeNwSe => SystemCursor::SizeNWSE,
743 egui::CursorIcon::ResizeVertical => SystemCursor::SizeNS,
744 egui::CursorIcon::Text => SystemCursor::IBeam,
745 egui::CursorIcon::NotAllowed | egui::CursorIcon::NoDrop => SystemCursor::No,
746 egui::CursorIcon::Wait => SystemCursor::Wait,
747 _ => SystemCursor::Arrow,
749 }
750}
751
752#[inline]
753pub fn screen_size_in_pixels(window: &Window) -> egui::Vec2 {
754 let (width, height) = window.drawable_size();
755 egui::vec2(width as f32, height as f32)
756}
757
758#[inline]
759pub fn pixels_per_point(egui_ctx: &egui::Context, window: &Window) -> f32 {
760 let native_pixels_per_point = native_pixels_per_point(window);
761 let egui_zoom_factor = egui_ctx.zoom_factor();
762 egui_zoom_factor * native_pixels_per_point
763}
764
765#[inline]
766fn new_screen_rect(
767 egui_ctx: &egui::Context,
768 window: &Window,
769 rotation: crate::Rotation,
770) -> Option<Rect> {
771 let screen_size_in_pixels = screen_size_in_pixels(window);
772 let screen_size_in_points = screen_size_in_pixels / pixels_per_point(egui_ctx, window);
773
774 (screen_size_in_points.x > 0.0 && screen_size_in_points.y > 0.0)
775 .then(|| Rect::from_min_size(Pos2::ZERO, rotation.screen_size(screen_size_in_points)))
776}
777
778#[inline]
779pub fn native_pixels_per_point(window: &Window) -> f32 {
780 let (win_w, win_h) = window.size();
781 let (draw_w, _draw_h) = window.drawable_size();
782
783 if win_w > 0 && win_h > 0 {
784 draw_w as f32 / win_w as f32
785 } else {
786 1.0
787 }
788}
789
790#[inline]
791pub fn into_egui_button(btn: MouseButton) -> Option<PointerButton> {
792 match btn {
793 MouseButton::Left => Some(egui::PointerButton::Primary),
794 MouseButton::Middle => Some(egui::PointerButton::Middle),
795 MouseButton::Right => Some(egui::PointerButton::Secondary),
796 MouseButton::Unknown => None,
797 MouseButton::X1 => Some(egui::PointerButton::Extra1),
798 MouseButton::X2 => Some(egui::PointerButton::Extra2),
799 }
800}
801
802pub fn into_egui_key(key: Keycode) -> Option<Key> {
803 Some(match key {
804 Keycode::Left => Key::ArrowLeft,
805 Keycode::Up => Key::ArrowUp,
806 Keycode::Right => Key::ArrowRight,
807 Keycode::Down => Key::ArrowDown,
808
809 Keycode::Escape => Key::Escape,
810 Keycode::Tab => Key::Tab,
811 Keycode::Backspace => Key::Backspace,
812 Keycode::Space => Key::Space,
813 Keycode::Return => Key::Enter,
814
815 Keycode::Insert => Key::Insert,
816 Keycode::Home => Key::Home,
817 Keycode::Delete => Key::Delete,
818 Keycode::End => Key::End,
819 Keycode::PageDown => Key::PageDown,
820 Keycode::PageUp => Key::PageUp,
821
822 Keycode::Kp0 | Keycode::Num0 => Key::Num0,
823 Keycode::Kp1 | Keycode::Num1 => Key::Num1,
824 Keycode::Kp2 | Keycode::Num2 => Key::Num2,
825 Keycode::Kp3 | Keycode::Num3 => Key::Num3,
826 Keycode::Kp4 | Keycode::Num4 => Key::Num4,
827 Keycode::Kp5 | Keycode::Num5 => Key::Num5,
828 Keycode::Kp6 | Keycode::Num6 => Key::Num6,
829 Keycode::Kp7 | Keycode::Num7 => Key::Num7,
830 Keycode::Kp8 | Keycode::Num8 => Key::Num8,
831 Keycode::Kp9 | Keycode::Num9 => Key::Num9,
832
833 Keycode::A => Key::A,
834 Keycode::B => Key::B,
835 Keycode::C => Key::C,
836 Keycode::D => Key::D,
837 Keycode::E => Key::E,
838 Keycode::F => Key::F,
839 Keycode::G => Key::G,
840 Keycode::H => Key::H,
841 Keycode::I => Key::I,
842 Keycode::J => Key::J,
843 Keycode::K => Key::K,
844 Keycode::L => Key::L,
845 Keycode::M => Key::M,
846 Keycode::N => Key::N,
847 Keycode::O => Key::O,
848 Keycode::P => Key::P,
849 Keycode::Q => Key::Q,
850 Keycode::R => Key::R,
851 Keycode::S => Key::S,
852 Keycode::T => Key::T,
853 Keycode::U => Key::U,
854 Keycode::V => Key::V,
855 Keycode::W => Key::W,
856 Keycode::X => Key::X,
857 Keycode::Y => Key::Y,
858 Keycode::Z => Key::Z,
859
860 Keycode::F1 => Key::F1,
861 Keycode::F2 => Key::F2,
862 Keycode::F3 => Key::F3,
863 Keycode::F4 => Key::F4,
864 Keycode::F5 => Key::F5,
865 Keycode::F6 => Key::F6,
866 Keycode::F7 => Key::F7,
867 Keycode::F8 => Key::F8,
868 Keycode::F9 => Key::F9,
869 Keycode::F10 => Key::F10,
870 Keycode::F11 => Key::F11,
871 Keycode::F12 => Key::F12,
872
873 Keycode::Minus => Key::Minus,
874 Keycode::Equals => Key::Equals,
875 Keycode::Semicolon => Key::Semicolon,
876 Keycode::Comma => Key::Comma,
877 Keycode::Period => Key::Period,
878 Keycode::Slash => Key::Slash,
879 Keycode::Backslash => Key::Backslash,
880
881 _ => {
882 return None;
883 }
884 })
885}
886
887pub fn into_egui_physical_key(scancode: Scancode) -> Option<Key> {
888 match scancode {
889 Scancode::A => Some(Key::A),
890 Scancode::B => Some(Key::B),
891 Scancode::C => Some(Key::C),
892 Scancode::D => Some(Key::D),
893 Scancode::E => Some(Key::E),
894 Scancode::F => Some(Key::F),
895 Scancode::G => Some(Key::G),
896 Scancode::H => Some(Key::H),
897 Scancode::I => Some(Key::I),
898 Scancode::J => Some(Key::J),
899 Scancode::K => Some(Key::K),
900 Scancode::L => Some(Key::L),
901 Scancode::M => Some(Key::M),
902 Scancode::N => Some(Key::N),
903 Scancode::O => Some(Key::O),
904 Scancode::P => Some(Key::P),
905 Scancode::Q => Some(Key::Q),
906 Scancode::R => Some(Key::R),
907 Scancode::S => Some(Key::S),
908 Scancode::T => Some(Key::T),
909 Scancode::U => Some(Key::U),
910 Scancode::V => Some(Key::V),
911 Scancode::W => Some(Key::W),
912 Scancode::X => Some(Key::X),
913 Scancode::Y => Some(Key::Y),
914 Scancode::Z => Some(Key::Z),
915
916 Scancode::Num0 => Some(Key::Num0),
917 Scancode::Num1 => Some(Key::Num1),
918 Scancode::Num2 => Some(Key::Num2),
919 Scancode::Num3 => Some(Key::Num3),
920 Scancode::Num4 => Some(Key::Num4),
921 Scancode::Num5 => Some(Key::Num5),
922 Scancode::Num6 => Some(Key::Num6),
923 Scancode::Num7 => Some(Key::Num7),
924 Scancode::Num8 => Some(Key::Num8),
925 Scancode::Num9 => Some(Key::Num9),
926
927 Scancode::F1 => Some(Key::F1),
928 Scancode::F2 => Some(Key::F2),
929 Scancode::F3 => Some(Key::F3),
930 Scancode::F4 => Some(Key::F4),
931 Scancode::F5 => Some(Key::F5),
932 Scancode::F6 => Some(Key::F6),
933 Scancode::F7 => Some(Key::F7),
934 Scancode::F8 => Some(Key::F8),
935 Scancode::F9 => Some(Key::F9),
936 Scancode::F10 => Some(Key::F10),
937 Scancode::F11 => Some(Key::F11),
938 Scancode::F12 => Some(Key::F12),
939
940 Scancode::Up => Some(Key::ArrowUp),
941 Scancode::Down => Some(Key::ArrowDown),
942 Scancode::Left => Some(Key::ArrowLeft),
943 Scancode::Right => Some(Key::ArrowRight),
944
945 Scancode::Return => Some(Key::Enter),
946 Scancode::Escape => Some(Key::Escape),
947 Scancode::Backspace => Some(Key::Backspace),
948 Scancode::Tab => Some(Key::Tab),
949 Scancode::Space => Some(Key::Space),
950
951 _ => None,
952 }
953}
954
955struct TouchInfo {
956 phase: egui::TouchPhase,
957 touch_id: i64,
958 finger_id: i64,
959 x: f32,
960 y: f32,
961 pressure: f32,
962}