use std::cell::Cell; use std::collections::VecDeque; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex, mpsc}; use std::time::Instant; use std::{iter, mem, slice}; use bitflags::bitflags; use orbclient::{ ButtonEvent, EventOption, FocusEvent, HoverEvent, KeyEvent, MouseEvent, MouseRelativeEvent, MoveEvent, QuitEvent, ResizeEvent, ScrollEvent, TextInputEvent, }; use redox_event::{EventFlags, EventQueue}; use smol_str::SmolStr; use winit_core::application::ApplicationHandler; use winit_core::cursor::{CustomCursor, CustomCursorSource}; use winit_core::error::{EventLoopError, NotSupportedError, RequestError}; use winit_core::event::{self, Ime, Modifiers, StartCause}; use winit_core::event_loop::{ ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; use winit_core::keyboard::{ Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode, PhysicalKey, }; use winit_core::window::{Theme, Window as CoreWindow, WindowId}; use crate::window::Window; use crate::{RedoxSocket, TimeSocket, WindowProperties}; fn convert_scancode(scancode: u8) -> (PhysicalKey, Option) { // Key constants from https://docs.rs/orbclient/latest/orbclient/event/index.html let (key_code, named_key_opt) = match scancode { orbclient::K_A => (KeyCode::KeyA, None), orbclient::K_B => (KeyCode::KeyB, None), orbclient::K_C => (KeyCode::KeyC, None), orbclient::K_D => (KeyCode::KeyD, None), orbclient::K_E => (KeyCode::KeyE, None), orbclient::K_F => (KeyCode::KeyF, None), orbclient::K_G => (KeyCode::KeyG, None), orbclient::K_H => (KeyCode::KeyH, None), orbclient::K_I => (KeyCode::KeyI, None), orbclient::K_J => (KeyCode::KeyJ, None), orbclient::K_K => (KeyCode::KeyK, None), orbclient::K_L => (KeyCode::KeyL, None), orbclient::K_M => (KeyCode::KeyM, None), orbclient::K_N => (KeyCode::KeyN, None), orbclient::K_O => (KeyCode::KeyO, None), orbclient::K_P => (KeyCode::KeyP, None), orbclient::K_Q => (KeyCode::KeyQ, None), orbclient::K_R => (KeyCode::KeyR, None), orbclient::K_S => (KeyCode::KeyS, None), orbclient::K_T => (KeyCode::KeyT, None), orbclient::K_U => (KeyCode::KeyU, None), orbclient::K_V => (KeyCode::KeyV, None), orbclient::K_W => (KeyCode::KeyW, None), orbclient::K_X => (KeyCode::KeyX, None), orbclient::K_Y => (KeyCode::KeyY, None), orbclient::K_Z => (KeyCode::KeyZ, None), orbclient::K_0 => (KeyCode::Digit0, None), orbclient::K_1 => (KeyCode::Digit1, None), orbclient::K_2 => (KeyCode::Digit2, None), orbclient::K_3 => (KeyCode::Digit3, None), orbclient::K_4 => (KeyCode::Digit4, None), orbclient::K_5 => (KeyCode::Digit5, None), orbclient::K_6 => (KeyCode::Digit6, None), orbclient::K_7 => (KeyCode::Digit7, None), orbclient::K_8 => (KeyCode::Digit8, None), orbclient::K_9 => (KeyCode::Digit9, None), orbclient::K_ALT => (KeyCode::AltLeft, Some(NamedKey::Alt)), orbclient::K_ALT_GR => (KeyCode::AltRight, Some(NamedKey::AltGraph)), orbclient::K_BACKSLASH => (KeyCode::Backslash, None), orbclient::K_BKSP => (KeyCode::Backspace, Some(NamedKey::Backspace)), orbclient::K_BRACE_CLOSE => (KeyCode::BracketRight, None), orbclient::K_BRACE_OPEN => (KeyCode::BracketLeft, None), orbclient::K_CAPS => (KeyCode::CapsLock, Some(NamedKey::CapsLock)), orbclient::K_COMMA => (KeyCode::Comma, None), orbclient::K_CTRL => (KeyCode::ControlLeft, Some(NamedKey::Control)), orbclient::K_DEL => (KeyCode::Delete, Some(NamedKey::Delete)), orbclient::K_DOWN => (KeyCode::ArrowDown, Some(NamedKey::ArrowDown)), orbclient::K_END => (KeyCode::End, Some(NamedKey::End)), orbclient::K_ENTER => (KeyCode::Enter, Some(NamedKey::Enter)), orbclient::K_EQUALS => (KeyCode::Equal, None), orbclient::K_ESC => (KeyCode::Escape, Some(NamedKey::Escape)), orbclient::K_F1 => (KeyCode::F1, Some(NamedKey::F1)), orbclient::K_F2 => (KeyCode::F2, Some(NamedKey::F2)), orbclient::K_F3 => (KeyCode::F3, Some(NamedKey::F3)), orbclient::K_F4 => (KeyCode::F4, Some(NamedKey::F4)), orbclient::K_F5 => (KeyCode::F5, Some(NamedKey::F5)), orbclient::K_F6 => (KeyCode::F6, Some(NamedKey::F6)), orbclient::K_F7 => (KeyCode::F7, Some(NamedKey::F7)), orbclient::K_F8 => (KeyCode::F8, Some(NamedKey::F8)), orbclient::K_F9 => (KeyCode::F9, Some(NamedKey::F9)), orbclient::K_F10 => (KeyCode::F10, Some(NamedKey::F10)), orbclient::K_F11 => (KeyCode::F11, Some(NamedKey::F11)), orbclient::K_F12 => (KeyCode::F12, Some(NamedKey::F12)), orbclient::K_HOME => (KeyCode::Home, Some(NamedKey::Home)), orbclient::K_LEFT => (KeyCode::ArrowLeft, Some(NamedKey::ArrowLeft)), orbclient::K_LEFT_SHIFT => (KeyCode::ShiftLeft, Some(NamedKey::Shift)), orbclient::K_MINUS => (KeyCode::Minus, None), orbclient::K_NUM_0 => (KeyCode::Numpad0, None), orbclient::K_NUM_1 => (KeyCode::Numpad1, None), orbclient::K_NUM_2 => (KeyCode::Numpad2, None), orbclient::K_NUM_3 => (KeyCode::Numpad3, None), orbclient::K_NUM_4 => (KeyCode::Numpad4, None), orbclient::K_NUM_5 => (KeyCode::Numpad5, None), orbclient::K_NUM_6 => (KeyCode::Numpad6, None), orbclient::K_NUM_7 => (KeyCode::Numpad7, None), orbclient::K_NUM_8 => (KeyCode::Numpad8, None), orbclient::K_NUM_9 => (KeyCode::Numpad9, None), orbclient::K_NUM_ASTERISK => (KeyCode::NumpadMultiply, None), orbclient::K_NUM_ENTER => (KeyCode::NumpadEnter, Some(NamedKey::Enter)), orbclient::K_NUM_MINUS => (KeyCode::NumpadSubtract, None), orbclient::K_NUM_PLUS => (KeyCode::NumpadAdd, None), orbclient::K_NUM_SLASH => (KeyCode::NumpadDivide, None), orbclient::K_NUM_PERIOD => (KeyCode::NumpadDecimal, None), orbclient::K_PERIOD => (KeyCode::Period, None), orbclient::K_PGDN => (KeyCode::PageDown, Some(NamedKey::PageDown)), orbclient::K_PGUP => (KeyCode::PageUp, Some(NamedKey::PageUp)), orbclient::K_QUOTE => (KeyCode::Quote, None), orbclient::K_RIGHT => (KeyCode::ArrowRight, Some(NamedKey::ArrowRight)), orbclient::K_RIGHT_SHIFT => (KeyCode::ShiftRight, Some(NamedKey::Shift)), orbclient::K_RIGHT_SUPER => (KeyCode::MetaRight, Some(NamedKey::Meta)), orbclient::K_SEMICOLON => (KeyCode::Semicolon, None), orbclient::K_SLASH => (KeyCode::Slash, None), orbclient::K_SPACE => (KeyCode::Space, None), orbclient::K_SUPER => (KeyCode::MetaLeft, Some(NamedKey::Meta)), orbclient::K_TAB => (KeyCode::Tab, Some(NamedKey::Tab)), orbclient::K_TICK => (KeyCode::Backquote, None), orbclient::K_UP => (KeyCode::ArrowUp, Some(NamedKey::ArrowUp)), orbclient::K_VOLUME_DOWN => (KeyCode::AudioVolumeDown, Some(NamedKey::AudioVolumeDown)), orbclient::K_VOLUME_TOGGLE => (KeyCode::AudioVolumeMute, Some(NamedKey::AudioVolumeMute)), orbclient::K_VOLUME_UP => (KeyCode::AudioVolumeUp, Some(NamedKey::AudioVolumeUp)), orbclient::K_INS => (KeyCode::Insert, Some(NamedKey::Insert)), orbclient::K_PRTSC => (KeyCode::PrintScreen, Some(NamedKey::PrintScreen)), orbclient::K_NUM => (KeyCode::NumLock, Some(NamedKey::NumLock)), orbclient::K_SCROLL => (KeyCode::ScrollLock, Some(NamedKey::ScrollLock)), orbclient::K_APP => (KeyCode::ContextMenu, Some(NamedKey::ContextMenu)), orbclient::K_MEDIA_FAST_FORWARD => { (KeyCode::MediaFastForward, Some(NamedKey::MediaFastForward)) }, orbclient::K_MEDIA_REWIND => (KeyCode::MediaRewind, Some(NamedKey::MediaRewind)), orbclient::K_MEDIA_STOP => (KeyCode::MediaStop, Some(NamedKey::MediaStop)), orbclient::K_POWER => (KeyCode::Power, Some(NamedKey::Power)), _ => return (PhysicalKey::Unidentified(NativeKeyCode::Unidentified), None), }; (PhysicalKey::Code(key_code), named_key_opt) } fn element_state(pressed: bool) -> event::ElementState { if pressed { event::ElementState::Pressed } else { event::ElementState::Released } } bitflags! { #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] struct KeyboardModifierState: u8 { const LSHIFT = 1 << 0; const RSHIFT = 1 << 1; const LCTRL = 1 << 2; const RCTRL = 1 << 3; const LALT = 1 << 4; const RALT = 1 << 5; const LMETA = 1 << 6; const RMETA = 1 << 7; } } bitflags! { #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] struct MouseButtonState: u8 { const LEFT = 1 << 0; const MIDDLE = 1 << 1; const RIGHT = 1 << 2; } } #[derive(Default, Debug)] struct EventState { keyboard: KeyboardModifierState, mouse: MouseButtonState, mouse_pos: (i32, i32), resize_opt: Option<(u32, u32)>, } impl EventState { fn character_all_modifiers(&self, character: char) -> char { // Modify character if Ctrl is pressed #[allow(clippy::collapsible_if)] if self.keyboard.contains(KeyboardModifierState::LCTRL) || self.keyboard.contains(KeyboardModifierState::RCTRL) { if character.is_ascii_lowercase() { return ((character as u8 - b'a') + 1) as char; } // TODO: more control key variants? } // Return character as-is if no special handling required character } fn key(&mut self, key: PhysicalKey, pressed: bool) { let code = match key { PhysicalKey::Code(code) => code, _ => return, }; match code { KeyCode::ShiftLeft => self.keyboard.set(KeyboardModifierState::LSHIFT, pressed), KeyCode::ShiftRight => self.keyboard.set(KeyboardModifierState::RSHIFT, pressed), KeyCode::ControlLeft => self.keyboard.set(KeyboardModifierState::LCTRL, pressed), KeyCode::ControlRight => self.keyboard.set(KeyboardModifierState::RCTRL, pressed), KeyCode::AltLeft => self.keyboard.set(KeyboardModifierState::LALT, pressed), KeyCode::AltRight => self.keyboard.set(KeyboardModifierState::RALT, pressed), KeyCode::MetaLeft => self.keyboard.set(KeyboardModifierState::LMETA, pressed), KeyCode::MetaRight => self.keyboard.set(KeyboardModifierState::RMETA, pressed), _ => (), } } fn mouse( &mut self, left: bool, middle: bool, right: bool, ) -> Option<(event::MouseButton, event::ElementState)> { if self.mouse.contains(MouseButtonState::LEFT) != left { self.mouse.set(MouseButtonState::LEFT, left); return Some((event::MouseButton::Left, element_state(left))); } if self.mouse.contains(MouseButtonState::MIDDLE) != middle { self.mouse.set(MouseButtonState::MIDDLE, middle); return Some((event::MouseButton::Middle, element_state(middle))); } if self.mouse.contains(MouseButtonState::RIGHT) != right { self.mouse.set(MouseButtonState::RIGHT, right); return Some((event::MouseButton::Right, element_state(right))); } None } fn modifiers(&self) -> Modifiers { let mut state = ModifiersState::empty(); let mut pressed_mods = ModifiersKeys::empty(); if self.keyboard.intersects(KeyboardModifierState::LSHIFT | KeyboardModifierState::RSHIFT) { state |= ModifiersState::SHIFT; } pressed_mods .set(ModifiersKeys::LSHIFT, self.keyboard.contains(KeyboardModifierState::LSHIFT)); pressed_mods .set(ModifiersKeys::RSHIFT, self.keyboard.contains(KeyboardModifierState::RSHIFT)); if self.keyboard.intersects(KeyboardModifierState::LCTRL | KeyboardModifierState::RCTRL) { state |= ModifiersState::CONTROL; } pressed_mods .set(ModifiersKeys::LCONTROL, self.keyboard.contains(KeyboardModifierState::LCTRL)); pressed_mods .set(ModifiersKeys::RCONTROL, self.keyboard.contains(KeyboardModifierState::RCTRL)); if self.keyboard.intersects(KeyboardModifierState::LALT | KeyboardModifierState::RALT) { state |= ModifiersState::ALT; } pressed_mods.set(ModifiersKeys::LALT, self.keyboard.contains(KeyboardModifierState::LALT)); pressed_mods.set(ModifiersKeys::RALT, self.keyboard.contains(KeyboardModifierState::RALT)); if self.keyboard.intersects(KeyboardModifierState::LMETA | KeyboardModifierState::RMETA) { state |= ModifiersState::META } pressed_mods .set(ModifiersKeys::LMETA, self.keyboard.contains(KeyboardModifierState::LMETA)); pressed_mods .set(ModifiersKeys::RMETA, self.keyboard.contains(KeyboardModifierState::RMETA)); Modifiers::new(state, pressed_mods) } } #[derive(Debug)] pub struct EventLoop { windows: Vec<(Arc, EventState)>, window_target: ActiveEventLoop, user_events_receiver: mpsc::Receiver<()>, } impl EventLoop { pub fn new(_: &PlatformSpecificEventLoopAttributes) -> Result { static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false); if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) { // For better cross-platformness. return Err(EventLoopError::RecreationAttempt); } // NOTE: Create a channel which can hold only one event to automatically _squash_ user // events. let (user_events_sender, user_events_receiver) = mpsc::sync_channel(1); let event_socket = Arc::new(EventQueue::new().map_err(|error| os_error!(format!("{error}")))?); let wake_socket = TimeSocket::open().map_err(|error| os_error!(format!("{error}")))?; event_socket .subscribe(wake_socket.0.fd(), EventSource::Time, EventFlags::READ) .map_err(|error| os_error!(format!("{error}")))?; Ok(Self { windows: Vec::new(), window_target: ActiveEventLoop { control_flow: Cell::new(ControlFlow::default()), exit: Cell::new(false), creates: Mutex::new(VecDeque::new()), redraws: Arc::new(Mutex::new(VecDeque::new())), destroys: Arc::new(Mutex::new(VecDeque::new())), event_socket, event_loop_proxy: Arc::new(EventLoopProxy { wake_socket, user_events_sender }), }, user_events_receiver, }) } fn process_event( window_id: WindowId, event_option: EventOption, event_state: &mut EventState, window_target: &ActiveEventLoop, app: &mut A, ) { match event_option { EventOption::Key(KeyEvent { character, scancode, pressed }) => { // Convert scancode let (physical_key, named_key_opt) = convert_scancode(scancode); // Get previous modifiers and update modifiers based on physical key let modifiers_before = event_state.keyboard; event_state.key(physical_key, pressed); // Default to unidentified key with no text let mut logical_key = Key::Unidentified(NativeKey::Unidentified); let mut key_without_modifiers = logical_key.clone(); let mut text = None; let mut text_with_all_modifiers = None; // Set key and text based on character if character != '\0' { let mut tmp = [0u8; 4]; let character_str = character.encode_utf8(&mut tmp); // The key with Shift and Caps Lock applied (but not Ctrl) logical_key = Key::Character(character_str.into()); // The key without Shift or Caps Lock applied key_without_modifiers = Key::Character(SmolStr::from_iter(character.to_lowercase())); if pressed { // The key with Shift and Caps Lock applied (but not Ctrl) text = Some(character_str.into()); // The key with Shift, Caps Lock, and Ctrl applied let character_all_modifiers = event_state.character_all_modifiers(character); text_with_all_modifiers = Some(character_all_modifiers.encode_utf8(&mut tmp).into()) } }; // Override key if a named key was found (this is to allow Enter to replace '\n') if let Some(named_key) = named_key_opt { logical_key = Key::Named(named_key); key_without_modifiers = logical_key.clone(); } let event = event::WindowEvent::KeyboardInput { device_id: None, event: event::KeyEvent { logical_key, physical_key, location: KeyLocation::Standard, state: element_state(pressed), repeat: false, text, key_without_modifiers, text_with_all_modifiers, }, is_synthetic: false, }; app.window_event(window_target, window_id, event); // If the state of the modifiers has changed, send the event. if modifiers_before != event_state.keyboard { app.window_event( window_target, window_id, event::WindowEvent::ModifiersChanged(event_state.modifiers()), ); } }, EventOption::TextInput(TextInputEvent { character }) => { app.window_event( window_target, window_id, event::WindowEvent::Ime(Ime::Preedit("".into(), None)), ); app.window_event( window_target, window_id, event::WindowEvent::Ime(Ime::Commit(character.into())), ); }, EventOption::Mouse(MouseEvent { x, y }) => { event_state.mouse_pos = (x, y); app.window_event( window_target, window_id, event::WindowEvent::PointerMoved { device_id: None, primary: true, position: event_state.mouse_pos.into(), source: event::PointerSource::Mouse, }, ); }, EventOption::MouseRelative(MouseRelativeEvent { dx, dy }) => { app.device_event( window_target, None, event::DeviceEvent::PointerMotion { delta: (dx as f64, dy as f64) }, ); }, EventOption::Button(ButtonEvent { left, middle, right }) => { while let Some((button, state)) = event_state.mouse(left, middle, right) { app.window_event( window_target, window_id, event::WindowEvent::PointerButton { device_id: None, primary: true, state, position: event_state.mouse_pos.into(), button: button.into(), }, ); } }, EventOption::Scroll(ScrollEvent { x, y }) => { app.window_event( window_target, window_id, event::WindowEvent::MouseWheel { device_id: None, delta: event::MouseScrollDelta::LineDelta(x as f32, y as f32), phase: event::TouchPhase::Moved, }, ); }, EventOption::Quit(QuitEvent {}) => { app.window_event(window_target, window_id, event::WindowEvent::CloseRequested); }, EventOption::Focus(FocusEvent { focused }) => { app.window_event(window_target, window_id, event::WindowEvent::Focused(focused)); }, EventOption::Move(MoveEvent { x, y }) => { app.window_event( window_target, window_id, event::WindowEvent::Moved((x, y).into()), ); }, EventOption::Resize(ResizeEvent { width, height }) => { app.window_event( window_target, window_id, event::WindowEvent::SurfaceResized((width, height).into()), ); // Acknowledge resize after event loop. event_state.resize_opt = Some((width, height)); }, // TODO: Screen, Clipboard, Drop EventOption::Hover(HoverEvent { entered }) => { let event = if entered { event::WindowEvent::PointerEntered { device_id: None, primary: true, position: dpi::PhysicalPosition::default(), kind: event::PointerKind::Mouse, } } else { event::WindowEvent::PointerLeft { device_id: None, primary: true, position: None, kind: event::PointerKind::Mouse, } }; app.window_event(window_target, window_id, event); }, other => { tracing::warn!("unhandled event: {:?}", other); }, } } pub fn run_app_on_demand( &mut self, mut app: A, ) -> Result<(), EventLoopError> { let mut start_cause = StartCause::Init; loop { app.new_events(&self.window_target, start_cause); if start_cause == StartCause::Init { app.can_create_surfaces(&self.window_target); } // Handle window creates. while let Some(window) = { let mut creates = self.window_target.creates.lock().unwrap(); creates.pop_front() } { let window_id = WindowId::from_raw(window.fd()); let mut buf: [u8; 4096] = [0; 4096]; let path = window.fpath(&mut buf).expect("failed to read properties"); let properties = WindowProperties::new(path); self.windows.push((window, EventState::default())); // Send resize event on create to indicate first size. let event = event::WindowEvent::SurfaceResized((properties.w, properties.h).into()); app.window_event(&self.window_target, window_id, event); // Send moved event on create to indicate first position. let event = event::WindowEvent::Moved((properties.x, properties.y).into()); app.window_event(&self.window_target, window_id, event); } // Handle window destroys. while let Some(destroy_id) = { let mut destroys = self.window_target.destroys.lock().unwrap(); destroys.pop_front() } { app.window_event(&self.window_target, destroy_id, event::WindowEvent::Destroyed); self.windows .retain(|(window, _event_state)| WindowId::from_raw(window.fd()) != destroy_id); } // Handle window events. let mut i = 0; // While loop is used here because the same window may be processed more than once. while let Some((window, event_state)) = self.windows.get_mut(i) { let window_id = WindowId::from_raw(window.fd()); let mut event_buf = [0u8; 16 * mem::size_of::()]; let count = libredox::call::read(window.fd(), &mut event_buf) .expect("failed to read window events"); // Safety: orbclient::Event is a packed struct designed to be transferred over a // socket. let events = unsafe { slice::from_raw_parts( event_buf.as_ptr() as *const orbclient::Event, count / mem::size_of::(), ) }; for orbital_event in events { Self::process_event( window_id, orbital_event.to_option(), event_state, &self.window_target, &mut app, ); } if count == event_buf.len() { // If event buf was full, process same window again to ensure all events are // drained. continue; } // Acknowledge the latest resize event. if let Some((w, h)) = event_state.resize_opt.take() { window .write(format!("S,{w},{h}").as_bytes()) .expect("failed to acknowledge resize"); // Require redraw after resize. let mut redraws = self.window_target.redraws.lock().unwrap(); if !redraws.contains(&window_id) { redraws.push_back(window_id); } } // Move to next window. i += 1; } while self.user_events_receiver.try_recv().is_ok() { app.proxy_wake_up(&self.window_target); } // To avoid deadlocks the redraws lock is not held during event processing. while let Some(window_id) = { let mut redraws = self.window_target.redraws.lock().unwrap(); redraws.pop_front() } { app.window_event( &self.window_target, window_id, event::WindowEvent::RedrawRequested, ); } app.about_to_wait(&self.window_target); if self.window_target.exiting() { break; } let requested_resume = match self.window_target.control_flow() { ControlFlow::Poll => { start_cause = StartCause::Poll; continue; }, ControlFlow::Wait => None, ControlFlow::WaitUntil(instant) => Some(instant), }; // Re-using wake socket caused extra wake events before because there were leftover // timeouts, and then new timeouts were added each time a spurious timeout expired. let timeout_socket = TimeSocket::open().unwrap(); self.window_target .event_socket .subscribe(timeout_socket.0.fd(), EventSource::Time, EventFlags::READ) .unwrap(); let start = Instant::now(); if let Some(instant) = requested_resume { let mut time = timeout_socket.current_time().unwrap(); if let Some(duration) = instant.checked_duration_since(start) { time.tv_sec += duration.as_secs() as i64; time.tv_nsec += duration.subsec_nanos() as i64; // Normalize timespec so tv_nsec is not greater than one second. while time.tv_nsec >= 1_000_000_000 { time.tv_sec += 1; time.tv_nsec -= 1_000_000_000; } } timeout_socket.timeout(&time).unwrap(); } // Wait for event if needed. let event = loop { match self.window_target.event_socket.next_event() { Ok(event) => break event, Err(err) if err.is_interrupt() => continue, Err(err) => { return Err(os_error!(format!("failed to read event: {err}")).into()); }, } }; // TODO: handle spurious wakeups (redraw caused wakeup but redraw already handled) match requested_resume { Some(requested_resume) if event.fd == timeout_socket.0.fd() && matches!(event.user_data, EventSource::Time) => { // If the event is from the special timeout socket, report that resume // time was reached. start_cause = StartCause::ResumeTimeReached { start, requested_resume }; }, _ => { // Normal window event or spurious timeout. start_cause = StartCause::WaitCancelled { start, requested_resume }; }, } } Ok(()) } pub fn window_target(&self) -> &dyn RootActiveEventLoop { &self.window_target } } #[derive(Debug)] pub struct EventLoopProxy { user_events_sender: mpsc::SyncSender<()>, pub(super) wake_socket: TimeSocket, } impl EventLoopProxyProvider for EventLoopProxy { fn wake_up(&self) { // When we fail to send the event it means that we haven't woken up to read the previous // event. if self.user_events_sender.try_send(()).is_ok() { self.wake_socket.wake().unwrap(); } } } impl Unpin for EventLoopProxy {} redox_event::user_data! { pub enum EventSource { Orbital, Time, } } #[derive(Debug)] pub struct ActiveEventLoop { control_flow: Cell, exit: Cell, pub(super) creates: Mutex>>, pub(super) redraws: Arc>>, pub(super) destroys: Arc>>, pub(super) event_socket: Arc>, pub(super) event_loop_proxy: Arc, } impl RootActiveEventLoop for ActiveEventLoop { fn create_proxy(&self) -> CoreEventLoopProxy { CoreEventLoopProxy::new(self.event_loop_proxy.clone()) } fn create_window( &self, window_attributes: winit_core::window::WindowAttributes, ) -> Result, RequestError> { Ok(Box::new(Window::new(self, window_attributes)?)) } fn create_custom_cursor(&self, _: CustomCursorSource) -> Result { Err(NotSupportedError::new("create_custom_cursor is not supported").into()) } fn available_monitors(&self) -> Box> { Box::new(iter::empty()) } fn system_theme(&self) -> Option { None } fn primary_monitor(&self) -> Option { None } fn listen_device_events(&self, _allowed: DeviceEvents) {} fn set_control_flow(&self, control_flow: ControlFlow) { self.control_flow.set(control_flow) } fn control_flow(&self) -> ControlFlow { self.control_flow.get() } fn exit(&self) { self.exit.set(true); } fn exiting(&self) -> bool { self.exit.get() } fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { CoreOwnedDisplayHandle::new(Arc::new(OwnedDisplayHandle)) } fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { self } } impl rwh_06::HasDisplayHandle for ActiveEventLoop { fn display_handle(&self) -> Result, rwh_06::HandleError> { let raw = rwh_06::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new()); unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } } } #[derive(Clone)] pub(crate) struct OwnedDisplayHandle; impl rwh_06::HasDisplayHandle for OwnedDisplayHandle { fn display_handle(&self) -> Result, rwh_06::HandleError> { let raw = rwh_06::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new()); unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } } } #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct PlatformSpecificEventLoopAttributes {}