api: unify error handling

Make error infrastructure more backend agnostic and let backends
just forward the os errors opaquely.
This commit is contained in:
Kirill Chibisov 2024-09-06 17:20:11 +03:00 committed by GitHub
parent 8db3e0e043
commit b674d20edf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 507 additions and 630 deletions

View file

@ -11,9 +11,8 @@ use objc2_foundation::{
NSString,
};
use super::OsError;
use crate::cursor::{CursorImage, OnlyCursorImageSource};
use crate::error::ExternalError;
use crate::error::RequestError;
use crate::window::CursorIcon;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@ -25,12 +24,12 @@ unsafe impl Send for CustomCursor {}
unsafe impl Sync for CustomCursor {}
impl CustomCursor {
pub(crate) fn new(cursor: OnlyCursorImageSource) -> Result<CustomCursor, ExternalError> {
pub(crate) fn new(cursor: OnlyCursorImageSource) -> Result<CustomCursor, RequestError> {
cursor_from_image(&cursor.0).map(Self)
}
}
pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Result<Retained<NSCursor>, ExternalError> {
pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Result<Retained<NSCursor>, RequestError> {
let width = cursor.width;
let height = cursor.height;
@ -48,7 +47,7 @@ pub(crate) fn cursor_from_image(cursor: &CursorImage) -> Result<Retained<NSCurso
width as isize * 4,
32,
)
}.ok_or_else(|| ExternalError::Os(os_error!(OsError::CreationError("parent view should be installed in a window"))))?;
}.ok_or_else(|| os_error!("parent view should be installed in a window"))?;
let bitmap_data = unsafe { slice::from_raw_parts_mut(bitmap.bitmapData(), cursor.rgba.len()) };
bitmap_data.copy_from_slice(&cursor.rgba);

View file

@ -29,7 +29,7 @@ use super::event::dummy_event;
use super::monitor;
use super::observer::setup_control_flow_observers;
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, ExternalError};
use crate::error::{EventLoopError, RequestError};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
@ -103,14 +103,14 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<Box<dyn crate::window::Window>, crate::error::OsError> {
) -> Result<Box<dyn crate::window::Window>, RequestError> {
Ok(Box::new(Window::new(self, window_attributes)?))
}
fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
) -> Result<RootCustomCursor, RequestError> {
Ok(RootCustomCursor { inner: CustomCursor::new(source.inner)? })
}

View file

@ -14,8 +14,6 @@ mod view;
mod window;
mod window_delegate;
use std::fmt;
pub(crate) use self::cursor::CustomCursor as PlatformCustomCursor;
pub(crate) use self::event::{physicalkey_to_scancode, scancode_to_physicalkey, KeyEventExtra};
pub(crate) use self::event_loop::{
@ -50,18 +48,3 @@ impl FingerId {
FingerId
}
}
#[derive(Debug)]
pub enum OsError {
CGError(core_graphics::base::CGError),
CreationError(&'static str),
}
impl fmt::Display for OsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
OsError::CGError(e) => f.pad(&format!("CGError {e}")),
OsError::CreationError(e) => f.pad(e),
}
}
}

View file

