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