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