@ -8,7 +8,7 @@ use objc2_foundation::{MainThreadBound, MainThreadMarker, NSObject};
use super::event_loop::ActiveEventLoop;
use super::window_delegate::WindowDelegate;
use crate::error::OsError as RootOsError;
use crate::error::RequestError;
use crate::monitor::MonitorHandle as CoreMonitorHandle;
use crate::window::{
Cursor, Fullscreen, Icon, ImePurpose, Theme, UserAttentionType, Window as CoreWindow,
@ -25,7 +25,7 @@ impl Window {
pub(crate) fn new(
window_target: &ActiveEventLoop,
attributes: WindowAttributes,
) -> Result<Self, RootOsError> {
) -> Result<Self, RequestError> {
let mtm = window_target.mtm;
let delegate =
autoreleasepool(|_| WindowDelegate::new(&window_target.app_state, attributes, mtm))?;
@ -111,16 +111,12 @@ impl CoreWindow for Window {
self.maybe_wait_on_main(|delegate| delegate.reset_dead_keys());
}
fn inner_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.inner_position())
fn inner_position(&self) -> Result<dpi::PhysicalPosition<i32>, RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.inner_position()))
}
fn outer_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.outer_position())
fn outer_position(&self) -> Result<dpi::PhysicalPosition<i32>, RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.outer_position()))
}
fn set_outer_position(&self, position: Position) {
@ -275,14 +271,11 @@ impl CoreWindow for Window {
self.maybe_wait_on_main(|delegate| delegate.set_cursor(cursor));
}
fn set_cursor_position(&self, position: Position) -> Result<(), crate::error::ExternalError> {
fn set_cursor_position(&self, position: Position) -> Result<(), RequestError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_position(position))
}
fn set_cursor_grab(
&self,
mode: crate::window::CursorGrabMode,
) -> Result<(), crate::error::ExternalError> {
fn set_cursor_grab(&self, mode: crate::window::CursorGrabMode) -> Result<(), RequestError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_grab(mode))
}
@ -290,23 +283,25 @@ impl CoreWindow for Window {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_visible(visible))
}
fn drag_window(&self) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_window())
fn drag_window(&self) -> Result<(), RequestError> {
self.maybe_wait_on_main(|delegate| delegate.drag_window());
Ok(())
}
fn drag_resize_window(
&self,
direction: crate::window::ResizeDirection,
) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_resize_window(direction))
) -> Result<(), RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.drag_resize_window(direction))?)
}
fn show_window_menu(&self, position: Position) {
self.maybe_wait_on_main(|delegate| delegate.show_window_menu(position))
}
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_hittest(hittest))
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), RequestError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_hittest(hittest));
Ok(())
}
fn current_monitor(&self) -> Option<CoreMonitorHandle> {

View file

@ -33,9 +33,9 @@ use super::monitor::{self, flip_window_screen_coordinates, get_display_id};
use super::observer::RunLoop;
use super::view::WinitView;
use super::window::WinitWindow;
use super::{ffi, Fullscreen, MonitorHandle, OsError, WindowId};
use super::{ffi, Fullscreen, MonitorHandle, WindowId};
use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
use crate::error::{NotSupportedError, RequestError};
use crate::event::{SurfaceSizeWriter, WindowEvent};
use crate::platform::macos::{OptionAsAlt, WindowExtMacOS};
use crate::window::{
@ -677,9 +677,9 @@ impl WindowDelegate {
app_state: &Rc<AppState>,
attrs: WindowAttributes,
mtm: MainThreadMarker,
) -> Result<Retained<Self>, RootOsError> {
) -> Result<Retained<Self>, RequestError> {
let window = new_window(app_state, &attrs, mtm)
.ok_or_else(|| os_error!(OsError::CreationError("couldn't create `NSWindow`")))?;
.ok_or_else(|| os_error!("couldn't create `NSWindow`"))?;
#[cfg(feature = "rwh_06")]
match attrs.parent_window.map(|handle| handle.0) {
@ -688,9 +688,9 @@ impl WindowDelegate {
// Unwrap is fine, since the pointer comes from `NonNull`.
let parent_view: Retained<NSView> =
unsafe { Retained::retain(handle.ns_view.as_ptr().cast()) }.unwrap();
let parent = parent_view.window().ok_or_else(|| {
os_error!(OsError::CreationError("parent view should be installed in a window"))
})?;
let parent = parent_view
.window()
.ok_or_else(|| os_error!("parent view should be installed in a window"))?;
// SAFETY: We know that there are no parent -> child -> parent cycles since the only
// place in `winit` where we allow making a window a child window is
@ -925,15 +925,15 @@ impl WindowDelegate {
#[inline]
pub fn pre_present_notify(&self) {}
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
pub fn outer_position(&self) -> PhysicalPosition<i32> {
let position = flip_window_screen_coordinates(self.window().frame());
Ok(LogicalPosition::new(position.x, position.y).to_physical(self.scale_factor()))
LogicalPosition::new(position.x, position.y).to_physical(self.scale_factor())
}
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
pub fn inner_position(&self) -> PhysicalPosition<i32> {
let content_rect = self.window().contentRectForFrameRect(self.window().frame());
let position = flip_window_screen_coordinates(content_rect);
Ok(LogicalPosition::new(position.x, position.y).to_physical(self.scale_factor()))
LogicalPosition::new(position.x, position.y).to_physical(self.scale_factor())
}
pub fn set_outer_position(&self, position: Position) {
@ -1125,18 +1125,18 @@ impl WindowDelegate {
}
#[inline]
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), RequestError> {
let associate_mouse_cursor = match mode {
CursorGrabMode::Locked => false,
CursorGrabMode::None => true,
CursorGrabMode::Confined => {
return Err(ExternalError::NotSupported(NotSupportedError::new()))
return Err(NotSupportedError::new("confined cursor is not supported").into())
},
};
// TODO: Do this for real https://stackoverflow.com/a/40922095/5435443
CGDisplay::associate_mouse_and_mouse_cursor_position(associate_mouse_cursor)
.map_err(|status| ExternalError::Os(os_error!(OsError::CGError(status))))
.map_err(|status| os_error!(format!("CGError {status}")).into())
}
#[inline]
@ -1154,8 +1154,8 @@ impl WindowDelegate {
}
#[inline]
pub fn set_cursor_position(&self, cursor_position: Position) -> Result<(), ExternalError> {
let physical_window_position = self.inner_position().unwrap();
pub fn set_cursor_position(&self, cursor_position: Position) -> Result<(), RequestError> {
let physical_window_position = self.inner_position();
let scale_factor = self.scale_factor();
let window_position = physical_window_position.to_logical::<CGFloat>(scale_factor);
let logical_cursor_position = cursor_position.to_logical::<CGFloat>(scale_factor);
@ -1164,33 +1164,31 @@ impl WindowDelegate {
y: logical_cursor_position.y + window_position.y,
};
CGDisplay::warp_mouse_cursor_position(point)
.map_err(|e| ExternalError::Os(os_error!(OsError::CGError(e))))?;
.map_err(|status| os_error!(format!("CGError {status}")))?;
CGDisplay::associate_mouse_and_mouse_cursor_position(true)
.map_err(|e| ExternalError::Os(os_error!(OsError::CGError(e))))?;
.map_err(|status| os_error!(format!("CGError {status}")))?;
Ok(())
}
#[inline]
pub fn drag_window(&self) -> Result<(), ExternalError> {
pub fn drag_window(&self) {
let mtm = MainThreadMarker::from(self);
let event = NSApplication::sharedApplication(mtm).currentEvent().unwrap();
self.window().performWindowDragWithEvent(&event);
Ok(())
}
#[inline]
pub fn drag_resize_window(&self, _direction: ResizeDirection) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
pub fn drag_resize_window(&self, _direction: ResizeDirection) -> Result<(), NotSupportedError> {
Err(NotSupportedError::new("drag_resize_window is not supported"))
}
#[inline]
pub fn show_window_menu(&self, _position: Position) {}
#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
pub fn set_cursor_hittest(&self, hittest: bool) {
self.window().setIgnoresMouseEvents(!hittest);
Ok(())
}
pub(crate) fn is_zoomed(&self) -> bool {

View file

@ -25,7 +25,7 @@ use super::super::notification_center::create_observer;
use super::app_state::{send_occluded_event_for_all_windows, AppState, EventWrapper};
use super::{app_state, monitor, MonitorHandle};
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError};
use crate::error::{EventLoopError, NotSupportedError, RequestError};
use crate::event::Event;
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
@ -49,15 +49,15 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<Box<dyn CoreWindow>, OsError> {
) -> Result<Box<dyn CoreWindow>, RequestError> {
Ok(Box::new(Window::new(self, window_attributes)?))
}
fn create_custom_cursor(
&self,
_source: CustomCursorSource,
) -> Result<CustomCursor, ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
) -> Result<CustomCursor, RequestError> {
Err(NotSupportedError::new("create_custom_cursor is not supported").into())
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {

View file

@ -20,7 +20,7 @@ use super::view_controller::WinitViewController;
use super::{app_state, monitor, ActiveEventLoop, Fullscreen, MonitorHandle};
use crate::cursor::Cursor;
use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
use crate::error::{NotSupportedError, RequestError};
use crate::event::{Event, WindowEvent};
use crate::icon::Icon;
use crate::monitor::MonitorHandle as CoreMonitorHandle;
@ -159,20 +159,20 @@ impl Inner {
pub fn pre_present_notify(&self) {}
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
pub fn inner_position(&self) -> PhysicalPosition<i32> {
let safe_area = self.safe_area_screen_space();
let position =
LogicalPosition { x: safe_area.origin.x as f64, y: safe_area.origin.y as f64 };
let scale_factor = self.scale_factor();
Ok(position.to_physical(scale_factor))
position.to_physical(scale_factor)
}
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
pub fn outer_position(&self) -> PhysicalPosition<i32> {
let screen_frame = self.screen_frame();
let position =
LogicalPosition { x: screen_frame.origin.x as f64, y: screen_frame.origin.y as f64 };
let scale_factor = self.scale_factor();
Ok(position.to_physical(scale_factor))
position.to_physical(scale_factor)
}
pub fn set_outer_position(&self, physical_position: Position) {
@ -256,31 +256,31 @@ impl Inner {
debug!("`Window::set_cursor` ignored on iOS")
}
pub fn set_cursor_position(&self, _position: Position) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
pub fn set_cursor_position(&self, _position: Position) -> Result<(), NotSupportedError> {
Err(NotSupportedError::new("set_cursor_position is not supported"))
}
pub fn set_cursor_grab(&self, _: CursorGrabMode) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
pub fn set_cursor_grab(&self, _: CursorGrabMode) -> Result<(), NotSupportedError> {
Err(NotSupportedError::new("set_cursor_grab is not supported"))
}
pub fn set_cursor_visible(&self, _visible: bool) {
debug!("`Window::set_cursor_visible` is ignored on iOS")
}
pub fn drag_window(&self) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
pub fn drag_window(&self) -> Result<(), NotSupportedError> {
Err(NotSupportedError::new("drag_window is not supported"))
}
pub fn drag_resize_window(&self, _direction: ResizeDirection) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
pub fn drag_resize_window(&self, _direction: ResizeDirection) -> Result<(), NotSupportedError> {
Err(NotSupportedError::new("drag_resize_window is not supported"))
}
#[inline]
pub fn show_window_menu(&self, _position: Position) {}
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), NotSupportedError> {
Err(NotSupportedError::new("set_cursor_hittest is not supported"))
}
pub fn set_minimized(&self, _minimized: bool) {
@ -466,7 +466,7 @@ impl Window {
pub(crate) fn new(
event_loop: &ActiveEventLoop,
window_attributes: WindowAttributes,
) -> Result<Window, RootOsError> {
) -> Result<Window, RequestError> {
let mtm = event_loop.mtm;
if window_attributes.min_surface_size.is_some() {
@ -606,31 +606,27 @@ impl CoreWindow for Window {
self.maybe_wait_on_main(|delegate| delegate.reset_dead_keys());
}
fn inner_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.inner_position())
fn inner_position(&self) -> Result<PhysicalPosition<i32>, RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.inner_position()))
}
fn outer_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.outer_position())
fn outer_position(&self) -> Result<PhysicalPosition<i32>, RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.outer_position()))
}
fn set_outer_position(&self, position: Position) {
self.maybe_wait_on_main(|delegate| delegate.set_outer_position(position));
}
fn surface_size(&self) -> dpi::PhysicalSize<u32> {
fn surface_size(&self) -> PhysicalSize<u32> {
self.maybe_wait_on_main(|delegate| delegate.surface_size())
}
fn request_surface_size(&self, size: Size) -> Option<dpi::PhysicalSize<u32>> {
fn request_surface_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
self.maybe_wait_on_main(|delegate| delegate.request_surface_size(size))
}
fn outer_size(&self) -> dpi::PhysicalSize<u32> {
fn outer_size(&self) -> PhysicalSize<u32> {
self.maybe_wait_on_main(|delegate| delegate.outer_size())
}
@ -642,7 +638,7 @@ impl CoreWindow for Window {
self.maybe_wait_on_main(|delegate| delegate.set_max_surface_size(max_size));
}
fn surface_resize_increments(&self) -> Option<dpi::PhysicalSize<u32>> {
fn surface_resize_increments(&self) -> Option<PhysicalSize<u32>> {
self.maybe_wait_on_main(|delegate| delegate.surface_resize_increments())
}
@ -770,38 +766,35 @@ impl CoreWindow for Window {
self.maybe_wait_on_main(|delegate| delegate.set_cursor(cursor));
}
fn set_cursor_position(&self, position: Position) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_position(position))
fn set_cursor_position(&self, position: Position) -> Result<(), RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.set_cursor_position(position))?)
}
fn set_cursor_grab(
&self,
mode: crate::window::CursorGrabMode,
) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_grab(mode))
fn set_cursor_grab(&self, mode: crate::window::CursorGrabMode) -> Result<(), RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.set_cursor_grab(mode))?)
}
fn set_cursor_visible(&self, visible: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_visible(visible))
}
fn drag_window(&self) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_window())
fn drag_window(&self) -> Result<(), RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.drag_window())?)
}
fn drag_resize_window(
&self,
direction: crate::window::ResizeDirection,
) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_resize_window(direction))
) -> Result<(), RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.drag_resize_window(direction))?)
}
fn show_window_menu(&self, position: Position) {
self.maybe_wait_on_main(|delegate| delegate.show_window_menu(position))
}
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_hittest(hittest))
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), RequestError> {
Ok(self.maybe_wait_on_main(|delegate| delegate.set_cursor_hittest(hittest))?)
}
fn current_monitor(&self) -> Option<CoreMonitorHandle> {