diff --git a/Cargo.toml b/Cargo.toml index f5164687..1dde01de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,9 +79,9 @@ x11rb = { version = "0.13.0", default-features = false } xkbcommon-dl = "0.4.2" # Orbital dependencies. -libredox = "0.1.12" orbclient = { version = "0.3.47", default-features = false } -redox_event = { package = "redox_event", version = "0.4.5" } +redox_syscall = "0.7" +libredox = "0.1.12" # Web dependencies. atomic-waker = "1" diff --git a/winit-orbital/Cargo.toml b/winit-orbital/Cargo.toml index f3178d87..330bd520 100644 --- a/winit-orbital/Cargo.toml +++ b/winit-orbital/Cargo.toml @@ -21,6 +21,6 @@ tracing.workspace = true winit-core.workspace = true # Platform-specific -libredox.workspace = true orbclient.workspace = true -redox_event.workspace = true +redox_syscall.workspace = true +libredox.workspace = true diff --git a/winit-orbital/src/event_loop.rs b/winit-orbital/src/event_loop.rs index 651560ee..7db55f14 100644 --- a/winit-orbital/src/event_loop.rs +++ b/winit-orbital/src/event_loop.rs @@ -10,7 +10,6 @@ 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}; @@ -101,7 +100,6 @@ fn convert_scancode(scancode: u8) -> (PhysicalKey, Option) { 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), @@ -112,20 +110,12 @@ fn convert_scancode(scancode: u8) -> (PhysicalKey, Option) { 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), @@ -137,20 +127,6 @@ fn convert_scancode(scancode: u8) -> (PhysicalKey, Option) { 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) @@ -187,7 +163,6 @@ bitflags! { struct EventState { keyboard: KeyboardModifierState, mouse: MouseButtonState, - mouse_pos: (i32, i32), resize_opt: Option<(u32, u32)>, } @@ -313,12 +288,16 @@ impl EventLoop { 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}")))?); + Arc::new(RedoxSocket::event().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) + .write(&syscall::Event { + id: wake_socket.0.fd, + flags: syscall::EventFlags::EVENT_READ, + data: wake_socket.0.fd, + }) .map_err(|error| os_error!(format!("{error}")))?; Ok(Self { @@ -423,50 +402,35 @@ impl EventLoop { ); }, 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, - }, - ); + app.window_event(window_target, window_id, event::WindowEvent::PointerMoved { + device_id: None, + primary: true, + position: (x, y).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) }, - ); + 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(), - }, - ); + app.window_event(window_target, window_id, event::WindowEvent::PointerButton { + device_id: None, + primary: true, + state, + position: dpi::PhysicalPosition::default(), + 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, - }, - ); + 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); @@ -534,7 +498,7 @@ impl EventLoop { let mut creates = self.window_target.creates.lock().unwrap(); creates.pop_front() } { - let window_id = WindowId::from_raw(window.fd()); + 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"); @@ -558,18 +522,18 @@ impl EventLoop { } { app.window_event(&self.window_target, destroy_id, event::WindowEvent::Destroyed); self.windows - .retain(|(window, _event_state)| WindowId::from_raw(window.fd()) != destroy_id); + .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 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"); + let count = + syscall::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 { @@ -649,7 +613,11 @@ impl EventLoop { self.window_target .event_socket - .subscribe(timeout_socket.0.fd(), EventSource::Time, EventFlags::READ) + .write(&syscall::Event { + id: timeout_socket.0.fd, + flags: syscall::EventFlags::EVENT_READ, + data: 0, + }) .unwrap(); let start = Instant::now(); @@ -658,7 +626,7 @@ impl EventLoop { 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; + time.tv_nsec += duration.subsec_nanos() as i32; // Normalize timespec so tv_nsec is not greater than one second. while time.tv_nsec >= 1_000_000_000 { time.tv_sec += 1; @@ -670,22 +638,18 @@ impl EventLoop { } // 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()); - }, + let mut event = syscall::Event::default(); + loop { + match self.window_target.event_socket.read(&mut event) { + Ok(_) => break, + Err(syscall::Error { errno: syscall::EINTR }) => continue, + Err(err) => unreachable!("failed to read event: {}", err), } - }; + } // 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) => - { + Some(requested_resume) if event.id == timeout_socket.0.fd => { // If the event is from the special timeout socket, report that resume // time was reached. start_cause = StartCause::ResumeTimeReached { start, requested_resume }; @@ -723,13 +687,6 @@ impl EventLoopProxyProvider for EventLoopProxy { impl Unpin for EventLoopProxy {} -redox_event::user_data! { - pub enum EventSource { - Orbital, - Time, - } -} - #[derive(Debug)] pub struct ActiveEventLoop { control_flow: Cell, @@ -737,7 +694,7 @@ pub struct ActiveEventLoop { pub(super) creates: Mutex>>, pub(super) redraws: Arc>>, pub(super) destroys: Arc>>, - pub(super) event_socket: Arc>, + pub(super) event_socket: Arc, pub(super) event_loop_proxy: Arc, } diff --git a/winit-orbital/src/lib.rs b/winit-orbital/src/lib.rs index 25ae16db..0a41dd0e 100644 --- a/winit-orbital/src/lib.rs +++ b/winit-orbital/src/lib.rs @@ -3,12 +3,7 @@ //! Redox OS has some functionality not yet present that will be implemented //! when its orbital display server provides it. -use std::fs::{File, OpenOptions}; -use std::io::{Read, Result, Write}; -use std::os::fd::AsRawFd; -use std::{fmt, mem, slice, str}; - -use libredox::data::TimeSpec; +use std::{fmt, str}; pub use self::event_loop::{EventLoop, PlatformSpecificEventLoopAttributes}; @@ -21,11 +16,15 @@ pub mod window; #[derive(Debug)] struct RedoxSocket { - fd: File, + fd: usize, } impl RedoxSocket { - fn orbital(properties: &WindowProperties<'_>) -> Result { + fn event() -> syscall::Result { + Self::open_raw("/scheme/event") + } + + fn orbital(properties: &WindowProperties<'_>) -> syscall::Result { Self::open_raw(&format!("{properties}")) } @@ -33,27 +32,30 @@ impl RedoxSocket { // non-socket path is used, it could cause read and write to not function as expected. For // example, the seek would change in a potentially unpredictable way if either read or write // were called at the same time by multiple threads. - fn open_raw(path: &str) -> Result { - let fd = OpenOptions::new().read(true).write(true).open(path)?; + fn open_raw(path: &str) -> syscall::Result { + let fd = libredox::call::open(path, libredox::flag::O_RDWR | libredox::flag::O_CLOEXEC, 0)?; Ok(Self { fd }) } - fn fd(&self) -> usize { - self.fd.as_raw_fd() as usize + fn read(&self, buf: &mut [u8]) -> syscall::Result<()> { + let count = syscall::read(self.fd, buf)?; + if count == buf.len() { Ok(()) } else { Err(syscall::Error::new(syscall::EINVAL)) } } - fn read(&self, buf: &mut [u8]) -> Result<()> { - (&self.fd).read_exact(buf) + fn write(&self, buf: &[u8]) -> syscall::Result<()> { + let count = syscall::write(self.fd, buf)?; + if count == buf.len() { Ok(()) } else { Err(syscall::Error::new(syscall::EINVAL)) } } - fn write(&self, buf: &[u8]) -> Result<()> { - (&self.fd).write_all(buf) + fn fpath<'a>(&self, buf: &'a mut [u8]) -> syscall::Result<&'a str> { + let count = syscall::fpath(self.fd, buf)?; + str::from_utf8(&buf[..count]).map_err(|_err| syscall::Error::new(syscall::EINVAL)) } +} - fn fpath<'a>(&self, buf: &'a mut [u8]) -> Result<&'a str> { - let count = libredox::call::fpath(self.fd(), buf)?; - str::from_utf8(&buf[..count]) - .map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData)) +impl Drop for RedoxSocket { + fn drop(&mut self) { + let _ = syscall::close(self.fd); } } @@ -61,36 +63,26 @@ impl RedoxSocket { struct TimeSocket(RedoxSocket); impl TimeSocket { - fn open() -> Result { + fn open() -> syscall::Result { RedoxSocket::open_raw("/scheme/time/4").map(Self) } // Read current time. - fn current_time(&self) -> Result { - let mut timespec: libredox::data::TimeSpec = unsafe { mem::zeroed() }; - let timespec_bytes = unsafe { - slice::from_raw_parts_mut( - &mut timespec as *mut _ as *mut u8, - mem::size_of::(), - ) - }; - self.0.read(timespec_bytes)?; + fn current_time(&self) -> syscall::Result { + let mut timespec = syscall::TimeSpec::default(); + self.0.read(&mut timespec)?; Ok(timespec) } // Write a timeout. - fn timeout(&self, timespec: &TimeSpec) -> Result<()> { - let timespec_bytes = unsafe { - slice::from_raw_parts(timespec as *const _ as *const u8, mem::size_of::()) - }; - self.0.write(timespec_bytes) + fn timeout(&self, timespec: &syscall::TimeSpec) -> syscall::Result<()> { + self.0.write(timespec) } // Wake immediately. - fn wake(&self) -> Result<()> { + fn wake(&self) -> syscall::Result<()> { // Writing a default TimeSpec will always trigger a time event. - let timespec: TimeSpec = unsafe { mem::zeroed() }; - self.timeout(×pec) + self.timeout(&syscall::TimeSpec::default()) } } diff --git a/winit-orbital/src/window.rs b/winit-orbital/src/window.rs index 728c262a..4858b29b 100644 --- a/winit-orbital/src/window.rs +++ b/winit-orbital/src/window.rs @@ -3,13 +3,12 @@ use std::iter; use std::sync::{Arc, Mutex}; use dpi::{PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size}; -use redox_event::EventFlags; use winit_core::cursor::Cursor; use winit_core::error::{NotSupportedError, RequestError}; use winit_core::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle}; use winit_core::window::{self, Window as CoreWindow, WindowId}; -use crate::event_loop::{ActiveEventLoop, EventLoopProxy, EventSource}; +use crate::event_loop::{ActiveEventLoop, EventLoopProxy}; use crate::{RedoxSocket, WindowProperties}; // These values match the values uses in the `window_new` function in orbital: @@ -104,7 +103,13 @@ impl Window { .expect("failed to open window"); // Add to event socket. - el.event_socket.subscribe(window.fd(), EventSource::Orbital, EventFlags::READ).unwrap(); + el.event_socket + .write(&syscall::Event { + id: window.fd, + flags: syscall::EventFlags::EVENT_READ, + data: window.fd, + }) + .unwrap(); let window_socket = Arc::new(window); @@ -141,7 +146,7 @@ impl Window { #[inline] fn raw_window_handle_rwh_06(&self) -> Result { let handle = rwh_06::OrbitalWindowHandle::new({ - let window = self.window_socket.fd() as *mut _; + let window = self.window_socket.fd as *mut _; std::ptr::NonNull::new(window).expect("orbital fd should never be null") }); Ok(rwh_06::RawWindowHandle::Orbital(handle)) @@ -155,7 +160,7 @@ impl Window { impl CoreWindow for Window { fn id(&self) -> WindowId { - WindowId::from_raw(self.window_socket.fd()) + WindowId::from_raw(self.window_socket.fd) } fn ime_capabilities(&self) -> Option {