1use std::any::Any;
2use std::backtrace::Backtrace;
3use std::cell::RefCell;
4use std::marker::PhantomData;
5use std::{cell::Cell, sync::Arc};
6use std::{fmt, ops};
7
8use rayon::ThreadPoolBuilder;
9use webrender::api as wr;
10use winit::event_loop::ActiveEventLoop;
11use winit::{event::ElementState, monitor::MonitorHandle};
12use zng_txt::{ToTxt, Txt};
13use zng_unit::*;
14use zng_view_api::access::AccessNodeId;
15use zng_view_api::keyboard::{KeyLocation, NativeKeyCode};
16use zng_view_api::window::{FrameCapture, FrameRequest, FrameUpdateRequest, ResizeDirection, WindowButton};
17use zng_view_api::{
18 keyboard::{Key, KeyCode, KeyState},
19 mouse::{ButtonState, MouseButton, MouseScrollDelta},
20 touch::{TouchForce, TouchPhase},
21 window::{CursorIcon, MonitorInfo, VideoMode},
22};
23
24#[cfg(not(target_os = "android"))]
25use zng_view_api::clipboard as clipboard_api;
26
27#[cfg(windows)]
49pub fn set_raw_windows_event_handler<H>(hwnd: windows_sys::Win32::Foundation::HWND, subclass_id: usize, handler: H) -> bool
50where
51 H: FnMut(
52 windows_sys::Win32::Foundation::HWND,
53 u32,
54 windows_sys::Win32::Foundation::WPARAM,
55 windows_sys::Win32::Foundation::LPARAM,
56 ) -> Option<windows_sys::Win32::Foundation::LRESULT>
57 + 'static,
58{
59 let data = Box::new(handler);
60 unsafe {
61 windows_sys::Win32::UI::Shell::SetWindowSubclass(hwnd, Some(subclass_raw_event_proc::<H>), subclass_id, Box::into_raw(data) as _)
62 != 0
63 }
64}
65
66#[cfg(windows)]
67unsafe extern "system" fn subclass_raw_event_proc<H>(
68 hwnd: windows_sys::Win32::Foundation::HWND,
69 msg: u32,
70 wparam: windows_sys::Win32::Foundation::WPARAM,
71 lparam: windows_sys::Win32::Foundation::LPARAM,
72 _id: usize,
73 data: usize,
74) -> windows_sys::Win32::Foundation::LRESULT
75where
76 H: FnMut(
77 windows_sys::Win32::Foundation::HWND,
78 u32,
79 windows_sys::Win32::Foundation::WPARAM,
80 windows_sys::Win32::Foundation::LPARAM,
81 ) -> Option<windows_sys::Win32::Foundation::LRESULT>
82 + 'static,
83{
84 use windows_sys::Win32::UI::WindowsAndMessaging::WM_DESTROY;
85 match msg {
86 WM_DESTROY => {
87 let mut handler = unsafe { Box::from_raw(data as *mut H) };
89 handler(hwnd, msg, wparam, lparam).unwrap_or_default()
90 }
91
92 msg => {
93 let handler = unsafe { &mut *(data as *mut H) };
94 if let Some(r) = handler(hwnd, msg, wparam, lparam) {
95 r
96 } else {
97 unsafe { windows_sys::Win32::UI::Shell::DefSubclassProc(hwnd, msg, wparam, lparam) }
98 }
99 }
100 }
101}
102
103pub(crate) trait WinitToDip {
107 type AsDip;
109
110 fn to_dip(self) -> Self::AsDip;
112}
113
114pub(crate) trait WinitToPx {
118 type AsPx;
120
121 fn to_px(self) -> Self::AsPx;
123}
124
125pub(crate) trait DipToWinit {
127 type AsWinit;
129
130 fn to_winit(self) -> Self::AsWinit;
132}
133
134pub(crate) trait PxToWinit {
136 type AsWinit;
138
139 fn to_winit(self) -> Self::AsWinit;
141}
142
143impl PxToWinit for PxSize {
144 type AsWinit = winit::dpi::PhysicalSize<u32>;
145
146 fn to_winit(self) -> Self::AsWinit {
147 winit::dpi::PhysicalSize::new(self.width.0 as _, self.height.0 as _)
148 }
149}
150impl PxToWinit for PxPoint {
151 type AsWinit = winit::dpi::PhysicalPosition<i32>;
152
153 fn to_winit(self) -> Self::AsWinit {
154 winit::dpi::PhysicalPosition::new(self.x.0, self.y.0)
155 }
156}
157
158impl DipToWinit for DipPoint {
159 type AsWinit = winit::dpi::LogicalPosition<f32>;
160
161 fn to_winit(self) -> Self::AsWinit {
162 winit::dpi::LogicalPosition::new(self.x.to_f32(), self.y.to_f32())
163 }
164}
165
166impl WinitToDip for winit::dpi::LogicalPosition<f64> {
167 type AsDip = DipPoint;
168
169 fn to_dip(self) -> Self::AsDip {
170 DipPoint::new(Dip::new_f32(self.x as f32), Dip::new_f32(self.y as f32))
171 }
172}
173
174impl WinitToPx for winit::dpi::PhysicalPosition<i32> {
175 type AsPx = PxPoint;
176
177 fn to_px(self) -> Self::AsPx {
178 PxPoint::new(Px(self.x), Px(self.y))
179 }
180}
181
182impl WinitToPx for winit::dpi::PhysicalPosition<f64> {
183 type AsPx = PxPoint;
184
185 fn to_px(self) -> Self::AsPx {
186 PxPoint::new(Px(self.x as i32), Px(self.y as i32))
187 }
188}
189
190impl DipToWinit for DipSize {
191 type AsWinit = winit::dpi::LogicalSize<f32>;
192
193 fn to_winit(self) -> Self::AsWinit {
194 winit::dpi::LogicalSize::new(self.width.to_f32(), self.height.to_f32())
195 }
196}
197
198impl WinitToDip for winit::dpi::LogicalSize<f64> {
199 type AsDip = DipSize;
200
201 fn to_dip(self) -> Self::AsDip {
202 DipSize::new(Dip::new_f32(self.width as f32), Dip::new_f32(self.height as f32))
203 }
204}
205
206impl WinitToPx for winit::dpi::PhysicalSize<u32> {
207 type AsPx = PxSize;
208
209 fn to_px(self) -> Self::AsPx {
210 PxSize::new(Px(self.width as i32), Px(self.height as i32))
211 }
212}
213pub trait ResizeDirectionToWinit {
214 fn to_winit(self) -> winit::window::ResizeDirection;
215}
216impl ResizeDirectionToWinit for ResizeDirection {
217 fn to_winit(self) -> winit::window::ResizeDirection {
218 use winit::window::ResizeDirection::*;
219 match self {
220 ResizeDirection::East => East,
221 ResizeDirection::North => North,
222 ResizeDirection::NorthEast => NorthEast,
223 ResizeDirection::NorthWest => NorthWest,
224 ResizeDirection::South => South,
225 ResizeDirection::SouthEast => SouthEast,
226 ResizeDirection::SouthWest => SouthWest,
227 ResizeDirection::West => West,
228 }
229 }
230}
231
232pub trait WindowButtonsToWinit {
233 fn to_winit(self) -> winit::window::WindowButtons;
234}
235impl WindowButtonsToWinit for WindowButton {
236 fn to_winit(self) -> winit::window::WindowButtons {
237 let mut r = winit::window::WindowButtons::empty();
238 r.set(winit::window::WindowButtons::CLOSE, self.contains(WindowButton::CLOSE));
239 r.set(winit::window::WindowButtons::MINIMIZE, self.contains(WindowButton::MINIMIZE));
240 r.set(winit::window::WindowButtons::MAXIMIZE, self.contains(WindowButton::MAXIMIZE));
241
242 r
243 }
244}
245
246pub trait CursorToWinit {
247 fn to_winit(self) -> winit::window::CursorIcon;
248}
249impl CursorToWinit for CursorIcon {
250 fn to_winit(self) -> winit::window::CursorIcon {
251 use winit::window::CursorIcon::*;
252 match self {
253 CursorIcon::Default => Default,
254 CursorIcon::ContextMenu => ContextMenu,
255 CursorIcon::Help => Help,
256 CursorIcon::Pointer => Pointer,
257 CursorIcon::Progress => Progress,
258 CursorIcon::Wait => Wait,
259 CursorIcon::Cell => Cell,
260 CursorIcon::Crosshair => Crosshair,
261 CursorIcon::Text => Text,
262 CursorIcon::VerticalText => VerticalText,
263 CursorIcon::Alias => Alias,
264 CursorIcon::Copy => Copy,
265 CursorIcon::Move => Move,
266 CursorIcon::NoDrop => NoDrop,
267 CursorIcon::NotAllowed => NotAllowed,
268 CursorIcon::Grab => Grab,
269 CursorIcon::Grabbing => Grabbing,
270 CursorIcon::EResize => EResize,
271 CursorIcon::NResize => NResize,
272 CursorIcon::NeResize => NeResize,
273 CursorIcon::NwResize => NwResize,
274 CursorIcon::SResize => SResize,
275 CursorIcon::SeResize => SeResize,
276 CursorIcon::SwResize => SwResize,
277 CursorIcon::WResize => WResize,
278 CursorIcon::EwResize => EwResize,
279 CursorIcon::NsResize => NsResize,
280 CursorIcon::NeswResize => NeswResize,
281 CursorIcon::NwseResize => NwseResize,
282 CursorIcon::ColResize => ColResize,
283 CursorIcon::RowResize => RowResize,
284 CursorIcon::AllScroll => AllScroll,
285 CursorIcon::ZoomIn => ZoomIn,
286 CursorIcon::ZoomOut => ZoomOut,
287 _ => Default,
288 }
289 }
290}
291
292pub(crate) fn monitor_handle_to_info(handle: &MonitorHandle) -> MonitorInfo {
293 let position = handle.position().to_px();
294 let size = handle.size().to_px();
295 MonitorInfo {
296 name: Txt::from_str(&handle.name().unwrap_or_default()),
297 position,
298 size,
299 scale_factor: Factor(handle.scale_factor() as _),
300 video_modes: handle.video_modes().map(glutin_video_mode_to_video_mode).collect(),
301 is_primary: false,
302 }
303}
304
305pub(crate) fn glutin_video_mode_to_video_mode(v: winit::monitor::VideoModeHandle) -> VideoMode {
306 let size = v.size();
307 VideoMode {
308 size: PxSize::new(Px(size.width as i32), Px(size.height as i32)),
309 bit_depth: v.bit_depth(),
310 refresh_rate: v.refresh_rate_millihertz(),
311 }
312}
313
314pub(crate) fn element_state_to_key_state(s: ElementState) -> KeyState {
315 match s {
316 ElementState::Pressed => KeyState::Pressed,
317 ElementState::Released => KeyState::Released,
318 }
319}
320
321pub(crate) fn element_state_to_button_state(s: ElementState) -> ButtonState {
322 match s {
323 ElementState::Pressed => ButtonState::Pressed,
324 ElementState::Released => ButtonState::Released,
325 }
326}
327
328pub(crate) fn winit_mouse_wheel_delta_to_zng(w: winit::event::MouseScrollDelta) -> MouseScrollDelta {
329 match w {
330 winit::event::MouseScrollDelta::LineDelta(x, y) => MouseScrollDelta::LineDelta(x, y),
331 winit::event::MouseScrollDelta::PixelDelta(d) => MouseScrollDelta::PixelDelta(d.x as f32, d.y as f32),
332 }
333}
334
335pub(crate) fn winit_touch_phase_to_zng(w: winit::event::TouchPhase) -> TouchPhase {
336 match w {
337 winit::event::TouchPhase::Started => TouchPhase::Start,
338 winit::event::TouchPhase::Moved => TouchPhase::Move,
339 winit::event::TouchPhase::Ended => TouchPhase::End,
340 winit::event::TouchPhase::Cancelled => TouchPhase::Cancel,
341 }
342}
343
344pub(crate) fn winit_force_to_zng(f: winit::event::Force) -> TouchForce {
345 match f {
346 winit::event::Force::Calibrated {
347 force,
348 max_possible_force,
349 altitude_angle,
350 } => TouchForce::Calibrated {
351 force,
352 max_possible_force,
353 altitude_angle,
354 },
355 winit::event::Force::Normalized(f) => TouchForce::Normalized(f),
356 }
357}
358
359pub(crate) fn winit_mouse_button_to_zng(b: winit::event::MouseButton) -> MouseButton {
360 match b {
361 winit::event::MouseButton::Left => MouseButton::Left,
362 winit::event::MouseButton::Right => MouseButton::Right,
363 winit::event::MouseButton::Middle => MouseButton::Middle,
364 winit::event::MouseButton::Back => MouseButton::Back,
365 winit::event::MouseButton::Forward => MouseButton::Forward,
366 winit::event::MouseButton::Other(btn) => MouseButton::Other(btn),
367 }
368}
369
370#[cfg(windows)]
371pub(crate) fn winit_to_hwnd(window: &winit::window::Window) -> isize {
372 use raw_window_handle::HasWindowHandle as _;
373
374 match window.window_handle().unwrap().as_raw() {
375 raw_window_handle::RawWindowHandle::Win32(w) => w.hwnd.get() as _,
376 _ => unreachable!(),
377 }
378}
379
380pub(crate) fn winit_key_location_to_zng(t: winit::keyboard::KeyLocation) -> KeyLocation {
381 match t {
382 winit::keyboard::KeyLocation::Standard => KeyLocation::Standard,
383 winit::keyboard::KeyLocation::Left => KeyLocation::Left,
384 winit::keyboard::KeyLocation::Right => KeyLocation::Right,
385 winit::keyboard::KeyLocation::Numpad => KeyLocation::Numpad,
386 }
387}
388
389use winit::keyboard::{Key as WinitKey, NamedKey as WinitNamedKey};
390pub(crate) fn winit_key_to_key(key: WinitKey) -> Key {
391 match key {
392 WinitKey::Named(k) => match k {
393 WinitNamedKey::Alt => Key::Alt,
394 WinitNamedKey::AltGraph => Key::AltGraph,
395 WinitNamedKey::CapsLock => Key::CapsLock,
396 WinitNamedKey::Control => Key::Ctrl,
397 WinitNamedKey::Fn => Key::Fn,
398 WinitNamedKey::FnLock => Key::FnLock,
399 WinitNamedKey::NumLock => Key::NumLock,
400 WinitNamedKey::ScrollLock => Key::ScrollLock,
401 WinitNamedKey::Shift => Key::Shift,
402 WinitNamedKey::Symbol => Key::Symbol,
403 WinitNamedKey::SymbolLock => Key::SymbolLock,
404 WinitNamedKey::Meta => Key::Meta,
405 WinitNamedKey::Hyper => Key::Hyper,
406 WinitNamedKey::Super => Key::Super,
407 WinitNamedKey::Enter => Key::Enter,
408 WinitNamedKey::Tab => Key::Tab,
409 WinitNamedKey::Space => Key::Space,
410 WinitNamedKey::ArrowDown => Key::ArrowDown,
411 WinitNamedKey::ArrowLeft => Key::ArrowLeft,
412 WinitNamedKey::ArrowRight => Key::ArrowRight,
413 WinitNamedKey::ArrowUp => Key::ArrowUp,
414 WinitNamedKey::End => Key::End,
415 WinitNamedKey::Home => Key::Home,
416 WinitNamedKey::PageDown => Key::PageDown,
417 WinitNamedKey::PageUp => Key::PageUp,
418 WinitNamedKey::Backspace => Key::Backspace,
419 WinitNamedKey::Clear => Key::Clear,
420 WinitNamedKey::Copy => Key::Copy,
421 WinitNamedKey::CrSel => Key::CrSel,
422 WinitNamedKey::Cut => Key::Cut,
423 WinitNamedKey::Delete => Key::Delete,
424 WinitNamedKey::EraseEof => Key::EraseEof,
425 WinitNamedKey::ExSel => Key::ExSel,
426 WinitNamedKey::Insert => Key::Insert,
427 WinitNamedKey::Paste => Key::Paste,
428 WinitNamedKey::Redo => Key::Redo,
429 WinitNamedKey::Undo => Key::Undo,
430 WinitNamedKey::Accept => Key::Accept,
431 WinitNamedKey::Again => Key::Again,
432 WinitNamedKey::Attn => Key::Attn,
433 WinitNamedKey::Cancel => Key::Cancel,
434 WinitNamedKey::ContextMenu => Key::ContextMenu,
435 WinitNamedKey::Escape => Key::Escape,
436 WinitNamedKey::Execute => Key::Execute,
437 WinitNamedKey::Find => Key::Find,
438 WinitNamedKey::Help => Key::Help,
439 WinitNamedKey::Pause => Key::Pause,
440 WinitNamedKey::Play => Key::Play,
441 WinitNamedKey::Props => Key::Props,
442 WinitNamedKey::Select => Key::Select,
443 WinitNamedKey::ZoomIn => Key::ZoomIn,
444 WinitNamedKey::ZoomOut => Key::ZoomOut,
445 WinitNamedKey::BrightnessDown => Key::BrightnessDown,
446 WinitNamedKey::BrightnessUp => Key::BrightnessUp,
447 WinitNamedKey::Eject => Key::Eject,
448 WinitNamedKey::LogOff => Key::LogOff,
449 WinitNamedKey::Power => Key::Power,
450 WinitNamedKey::PowerOff => Key::PowerOff,
451 WinitNamedKey::PrintScreen => Key::PrintScreen,
452 WinitNamedKey::Hibernate => Key::Hibernate,
453 WinitNamedKey::Standby => Key::Standby,
454 WinitNamedKey::WakeUp => Key::WakeUp,
455 WinitNamedKey::AllCandidates => Key::AllCandidates,
456 WinitNamedKey::Alphanumeric => Key::Alphanumeric,
457 WinitNamedKey::CodeInput => Key::CodeInput,
458 WinitNamedKey::Compose => Key::Compose,
459 WinitNamedKey::Convert => Key::Convert,
460 WinitNamedKey::FinalMode => Key::FinalMode,
461 WinitNamedKey::GroupFirst => Key::GroupFirst,
462 WinitNamedKey::GroupLast => Key::GroupLast,
463 WinitNamedKey::GroupNext => Key::GroupNext,
464 WinitNamedKey::GroupPrevious => Key::GroupPrevious,
465 WinitNamedKey::ModeChange => Key::ModeChange,
466 WinitNamedKey::NextCandidate => Key::NextCandidate,
467 WinitNamedKey::NonConvert => Key::NonConvert,
468 WinitNamedKey::PreviousCandidate => Key::PreviousCandidate,
469 WinitNamedKey::Process => Key::Process,
470 WinitNamedKey::SingleCandidate => Key::SingleCandidate,
471 WinitNamedKey::HangulMode => Key::HangulMode,
472 WinitNamedKey::HanjaMode => Key::HanjaMode,
473 WinitNamedKey::JunjaMode => Key::JunjaMode,
474 WinitNamedKey::Eisu => Key::Eisu,
475 WinitNamedKey::Hankaku => Key::Hankaku,
476 WinitNamedKey::Hiragana => Key::Hiragana,
477 WinitNamedKey::HiraganaKatakana => Key::HiraganaKatakana,
478 WinitNamedKey::KanaMode => Key::KanaMode,
479 WinitNamedKey::KanjiMode => Key::KanjiMode,
480 WinitNamedKey::Katakana => Key::Katakana,
481 WinitNamedKey::Romaji => Key::Romaji,
482 WinitNamedKey::Zenkaku => Key::Zenkaku,
483 WinitNamedKey::ZenkakuHankaku => Key::ZenkakuHankaku,
484 WinitNamedKey::Soft1 => Key::Soft1,
485 WinitNamedKey::Soft2 => Key::Soft2,
486 WinitNamedKey::Soft3 => Key::Soft3,
487 WinitNamedKey::Soft4 => Key::Soft4,
488 WinitNamedKey::ChannelDown => Key::ChannelDown,
489 WinitNamedKey::ChannelUp => Key::ChannelUp,
490 WinitNamedKey::Close => Key::Close,
491 WinitNamedKey::MailForward => Key::MailForward,
492 WinitNamedKey::MailReply => Key::MailReply,
493 WinitNamedKey::MailSend => Key::MailSend,
494 WinitNamedKey::MediaClose => Key::MediaClose,
495 WinitNamedKey::MediaFastForward => Key::MediaFastForward,
496 WinitNamedKey::MediaPause => Key::MediaPause,
497 WinitNamedKey::MediaPlay => Key::MediaPlay,
498 WinitNamedKey::MediaPlayPause => Key::MediaPlayPause,
499 WinitNamedKey::MediaRecord => Key::MediaRecord,
500 WinitNamedKey::MediaRewind => Key::MediaRewind,
501 WinitNamedKey::MediaStop => Key::MediaStop,
502 WinitNamedKey::MediaTrackNext => Key::MediaTrackNext,
503 WinitNamedKey::MediaTrackPrevious => Key::MediaTrackPrevious,
504 WinitNamedKey::New => Key::New,
505 WinitNamedKey::Open => Key::Open,
506 WinitNamedKey::Print => Key::Print,
507 WinitNamedKey::Save => Key::Save,
508 WinitNamedKey::SpellCheck => Key::SpellCheck,
509 WinitNamedKey::Key11 => Key::Key11,
510 WinitNamedKey::Key12 => Key::Key12,
511 WinitNamedKey::AudioBalanceLeft => Key::AudioBalanceLeft,
512 WinitNamedKey::AudioBalanceRight => Key::AudioBalanceRight,
513 WinitNamedKey::AudioBassBoostDown => Key::AudioBassBoostDown,
514 WinitNamedKey::AudioBassBoostToggle => Key::AudioBassBoostToggle,
515 WinitNamedKey::AudioBassBoostUp => Key::AudioBassBoostUp,
516 WinitNamedKey::AudioFaderFront => Key::AudioFaderFront,
517 WinitNamedKey::AudioFaderRear => Key::AudioFaderRear,
518 WinitNamedKey::AudioSurroundModeNext => Key::AudioSurroundModeNext,
519 WinitNamedKey::AudioTrebleDown => Key::AudioTrebleDown,
520 WinitNamedKey::AudioTrebleUp => Key::AudioTrebleUp,
521 WinitNamedKey::AudioVolumeDown => Key::AudioVolumeDown,
522 WinitNamedKey::AudioVolumeUp => Key::AudioVolumeUp,
523 WinitNamedKey::AudioVolumeMute => Key::AudioVolumeMute,
524 WinitNamedKey::MicrophoneToggle => Key::MicrophoneToggle,
525 WinitNamedKey::MicrophoneVolumeDown => Key::MicrophoneVolumeDown,
526 WinitNamedKey::MicrophoneVolumeUp => Key::MicrophoneVolumeUp,
527 WinitNamedKey::MicrophoneVolumeMute => Key::MicrophoneVolumeMute,
528 WinitNamedKey::SpeechCorrectionList => Key::SpeechCorrectionList,
529 WinitNamedKey::SpeechInputToggle => Key::SpeechInputToggle,
530 WinitNamedKey::LaunchApplication1 => Key::LaunchApplication1,
531 WinitNamedKey::LaunchApplication2 => Key::LaunchApplication2,
532 WinitNamedKey::LaunchCalendar => Key::LaunchCalendar,
533 WinitNamedKey::LaunchContacts => Key::LaunchContacts,
534 WinitNamedKey::LaunchMail => Key::LaunchMail,
535 WinitNamedKey::LaunchMediaPlayer => Key::LaunchMediaPlayer,
536 WinitNamedKey::LaunchMusicPlayer => Key::LaunchMusicPlayer,
537 WinitNamedKey::LaunchPhone => Key::LaunchPhone,
538 WinitNamedKey::LaunchScreenSaver => Key::LaunchScreenSaver,
539 WinitNamedKey::LaunchSpreadsheet => Key::LaunchSpreadsheet,
540 WinitNamedKey::LaunchWebBrowser => Key::LaunchWebBrowser,
541 WinitNamedKey::LaunchWebCam => Key::LaunchWebCam,
542 WinitNamedKey::LaunchWordProcessor => Key::LaunchWordProcessor,
543 WinitNamedKey::BrowserBack => Key::BrowserBack,
544 WinitNamedKey::BrowserFavorites => Key::BrowserFavorites,
545 WinitNamedKey::BrowserForward => Key::BrowserForward,
546 WinitNamedKey::BrowserHome => Key::BrowserHome,
547 WinitNamedKey::BrowserRefresh => Key::BrowserRefresh,
548 WinitNamedKey::BrowserSearch => Key::BrowserSearch,
549 WinitNamedKey::BrowserStop => Key::BrowserStop,
550 WinitNamedKey::AppSwitch => Key::AppSwitch,
551 WinitNamedKey::Call => Key::Call,
552 WinitNamedKey::Camera => Key::Camera,
553 WinitNamedKey::CameraFocus => Key::CameraFocus,
554 WinitNamedKey::EndCall => Key::EndCall,
555 WinitNamedKey::GoBack => Key::GoBack,
556 WinitNamedKey::GoHome => Key::GoHome,
557 WinitNamedKey::HeadsetHook => Key::HeadsetHook,
558 WinitNamedKey::LastNumberRedial => Key::LastNumberRedial,
559 WinitNamedKey::Notification => Key::Notification,
560 WinitNamedKey::MannerMode => Key::MannerMode,
561 WinitNamedKey::VoiceDial => Key::VoiceDial,
562 WinitNamedKey::TV => Key::TV,
563 WinitNamedKey::TV3DMode => Key::TV3DMode,
564 WinitNamedKey::TVAntennaCable => Key::TVAntennaCable,
565 WinitNamedKey::TVAudioDescription => Key::TVAudioDescription,
566 WinitNamedKey::TVAudioDescriptionMixDown => Key::TVAudioDescriptionMixDown,
567 WinitNamedKey::TVAudioDescriptionMixUp => Key::TVAudioDescriptionMixUp,
568 WinitNamedKey::TVContentsMenu => Key::TVContentsMenu,
569 WinitNamedKey::TVDataService => Key::TVDataService,
570 WinitNamedKey::TVInput => Key::TVInput,
571 WinitNamedKey::TVInputComponent1 => Key::TVInputComponent1,
572 WinitNamedKey::TVInputComponent2 => Key::TVInputComponent2,
573 WinitNamedKey::TVInputComposite1 => Key::TVInputComposite1,
574 WinitNamedKey::TVInputComposite2 => Key::TVInputComposite2,
575 WinitNamedKey::TVInputHDMI1 => Key::TVInputHDMI1,
576 WinitNamedKey::TVInputHDMI2 => Key::TVInputHDMI2,
577 WinitNamedKey::TVInputHDMI3 => Key::TVInputHDMI3,
578 WinitNamedKey::TVInputHDMI4 => Key::TVInputHDMI4,
579 WinitNamedKey::TVInputVGA1 => Key::TVInputVGA1,
580 WinitNamedKey::TVMediaContext => Key::TVMediaContext,
581 WinitNamedKey::TVNetwork => Key::TVNetwork,
582 WinitNamedKey::TVNumberEntry => Key::TVNumberEntry,
583 WinitNamedKey::TVPower => Key::TVPower,
584 WinitNamedKey::TVRadioService => Key::TVRadioService,
585 WinitNamedKey::TVSatellite => Key::TVSatellite,
586 WinitNamedKey::TVSatelliteBS => Key::TVSatelliteBS,
587 WinitNamedKey::TVSatelliteCS => Key::TVSatelliteCS,
588 WinitNamedKey::TVSatelliteToggle => Key::TVSatelliteToggle,
589 WinitNamedKey::TVTerrestrialAnalog => Key::TVTerrestrialAnalog,
590 WinitNamedKey::TVTerrestrialDigital => Key::TVTerrestrialDigital,
591 WinitNamedKey::TVTimer => Key::TVTimer,
592 WinitNamedKey::AVRInput => Key::AVRInput,
593 WinitNamedKey::AVRPower => Key::AVRPower,
594 WinitNamedKey::ColorF0Red => Key::ColorF0Red,
595 WinitNamedKey::ColorF1Green => Key::ColorF1Green,
596 WinitNamedKey::ColorF2Yellow => Key::ColorF2Yellow,
597 WinitNamedKey::ColorF3Blue => Key::ColorF3Blue,
598 WinitNamedKey::ColorF4Grey => Key::ColorF4Grey,
599 WinitNamedKey::ColorF5Brown => Key::ColorF5Brown,
600 WinitNamedKey::ClosedCaptionToggle => Key::ClosedCaptionToggle,
601 WinitNamedKey::Dimmer => Key::Dimmer,
602 WinitNamedKey::DisplaySwap => Key::DisplaySwap,
603 WinitNamedKey::DVR => Key::DVR,
604 WinitNamedKey::Exit => Key::Exit,
605 WinitNamedKey::FavoriteClear0 => Key::FavoriteClear0,
606 WinitNamedKey::FavoriteClear1 => Key::FavoriteClear1,
607 WinitNamedKey::FavoriteClear2 => Key::FavoriteClear2,
608 WinitNamedKey::FavoriteClear3 => Key::FavoriteClear3,
609 WinitNamedKey::FavoriteRecall0 => Key::FavoriteRecall0,
610 WinitNamedKey::FavoriteRecall1 => Key::FavoriteRecall1,
611 WinitNamedKey::FavoriteRecall2 => Key::FavoriteRecall2,
612 WinitNamedKey::FavoriteRecall3 => Key::FavoriteRecall3,
613 WinitNamedKey::FavoriteStore0 => Key::FavoriteStore0,
614 WinitNamedKey::FavoriteStore1 => Key::FavoriteStore1,
615 WinitNamedKey::FavoriteStore2 => Key::FavoriteStore2,
616 WinitNamedKey::FavoriteStore3 => Key::FavoriteStore3,
617 WinitNamedKey::Guide => Key::Guide,
618 WinitNamedKey::GuideNextDay => Key::GuideNextDay,
619 WinitNamedKey::GuidePreviousDay => Key::GuidePreviousDay,
620 WinitNamedKey::Info => Key::Info,
621 WinitNamedKey::InstantReplay => Key::InstantReplay,
622 WinitNamedKey::Link => Key::Link,
623 WinitNamedKey::ListProgram => Key::ListProgram,
624 WinitNamedKey::LiveContent => Key::LiveContent,
625 WinitNamedKey::Lock => Key::Lock,
626 WinitNamedKey::MediaApps => Key::MediaApps,
627 WinitNamedKey::MediaAudioTrack => Key::MediaAudioTrack,
628 WinitNamedKey::MediaLast => Key::MediaLast,
629 WinitNamedKey::MediaSkipBackward => Key::MediaSkipBackward,
630 WinitNamedKey::MediaSkipForward => Key::MediaSkipForward,
631 WinitNamedKey::MediaStepBackward => Key::MediaStepBackward,
632 WinitNamedKey::MediaStepForward => Key::MediaStepForward,
633 WinitNamedKey::MediaTopMenu => Key::MediaTopMenu,
634 WinitNamedKey::NavigateIn => Key::NavigateIn,
635 WinitNamedKey::NavigateNext => Key::NavigateNext,
636 WinitNamedKey::NavigateOut => Key::NavigateOut,
637 WinitNamedKey::NavigatePrevious => Key::NavigatePrevious,
638 WinitNamedKey::NextFavoriteChannel => Key::NextFavoriteChannel,
639 WinitNamedKey::NextUserProfile => Key::NextUserProfile,
640 WinitNamedKey::OnDemand => Key::OnDemand,
641 WinitNamedKey::Pairing => Key::Pairing,
642 WinitNamedKey::PinPDown => Key::PinPDown,
643 WinitNamedKey::PinPMove => Key::PinPMove,
644 WinitNamedKey::PinPToggle => Key::PinPToggle,
645 WinitNamedKey::PinPUp => Key::PinPUp,
646 WinitNamedKey::PlaySpeedDown => Key::PlaySpeedDown,
647 WinitNamedKey::PlaySpeedReset => Key::PlaySpeedReset,
648 WinitNamedKey::PlaySpeedUp => Key::PlaySpeedUp,
649 WinitNamedKey::RandomToggle => Key::RandomToggle,
650 WinitNamedKey::RcLowBattery => Key::RcLowBattery,
651 WinitNamedKey::RecordSpeedNext => Key::RecordSpeedNext,
652 WinitNamedKey::RfBypass => Key::RfBypass,
653 WinitNamedKey::ScanChannelsToggle => Key::ScanChannelsToggle,
654 WinitNamedKey::ScreenModeNext => Key::ScreenModeNext,
655 WinitNamedKey::Settings => Key::Settings,
656 WinitNamedKey::SplitScreenToggle => Key::SplitScreenToggle,
657 WinitNamedKey::STBInput => Key::STBInput,
658 WinitNamedKey::STBPower => Key::STBPower,
659 WinitNamedKey::Subtitle => Key::Subtitle,
660 WinitNamedKey::Teletext => Key::Teletext,
661 WinitNamedKey::VideoModeNext => Key::VideoModeNext,
662 WinitNamedKey::Wink => Key::Wink,
663 WinitNamedKey::ZoomToggle => Key::ZoomToggle,
664 WinitNamedKey::F1 => Key::F1,
665 WinitNamedKey::F2 => Key::F2,
666 WinitNamedKey::F3 => Key::F3,
667 WinitNamedKey::F4 => Key::F4,
668 WinitNamedKey::F5 => Key::F5,
669 WinitNamedKey::F6 => Key::F6,
670 WinitNamedKey::F7 => Key::F7,
671 WinitNamedKey::F8 => Key::F8,
672 WinitNamedKey::F9 => Key::F9,
673 WinitNamedKey::F10 => Key::F10,
674 WinitNamedKey::F11 => Key::F11,
675 WinitNamedKey::F12 => Key::F12,
676 WinitNamedKey::F13 => Key::F13,
677 WinitNamedKey::F14 => Key::F14,
678 WinitNamedKey::F15 => Key::F15,
679 WinitNamedKey::F16 => Key::F16,
680 WinitNamedKey::F17 => Key::F17,
681 WinitNamedKey::F18 => Key::F18,
682 WinitNamedKey::F19 => Key::F19,
683 WinitNamedKey::F20 => Key::F20,
684 WinitNamedKey::F21 => Key::F21,
685 WinitNamedKey::F22 => Key::F22,
686 WinitNamedKey::F23 => Key::F23,
687 WinitNamedKey::F24 => Key::F24,
688 WinitNamedKey::F25 => Key::F25,
689 WinitNamedKey::F26 => Key::F26,
690 WinitNamedKey::F27 => Key::F27,
691 WinitNamedKey::F28 => Key::F28,
692 WinitNamedKey::F29 => Key::F29,
693 WinitNamedKey::F30 => Key::F30,
694 WinitNamedKey::F31 => Key::F31,
695 WinitNamedKey::F32 => Key::F32,
696 WinitNamedKey::F33 => Key::F33,
697 WinitNamedKey::F34 => Key::F34,
698 WinitNamedKey::F35 => Key::F35,
699 k => {
700 tracing::error!("matched unknown key code `{k:?}`");
701 Key::Unidentified
702 }
703 },
704 WinitKey::Character(c) => {
705 let mut chars = c.chars();
706 match (chars.next(), chars.next()) {
707 (Some(c), None) => Key::Char(c),
708 _ => Key::Str(c.as_str().to_owned().into()),
709 }
710 }
711 WinitKey::Unidentified(_) => Key::Unidentified,
712 WinitKey::Dead(k) => Key::Dead(k),
713 }
714}
715
716use winit::keyboard::KeyCode as WinitKeyCode;
717pub(crate) fn winit_key_code_to_key_code(key: WinitKeyCode) -> KeyCode {
718 match key {
719 WinitKeyCode::Backquote => KeyCode::Backquote,
720 WinitKeyCode::Backslash => KeyCode::Backslash,
721 WinitKeyCode::BracketLeft => KeyCode::BracketLeft,
722 WinitKeyCode::BracketRight => KeyCode::BracketRight,
723 WinitKeyCode::Comma => KeyCode::Comma,
724 WinitKeyCode::Digit0 => KeyCode::Digit0,
725 WinitKeyCode::Digit1 => KeyCode::Digit1,
726 WinitKeyCode::Digit2 => KeyCode::Digit2,
727 WinitKeyCode::Digit3 => KeyCode::Digit3,
728 WinitKeyCode::Digit4 => KeyCode::Digit4,
729 WinitKeyCode::Digit5 => KeyCode::Digit5,
730 WinitKeyCode::Digit6 => KeyCode::Digit6,
731 WinitKeyCode::Digit7 => KeyCode::Digit7,
732 WinitKeyCode::Digit8 => KeyCode::Digit8,
733 WinitKeyCode::Digit9 => KeyCode::Digit9,
734 WinitKeyCode::Equal => KeyCode::Equal,
735 WinitKeyCode::IntlBackslash => KeyCode::IntlBackslash,
736 WinitKeyCode::IntlRo => KeyCode::IntlRo,
737 WinitKeyCode::IntlYen => KeyCode::IntlYen,
738 WinitKeyCode::KeyA => KeyCode::KeyA,
739 WinitKeyCode::KeyB => KeyCode::KeyB,
740 WinitKeyCode::KeyC => KeyCode::KeyC,
741 WinitKeyCode::KeyD => KeyCode::KeyD,
742 WinitKeyCode::KeyE => KeyCode::KeyE,
743 WinitKeyCode::KeyF => KeyCode::KeyF,
744 WinitKeyCode::KeyG => KeyCode::KeyG,
745 WinitKeyCode::KeyH => KeyCode::KeyH,
746 WinitKeyCode::KeyI => KeyCode::KeyI,
747 WinitKeyCode::KeyJ => KeyCode::KeyJ,
748 WinitKeyCode::KeyK => KeyCode::KeyK,
749 WinitKeyCode::KeyL => KeyCode::KeyL,
750 WinitKeyCode::KeyM => KeyCode::KeyM,
751 WinitKeyCode::KeyN => KeyCode::KeyN,
752 WinitKeyCode::KeyO => KeyCode::KeyO,
753 WinitKeyCode::KeyP => KeyCode::KeyP,
754 WinitKeyCode::KeyQ => KeyCode::KeyQ,
755 WinitKeyCode::KeyR => KeyCode::KeyR,
756 WinitKeyCode::KeyS => KeyCode::KeyS,
757 WinitKeyCode::KeyT => KeyCode::KeyT,
758 WinitKeyCode::KeyU => KeyCode::KeyU,
759 WinitKeyCode::KeyV => KeyCode::KeyV,
760 WinitKeyCode::KeyW => KeyCode::KeyW,
761 WinitKeyCode::KeyX => KeyCode::KeyX,
762 WinitKeyCode::KeyY => KeyCode::KeyY,
763 WinitKeyCode::KeyZ => KeyCode::KeyZ,
764 WinitKeyCode::Minus => KeyCode::Minus,
765 WinitKeyCode::Period => KeyCode::Period,
766 WinitKeyCode::Quote => KeyCode::Quote,
767 WinitKeyCode::Semicolon => KeyCode::Semicolon,
768 WinitKeyCode::Slash => KeyCode::Slash,
769 WinitKeyCode::AltLeft => KeyCode::AltLeft,
770 WinitKeyCode::AltRight => KeyCode::AltRight,
771 WinitKeyCode::Backspace => KeyCode::Backspace,
772 WinitKeyCode::CapsLock => KeyCode::CapsLock,
773 WinitKeyCode::ContextMenu => KeyCode::ContextMenu,
774 WinitKeyCode::ControlLeft => KeyCode::CtrlLeft,
775 WinitKeyCode::ControlRight => KeyCode::CtrlRight,
776 WinitKeyCode::Enter => KeyCode::Enter,
777 WinitKeyCode::SuperLeft => KeyCode::SuperLeft,
778 WinitKeyCode::SuperRight => KeyCode::SuperRight,
779 WinitKeyCode::ShiftLeft => KeyCode::ShiftLeft,
780 WinitKeyCode::ShiftRight => KeyCode::ShiftRight,
781 WinitKeyCode::Space => KeyCode::Space,
782 WinitKeyCode::Tab => KeyCode::Tab,
783 WinitKeyCode::Convert => KeyCode::Convert,
784 WinitKeyCode::KanaMode => KeyCode::KanaMode,
785 WinitKeyCode::Lang1 => KeyCode::Lang1,
786 WinitKeyCode::Lang2 => KeyCode::Lang2,
787 WinitKeyCode::Lang3 => KeyCode::Lang3,
788 WinitKeyCode::Lang4 => KeyCode::Lang4,
789 WinitKeyCode::Lang5 => KeyCode::Lang5,
790 WinitKeyCode::NonConvert => KeyCode::NonConvert,
791 WinitKeyCode::Delete => KeyCode::Delete,
792 WinitKeyCode::End => KeyCode::End,
793 WinitKeyCode::Help => KeyCode::Help,
794 WinitKeyCode::Home => KeyCode::Home,
795 WinitKeyCode::Insert => KeyCode::Insert,
796 WinitKeyCode::PageDown => KeyCode::PageDown,
797 WinitKeyCode::PageUp => KeyCode::PageUp,
798 WinitKeyCode::ArrowDown => KeyCode::ArrowDown,
799 WinitKeyCode::ArrowLeft => KeyCode::ArrowLeft,
800 WinitKeyCode::ArrowRight => KeyCode::ArrowRight,
801 WinitKeyCode::ArrowUp => KeyCode::ArrowUp,
802 WinitKeyCode::NumLock => KeyCode::NumLock,
803 WinitKeyCode::Numpad0 => KeyCode::Numpad0,
804 WinitKeyCode::Numpad1 => KeyCode::Numpad1,
805 WinitKeyCode::Numpad2 => KeyCode::Numpad2,
806 WinitKeyCode::Numpad3 => KeyCode::Numpad3,
807 WinitKeyCode::Numpad4 => KeyCode::Numpad4,
808 WinitKeyCode::Numpad5 => KeyCode::Numpad5,
809 WinitKeyCode::Numpad6 => KeyCode::Numpad6,
810 WinitKeyCode::Numpad7 => KeyCode::Numpad7,
811 WinitKeyCode::Numpad8 => KeyCode::Numpad8,
812 WinitKeyCode::Numpad9 => KeyCode::Numpad9,
813 WinitKeyCode::NumpadAdd => KeyCode::NumpadAdd,
814 WinitKeyCode::NumpadBackspace => KeyCode::NumpadBackspace,
815 WinitKeyCode::NumpadClear => KeyCode::NumpadClear,
816 WinitKeyCode::NumpadClearEntry => KeyCode::NumpadClearEntry,
817 WinitKeyCode::NumpadComma => KeyCode::NumpadComma,
818 WinitKeyCode::NumpadDecimal => KeyCode::NumpadDecimal,
819 WinitKeyCode::NumpadDivide => KeyCode::NumpadDivide,
820 WinitKeyCode::NumpadEnter => KeyCode::NumpadEnter,
821 WinitKeyCode::NumpadEqual => KeyCode::NumpadEqual,
822 WinitKeyCode::NumpadHash => KeyCode::NumpadHash,
823 WinitKeyCode::NumpadMemoryAdd => KeyCode::NumpadMemoryAdd,
824 WinitKeyCode::NumpadMemoryClear => KeyCode::NumpadMemoryClear,
825 WinitKeyCode::NumpadMemoryRecall => KeyCode::NumpadMemoryRecall,
826 WinitKeyCode::NumpadMemoryStore => KeyCode::NumpadMemoryStore,
827 WinitKeyCode::NumpadMemorySubtract => KeyCode::NumpadMemorySubtract,
828 WinitKeyCode::NumpadMultiply => KeyCode::NumpadMultiply,
829 WinitKeyCode::NumpadParenLeft => KeyCode::NumpadParenLeft,
830 WinitKeyCode::NumpadParenRight => KeyCode::NumpadParenRight,
831 WinitKeyCode::NumpadStar => KeyCode::NumpadStar,
832 WinitKeyCode::NumpadSubtract => KeyCode::NumpadSubtract,
833 WinitKeyCode::Escape => KeyCode::Escape,
834 WinitKeyCode::Fn => KeyCode::Fn,
835 WinitKeyCode::FnLock => KeyCode::FnLock,
836 WinitKeyCode::PrintScreen => KeyCode::PrintScreen,
837 WinitKeyCode::ScrollLock => KeyCode::ScrollLock,
838 WinitKeyCode::Pause => KeyCode::Pause,
839 WinitKeyCode::BrowserBack => KeyCode::BrowserBack,
840 WinitKeyCode::BrowserFavorites => KeyCode::BrowserFavorites,
841 WinitKeyCode::BrowserForward => KeyCode::BrowserForward,
842 WinitKeyCode::BrowserHome => KeyCode::BrowserHome,
843 WinitKeyCode::BrowserRefresh => KeyCode::BrowserRefresh,
844 WinitKeyCode::BrowserSearch => KeyCode::BrowserSearch,
845 WinitKeyCode::BrowserStop => KeyCode::BrowserStop,
846 WinitKeyCode::Eject => KeyCode::Eject,
847 WinitKeyCode::LaunchApp1 => KeyCode::LaunchApp1,
848 WinitKeyCode::LaunchApp2 => KeyCode::LaunchApp2,
849 WinitKeyCode::LaunchMail => KeyCode::LaunchMail,
850 WinitKeyCode::MediaPlayPause => KeyCode::MediaPlayPause,
851 WinitKeyCode::MediaSelect => KeyCode::MediaSelect,
852 WinitKeyCode::MediaStop => KeyCode::MediaStop,
853 WinitKeyCode::MediaTrackNext => KeyCode::MediaTrackNext,
854 WinitKeyCode::MediaTrackPrevious => KeyCode::MediaTrackPrevious,
855 WinitKeyCode::Power => KeyCode::Power,
856 WinitKeyCode::Sleep => KeyCode::Sleep,
857 WinitKeyCode::AudioVolumeDown => KeyCode::AudioVolumeDown,
858 WinitKeyCode::AudioVolumeMute => KeyCode::AudioVolumeMute,
859 WinitKeyCode::AudioVolumeUp => KeyCode::AudioVolumeUp,
860 WinitKeyCode::WakeUp => KeyCode::WakeUp,
861 WinitKeyCode::Meta => KeyCode::Meta,
862 WinitKeyCode::Hyper => KeyCode::Hyper,
863 WinitKeyCode::Turbo => KeyCode::Turbo,
864 WinitKeyCode::Abort => KeyCode::Abort,
865 WinitKeyCode::Resume => KeyCode::Resume,
866 WinitKeyCode::Suspend => KeyCode::Suspend,
867 WinitKeyCode::Again => KeyCode::Again,
868 WinitKeyCode::Copy => KeyCode::Copy,
869 WinitKeyCode::Cut => KeyCode::Cut,
870 WinitKeyCode::Find => KeyCode::Find,
871 WinitKeyCode::Open => KeyCode::Open,
872 WinitKeyCode::Paste => KeyCode::Paste,
873 WinitKeyCode::Props => KeyCode::Props,
874 WinitKeyCode::Select => KeyCode::Select,
875 WinitKeyCode::Undo => KeyCode::Undo,
876 WinitKeyCode::Hiragana => KeyCode::Hiragana,
877 WinitKeyCode::Katakana => KeyCode::Katakana,
878 WinitKeyCode::F1 => KeyCode::F1,
879 WinitKeyCode::F2 => KeyCode::F2,
880 WinitKeyCode::F3 => KeyCode::F3,
881 WinitKeyCode::F4 => KeyCode::F4,
882 WinitKeyCode::F5 => KeyCode::F5,
883 WinitKeyCode::F6 => KeyCode::F6,
884 WinitKeyCode::F7 => KeyCode::F7,
885 WinitKeyCode::F8 => KeyCode::F8,
886 WinitKeyCode::F9 => KeyCode::F9,
887 WinitKeyCode::F10 => KeyCode::F10,
888 WinitKeyCode::F11 => KeyCode::F11,
889 WinitKeyCode::F12 => KeyCode::F12,
890 WinitKeyCode::F13 => KeyCode::F13,
891 WinitKeyCode::F14 => KeyCode::F14,
892 WinitKeyCode::F15 => KeyCode::F15,
893 WinitKeyCode::F16 => KeyCode::F16,
894 WinitKeyCode::F17 => KeyCode::F17,
895 WinitKeyCode::F18 => KeyCode::F18,
896 WinitKeyCode::F19 => KeyCode::F19,
897 WinitKeyCode::F20 => KeyCode::F20,
898 WinitKeyCode::F21 => KeyCode::F21,
899 WinitKeyCode::F22 => KeyCode::F22,
900 WinitKeyCode::F23 => KeyCode::F23,
901 WinitKeyCode::F24 => KeyCode::F24,
902 WinitKeyCode::F25 => KeyCode::F25,
903 WinitKeyCode::F26 => KeyCode::F26,
904 WinitKeyCode::F27 => KeyCode::F27,
905 WinitKeyCode::F28 => KeyCode::F28,
906 WinitKeyCode::F29 => KeyCode::F29,
907 WinitKeyCode::F30 => KeyCode::F30,
908 WinitKeyCode::F31 => KeyCode::F31,
909 WinitKeyCode::F32 => KeyCode::F32,
910 WinitKeyCode::F33 => KeyCode::F33,
911 WinitKeyCode::F34 => KeyCode::F34,
912 WinitKeyCode::F35 => KeyCode::F35,
913 key => {
914 tracing::error!("matched unknown key code `{key:?}`");
915 KeyCode::Unidentified(NativeKeyCode::Unidentified)
916 }
917 }
918}
919
920use winit::keyboard::PhysicalKey as WinitPhysicalKey;
921pub(crate) fn winit_physical_key_to_key_code(key: WinitPhysicalKey) -> KeyCode {
922 match key {
923 WinitPhysicalKey::Code(code) => winit_key_code_to_key_code(code),
924 WinitPhysicalKey::Unidentified(u) => match u {
925 winit::keyboard::NativeKeyCode::Unidentified => KeyCode::Unidentified(NativeKeyCode::Unidentified),
926 winit::keyboard::NativeKeyCode::Android(c) => KeyCode::Unidentified(NativeKeyCode::Android(c)),
927 winit::keyboard::NativeKeyCode::MacOS(c) => KeyCode::Unidentified(NativeKeyCode::MacOS(c)),
928 winit::keyboard::NativeKeyCode::Windows(c) => KeyCode::Unidentified(NativeKeyCode::Windows(c)),
929 winit::keyboard::NativeKeyCode::Xkb(c) => KeyCode::Unidentified(NativeKeyCode::Xkb(c)),
930 },
931 }
932}
933
934thread_local! {
935 static SUPPRESS: Cell<bool> = const { Cell::new(false) };
936 static SUPPRESSED_PANIC: RefCell<Option<SuppressedPanic>> = const { RefCell::new(None) };
937}
938
939#[cfg(ipc)]
941pub(crate) fn suppress_panic() -> bool {
942 SUPPRESS.get()
943}
944#[cfg(ipc)]
945pub(crate) fn set_suppressed_panic(panic: SuppressedPanic) {
946 SUPPRESSED_PANIC.set(Some(panic));
947}
948
949#[derive(Debug)]
950pub(crate) struct SuppressedPanic {
951 pub thread: Txt,
952 pub msg: Txt,
953 pub file: Txt,
954 pub line: u32,
955 pub column: u32,
956 pub backtrace: Backtrace,
957}
958impl SuppressedPanic {
959 #[cfg(ipc)]
960 pub fn from_hook(info: &std::panic::PanicHookInfo, backtrace: Backtrace) -> Self {
961 let current_thread = std::thread::current();
962 let thread = current_thread.name().unwrap_or("<unnamed>");
963 let msg = Self::payload(info.payload());
964
965 let (file, line, column) = if let Some(l) = info.location() {
966 (l.file(), l.line(), l.column())
967 } else {
968 ("<unknown>", 0, 0)
969 };
970 Self {
971 thread: thread.to_txt(),
972 msg,
973 file: file.to_txt(),
974 line,
975 column,
976 backtrace,
977 }
978 }
979
980 pub fn from_catch(p: Box<dyn Any>) -> Self {
981 Self {
982 thread: Txt::from("<unknown>"),
983 msg: Self::payload(&*p),
984 file: Txt::from("<unknown>"),
985 line: 0,
986 column: 0,
987 backtrace: Backtrace::disabled(),
988 }
989 }
990
991 fn payload(p: &dyn Any) -> Txt {
992 match p.downcast_ref::<&'static str>() {
993 Some(s) => s,
994 None => match p.downcast_ref::<String>() {
995 Some(s) => &s[..],
996 None => "Box<dyn Any>",
997 },
998 }
999 .to_txt()
1000 }
1001}
1002impl std::error::Error for SuppressedPanic {}
1003impl fmt::Display for SuppressedPanic {
1004 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1005 write!(
1006 f,
1007 "thread '{}' panicked at {}:{}:{}:\n{}\n{}",
1008 self.thread, self.file, self.line, self.column, self.msg, self.backtrace,
1009 )
1010 }
1011}
1012
1013pub(crate) fn catch_suppress<T>(f: impl FnOnce() -> T + std::panic::UnwindSafe) -> Result<T, Box<SuppressedPanic>> {
1015 SUPPRESS.set(true);
1016 let _cleanup = RunOnDrop::new(|| SUPPRESS.set(false));
1017 std::panic::catch_unwind(f).map_err(|e| {
1018 SUPPRESSED_PANIC.with_borrow_mut(|p| match p.take() {
1019 Some(p) => Box::new(p),
1020 None => Box::new(SuppressedPanic::from_catch(e)),
1021 })
1022 })
1023}
1024
1025struct RunOnDrop<F: FnOnce()>(Option<F>);
1026impl<F: FnOnce()> RunOnDrop<F> {
1027 pub fn new(clean: F) -> Self {
1028 RunOnDrop(Some(clean))
1029 }
1030}
1031impl<F: FnOnce()> Drop for RunOnDrop<F> {
1032 fn drop(&mut self) {
1033 if let Some(clean) = self.0.take() {
1034 clean();
1035 }
1036 }
1037}
1038
1039#[cfg(windows)]
1040pub(crate) extern "system" fn minimal_wndproc(
1041 window: windows_sys::Win32::Foundation::HWND,
1042 message: u32,
1043 wparam: windows_sys::Win32::Foundation::WPARAM,
1044 lparam: windows_sys::Win32::Foundation::LPARAM,
1045) -> windows_sys::Win32::Foundation::LRESULT {
1046 unsafe { windows_sys::Win32::UI::WindowsAndMessaging::DefWindowProcW(window, message, wparam, lparam) }
1047}
1048
1049#[cfg(windows)]
1050pub fn get_instance_handle() -> isize {
1051 unsafe extern "C" {
1060 static __ImageBase: windows_sys::Win32::System::SystemServices::IMAGE_DOS_HEADER;
1061 }
1062
1063 unsafe { (&__ImageBase) as *const _ as _ }
1064}
1065
1066#[cfg(windows)]
1067pub mod taskbar_com {
1068 #![expect(non_snake_case)]
1071 #![expect(non_upper_case_globals)]
1072
1073 use std::ffi::c_void;
1074
1075 use windows_sys::{
1076 Win32::Foundation::{BOOL, HWND},
1077 core::{GUID, HRESULT, IUnknown},
1078 };
1079
1080 #[repr(C)]
1081 pub struct IUnknownVtbl {
1082 pub QueryInterface: unsafe extern "system" fn(This: *mut IUnknown, riid: *const GUID, ppvObject: *mut *mut c_void) -> HRESULT,
1083 pub AddRef: unsafe extern "system" fn(This: *mut IUnknown) -> u32,
1084 pub Release: unsafe extern "system" fn(This: *mut IUnknown) -> u32,
1085 }
1086
1087 #[repr(C)]
1088 pub struct ITaskbarListVtbl {
1089 pub parent: IUnknownVtbl,
1090 pub HrInit: unsafe extern "system" fn(This: *mut ITaskbarList) -> HRESULT,
1091 pub AddTab: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT,
1092 pub DeleteTab: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT,
1093 pub ActivateTab: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT,
1094 pub SetActiveAlt: unsafe extern "system" fn(This: *mut ITaskbarList, hwnd: HWND) -> HRESULT,
1095 }
1096
1097 #[repr(C)]
1098 pub struct ITaskbarList {
1099 pub lpVtbl: *const ITaskbarListVtbl,
1100 }
1101
1102 #[repr(C)]
1103 pub struct ITaskbarList2Vtbl {
1104 pub parent: ITaskbarListVtbl,
1105 pub MarkFullscreenWindow: unsafe extern "system" fn(This: *mut ITaskbarList2, hwnd: HWND, fFullscreen: BOOL) -> HRESULT,
1106 }
1107
1108 #[repr(C)]
1109 pub struct ITaskbarList2 {
1110 pub lpVtbl: *const ITaskbarList2Vtbl,
1111 }
1112
1113 pub const CLSID_TaskbarList: GUID = GUID {
1114 data1: 0x56fdf344,
1115 data2: 0xfd6d,
1116 data3: 0x11d0,
1117 data4: [0x95, 0x8a, 0x00, 0x60, 0x97, 0xc9, 0xa0, 0x90],
1118 };
1119
1120 pub const IID_ITaskbarList2: GUID = GUID {
1121 data1: 0x602d4995,
1122 data2: 0xb13a,
1123 data3: 0x429b,
1124 data4: [0xa6, 0x6e, 0x19, 0x35, 0xe4, 0x4f, 0x43, 0x17],
1125 };
1126}
1127
1128pub(crate) fn wr_workers() -> Arc<rayon::ThreadPool> {
1129 let worker = ThreadPoolBuilder::new().thread_name(|idx| format!("WRWorker#{}", idx)).build();
1134 Arc::new(worker.unwrap())
1135}
1136
1137#[cfg(not(any(windows, target_os = "android")))]
1138pub(crate) fn arboard_to_clip(e: arboard::Error) -> clipboard_api::ClipboardError {
1139 match e {
1140 arboard::Error::ContentNotAvailable => clipboard_api::ClipboardError::NotFound,
1141 arboard::Error::ClipboardNotSupported => clipboard_api::ClipboardError::NotSupported,
1142 e => clipboard_api::ClipboardError::Other(zng_txt::formatx!("{e:?}")),
1143 }
1144}
1145
1146#[cfg(windows)]
1147pub(crate) fn clipboard_win_to_clip(e: clipboard_win::ErrorCode) -> clipboard_api::ClipboardError {
1148 use zng_txt::formatx;
1149
1150 if e.raw_code() == 0 {
1151 clipboard_api::ClipboardError::NotFound
1153 } else {
1154 clipboard_api::ClipboardError::Other(formatx!("{e:?}"))
1155 }
1156}
1157
1158fn accesskit_to_px(length: f64) -> Px {
1159 Px(length.round() as _)
1160}
1161
1162fn accesskit_point_to_px(p: accesskit::Point) -> PxPoint {
1163 PxPoint::new(accesskit_to_px(p.x), accesskit_to_px(p.y))
1164}
1165
1166pub(crate) fn accesskit_to_event(
1167 window_id: zng_view_api::window::WindowId,
1168 request: accesskit::ActionRequest,
1169) -> Option<zng_view_api::Event> {
1170 use accesskit::Action;
1171 use zng_view_api::access::*;
1172
1173 let target = AccessNodeId(request.target.0);
1174
1175 Some(zng_view_api::Event::AccessCommand {
1176 window: window_id,
1177 target,
1178 command: match request.action {
1179 Action::Click => AccessCmd::Click(true),
1180 Action::ShowContextMenu => AccessCmd::Click(false),
1181 Action::Focus => AccessCmd::Focus(true),
1182 Action::SetSequentialFocusNavigationStartingPoint => AccessCmd::FocusNavOrigin,
1183 Action::Blur => AccessCmd::Focus(false),
1184 Action::Collapse => AccessCmd::SetExpanded(false),
1185 Action::Expand => AccessCmd::SetExpanded(true),
1186 Action::CustomAction => return None,
1187 Action::Decrement => AccessCmd::Increment(-1),
1188 Action::Increment => AccessCmd::Increment(1),
1189 Action::HideTooltip => AccessCmd::SetToolTipVis(false),
1190 Action::ShowTooltip => AccessCmd::SetToolTipVis(true),
1191 Action::ReplaceSelectedText => {
1192 if let Some(accesskit::ActionData::Value(s)) = request.data {
1193 AccessCmd::ReplaceSelectedText(Txt::from_str(&s))
1194 } else {
1195 AccessCmd::ReplaceSelectedText(Txt::from_str(""))
1196 }
1197 }
1198 Action::ScrollBackward => AccessCmd::Scroll(ScrollCmd::PageUp),
1199 Action::ScrollForward => AccessCmd::Scroll(ScrollCmd::PageDown),
1200
1201 Action::ScrollDown => AccessCmd::Scroll(ScrollCmd::PageDown),
1202 Action::ScrollLeft => AccessCmd::Scroll(ScrollCmd::PageLeft),
1203 Action::ScrollRight => AccessCmd::Scroll(ScrollCmd::PageRight),
1204 Action::ScrollUp => AccessCmd::Scroll(ScrollCmd::PageUp),
1205 Action::ScrollIntoView => {
1206 if let Some(accesskit::ActionData::ScrollTargetRect(r)) = request.data {
1207 let r = PxRect::new(
1208 accesskit_point_to_px(r.origin()),
1209 PxSize::new(accesskit_to_px(r.width()), accesskit_to_px(r.height())),
1210 );
1211 AccessCmd::Scroll(ScrollCmd::ScrollToRect(r))
1212 } else {
1213 AccessCmd::Scroll(ScrollCmd::ScrollTo)
1214 }
1215 }
1216 Action::ScrollToPoint => {
1217 if let Some(accesskit::ActionData::ScrollToPoint(p)) = request.data {
1218 AccessCmd::Scroll(ScrollCmd::ScrollToRect(PxRect::new(accesskit_point_to_px(p), PxSize::splat(Px(1)))))
1219 } else {
1220 return None;
1221 }
1222 }
1223 Action::SetScrollOffset => {
1224 if let Some(accesskit::ActionData::SetScrollOffset(o)) = request.data {
1225 AccessCmd::Scroll(ScrollCmd::ScrollToRect(PxRect::new(accesskit_point_to_px(o), PxSize::splat(Px(1)))))
1226 } else {
1227 return None;
1228 }
1229 }
1230 Action::SetTextSelection => {
1231 if let Some(accesskit::ActionData::SetTextSelection(s)) = request.data {
1232 AccessCmd::SelectText {
1233 start: (AccessNodeId(s.anchor.node.0), s.anchor.character_index),
1234 caret: (AccessNodeId(s.focus.node.0), s.focus.character_index),
1235 }
1236 } else {
1237 return None;
1238 }
1239 }
1240 Action::SetValue => match request.data {
1241 Some(accesskit::ActionData::Value(s)) => AccessCmd::SetString(Txt::from_str(&s)),
1242 Some(accesskit::ActionData::NumericValue(n)) => AccessCmd::SetNumber(n),
1243 _ => return None,
1244 },
1245 },
1246 })
1247}
1248
1249pub(crate) fn access_tree_update_to_kit(update: zng_view_api::access::AccessTreeUpdate) -> accesskit::TreeUpdate {
1250 let mut nodes = Vec::with_capacity(update.updates.iter().map(|t| t.len()).sum());
1251
1252 for update in update.updates {
1253 access_node_to_kit(update.root(), &mut nodes);
1254 }
1255
1256 accesskit::TreeUpdate {
1257 nodes,
1258 tree: update.full_root.map(|id| accesskit::Tree::new(access_id_to_kit(id))),
1259 focus: access_id_to_kit(update.focused),
1260 }
1261}
1262
1263fn access_node_to_kit(
1264 node: zng_view_api::access::AccessNodeRef,
1265 output: &mut Vec<(accesskit::NodeId, accesskit::Node)>,
1266) -> accesskit::NodeId {
1267 let node_id = access_id_to_kit(node.id);
1268 let node_role = node.role.map(access_role_to_kit).unwrap_or(accesskit::Role::Unknown);
1269 let mut builder = accesskit::Node::new(node_role);
1270
1271 if !node.size.is_empty() {
1273 let mut bounds = accesskit::Rect::new(0.0, 0.0, node.size.width.0 as f64, node.size.height.0 as f64);
1274 if !node.transform.is_identity() {
1275 if let (0, PxTransform::Offset(o)) = (node.children_count(), node.transform) {
1276 let (x, y) = o.cast().to_tuple();
1277 bounds = bounds.with_origin(accesskit::Point::new(x, y));
1278 } else {
1279 let t = node.transform.to_transform().to_2d();
1280 builder.set_transform(accesskit::Affine::new(t.cast().to_array()));
1281 }
1282 }
1283 builder.set_bounds(bounds);
1284 }
1285
1286 for cmd in &node.commands {
1288 use zng_view_api::access::AccessCmdName::*;
1289
1290 match cmd {
1291 Click => {
1292 builder.add_action(accesskit::Action::Click);
1293 builder.add_action(accesskit::Action::ShowContextMenu);
1294 }
1295 Focus => {
1296 builder.add_action(accesskit::Action::Focus);
1297 builder.add_action(accesskit::Action::Blur);
1298 }
1299 SetExpanded => {
1300 builder.add_action(accesskit::Action::Expand);
1301 builder.add_action(accesskit::Action::Collapse);
1302 }
1303 Increment => {
1304 builder.add_action(accesskit::Action::Increment);
1305 }
1306 SetToolTipVis => {
1307 builder.add_action(accesskit::Action::ShowTooltip);
1308 builder.add_action(accesskit::Action::HideTooltip);
1309 }
1310 Scroll => {
1311 builder.add_action(accesskit::Action::ScrollBackward);
1312 builder.add_action(accesskit::Action::ScrollUp);
1313 builder.add_action(accesskit::Action::ScrollLeft);
1314 builder.add_action(accesskit::Action::ScrollForward);
1315 builder.add_action(accesskit::Action::ScrollDown);
1316 builder.add_action(accesskit::Action::ScrollRight);
1317 builder.add_action(accesskit::Action::ScrollIntoView);
1318 builder.add_action(accesskit::Action::ScrollToPoint);
1319 }
1320 ReplaceSelectedText => {
1321 builder.add_action(accesskit::Action::ReplaceSelectedText);
1322 }
1323 SelectText => {
1324 builder.add_action(accesskit::Action::SetTextSelection);
1325 }
1326 SetString => {
1327 builder.add_action(accesskit::Action::SetValue);
1328 }
1329 SetNumber => {
1330 builder.add_action(accesskit::Action::SetValue);
1331 }
1332 _ => {}
1333 }
1334 }
1335
1336 for state in &node.state {
1338 use zng_view_api::access::{self, AccessState::*};
1339
1340 match state {
1341 AutoComplete(s) => {
1342 if *s == access::AutoComplete::BOTH {
1343 builder.set_auto_complete(accesskit::AutoComplete::Both)
1344 } else if *s == access::AutoComplete::INLINE {
1345 builder.set_auto_complete(accesskit::AutoComplete::Inline)
1346 } else if *s == access::AutoComplete::LIST {
1347 builder.set_auto_complete(accesskit::AutoComplete::List)
1348 }
1349 }
1350 Checked(b) => builder.set_toggled(match b {
1351 Some(true) => accesskit::Toggled::True,
1352 Some(false) => accesskit::Toggled::False,
1353 None => accesskit::Toggled::Mixed,
1354 }),
1355 Current(kind) => match kind {
1356 access::CurrentKind::Page => builder.set_aria_current(accesskit::AriaCurrent::Page),
1357 access::CurrentKind::Step => builder.set_aria_current(accesskit::AriaCurrent::Step),
1358 access::CurrentKind::Location => builder.set_aria_current(accesskit::AriaCurrent::Location),
1359 access::CurrentKind::Date => builder.set_aria_current(accesskit::AriaCurrent::Date),
1360 access::CurrentKind::Time => builder.set_aria_current(accesskit::AriaCurrent::Time),
1361 access::CurrentKind::Item => builder.set_aria_current(accesskit::AriaCurrent::True),
1362 },
1363 Disabled => builder.set_disabled(),
1364 ErrorMessage(id) => builder.set_error_message(access_id_to_kit(*id)),
1365 Expanded(b) => builder.set_expanded(*b),
1366 Popup(pop) => match pop {
1367 access::Popup::Menu => builder.set_has_popup(accesskit::HasPopup::Menu),
1368 access::Popup::ListBox => builder.set_has_popup(accesskit::HasPopup::Listbox),
1369 access::Popup::Tree => builder.set_has_popup(accesskit::HasPopup::Tree),
1370 access::Popup::Grid => builder.set_has_popup(accesskit::HasPopup::Grid),
1371 access::Popup::Dialog => builder.set_has_popup(accesskit::HasPopup::Dialog),
1372 },
1373 Invalid(i) => {
1374 if i.contains(access::Invalid::SPELLING) {
1375 builder.set_invalid(accesskit::Invalid::Spelling)
1376 } else if i.contains(access::Invalid::GRAMMAR) {
1377 builder.set_invalid(accesskit::Invalid::Grammar)
1378 } else if i.contains(access::Invalid::ANY) {
1379 builder.set_invalid(accesskit::Invalid::True)
1380 }
1381 }
1382 Label(s) => builder.set_label(s.clone().into_owned().into_boxed_str()),
1383 Level(n) => builder.set_level(n.get() as usize),
1384 Modal => builder.set_modal(),
1385 MultiSelectable => builder.set_multiselectable(),
1386 Orientation(o) => match o {
1387 access::Orientation::Horizontal => builder.set_orientation(accesskit::Orientation::Horizontal),
1388 access::Orientation::Vertical => builder.set_orientation(accesskit::Orientation::Vertical),
1389 },
1390 Placeholder(p) => builder.set_placeholder(p.clone().into_owned().into_boxed_str()),
1391 ReadOnly => builder.set_read_only(),
1392 Required => builder.set_required(),
1393 Selected => builder.set_selected(true),
1394 Sort(o) => match o {
1395 access::SortDirection::Ascending => builder.set_sort_direction(accesskit::SortDirection::Ascending),
1396 access::SortDirection::Descending => builder.set_sort_direction(accesskit::SortDirection::Descending),
1397 },
1398 ValueMax(m) => builder.set_max_numeric_value(*m),
1399 ValueMin(m) => builder.set_min_numeric_value(*m),
1400 Value(v) => builder.set_numeric_value(*v),
1401 ValueText(v) => builder.set_value(v.clone().into_owned().into_boxed_str()),
1402 Live { indicator, atomic, busy } => {
1403 builder.set_live(match indicator {
1404 access::LiveIndicator::Assertive => accesskit::Live::Assertive,
1405 access::LiveIndicator::OnlyFocused => accesskit::Live::Off,
1406 access::LiveIndicator::Polite => accesskit::Live::Polite,
1407 });
1408 if *atomic {
1409 builder.set_live_atomic();
1410 }
1411 if *busy {
1412 builder.set_busy();
1413 }
1414 }
1415 ActiveDescendant(id) => builder.set_active_descendant(access_id_to_kit(*id)),
1416 ColCount(c) => builder.set_column_count(*c),
1417 ColIndex(i) => builder.set_column_index(*i),
1418 ColSpan(s) => builder.set_column_span(*s),
1419 Controls(ids) => builder.set_controls(ids.iter().copied().map(access_id_to_kit).collect::<Vec<_>>()),
1420 DescribedBy(ids) => builder.set_described_by(ids.iter().copied().map(access_id_to_kit).collect::<Vec<_>>()),
1421 Details(ids) => builder.set_details(ids.iter().copied().map(access_id_to_kit).collect::<Vec<_>>()),
1422 FlowTo(ids) => builder.set_flow_to(ids.iter().copied().map(access_id_to_kit).collect::<Vec<_>>()),
1423 LabelledBy(ids) => builder.set_labelled_by(ids.iter().copied().map(access_id_to_kit).collect::<Vec<_>>()),
1424 LabelledByChild => {
1425 let labelled_by: Vec<_> = if node.children.is_empty() {
1426 node.children().map(|c| access_id_to_kit(c.id)).collect()
1427 } else {
1428 node.children.iter().map(|id| access_id_to_kit(*id)).collect()
1429 };
1430 builder.set_labelled_by(labelled_by);
1431 }
1432 Owns(ids) => {
1433 for id in ids {
1434 builder.push_child(access_id_to_kit(*id));
1435 }
1436 }
1437 ItemIndex(p) => builder.set_position_in_set(*p),
1438 RowCount(c) => builder.set_row_count(*c),
1439 RowIndex(i) => builder.set_row_index(*i),
1440 RowSpan(s) => builder.set_row_span(*s),
1441 ItemCount(s) => builder.set_size_of_set(*s),
1442 Lang(l) => builder.set_language(l.to_string()),
1443
1444 ScrollHorizontal(x) => {
1445 builder.set_scroll_x(*x as f64);
1446 builder.set_scroll_x_min(0.0);
1447 builder.set_scroll_x_max(1.0);
1448 }
1449 ScrollVertical(y) => {
1450 builder.set_scroll_y(*y as f64);
1451 builder.set_scroll_y_min(0.0);
1452 builder.set_scroll_y_max(1.0);
1453 }
1454 _ => {}
1455 }
1456 }
1457
1458 if node.children.is_empty() {
1460 for child in node.children() {
1461 let child_id = access_node_to_kit(child, output);
1462 builder.push_child(child_id);
1463 }
1464 } else {
1465 for id in &node.children {
1466 builder.push_child(access_id_to_kit(*id));
1467 }
1468 for child in node.children() {
1469 let _ = access_node_to_kit(child, output);
1470 }
1471 }
1472
1473 let node = builder;
1474 output.push((node_id, node));
1475 node_id
1476}
1477
1478fn access_id_to_kit(id: AccessNodeId) -> accesskit::NodeId {
1479 accesskit::NodeId(id.0)
1480}
1481
1482fn access_role_to_kit(role: zng_view_api::access::AccessRole) -> accesskit::Role {
1483 use accesskit::Role;
1484 use zng_view_api::access::AccessRole::*;
1485 match role {
1486 Button => Role::Button,
1487 CheckBox => Role::CheckBox,
1488 GridCell => Role::Cell,
1489 Link => Role::Link,
1490 MenuItem => Role::MenuItem,
1491 MenuItemCheckBox => Role::MenuItemCheckBox,
1492 MenuItemRadio => Role::MenuItemRadio,
1493 Option => Role::ListBoxOption,
1494 ProgressBar => Role::ProgressIndicator,
1495 Radio => Role::RadioButton,
1496 ScrollBar => Role::ScrollBar,
1497 SearchBox => Role::SearchInput,
1498 Slider => Role::Slider,
1499 SpinButton => Role::SpinButton,
1500 Switch => Role::Switch,
1501 Tab => Role::Tab,
1502 TabPanel => Role::TabPanel,
1503 TextInput => Role::TextInput,
1504 TreeItem => Role::TreeItem,
1505 ComboBox => Role::ComboBox,
1506 Grid => Role::Grid,
1507 ListBox => Role::ListBox,
1508 Menu => Role::Menu,
1509 MenuBar => Role::MenuBar,
1510 RadioGroup => Role::RadioGroup,
1511 TabList => Role::TabList,
1512 Tree => Role::Tree,
1513 TreeGrid => Role::TreeGrid,
1514 Application => Role::Application,
1515 Article => Role::Article,
1516 Cell => Role::Cell,
1517 ColumnHeader => Role::ColumnHeader,
1518 Definition => Role::Definition,
1519 Document => Role::Document,
1520 Feed => Role::Feed,
1521 Figure => Role::Figure,
1522 Group => Role::Group,
1523 Heading => Role::Heading,
1524 Image => Role::Image,
1525 List => Role::List,
1526 ListItem => Role::ListItem,
1527 Math => Role::Math,
1528 Note => Role::Note,
1529 Row => Role::Row,
1530 RowGroup => Role::RowGroup,
1531 RowHeader => Role::RowHeader,
1532 Separator => Role::Splitter,
1533 Table => Role::Table,
1534 Term => Role::Term,
1535 ToolBar => Role::Toolbar,
1536 ToolTip => Role::Tooltip,
1537 Banner => Role::Banner,
1538 Complementary => Role::Complementary,
1539 ContentInfo => Role::ContentInfo,
1540 Form => Role::Form,
1541 Main => Role::Main,
1542 Navigation => Role::Navigation,
1543 Region => Role::Region,
1544 Search => Role::Search,
1545 Alert => Role::Alert,
1546 Log => Role::Log,
1547 Marquee => Role::Marquee,
1548 Status => Role::Status,
1549 Timer => Role::Timer,
1550 AlertDialog => Role::AlertDialog,
1551 Dialog => Role::Dialog,
1552 _ => Role::Unknown,
1553 }
1554}
1555
1556pub(crate) fn frame_render_reasons(frame: &FrameRequest) -> wr::RenderReasons {
1557 let mut reasons = wr::RenderReasons::SCENE;
1558
1559 if frame.capture != FrameCapture::None {
1560 reasons |= wr::RenderReasons::SNAPSHOT;
1561 }
1562
1563 reasons
1564}
1565
1566pub(crate) fn frame_update_render_reasons(update: &FrameUpdateRequest) -> wr::RenderReasons {
1567 let mut reasons = wr::RenderReasons::empty();
1568
1569 if update.has_bounds() {
1570 reasons |= wr::RenderReasons::ANIMATED_PROPERTY;
1571 }
1572
1573 if update.capture != FrameCapture::None {
1574 reasons |= wr::RenderReasons::SNAPSHOT;
1575 }
1576
1577 if update.clear_color.is_some() {
1578 reasons |= wr::RenderReasons::CONFIG_CHANGE;
1579 }
1580
1581 reasons
1582}
1583
1584#[must_use = "call unset before drop"]
1585pub(crate) struct WinitEventLoop(*const ActiveEventLoop);
1586impl WinitEventLoop {
1587 pub fn set<'l>(&mut self, winit_loop: &'l ActiveEventLoop) -> WinitEventLoopGuard<'l> {
1588 self.0 = winit_loop;
1589 WinitEventLoopGuard {
1590 defused: false,
1591 _loop_lifetime: PhantomData,
1592 }
1593 }
1594}
1595impl Default for WinitEventLoop {
1596 fn default() -> Self {
1597 Self(std::ptr::null())
1598 }
1599}
1600impl ops::Deref for WinitEventLoop {
1601 type Target = ActiveEventLoop;
1602
1603 fn deref(&self) -> &Self::Target {
1604 assert!(!self.0.is_null(), "winit event loop not active");
1605 unsafe { &*self.0 }
1607 }
1608}
1609pub(crate) struct WinitEventLoopGuard<'l> {
1610 defused: bool,
1611 _loop_lifetime: PhantomData<&'l ActiveEventLoop>,
1612}
1613impl WinitEventLoopGuard<'_> {
1614 pub fn unset(&mut self, l: &mut WinitEventLoop) {
1615 self.defused = true;
1616 l.0 = std::ptr::null();
1617 }
1618}
1619impl Drop for WinitEventLoopGuard<'_> {
1620 fn drop(&mut self) {
1621 if !self.defused {
1622 let msg = "unsafe pointer to winit ActiveEventLoop not cleared";
1623 if std::thread::panicking() {
1624 tracing::error!("{msg}");
1625 } else {
1626 panic!("{msg}");
1627 }
1628 }
1629 }
1630}