iced_winit/
conversion.rs

1//! Convert [`winit`] types into [`iced_runtime`] types, and viceversa.
2//!
3//! [`winit`]: https://github.com/rust-windowing/winit
4//! [`iced_runtime`]: https://github.com/iced-rs/iced/tree/0.13/runtime
5use std::hash::DefaultHasher;
6use std::hash::Hash;
7use std::hash::Hasher;
8
9use crate::core::keyboard;
10use crate::core::mouse;
11use crate::core::touch;
12use crate::core::window;
13use crate::core::{Event, Point, Size};
14
15/// Converts some [`window::Settings`] into some `WindowAttributes` from `winit`.
16pub fn window_attributes(
17    settings: window::Settings,
18    title: &str,
19    primary_monitor: Option<winit::monitor::MonitorHandle>,
20    _id: Option<String>,
21) -> winit::window::WindowAttributes {
22    let mut attributes = winit::window::WindowAttributes::default();
23
24    attributes = attributes
25        .with_title(title)
26        .with_surface_size(winit::dpi::LogicalSize {
27            width: settings.size.width,
28            height: settings.size.height,
29        })
30        .with_resizable(settings.resizable)
31        .with_enabled_buttons(if settings.resizable {
32            winit::window::WindowButtons::all()
33        } else {
34            winit::window::WindowButtons::CLOSE
35                | winit::window::WindowButtons::MINIMIZE
36        })
37        .with_decorations(settings.decorations)
38        .with_transparent(settings.transparent)
39        .with_window_icon(settings.icon.and_then(icon))
40        .with_window_level(window_level(settings.level))
41        .with_visible(settings.visible);
42
43    if let Some(position) =
44        position(primary_monitor.as_ref(), settings.size, settings.position)
45    {
46        attributes = attributes.with_position(position);
47    }
48
49    if let Some(min_size) = settings.min_size {
50        attributes =
51            attributes.with_min_surface_size(winit::dpi::LogicalSize {
52                width: min_size.width,
53                height: min_size.height,
54            });
55    }
56
57    if let Some(max_size) = settings.max_size {
58        attributes =
59            attributes.with_max_surface_size(winit::dpi::LogicalSize {
60                width: max_size.width,
61                height: max_size.height,
62            });
63    }
64
65    #[cfg(any(
66        target_os = "dragonfly",
67        target_os = "freebsd",
68        target_os = "netbsd",
69        target_os = "openbsd"
70    ))]
71    {
72        use ::winit::platform::wayland::WindowAttributesExtWayland;
73
74        if let Some(id) = _id {
75            attributes = attributes.with_name(id.clone(), id);
76        }
77    }
78
79    #[cfg(target_os = "windows")]
80    {
81        use winit::platform::windows::WindowAttributesExtWindows;
82
83        attributes = attributes
84            .with_drag_and_drop(settings.platform_specific.drag_and_drop);
85
86        attributes = attributes
87            .with_skip_taskbar(settings.platform_specific.skip_taskbar);
88
89        attributes = attributes.with_undecorated_shadow(
90            settings.platform_specific.undecorated_shadow,
91        );
92    }
93
94    #[cfg(target_os = "macos")]
95    {
96        use winit::platform::macos::WindowAttributesExtMacOS;
97
98        attributes = attributes
99            .with_title_hidden(settings.platform_specific.title_hidden)
100            .with_titlebar_transparent(
101                settings.platform_specific.titlebar_transparent,
102            )
103            .with_fullsize_content_view(
104                settings.platform_specific.fullsize_content_view,
105            );
106    }
107
108    #[cfg(target_os = "linux")]
109    {
110        #[cfg(feature = "x11")]
111        {
112            use winit::platform::x11::WindowAttributesExtX11;
113
114            attributes = attributes
115                .with_override_redirect(
116                    settings.platform_specific.override_redirect,
117                )
118                .with_name(
119                    &settings.platform_specific.application_id,
120                    &settings.platform_specific.application_id,
121                );
122        }
123        #[cfg(feature = "wayland")]
124        {
125            use winit::platform::wayland::WindowAttributesExtWayland;
126
127            attributes = attributes.with_name(
128                &settings.platform_specific.application_id,
129                &settings.platform_specific.application_id,
130            );
131        }
132    }
133
134    attributes
135}
136
137/// Converts a winit window event into an iced event.
138pub fn window_event(
139    event: winit::event::WindowEvent,
140    scale_factor: f64,
141    modifiers: winit::keyboard::ModifiersState,
142    window: &dyn winit::window::Window,
143) -> Option<Event> {
144    use winit::event::WindowEvent;
145
146    match event {
147        WindowEvent::SurfaceResized(new_size) => {
148            let logical_size = new_size.to_logical(scale_factor);
149
150            Some(Event::Window(window::Event::Resized(Size {
151                width: logical_size.width,
152                height: logical_size.height,
153            })))
154        }
155        WindowEvent::CloseRequested => {
156            Some(Event::Window(window::Event::CloseRequested))
157        }
158        WindowEvent::CursorMoved { position, .. } => {
159            let position = position.to_logical::<f64>(scale_factor);
160
161            Some(Event::Mouse(mouse::Event::CursorMoved {
162                position: Point::new(position.x as f32, position.y as f32),
163            }))
164        }
165        WindowEvent::CursorEntered { .. } => {
166            Some(Event::Mouse(mouse::Event::CursorEntered))
167        }
168        WindowEvent::CursorLeft { .. } => {
169            Some(Event::Mouse(mouse::Event::CursorLeft))
170        }
171        WindowEvent::MouseInput { button, state, .. } => {
172            let button = mouse_button(button);
173
174            Some(Event::Mouse(match state {
175                winit::event::ElementState::Pressed => {
176                    mouse::Event::ButtonPressed(button)
177                }
178                winit::event::ElementState::Released => {
179                    mouse::Event::ButtonReleased(button)
180                }
181            }))
182        }
183        WindowEvent::MouseWheel { delta, .. } => match delta {
184            winit::event::MouseScrollDelta::LineDelta(delta_x, delta_y) => {
185                Some(Event::Mouse(mouse::Event::WheelScrolled {
186                    delta: mouse::ScrollDelta::Lines {
187                        x: delta_x,
188                        y: delta_y,
189                    },
190                }))
191            }
192            winit::event::MouseScrollDelta::PixelDelta(position) => {
193                Some(Event::Mouse(mouse::Event::WheelScrolled {
194                    delta: mouse::ScrollDelta::Pixels {
195                        x: position.x as f32,
196                        y: position.y as f32,
197                    },
198                }))
199            }
200        },
201        WindowEvent::KeyboardInput { event, .. } => Some(Event::Keyboard({
202            let key = {
203                #[cfg(not(target_arch = "wasm32"))]
204                {
205                    use winit::platform::modifier_supplement::KeyEventExtModifierSupplement;
206                    event.key_without_modifiers()
207                }
208
209                #[cfg(target_arch = "wasm32")]
210                {
211                    // TODO: Fix inconsistent API on Wasm
212                    event.logical_key.clone()
213                }
214            };
215
216            let text = {
217                #[cfg(not(target_arch = "wasm32"))]
218                {
219                    use crate::core::SmolStr;
220                    use winit::platform::modifier_supplement::KeyEventExtModifierSupplement;
221
222                    event.text_with_all_modifiers().map(SmolStr::new)
223                }
224
225                #[cfg(target_arch = "wasm32")]
226                {
227                    // TODO: Fix inconsistent API on Wasm
228                    event.text
229                }
230            }.filter(|text| !text.as_str().chars().any(is_private_use));
231
232            let winit::event::KeyEvent {
233                state,
234                location,
235                logical_key,
236                physical_key,
237                ..
238            } = event;
239
240            let key = self::key(key);
241            let modified_key = self::key(logical_key);
242            let physical_key = self::physical_key(physical_key);
243            let modifiers = self::modifiers(modifiers);
244
245            let location = match location {
246                winit::keyboard::KeyLocation::Standard => {
247                    keyboard::Location::Standard
248                }
249                winit::keyboard::KeyLocation::Left => keyboard::Location::Left,
250                winit::keyboard::KeyLocation::Right => {
251                    keyboard::Location::Right
252                }
253                winit::keyboard::KeyLocation::Numpad => {
254                    keyboard::Location::Numpad
255                }
256            };
257
258            match state {
259                winit::event::ElementState::Pressed => {
260                    keyboard::Event::KeyPressed {
261                        key,
262                        modified_key,
263                        physical_key,
264                        modifiers,
265                        location,
266                        text,
267                    }
268                }
269                winit::event::ElementState::Released => {
270                    keyboard::Event::KeyReleased {
271                        key,
272                        modified_key,
273                        physical_key,
274                        modifiers,
275                        location,
276                    }
277                }
278            }
279        })),
280        WindowEvent::ModifiersChanged(new_modifiers) => {
281            Some(Event::Keyboard(keyboard::Event::ModifiersChanged(
282                self::modifiers(new_modifiers.state()),
283            )))
284        }
285        WindowEvent::Focused(focused) => Some(Event::Window(if focused {
286            window::Event::Focused
287        } else {
288            window::Event::Unfocused
289        })),
290        WindowEvent::HoveredFile(path) => {
291            Some(Event::Window(window::Event::FileHovered(path.clone())))
292        }
293        WindowEvent::DroppedFile(path) => {
294            Some(Event::Window(window::Event::FileDropped(path.clone())))
295        }
296        WindowEvent::HoveredFileCancelled => {
297            Some(Event::Window(window::Event::FilesHoveredLeft))
298        }
299        WindowEvent::Touch(touch) => {
300            Some(Event::Touch(touch_event(touch, scale_factor)))
301        }
302        WindowEvent::Moved(position) => {
303            let winit::dpi::LogicalPosition { x, y } =
304                position.to_logical(scale_factor);
305
306            Some(Event::Window(window::Event::Moved(Point::new(x, y))))
307        }
308        #[cfg(feature = "wayland")]
309        WindowEvent::SuggestedBounds(bounds) => {
310            let size = bounds.map(|bounds| {
311                let size = bounds.to_logical(scale_factor);
312                Size::new(size.width, size.height)
313            });
314
315            Some(Event::PlatformSpecific(iced_futures::core::event::PlatformSpecific::Wayland(
316                iced_runtime::core::event::wayland::Event::Window(
317                    iced_runtime::core::event::wayland::WindowEvent::SuggestedBounds(size)
318                ),
319            )))
320        }
321        #[cfg(feature = "wayland")]
322        WindowEvent::WindowStateChanged => {
323            use cctk::sctk::reexports::csd_frame::WindowState;
324            use winit::platform::wayland::WindowExtWayland;
325
326            let s = window.window_state();
327            Some(Event::PlatformSpecific(iced_futures::core::event::PlatformSpecific::Wayland(
328                iced_runtime::core::event::wayland::Event::Window(
329                    iced_runtime::core::event::wayland::WindowEvent::WindowState(s.unwrap_or(WindowState::empty()))
330                ),
331            )))
332        }
333        _ => None,
334    }
335}
336
337/// Converts a [`window::Level`] to a [`winit`] window level.
338///
339/// [`winit`]: https://github.com/rust-windowing/winit
340pub fn window_level(level: window::Level) -> winit::window::WindowLevel {
341    match level {
342        window::Level::Normal => winit::window::WindowLevel::Normal,
343        window::Level::AlwaysOnBottom => {
344            winit::window::WindowLevel::AlwaysOnBottom
345        }
346        window::Level::AlwaysOnTop => winit::window::WindowLevel::AlwaysOnTop,
347    }
348}
349
350/// Converts a [`window::Position`] to a [`winit`] logical position for a given monitor.
351///
352/// [`winit`]: https://github.com/rust-windowing/winit
353pub fn position(
354    monitor: Option<&winit::monitor::MonitorHandle>,
355    size: Size,
356    position: window::Position,
357) -> Option<winit::dpi::Position> {
358    match position {
359        window::Position::Default => None,
360        window::Position::Specific(position) => {
361            Some(winit::dpi::Position::Logical(winit::dpi::LogicalPosition {
362                x: f64::from(position.x),
363                y: f64::from(position.y),
364            }))
365        }
366        window::Position::SpecificWith(to_position) => {
367            if let Some(monitor) = monitor {
368                let start = monitor.position().unwrap_or_default();
369
370                let resolution: winit::dpi::LogicalSize<f32> = monitor
371                    .current_video_mode()
372                    .map(|m| m.size().to_logical(monitor.scale_factor()))
373                    .unwrap_or_default();
374
375                let position = to_position(
376                    size,
377                    Size::new(resolution.width, resolution.height),
378                );
379
380                let centered: winit::dpi::PhysicalPosition<i32> =
381                    winit::dpi::LogicalPosition {
382                        x: position.x,
383                        y: position.y,
384                    }
385                    .to_physical(monitor.scale_factor());
386
387                Some(winit::dpi::Position::Physical(
388                    winit::dpi::PhysicalPosition {
389                        x: start.x + centered.x,
390                        y: start.y + centered.y,
391                    },
392                ))
393            } else {
394                None
395            }
396        }
397        window::Position::Centered => {
398            if let Some(monitor) = monitor {
399                let start = monitor.position().unwrap_or_default();
400
401                let resolution: winit::dpi::LogicalSize<f64> = monitor
402                    .current_video_mode()
403                    .map(|m| m.size().to_logical(monitor.scale_factor()))
404                    .unwrap_or_default();
405
406                let centered: winit::dpi::PhysicalPosition<i32> =
407                    winit::dpi::LogicalPosition {
408                        x: (resolution.width - f64::from(size.width)) / 2.0,
409                        y: (resolution.height - f64::from(size.height)) / 2.0,
410                    }
411                    .to_physical(monitor.scale_factor());
412
413                Some(winit::dpi::Position::Physical(
414                    winit::dpi::PhysicalPosition {
415                        x: start.x + centered.x,
416                        y: start.y + centered.y,
417                    },
418                ))
419            } else {
420                None
421            }
422        }
423    }
424}
425
426/// Converts a [`window::Mode`] to a [`winit`] fullscreen mode.
427///
428/// [`winit`]: https://github.com/rust-windowing/winit
429pub fn fullscreen(
430    monitor: Option<winit::monitor::MonitorHandle>,
431    mode: window::Mode,
432) -> Option<winit::window::Fullscreen> {
433    match mode {
434        window::Mode::Windowed | window::Mode::Hidden => None,
435        window::Mode::Fullscreen => {
436            Some(winit::window::Fullscreen::Borderless(monitor))
437        }
438    }
439}
440
441/// Converts a [`window::Mode`] to a visibility flag.
442pub fn visible(mode: window::Mode) -> bool {
443    match mode {
444        window::Mode::Windowed | window::Mode::Fullscreen => true,
445        window::Mode::Hidden => false,
446    }
447}
448
449/// Converts a [`winit`] fullscreen mode to a [`window::Mode`].
450///
451/// [`winit`]: https://github.com/rust-windowing/winit
452pub fn mode(mode: Option<winit::window::Fullscreen>) -> window::Mode {
453    match mode {
454        None => window::Mode::Windowed,
455        Some(_) => window::Mode::Fullscreen,
456    }
457}
458
459/// Converts a [`mouse::Interaction`] to a [`winit`] cursor icon.
460///
461/// [`winit`]: https://github.com/rust-windowing/winit
462pub fn mouse_interaction(
463    interaction: mouse::Interaction,
464) -> Option<winit::window::CursorIcon> {
465    use mouse::Interaction;
466
467    Some(match interaction {
468        Interaction::None | Interaction::Idle => {
469            winit::window::CursorIcon::Default
470        }
471        Interaction::Pointer => winit::window::CursorIcon::Pointer,
472        Interaction::Working => winit::window::CursorIcon::Progress,
473        Interaction::Grab => winit::window::CursorIcon::Grab,
474        Interaction::Grabbing => winit::window::CursorIcon::Grabbing,
475        Interaction::Crosshair => winit::window::CursorIcon::Crosshair,
476        Interaction::Text => winit::window::CursorIcon::Text,
477        Interaction::ResizingHorizontally => {
478            winit::window::CursorIcon::EwResize
479        }
480        Interaction::ResizingVertically => winit::window::CursorIcon::NsResize,
481        Interaction::ResizingDiagonallyUp => {
482            winit::window::CursorIcon::NeswResize
483        }
484        Interaction::ResizingDiagonallyDown => {
485            winit::window::CursorIcon::NwseResize
486        }
487        Interaction::NotAllowed => winit::window::CursorIcon::NotAllowed,
488        Interaction::ZoomIn => winit::window::CursorIcon::ZoomIn,
489        Interaction::ZoomOut => winit::window::CursorIcon::ZoomOut,
490        Interaction::Cell => winit::window::CursorIcon::Cell,
491        Interaction::Move => winit::window::CursorIcon::Move,
492        Interaction::Copy => winit::window::CursorIcon::Copy,
493        Interaction::Help => winit::window::CursorIcon::Help,
494        Interaction::Hide => {
495            return None;
496        }
497    })
498}
499
500/// Converts a `MouseButton` from [`winit`] to an [`iced`] mouse button.
501///
502/// [`winit`]: https://github.com/rust-windowing/winit
503/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12
504pub fn mouse_button(mouse_button: winit::event::MouseButton) -> mouse::Button {
505    match mouse_button {
506        winit::event::MouseButton::Left => mouse::Button::Left,
507        winit::event::MouseButton::Right => mouse::Button::Right,
508        winit::event::MouseButton::Middle => mouse::Button::Middle,
509        winit::event::MouseButton::Back => mouse::Button::Back,
510        winit::event::MouseButton::Forward => mouse::Button::Forward,
511        winit::event::MouseButton::Other(other) => mouse::Button::Other(other),
512    }
513}
514
515/// Converts some `ModifiersState` from [`winit`] to an [`iced`] modifiers
516/// state.
517///
518/// [`winit`]: https://github.com/rust-windowing/winit
519/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12
520pub fn modifiers(
521    modifiers: winit::keyboard::ModifiersState,
522) -> keyboard::Modifiers {
523    let mut result = keyboard::Modifiers::empty();
524
525    result.set(keyboard::Modifiers::SHIFT, modifiers.shift_key());
526    result.set(keyboard::Modifiers::CTRL, modifiers.control_key());
527    result.set(keyboard::Modifiers::ALT, modifiers.alt_key());
528    result.set(keyboard::Modifiers::LOGO, modifiers.super_key());
529
530    result
531}
532
533/// Converts a physical cursor position to a logical `Point`.
534pub fn cursor_position(
535    position: winit::dpi::PhysicalPosition<f64>,
536    scale_factor: f64,
537) -> Point {
538    let logical_position = position.to_logical(scale_factor);
539
540    Point::new(logical_position.x, logical_position.y)
541}
542
543/// Converts a `Touch` from [`winit`] to an [`iced`] touch event.
544///
545/// [`winit`]: https://github.com/rust-windowing/winit
546/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12
547pub fn touch_event(
548    touch: winit::event::Touch,
549    scale_factor: f64,
550) -> touch::Event {
551    // TODO we probably should get the actual internal id in some way instead
552    let mut s = DefaultHasher::new();
553    touch.finger_id.hash(&mut s);
554
555    let id = touch::Finger(s.finish());
556    let position = {
557        let location = touch.location.to_logical::<f64>(scale_factor);
558
559        Point::new(location.x as f32, location.y as f32)
560    };
561
562    match touch.phase {
563        winit::event::TouchPhase::Started => {
564            touch::Event::FingerPressed { id, position }
565        }
566        winit::event::TouchPhase::Moved => {
567            touch::Event::FingerMoved { id, position }
568        }
569        winit::event::TouchPhase::Ended => {
570            touch::Event::FingerLifted { id, position }
571        }
572        winit::event::TouchPhase::Cancelled => {
573            touch::Event::FingerLost { id, position }
574        }
575    }
576}
577
578/// Converts a `Key` from [`winit`] to an [`iced`] key.
579///
580/// [`winit`]: https://github.com/rust-windowing/winit
581/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12
582pub fn key(key: winit::keyboard::Key) -> keyboard::Key {
583    use keyboard::key::Named;
584    use winit::keyboard::NamedKey;
585
586    match key {
587        winit::keyboard::Key::Character(c) => keyboard::Key::Character(c),
588        winit::keyboard::Key::Named(named_key) => {
589            keyboard::Key::Named(match named_key {
590                NamedKey::Alt => Named::Alt,
591                NamedKey::AltGraph => Named::AltGraph,
592                NamedKey::CapsLock => Named::CapsLock,
593                NamedKey::Control => Named::Control,
594                NamedKey::Fn => Named::Fn,
595                NamedKey::FnLock => Named::FnLock,
596                NamedKey::NumLock => Named::NumLock,
597                NamedKey::ScrollLock => Named::ScrollLock,
598                NamedKey::Shift => Named::Shift,
599                NamedKey::Symbol => Named::Symbol,
600                NamedKey::SymbolLock => Named::SymbolLock,
601                NamedKey::Meta => Named::Meta,
602                NamedKey::Hyper => Named::Hyper,
603                NamedKey::Super => Named::Super,
604                NamedKey::Enter => Named::Enter,
605                NamedKey::Tab => Named::Tab,
606                NamedKey::Space => Named::Space,
607                NamedKey::ArrowDown => Named::ArrowDown,
608                NamedKey::ArrowLeft => Named::ArrowLeft,
609                NamedKey::ArrowRight => Named::ArrowRight,
610                NamedKey::ArrowUp => Named::ArrowUp,
611                NamedKey::End => Named::End,
612                NamedKey::Home => Named::Home,
613                NamedKey::PageDown => Named::PageDown,
614                NamedKey::PageUp => Named::PageUp,
615                NamedKey::Backspace => Named::Backspace,
616                NamedKey::Clear => Named::Clear,
617                NamedKey::Copy => Named::Copy,
618                NamedKey::CrSel => Named::CrSel,
619                NamedKey::Cut => Named::Cut,
620                NamedKey::Delete => Named::Delete,
621                NamedKey::EraseEof => Named::EraseEof,
622                NamedKey::ExSel => Named::ExSel,
623                NamedKey::Insert => Named::Insert,
624                NamedKey::Paste => Named::Paste,
625                NamedKey::Redo => Named::Redo,
626                NamedKey::Undo => Named::Undo,
627                NamedKey::Accept => Named::Accept,
628                NamedKey::Again => Named::Again,
629                NamedKey::Attn => Named::Attn,
630                NamedKey::Cancel => Named::Cancel,
631                NamedKey::ContextMenu => Named::ContextMenu,
632                NamedKey::Escape => Named::Escape,
633                NamedKey::Execute => Named::Execute,
634                NamedKey::Find => Named::Find,
635                NamedKey::Help => Named::Help,
636                NamedKey::Pause => Named::Pause,
637                NamedKey::Play => Named::Play,
638                NamedKey::Props => Named::Props,
639                NamedKey::Select => Named::Select,
640                NamedKey::ZoomIn => Named::ZoomIn,
641                NamedKey::ZoomOut => Named::ZoomOut,
642                NamedKey::BrightnessDown => Named::BrightnessDown,
643                NamedKey::BrightnessUp => Named::BrightnessUp,
644                NamedKey::Eject => Named::Eject,
645                NamedKey::LogOff => Named::LogOff,
646                NamedKey::Power => Named::Power,
647                NamedKey::PowerOff => Named::PowerOff,
648                NamedKey::PrintScreen => Named::PrintScreen,
649                NamedKey::Hibernate => Named::Hibernate,
650                NamedKey::Standby => Named::Standby,
651                NamedKey::WakeUp => Named::WakeUp,
652                NamedKey::AllCandidates => Named::AllCandidates,
653                NamedKey::Alphanumeric => Named::Alphanumeric,
654                NamedKey::CodeInput => Named::CodeInput,
655                NamedKey::Compose => Named::Compose,
656                NamedKey::Convert => Named::Convert,
657                NamedKey::FinalMode => Named::FinalMode,
658                NamedKey::GroupFirst => Named::GroupFirst,
659                NamedKey::GroupLast => Named::GroupLast,
660                NamedKey::GroupNext => Named::GroupNext,
661                NamedKey::GroupPrevious => Named::GroupPrevious,
662                NamedKey::ModeChange => Named::ModeChange,
663                NamedKey::NextCandidate => Named::NextCandidate,
664                NamedKey::NonConvert => Named::NonConvert,
665                NamedKey::PreviousCandidate => Named::PreviousCandidate,
666                NamedKey::Process => Named::Process,
667                NamedKey::SingleCandidate => Named::SingleCandidate,
668                NamedKey::HangulMode => Named::HangulMode,
669                NamedKey::HanjaMode => Named::HanjaMode,
670                NamedKey::JunjaMode => Named::JunjaMode,
671                NamedKey::Eisu => Named::Eisu,
672                NamedKey::Hankaku => Named::Hankaku,
673                NamedKey::Hiragana => Named::Hiragana,
674                NamedKey::HiraganaKatakana => Named::HiraganaKatakana,
675                NamedKey::KanaMode => Named::KanaMode,
676                NamedKey::KanjiMode => Named::KanjiMode,
677                NamedKey::Katakana => Named::Katakana,
678                NamedKey::Romaji => Named::Romaji,
679                NamedKey::Zenkaku => Named::Zenkaku,
680                NamedKey::ZenkakuHankaku => Named::ZenkakuHankaku,
681                NamedKey::Soft1 => Named::Soft1,
682                NamedKey::Soft2 => Named::Soft2,
683                NamedKey::Soft3 => Named::Soft3,
684                NamedKey::Soft4 => Named::Soft4,
685                NamedKey::ChannelDown => Named::ChannelDown,
686                NamedKey::ChannelUp => Named::ChannelUp,
687                NamedKey::Close => Named::Close,
688                NamedKey::MailForward => Named::MailForward,
689                NamedKey::MailReply => Named::MailReply,
690                NamedKey::MailSend => Named::MailSend,
691                NamedKey::MediaClose => Named::MediaClose,
692                NamedKey::MediaFastForward => Named::MediaFastForward,
693                NamedKey::MediaPause => Named::MediaPause,
694                NamedKey::MediaPlay => Named::MediaPlay,
695                NamedKey::MediaPlayPause => Named::MediaPlayPause,
696                NamedKey::MediaRecord => Named::MediaRecord,
697                NamedKey::MediaRewind => Named::MediaRewind,
698                NamedKey::MediaStop => Named::MediaStop,
699                NamedKey::MediaTrackNext => Named::MediaTrackNext,
700                NamedKey::MediaTrackPrevious => Named::MediaTrackPrevious,
701                NamedKey::New => Named::New,
702                NamedKey::Open => Named::Open,
703                NamedKey::Print => Named::Print,
704                NamedKey::Save => Named::Save,
705                NamedKey::SpellCheck => Named::SpellCheck,
706                NamedKey::Key11 => Named::Key11,
707                NamedKey::Key12 => Named::Key12,
708                NamedKey::AudioBalanceLeft => Named::AudioBalanceLeft,
709                NamedKey::AudioBalanceRight => Named::AudioBalanceRight,
710                NamedKey::AudioBassBoostDown => Named::AudioBassBoostDown,
711                NamedKey::AudioBassBoostToggle => Named::AudioBassBoostToggle,
712                NamedKey::AudioBassBoostUp => Named::AudioBassBoostUp,
713                NamedKey::AudioFaderFront => Named::AudioFaderFront,
714                NamedKey::AudioFaderRear => Named::AudioFaderRear,
715                NamedKey::AudioSurroundModeNext => Named::AudioSurroundModeNext,
716                NamedKey::AudioTrebleDown => Named::AudioTrebleDown,
717                NamedKey::AudioTrebleUp => Named::AudioTrebleUp,
718                NamedKey::AudioVolumeDown => Named::AudioVolumeDown,
719                NamedKey::AudioVolumeUp => Named::AudioVolumeUp,
720                NamedKey::AudioVolumeMute => Named::AudioVolumeMute,
721                NamedKey::MicrophoneToggle => Named::MicrophoneToggle,
722                NamedKey::MicrophoneVolumeDown => Named::MicrophoneVolumeDown,
723                NamedKey::MicrophoneVolumeUp => Named::MicrophoneVolumeUp,
724                NamedKey::MicrophoneVolumeMute => Named::MicrophoneVolumeMute,
725                NamedKey::SpeechCorrectionList => Named::SpeechCorrectionList,
726                NamedKey::SpeechInputToggle => Named::SpeechInputToggle,
727                NamedKey::LaunchApplication1 => Named::LaunchApplication1,
728                NamedKey::LaunchApplication2 => Named::LaunchApplication2,
729                NamedKey::LaunchCalendar => Named::LaunchCalendar,
730                NamedKey::LaunchContacts => Named::LaunchContacts,
731                NamedKey::LaunchMail => Named::LaunchMail,
732                NamedKey::LaunchMediaPlayer => Named::LaunchMediaPlayer,
733                NamedKey::LaunchMusicPlayer => Named::LaunchMusicPlayer,
734                NamedKey::LaunchPhone => Named::LaunchPhone,
735                NamedKey::LaunchScreenSaver => Named::LaunchScreenSaver,
736                NamedKey::LaunchSpreadsheet => Named::LaunchSpreadsheet,
737                NamedKey::LaunchWebBrowser => Named::LaunchWebBrowser,
738                NamedKey::LaunchWebCam => Named::LaunchWebCam,
739                NamedKey::LaunchWordProcessor => Named::LaunchWordProcessor,
740                NamedKey::BrowserBack => Named::BrowserBack,
741                NamedKey::BrowserFavorites => Named::BrowserFavorites,
742                NamedKey::BrowserForward => Named::BrowserForward,
743                NamedKey::BrowserHome => Named::BrowserHome,
744                NamedKey::BrowserRefresh => Named::BrowserRefresh,
745                NamedKey::BrowserSearch => Named::BrowserSearch,
746                NamedKey::BrowserStop => Named::BrowserStop,
747                NamedKey::AppSwitch => Named::AppSwitch,
748                NamedKey::Call => Named::Call,
749                NamedKey::Camera => Named::Camera,
750                NamedKey::CameraFocus => Named::CameraFocus,
751                NamedKey::EndCall => Named::EndCall,
752                NamedKey::GoBack => Named::GoBack,
753                NamedKey::GoHome => Named::GoHome,
754                NamedKey::HeadsetHook => Named::HeadsetHook,
755                NamedKey::LastNumberRedial => Named::LastNumberRedial,
756                NamedKey::Notification => Named::Notification,
757                NamedKey::MannerMode => Named::MannerMode,
758                NamedKey::VoiceDial => Named::VoiceDial,
759                NamedKey::TV => Named::TV,
760                NamedKey::TV3DMode => Named::TV3DMode,
761                NamedKey::TVAntennaCable => Named::TVAntennaCable,
762                NamedKey::TVAudioDescription => Named::TVAudioDescription,
763                NamedKey::TVAudioDescriptionMixDown => {
764                    Named::TVAudioDescriptionMixDown
765                }
766                NamedKey::TVAudioDescriptionMixUp => {
767                    Named::TVAudioDescriptionMixUp
768                }
769                NamedKey::TVContentsMenu => Named::TVContentsMenu,
770                NamedKey::TVDataService => Named::TVDataService,
771                NamedKey::TVInput => Named::TVInput,
772                NamedKey::TVInputComponent1 => Named::TVInputComponent1,
773                NamedKey::TVInputComponent2 => Named::TVInputComponent2,
774                NamedKey::TVInputComposite1 => Named::TVInputComposite1,
775                NamedKey::TVInputComposite2 => Named::TVInputComposite2,
776                NamedKey::TVInputHDMI1 => Named::TVInputHDMI1,
777                NamedKey::TVInputHDMI2 => Named::TVInputHDMI2,
778                NamedKey::TVInputHDMI3 => Named::TVInputHDMI3,
779                NamedKey::TVInputHDMI4 => Named::TVInputHDMI4,
780                NamedKey::TVInputVGA1 => Named::TVInputVGA1,
781                NamedKey::TVMediaContext => Named::TVMediaContext,
782                NamedKey::TVNetwork => Named::TVNetwork,
783                NamedKey::TVNumberEntry => Named::TVNumberEntry,
784                NamedKey::TVPower => Named::TVPower,
785                NamedKey::TVRadioService => Named::TVRadioService,
786                NamedKey::TVSatellite => Named::TVSatellite,
787                NamedKey::TVSatelliteBS => Named::TVSatelliteBS,
788                NamedKey::TVSatelliteCS => Named::TVSatelliteCS,
789                NamedKey::TVSatelliteToggle => Named::TVSatelliteToggle,
790                NamedKey::TVTerrestrialAnalog => Named::TVTerrestrialAnalog,
791                NamedKey::TVTerrestrialDigital => Named::TVTerrestrialDigital,
792                NamedKey::TVTimer => Named::TVTimer,
793                NamedKey::AVRInput => Named::AVRInput,
794                NamedKey::AVRPower => Named::AVRPower,
795                NamedKey::ColorF0Red => Named::ColorF0Red,
796                NamedKey::ColorF1Green => Named::ColorF1Green,
797                NamedKey::ColorF2Yellow => Named::ColorF2Yellow,
798                NamedKey::ColorF3Blue => Named::ColorF3Blue,
799                NamedKey::ColorF4Grey => Named::ColorF4Grey,
800                NamedKey::ColorF5Brown => Named::ColorF5Brown,
801                NamedKey::ClosedCaptionToggle => Named::ClosedCaptionToggle,
802                NamedKey::Dimmer => Named::Dimmer,
803                NamedKey::DisplaySwap => Named::DisplaySwap,
804                NamedKey::DVR => Named::DVR,
805                NamedKey::Exit => Named::Exit,
806                NamedKey::FavoriteClear0 => Named::FavoriteClear0,
807                NamedKey::FavoriteClear1 => Named::FavoriteClear1,
808                NamedKey::FavoriteClear2 => Named::FavoriteClear2,
809                NamedKey::FavoriteClear3 => Named::FavoriteClear3,
810                NamedKey::FavoriteRecall0 => Named::FavoriteRecall0,
811                NamedKey::FavoriteRecall1 => Named::FavoriteRecall1,
812                NamedKey::FavoriteRecall2 => Named::FavoriteRecall2,
813                NamedKey::FavoriteRecall3 => Named::FavoriteRecall3,
814                NamedKey::FavoriteStore0 => Named::FavoriteStore0,
815                NamedKey::FavoriteStore1 => Named::FavoriteStore1,
816                NamedKey::FavoriteStore2 => Named::FavoriteStore2,
817                NamedKey::FavoriteStore3 => Named::FavoriteStore3,
818                NamedKey::Guide => Named::Guide,
819                NamedKey::GuideNextDay => Named::GuideNextDay,
820                NamedKey::GuidePreviousDay => Named::GuidePreviousDay,
821                NamedKey::Info => Named::Info,
822                NamedKey::InstantReplay => Named::InstantReplay,
823                NamedKey::Link => Named::Link,
824                NamedKey::ListProgram => Named::ListProgram,
825                NamedKey::LiveContent => Named::LiveContent,
826                NamedKey::Lock => Named::Lock,
827                NamedKey::MediaApps => Named::MediaApps,
828                NamedKey::MediaAudioTrack => Named::MediaAudioTrack,
829                NamedKey::MediaLast => Named::MediaLast,
830                NamedKey::MediaSkipBackward => Named::MediaSkipBackward,
831                NamedKey::MediaSkipForward => Named::MediaSkipForward,
832                NamedKey::MediaStepBackward => Named::MediaStepBackward,
833                NamedKey::MediaStepForward => Named::MediaStepForward,
834                NamedKey::MediaTopMenu => Named::MediaTopMenu,
835                NamedKey::NavigateIn => Named::NavigateIn,
836                NamedKey::NavigateNext => Named::NavigateNext,
837                NamedKey::NavigateOut => Named::NavigateOut,
838                NamedKey::NavigatePrevious => Named::NavigatePrevious,
839                NamedKey::NextFavoriteChannel => Named::NextFavoriteChannel,
840                NamedKey::NextUserProfile => Named::NextUserProfile,
841                NamedKey::OnDemand => Named::OnDemand,
842                NamedKey::Pairing => Named::Pairing,
843                NamedKey::PinPDown => Named::PinPDown,
844                NamedKey::PinPMove => Named::PinPMove,
845                NamedKey::PinPToggle => Named::PinPToggle,
846                NamedKey::PinPUp => Named::PinPUp,
847                NamedKey::PlaySpeedDown => Named::PlaySpeedDown,
848                NamedKey::PlaySpeedReset => Named::PlaySpeedReset,
849                NamedKey::PlaySpeedUp => Named::PlaySpeedUp,
850                NamedKey::RandomToggle => Named::RandomToggle,
851                NamedKey::RcLowBattery => Named::RcLowBattery,
852                NamedKey::RecordSpeedNext => Named::RecordSpeedNext,
853                NamedKey::RfBypass => Named::RfBypass,
854                NamedKey::ScanChannelsToggle => Named::ScanChannelsToggle,
855                NamedKey::ScreenModeNext => Named::ScreenModeNext,
856                NamedKey::Settings => Named::Settings,
857                NamedKey::SplitScreenToggle => Named::SplitScreenToggle,
858                NamedKey::STBInput => Named::STBInput,
859                NamedKey::STBPower => Named::STBPower,
860                NamedKey::Subtitle => Named::Subtitle,
861                NamedKey::Teletext => Named::Teletext,
862                NamedKey::VideoModeNext => Named::VideoModeNext,
863                NamedKey::Wink => Named::Wink,
864                NamedKey::ZoomToggle => Named::ZoomToggle,
865                NamedKey::F1 => Named::F1,
866                NamedKey::F2 => Named::F2,
867                NamedKey::F3 => Named::F3,
868                NamedKey::F4 => Named::F4,
869                NamedKey::F5 => Named::F5,
870                NamedKey::F6 => Named::F6,
871                NamedKey::F7 => Named::F7,
872                NamedKey::F8 => Named::F8,
873                NamedKey::F9 => Named::F9,
874                NamedKey::F10 => Named::F10,
875                NamedKey::F11 => Named::F11,
876                NamedKey::F12 => Named::F12,
877                NamedKey::F13 => Named::F13,
878                NamedKey::F14 => Named::F14,
879                NamedKey::F15 => Named::F15,
880                NamedKey::F16 => Named::F16,
881                NamedKey::F17 => Named::F17,
882                NamedKey::F18 => Named::F18,
883                NamedKey::F19 => Named::F19,
884                NamedKey::F20 => Named::F20,
885                NamedKey::F21 => Named::F21,
886                NamedKey::F22 => Named::F22,
887                NamedKey::F23 => Named::F23,
888                NamedKey::F24 => Named::F24,
889                NamedKey::F25 => Named::F25,
890                NamedKey::F26 => Named::F26,
891                NamedKey::F27 => Named::F27,
892                NamedKey::F28 => Named::F28,
893                NamedKey::F29 => Named::F29,
894                NamedKey::F30 => Named::F30,
895                NamedKey::F31 => Named::F31,
896                NamedKey::F32 => Named::F32,
897                NamedKey::F33 => Named::F33,
898                NamedKey::F34 => Named::F34,
899                NamedKey::F35 => Named::F35,
900                _ => return keyboard::Key::Unidentified,
901            })
902        }
903        _ => keyboard::Key::Unidentified,
904    }
905}
906
907/// Converts a `PhysicalKey` from [`winit`] to an [`iced`] physical key.
908///
909/// [`winit`]: https://github.com/rust-windowing/winit
910/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12
911pub fn physical_key(
912    physical_key: winit::keyboard::PhysicalKey,
913) -> keyboard::key::Physical {
914    match physical_key {
915        winit::keyboard::PhysicalKey::Code(code) => key_code(code)
916            .map(keyboard::key::Physical::Code)
917            .unwrap_or(keyboard::key::Physical::Unidentified(
918                keyboard::key::NativeCode::Unidentified,
919            )),
920        winit::keyboard::PhysicalKey::Unidentified(code) => {
921            keyboard::key::Physical::Unidentified(native_key_code(code))
922        }
923    }
924}
925
926/// Converts a `KeyCode` from [`winit`] to an [`iced`] key code.
927///
928/// [`winit`]: https://github.com/rust-windowing/winit
929/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12
930pub fn key_code(
931    key_code: winit::keyboard::KeyCode,
932) -> Option<keyboard::key::Code> {
933    use winit::keyboard::KeyCode;
934
935    Some(match key_code {
936        KeyCode::Backquote => keyboard::key::Code::Backquote,
937        KeyCode::Backslash => keyboard::key::Code::Backslash,
938        KeyCode::BracketLeft => keyboard::key::Code::BracketLeft,
939        KeyCode::BracketRight => keyboard::key::Code::BracketRight,
940        KeyCode::Comma => keyboard::key::Code::Comma,
941        KeyCode::Digit0 => keyboard::key::Code::Digit0,
942        KeyCode::Digit1 => keyboard::key::Code::Digit1,
943        KeyCode::Digit2 => keyboard::key::Code::Digit2,
944        KeyCode::Digit3 => keyboard::key::Code::Digit3,
945        KeyCode::Digit4 => keyboard::key::Code::Digit4,
946        KeyCode::Digit5 => keyboard::key::Code::Digit5,
947        KeyCode::Digit6 => keyboard::key::Code::Digit6,
948        KeyCode::Digit7 => keyboard::key::Code::Digit7,
949        KeyCode::Digit8 => keyboard::key::Code::Digit8,
950        KeyCode::Digit9 => keyboard::key::Code::Digit9,
951        KeyCode::Equal => keyboard::key::Code::Equal,
952        KeyCode::IntlBackslash => keyboard::key::Code::IntlBackslash,
953        KeyCode::IntlRo => keyboard::key::Code::IntlRo,
954        KeyCode::IntlYen => keyboard::key::Code::IntlYen,
955        KeyCode::KeyA => keyboard::key::Code::KeyA,
956        KeyCode::KeyB => keyboard::key::Code::KeyB,
957        KeyCode::KeyC => keyboard::key::Code::KeyC,
958        KeyCode::KeyD => keyboard::key::Code::KeyD,
959        KeyCode::KeyE => keyboard::key::Code::KeyE,
960        KeyCode::KeyF => keyboard::key::Code::KeyF,
961        KeyCode::KeyG => keyboard::key::Code::KeyG,
962        KeyCode::KeyH => keyboard::key::Code::KeyH,
963        KeyCode::KeyI => keyboard::key::Code::KeyI,
964        KeyCode::KeyJ => keyboard::key::Code::KeyJ,
965        KeyCode::KeyK => keyboard::key::Code::KeyK,
966        KeyCode::KeyL => keyboard::key::Code::KeyL,
967        KeyCode::KeyM => keyboard::key::Code::KeyM,
968        KeyCode::KeyN => keyboard::key::Code::KeyN,
969        KeyCode::KeyO => keyboard::key::Code::KeyO,
970        KeyCode::KeyP => keyboard::key::Code::KeyP,
971        KeyCode::KeyQ => keyboard::key::Code::KeyQ,
972        KeyCode::KeyR => keyboard::key::Code::KeyR,
973        KeyCode::KeyS => keyboard::key::Code::KeyS,
974        KeyCode::KeyT => keyboard::key::Code::KeyT,
975        KeyCode::KeyU => keyboard::key::Code::KeyU,
976        KeyCode::KeyV => keyboard::key::Code::KeyV,
977        KeyCode::KeyW => keyboard::key::Code::KeyW,
978        KeyCode::KeyX => keyboard::key::Code::KeyX,
979        KeyCode::KeyY => keyboard::key::Code::KeyY,
980        KeyCode::KeyZ => keyboard::key::Code::KeyZ,
981        KeyCode::Minus => keyboard::key::Code::Minus,
982        KeyCode::Period => keyboard::key::Code::Period,
983        KeyCode::Quote => keyboard::key::Code::Quote,
984        KeyCode::Semicolon => keyboard::key::Code::Semicolon,
985        KeyCode::Slash => keyboard::key::Code::Slash,
986        KeyCode::AltLeft => keyboard::key::Code::AltLeft,
987        KeyCode::AltRight => keyboard::key::Code::AltRight,
988        KeyCode::Backspace => keyboard::key::Code::Backspace,
989        KeyCode::CapsLock => keyboard::key::Code::CapsLock,
990        KeyCode::ContextMenu => keyboard::key::Code::ContextMenu,
991        KeyCode::ControlLeft => keyboard::key::Code::ControlLeft,
992        KeyCode::ControlRight => keyboard::key::Code::ControlRight,
993        KeyCode::Enter => keyboard::key::Code::Enter,
994        KeyCode::SuperLeft => keyboard::key::Code::SuperLeft,
995        KeyCode::SuperRight => keyboard::key::Code::SuperRight,
996        KeyCode::ShiftLeft => keyboard::key::Code::ShiftLeft,
997        KeyCode::ShiftRight => keyboard::key::Code::ShiftRight,
998        KeyCode::Space => keyboard::key::Code::Space,
999        KeyCode::Tab => keyboard::key::Code::Tab,
1000        KeyCode::Convert => keyboard::key::Code::Convert,
1001        KeyCode::KanaMode => keyboard::key::Code::KanaMode,
1002        KeyCode::Lang1 => keyboard::key::Code::Lang1,
1003        KeyCode::Lang2 => keyboard::key::Code::Lang2,
1004        KeyCode::Lang3 => keyboard::key::Code::Lang3,
1005        KeyCode::Lang4 => keyboard::key::Code::Lang4,
1006        KeyCode::Lang5 => keyboard::key::Code::Lang5,
1007        KeyCode::NonConvert => keyboard::key::Code::NonConvert,
1008        KeyCode::Delete => keyboard::key::Code::Delete,
1009        KeyCode::End => keyboard::key::Code::End,
1010        KeyCode::Help => keyboard::key::Code::Help,
1011        KeyCode::Home => keyboard::key::Code::Home,
1012        KeyCode::Insert => keyboard::key::Code::Insert,
1013        KeyCode::PageDown => keyboard::key::Code::PageDown,
1014        KeyCode::PageUp => keyboard::key::Code::PageUp,
1015        KeyCode::ArrowDown => keyboard::key::Code::ArrowDown,
1016        KeyCode::ArrowLeft => keyboard::key::Code::ArrowLeft,
1017        KeyCode::ArrowRight => keyboard::key::Code::ArrowRight,
1018        KeyCode::ArrowUp => keyboard::key::Code::ArrowUp,
1019        KeyCode::NumLock => keyboard::key::Code::NumLock,
1020        KeyCode::Numpad0 => keyboard::key::Code::Numpad0,
1021        KeyCode::Numpad1 => keyboard::key::Code::Numpad1,
1022        KeyCode::Numpad2 => keyboard::key::Code::Numpad2,
1023        KeyCode::Numpad3 => keyboard::key::Code::Numpad3,
1024        KeyCode::Numpad4 => keyboard::key::Code::Numpad4,
1025        KeyCode::Numpad5 => keyboard::key::Code::Numpad5,
1026        KeyCode::Numpad6 => keyboard::key::Code::Numpad6,
1027        KeyCode::Numpad7 => keyboard::key::Code::Numpad7,
1028        KeyCode::Numpad8 => keyboard::key::Code::Numpad8,
1029        KeyCode::Numpad9 => keyboard::key::Code::Numpad9,
1030        KeyCode::NumpadAdd => keyboard::key::Code::NumpadAdd,
1031        KeyCode::NumpadBackspace => keyboard::key::Code::NumpadBackspace,
1032        KeyCode::NumpadClear => keyboard::key::Code::NumpadClear,
1033        KeyCode::NumpadClearEntry => keyboard::key::Code::NumpadClearEntry,
1034        KeyCode::NumpadComma => keyboard::key::Code::NumpadComma,
1035        KeyCode::NumpadDecimal => keyboard::key::Code::NumpadDecimal,
1036        KeyCode::NumpadDivide => keyboard::key::Code::NumpadDivide,
1037        KeyCode::NumpadEnter => keyboard::key::Code::NumpadEnter,
1038        KeyCode::NumpadEqual => keyboard::key::Code::NumpadEqual,
1039        KeyCode::NumpadHash => keyboard::key::Code::NumpadHash,
1040        KeyCode::NumpadMemoryAdd => keyboard::key::Code::NumpadMemoryAdd,
1041        KeyCode::NumpadMemoryClear => keyboard::key::Code::NumpadMemoryClear,
1042        KeyCode::NumpadMemoryRecall => keyboard::key::Code::NumpadMemoryRecall,
1043        KeyCode::NumpadMemoryStore => keyboard::key::Code::NumpadMemoryStore,
1044        KeyCode::NumpadMemorySubtract => {
1045            keyboard::key::Code::NumpadMemorySubtract
1046        }
1047        KeyCode::NumpadMultiply => keyboard::key::Code::NumpadMultiply,
1048        KeyCode::NumpadParenLeft => keyboard::key::Code::NumpadParenLeft,
1049        KeyCode::NumpadParenRight => keyboard::key::Code::NumpadParenRight,
1050        KeyCode::NumpadStar => keyboard::key::Code::NumpadStar,
1051        KeyCode::NumpadSubtract => keyboard::key::Code::NumpadSubtract,
1052        KeyCode::Escape => keyboard::key::Code::Escape,
1053        KeyCode::Fn => keyboard::key::Code::Fn,
1054        KeyCode::FnLock => keyboard::key::Code::FnLock,
1055        KeyCode::PrintScreen => keyboard::key::Code::PrintScreen,
1056        KeyCode::ScrollLock => keyboard::key::Code::ScrollLock,
1057        KeyCode::Pause => keyboard::key::Code::Pause,
1058        KeyCode::BrowserBack => keyboard::key::Code::BrowserBack,
1059        KeyCode::BrowserFavorites => keyboard::key::Code::BrowserFavorites,
1060        KeyCode::BrowserForward => keyboard::key::Code::BrowserForward,
1061        KeyCode::BrowserHome => keyboard::key::Code::BrowserHome,
1062        KeyCode::BrowserRefresh => keyboard::key::Code::BrowserRefresh,
1063        KeyCode::BrowserSearch => keyboard::key::Code::BrowserSearch,
1064        KeyCode::BrowserStop => keyboard::key::Code::BrowserStop,
1065        KeyCode::Eject => keyboard::key::Code::Eject,
1066        KeyCode::LaunchApp1 => keyboard::key::Code::LaunchApp1,
1067        KeyCode::LaunchApp2 => keyboard::key::Code::LaunchApp2,
1068        KeyCode::LaunchMail => keyboard::key::Code::LaunchMail,
1069        KeyCode::MediaPlayPause => keyboard::key::Code::MediaPlayPause,
1070        KeyCode::MediaSelect => keyboard::key::Code::MediaSelect,
1071        KeyCode::MediaStop => keyboard::key::Code::MediaStop,
1072        KeyCode::MediaTrackNext => keyboard::key::Code::MediaTrackNext,
1073        KeyCode::MediaTrackPrevious => keyboard::key::Code::MediaTrackPrevious,
1074        KeyCode::Power => keyboard::key::Code::Power,
1075        KeyCode::Sleep => keyboard::key::Code::Sleep,
1076        KeyCode::AudioVolumeDown => keyboard::key::Code::AudioVolumeDown,
1077        KeyCode::AudioVolumeMute => keyboard::key::Code::AudioVolumeMute,
1078        KeyCode::AudioVolumeUp => keyboard::key::Code::AudioVolumeUp,
1079        KeyCode::WakeUp => keyboard::key::Code::WakeUp,
1080        KeyCode::Meta => keyboard::key::Code::Meta,
1081        KeyCode::Hyper => keyboard::key::Code::Hyper,
1082        KeyCode::Turbo => keyboard::key::Code::Turbo,
1083        KeyCode::Abort => keyboard::key::Code::Abort,
1084        KeyCode::Resume => keyboard::key::Code::Resume,
1085        KeyCode::Suspend => keyboard::key::Code::Suspend,
1086        KeyCode::Again => keyboard::key::Code::Again,
1087        KeyCode::Copy => keyboard::key::Code::Copy,
1088        KeyCode::Cut => keyboard::key::Code::Cut,
1089        KeyCode::Find => keyboard::key::Code::Find,
1090        KeyCode::Open => keyboard::key::Code::Open,
1091        KeyCode::Paste => keyboard::key::Code::Paste,
1092        KeyCode::Props => keyboard::key::Code::Props,
1093        KeyCode::Select => keyboard::key::Code::Select,
1094        KeyCode::Undo => keyboard::key::Code::Undo,
1095        KeyCode::Hiragana => keyboard::key::Code::Hiragana,
1096        KeyCode::Katakana => keyboard::key::Code::Katakana,
1097        KeyCode::F1 => keyboard::key::Code::F1,
1098        KeyCode::F2 => keyboard::key::Code::F2,
1099        KeyCode::F3 => keyboard::key::Code::F3,
1100        KeyCode::F4 => keyboard::key::Code::F4,
1101        KeyCode::F5 => keyboard::key::Code::F5,
1102        KeyCode::F6 => keyboard::key::Code::F6,
1103        KeyCode::F7 => keyboard::key::Code::F7,
1104        KeyCode::F8 => keyboard::key::Code::F8,
1105        KeyCode::F9 => keyboard::key::Code::F9,
1106        KeyCode::F10 => keyboard::key::Code::F10,
1107        KeyCode::F11 => keyboard::key::Code::F11,
1108        KeyCode::F12 => keyboard::key::Code::F12,
1109        KeyCode::F13 => keyboard::key::Code::F13,
1110        KeyCode::F14 => keyboard::key::Code::F14,
1111        KeyCode::F15 => keyboard::key::Code::F15,
1112        KeyCode::F16 => keyboard::key::Code::F16,
1113        KeyCode::F17 => keyboard::key::Code::F17,
1114        KeyCode::F18 => keyboard::key::Code::F18,
1115        KeyCode::F19 => keyboard::key::Code::F19,
1116        KeyCode::F20 => keyboard::key::Code::F20,
1117        KeyCode::F21 => keyboard::key::Code::F21,
1118        KeyCode::F22 => keyboard::key::Code::F22,
1119        KeyCode::F23 => keyboard::key::Code::F23,
1120        KeyCode::F24 => keyboard::key::Code::F24,
1121        KeyCode::F25 => keyboard::key::Code::F25,
1122        KeyCode::F26 => keyboard::key::Code::F26,
1123        KeyCode::F27 => keyboard::key::Code::F27,
1124        KeyCode::F28 => keyboard::key::Code::F28,
1125        KeyCode::F29 => keyboard::key::Code::F29,
1126        KeyCode::F30 => keyboard::key::Code::F30,
1127        KeyCode::F31 => keyboard::key::Code::F31,
1128        KeyCode::F32 => keyboard::key::Code::F32,
1129        KeyCode::F33 => keyboard::key::Code::F33,
1130        KeyCode::F34 => keyboard::key::Code::F34,
1131        KeyCode::F35 => keyboard::key::Code::F35,
1132        _ => None?,
1133    })
1134}
1135
1136pub fn winit_key_code(
1137    key_code: keyboard::key::Code,
1138) -> Option<winit::keyboard::KeyCode> {
1139    use winit::keyboard::KeyCode;
1140
1141    Some(match key_code {
1142        keyboard::key::Code::Backquote => KeyCode::Backquote,
1143        keyboard::key::Code::Backslash => KeyCode::Backslash,
1144        keyboard::key::Code::BracketLeft => KeyCode::BracketLeft,
1145        keyboard::key::Code::BracketRight => KeyCode::BracketRight,
1146        keyboard::key::Code::Comma => KeyCode::Comma,
1147        keyboard::key::Code::Digit0 => KeyCode::Digit0,
1148        keyboard::key::Code::Digit1 => KeyCode::Digit1,
1149        keyboard::key::Code::Digit2 => KeyCode::Digit2,
1150        keyboard::key::Code::Digit3 => KeyCode::Digit3,
1151        keyboard::key::Code::Digit4 => KeyCode::Digit4,
1152        keyboard::key::Code::Digit5 => KeyCode::Digit5,
1153        keyboard::key::Code::Digit6 => KeyCode::Digit6,
1154        keyboard::key::Code::Digit7 => KeyCode::Digit7,
1155        keyboard::key::Code::Digit8 => KeyCode::Digit8,
1156        keyboard::key::Code::Digit9 => KeyCode::Digit9,
1157        keyboard::key::Code::Equal => KeyCode::Equal,
1158        keyboard::key::Code::IntlBackslash => KeyCode::IntlBackslash,
1159        keyboard::key::Code::IntlRo => KeyCode::IntlRo,
1160        keyboard::key::Code::IntlYen => KeyCode::IntlYen,
1161        keyboard::key::Code::KeyA => KeyCode::KeyA,
1162        keyboard::key::Code::KeyB => KeyCode::KeyB,
1163        keyboard::key::Code::KeyC => KeyCode::KeyC,
1164        keyboard::key::Code::KeyD => KeyCode::KeyD,
1165        keyboard::key::Code::KeyE => KeyCode::KeyE,
1166        keyboard::key::Code::KeyF => KeyCode::KeyF,
1167        keyboard::key::Code::KeyG => KeyCode::KeyG,
1168        keyboard::key::Code::KeyH => KeyCode::KeyH,
1169        keyboard::key::Code::KeyI => KeyCode::KeyI,
1170        keyboard::key::Code::KeyJ => KeyCode::KeyJ,
1171        keyboard::key::Code::KeyK => KeyCode::KeyK,
1172        keyboard::key::Code::KeyL => KeyCode::KeyL,
1173        keyboard::key::Code::KeyM => KeyCode::KeyM,
1174        keyboard::key::Code::KeyN => KeyCode::KeyN,
1175        keyboard::key::Code::KeyO => KeyCode::KeyO,
1176        keyboard::key::Code::KeyP => KeyCode::KeyP,
1177        keyboard::key::Code::KeyQ => KeyCode::KeyQ,
1178        keyboard::key::Code::KeyR => KeyCode::KeyR,
1179        keyboard::key::Code::KeyS => KeyCode::KeyS,
1180        keyboard::key::Code::KeyT => KeyCode::KeyT,
1181        keyboard::key::Code::KeyU => KeyCode::KeyU,
1182        keyboard::key::Code::KeyV => KeyCode::KeyV,
1183        keyboard::key::Code::KeyW => KeyCode::KeyW,
1184        keyboard::key::Code::KeyX => KeyCode::KeyX,
1185        keyboard::key::Code::KeyY => KeyCode::KeyY,
1186        keyboard::key::Code::KeyZ => KeyCode::KeyZ,
1187        keyboard::key::Code::Minus => KeyCode::Minus,
1188        keyboard::key::Code::Period => KeyCode::Period,
1189        keyboard::key::Code::Quote => KeyCode::Quote,
1190        keyboard::key::Code::Semicolon => KeyCode::Semicolon,
1191        keyboard::key::Code::Slash => KeyCode::Slash,
1192        keyboard::key::Code::AltLeft => KeyCode::AltLeft,
1193        keyboard::key::Code::AltRight => KeyCode::AltRight,
1194        keyboard::key::Code::Backspace => KeyCode::Backspace,
1195        keyboard::key::Code::CapsLock => KeyCode::CapsLock,
1196        keyboard::key::Code::ContextMenu => KeyCode::ContextMenu,
1197        keyboard::key::Code::ControlLeft => KeyCode::ControlLeft,
1198        keyboard::key::Code::ControlRight => KeyCode::ControlRight,
1199        keyboard::key::Code::Enter => KeyCode::Enter,
1200        keyboard::key::Code::SuperLeft => KeyCode::SuperLeft,
1201        keyboard::key::Code::SuperRight => KeyCode::SuperRight,
1202        keyboard::key::Code::ShiftLeft => KeyCode::ShiftLeft,
1203        keyboard::key::Code::ShiftRight => KeyCode::ShiftRight,
1204        keyboard::key::Code::Space => KeyCode::Space,
1205        keyboard::key::Code::Tab => KeyCode::Tab,
1206        keyboard::key::Code::Convert => KeyCode::Convert,
1207        keyboard::key::Code::KanaMode => KeyCode::KanaMode,
1208        keyboard::key::Code::Lang1 => KeyCode::Lang1,
1209        keyboard::key::Code::Lang2 => KeyCode::Lang2,
1210        keyboard::key::Code::Lang3 => KeyCode::Lang3,
1211        keyboard::key::Code::Lang4 => KeyCode::Lang4,
1212        keyboard::key::Code::Lang5 => KeyCode::Lang5,
1213        keyboard::key::Code::NonConvert => KeyCode::NonConvert,
1214        keyboard::key::Code::Delete => KeyCode::Delete,
1215        keyboard::key::Code::End => KeyCode::End,
1216        keyboard::key::Code::Help => KeyCode::Help,
1217        keyboard::key::Code::Home => KeyCode::Home,
1218        keyboard::key::Code::Insert => KeyCode::Insert,
1219        keyboard::key::Code::PageDown => KeyCode::PageDown,
1220        keyboard::key::Code::PageUp => KeyCode::PageUp,
1221        keyboard::key::Code::ArrowDown => KeyCode::ArrowDown,
1222        keyboard::key::Code::ArrowLeft => KeyCode::ArrowLeft,
1223        keyboard::key::Code::ArrowRight => KeyCode::ArrowRight,
1224        keyboard::key::Code::ArrowUp => KeyCode::ArrowUp,
1225        keyboard::key::Code::NumLock => KeyCode::NumLock,
1226        keyboard::key::Code::Numpad0 => KeyCode::Numpad0,
1227        keyboard::key::Code::Numpad1 => KeyCode::Numpad1,
1228        keyboard::key::Code::Numpad2 => KeyCode::Numpad2,
1229        keyboard::key::Code::Numpad3 => KeyCode::Numpad3,
1230        keyboard::key::Code::Numpad4 => KeyCode::Numpad4,
1231        keyboard::key::Code::Numpad5 => KeyCode::Numpad5,
1232        keyboard::key::Code::Numpad6 => KeyCode::Numpad6,
1233        keyboard::key::Code::Numpad7 => KeyCode::Numpad7,
1234        keyboard::key::Code::Numpad8 => KeyCode::Numpad8,
1235        keyboard::key::Code::Numpad9 => KeyCode::Numpad9,
1236        keyboard::key::Code::NumpadAdd => KeyCode::NumpadAdd,
1237        keyboard::key::Code::NumpadBackspace => KeyCode::NumpadBackspace,
1238        keyboard::key::Code::NumpadClear => KeyCode::NumpadClear,
1239        keyboard::key::Code::NumpadClearEntry => KeyCode::NumpadClearEntry,
1240        keyboard::key::Code::NumpadComma => KeyCode::NumpadComma,
1241        keyboard::key::Code::NumpadDecimal => KeyCode::NumpadDecimal,
1242        keyboard::key::Code::NumpadDivide => KeyCode::NumpadDivide,
1243        keyboard::key::Code::NumpadEnter => KeyCode::NumpadEnter,
1244        keyboard::key::Code::NumpadEqual => KeyCode::NumpadEqual,
1245        keyboard::key::Code::NumpadHash => KeyCode::NumpadHash,
1246        keyboard::key::Code::NumpadMemoryAdd => KeyCode::NumpadMemoryAdd,
1247        keyboard::key::Code::NumpadMemoryClear => KeyCode::NumpadMemoryClear,
1248        keyboard::key::Code::NumpadMemoryRecall => KeyCode::NumpadMemoryRecall,
1249        keyboard::key::Code::NumpadMemoryStore => KeyCode::NumpadMemoryStore,
1250        keyboard::key::Code::NumpadMemorySubtract => {
1251            KeyCode::NumpadMemorySubtract
1252        }
1253        keyboard::key::Code::NumpadMultiply => KeyCode::NumpadMultiply,
1254        keyboard::key::Code::NumpadParenLeft => KeyCode::NumpadParenLeft,
1255        keyboard::key::Code::NumpadParenRight => KeyCode::NumpadParenRight,
1256        keyboard::key::Code::NumpadStar => KeyCode::NumpadStar,
1257        keyboard::key::Code::NumpadSubtract => KeyCode::NumpadSubtract,
1258        keyboard::key::Code::Escape => KeyCode::Escape,
1259        keyboard::key::Code::Fn => KeyCode::Fn,
1260        keyboard::key::Code::FnLock => KeyCode::FnLock,
1261        keyboard::key::Code::PrintScreen => KeyCode::PrintScreen,
1262        keyboard::key::Code::ScrollLock => KeyCode::ScrollLock,
1263        keyboard::key::Code::Pause => KeyCode::Pause,
1264        keyboard::key::Code::BrowserBack => KeyCode::BrowserBack,
1265        keyboard::key::Code::BrowserFavorites => KeyCode::BrowserFavorites,
1266        keyboard::key::Code::BrowserForward => KeyCode::BrowserForward,
1267        keyboard::key::Code::BrowserHome => KeyCode::BrowserHome,
1268        keyboard::key::Code::BrowserRefresh => KeyCode::BrowserRefresh,
1269        keyboard::key::Code::BrowserSearch => KeyCode::BrowserSearch,
1270        keyboard::key::Code::BrowserStop => KeyCode::BrowserStop,
1271        keyboard::key::Code::Eject => KeyCode::Eject,
1272        keyboard::key::Code::LaunchApp1 => KeyCode::LaunchApp1,
1273        keyboard::key::Code::LaunchApp2 => KeyCode::LaunchApp2,
1274        keyboard::key::Code::LaunchMail => KeyCode::LaunchMail,
1275        keyboard::key::Code::MediaPlayPause => KeyCode::MediaPlayPause,
1276        keyboard::key::Code::MediaSelect => KeyCode::MediaSelect,
1277        keyboard::key::Code::MediaStop => KeyCode::MediaStop,
1278        keyboard::key::Code::MediaTrackNext => KeyCode::MediaTrackNext,
1279        keyboard::key::Code::MediaTrackPrevious => KeyCode::MediaTrackPrevious,
1280        keyboard::key::Code::Power => KeyCode::Power,
1281        keyboard::key::Code::Sleep => KeyCode::Sleep,
1282        keyboard::key::Code::AudioVolumeDown => KeyCode::AudioVolumeDown,
1283        keyboard::key::Code::AudioVolumeMute => KeyCode::AudioVolumeMute,
1284        keyboard::key::Code::AudioVolumeUp => KeyCode::AudioVolumeUp,
1285        keyboard::key::Code::WakeUp => KeyCode::WakeUp,
1286        keyboard::key::Code::Meta => KeyCode::Meta,
1287        keyboard::key::Code::Hyper => KeyCode::Hyper,
1288        keyboard::key::Code::Turbo => KeyCode::Turbo,
1289        keyboard::key::Code::Abort => KeyCode::Abort,
1290        keyboard::key::Code::Resume => KeyCode::Resume,
1291        keyboard::key::Code::Suspend => KeyCode::Suspend,
1292        keyboard::key::Code::Again => KeyCode::Again,
1293        keyboard::key::Code::Copy => KeyCode::Copy,
1294        keyboard::key::Code::Cut => KeyCode::Cut,
1295        keyboard::key::Code::Find => KeyCode::Find,
1296        keyboard::key::Code::Open => KeyCode::Open,
1297        keyboard::key::Code::Paste => KeyCode::Paste,
1298        keyboard::key::Code::Props => KeyCode::Props,
1299        keyboard::key::Code::Select => KeyCode::Select,
1300        keyboard::key::Code::Undo => KeyCode::Undo,
1301        keyboard::key::Code::Hiragana => KeyCode::Hiragana,
1302        keyboard::key::Code::Katakana => KeyCode::Katakana,
1303        keyboard::key::Code::F1 => KeyCode::F1,
1304        keyboard::key::Code::F2 => KeyCode::F2,
1305        keyboard::key::Code::F3 => KeyCode::F3,
1306        keyboard::key::Code::F4 => KeyCode::F4,
1307        keyboard::key::Code::F5 => KeyCode::F5,
1308        keyboard::key::Code::F6 => KeyCode::F6,
1309        keyboard::key::Code::F7 => KeyCode::F7,
1310        keyboard::key::Code::F8 => KeyCode::F8,
1311        keyboard::key::Code::F9 => KeyCode::F9,
1312        keyboard::key::Code::F10 => KeyCode::F10,
1313        keyboard::key::Code::F11 => KeyCode::F11,
1314        keyboard::key::Code::F12 => KeyCode::F12,
1315        keyboard::key::Code::F13 => KeyCode::F13,
1316        keyboard::key::Code::F14 => KeyCode::F14,
1317        keyboard::key::Code::F15 => KeyCode::F15,
1318        keyboard::key::Code::F16 => KeyCode::F16,
1319        keyboard::key::Code::F17 => KeyCode::F17,
1320        keyboard::key::Code::F18 => KeyCode::F18,
1321        keyboard::key::Code::F19 => KeyCode::F19,
1322        keyboard::key::Code::F20 => KeyCode::F20,
1323        keyboard::key::Code::F21 => KeyCode::F21,
1324        keyboard::key::Code::F22 => KeyCode::F22,
1325        keyboard::key::Code::F23 => KeyCode::F23,
1326        keyboard::key::Code::F24 => KeyCode::F24,
1327        keyboard::key::Code::F25 => KeyCode::F25,
1328        keyboard::key::Code::F26 => KeyCode::F26,
1329        keyboard::key::Code::F27 => KeyCode::F27,
1330        keyboard::key::Code::F28 => KeyCode::F28,
1331        keyboard::key::Code::F29 => KeyCode::F29,
1332        keyboard::key::Code::F30 => KeyCode::F30,
1333        keyboard::key::Code::F31 => KeyCode::F31,
1334        keyboard::key::Code::F32 => KeyCode::F32,
1335        keyboard::key::Code::F33 => KeyCode::F33,
1336        keyboard::key::Code::F34 => KeyCode::F34,
1337        keyboard::key::Code::F35 => KeyCode::F35,
1338        _ => None?,
1339    })
1340}
1341
1342#[cfg(feature = "wayland")]
1343fn winit_native_key_code(
1344    keycode: keyboard::key::NativeCode,
1345) -> winit::keyboard::NativeKeyCode {
1346    match keycode {
1347        keyboard::key::NativeCode::Unidentified => {
1348            winit::keyboard::NativeKeyCode::Unidentified
1349        }
1350        keyboard::key::NativeCode::Android(k) => {
1351            winit::keyboard::NativeKeyCode::Android(k)
1352        }
1353        keyboard::key::NativeCode::MacOS(k) => {
1354            winit::keyboard::NativeKeyCode::MacOS(k)
1355        }
1356        keyboard::key::NativeCode::Windows(k) => {
1357            winit::keyboard::NativeKeyCode::Windows(k)
1358        }
1359        keyboard::key::NativeCode::Xkb(k) => {
1360            winit::keyboard::NativeKeyCode::Xkb(k)
1361        }
1362    }
1363}
1364
1365/// Reconstruct the raw keycode
1366#[cfg(feature = "wayland")]
1367pub fn physical_to_scancode(physical: keyboard::key::Physical) -> Option<u32> {
1368    let Some(physical_key) = (match physical {
1369        keyboard::key::Physical::Code(code) => {
1370            winit_key_code(code).map(|k| winit::keyboard::PhysicalKey::Code(k))
1371        }
1372        keyboard::key::Physical::Unidentified(native_code) => {
1373            Some(winit::keyboard::PhysicalKey::Unidentified(
1374                winit_native_key_code(native_code),
1375            ))
1376        }
1377    }) else {
1378        return None;
1379    };
1380
1381    crate::keymap::physicalkey_to_scancode(physical_key)
1382}
1383
1384/// Converts a `NativeKeyCode` from [`winit`] to an [`iced`] native key code.
1385///
1386/// [`winit`]: https://github.com/rust-windowing/winit
1387/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12
1388pub fn native_key_code(
1389    native_key_code: winit::keyboard::NativeKeyCode,
1390) -> keyboard::key::NativeCode {
1391    use winit::keyboard::NativeKeyCode;
1392
1393    match native_key_code {
1394        NativeKeyCode::Unidentified => keyboard::key::NativeCode::Unidentified,
1395        NativeKeyCode::Android(code) => {
1396            keyboard::key::NativeCode::Android(code)
1397        }
1398        NativeKeyCode::MacOS(code) => keyboard::key::NativeCode::MacOS(code),
1399        NativeKeyCode::Windows(code) => {
1400            keyboard::key::NativeCode::Windows(code)
1401        }
1402        NativeKeyCode::Xkb(code) => keyboard::key::NativeCode::Xkb(code),
1403    }
1404}
1405
1406/// Converts some [`UserAttention`] into it's `winit` counterpart.
1407///
1408/// [`UserAttention`]: window::UserAttention
1409pub fn user_attention(
1410    user_attention: window::UserAttention,
1411) -> winit::window::UserAttentionType {
1412    match user_attention {
1413        window::UserAttention::Critical => {
1414            winit::window::UserAttentionType::Critical
1415        }
1416        window::UserAttention::Informational => {
1417            winit::window::UserAttentionType::Informational
1418        }
1419    }
1420}
1421
1422/// Converts some [`window::Icon`] into it's `winit` counterpart.
1423///
1424/// Returns `None` if there is an error during the conversion.
1425pub fn icon(icon: window::Icon) -> Option<winit::window::Icon> {
1426    let (pixels, size) = icon.into_raw();
1427
1428    winit::window::Icon::from_rgba(pixels, size.width, size.height).ok()
1429}
1430
1431// See: https://en.wikipedia.org/wiki/Private_Use_Areas
1432fn is_private_use(c: char) -> bool {
1433    ('\u{E000}'..='\u{F8FF}').contains(&c)
1434}
1435
1436#[cfg(feature = "a11y")]
1437pub(crate) fn a11y(
1438    event: iced_accessibility::accesskit::ActionRequest,
1439) -> Event {
1440    // XXX
1441    let id =
1442        iced_runtime::core::id::Id::from(u128::from(event.target.0) as u64);
1443    Event::A11y(id, event)
1444}