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