api: refactor ActiveEventLoop into trait

This should help with further extensions because the backend event
loops are used directly now.
This commit is contained in:
Kirill Chibisov 2024-08-06 21:02:53 +03:00 committed by GitHub
parent f5304815a1
commit f07153b8e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1058 additions and 1071 deletions

View file

@ -1,11 +1,9 @@
use std::marker::PhantomData;
use super::{backend, device, window, HasMonitorPermissionFuture, MonitorPermissionFuture};
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, NotSupportedError};
use crate::event::Event;
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
use crate::platform::web::{ActiveEventLoopExtWeb, PollStrategy, WaitUntilStrategy};
use crate::platform::web::{PollStrategy, WaitUntilStrategy};
mod proxy;
pub(crate) mod runner;
@ -16,7 +14,7 @@ pub(crate) use proxy::EventLoopProxy;
pub(crate) use window_target::{ActiveEventLoop, OwnedDisplayHandle};
pub struct EventLoop {
elw: RootActiveEventLoop,
elw: ActiveEventLoop,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -24,16 +22,15 @@ pub(crate) struct PlatformSpecificEventLoopAttributes {}
impl EventLoop {
pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
let elw = RootActiveEventLoop { p: ActiveEventLoop::new(), _marker: PhantomData };
Ok(EventLoop { elw })
Ok(EventLoop { elw: ActiveEventLoop::new() })
}
pub fn run_app<A: ApplicationHandler>(self, mut app: A) -> ! {
let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData };
let event_loop = self.elw.clone();
// SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`.
let handler: Box<dyn FnMut(Event)> =
Box::new(|event| handle_event(&mut app, &target, event));
Box::new(|event| handle_event(&mut app, &event_loop, event));
// SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe
// because this function will never return and all resources not cleaned up by the point we
@ -41,7 +38,7 @@ impl EventLoop {
let handler = unsafe {
std::mem::transmute::<Box<dyn FnMut(Event)>, Box<dyn FnMut(Event) + 'static>>(handler)
};
self.elw.p.run(handler, false);
self.elw.run(handler, false);
// Throw an exception to break out of Rust execution and use unreachable to tell the
// compiler this function won't return, giving it a return type of '!'
@ -53,12 +50,11 @@ impl EventLoop {
}
pub fn spawn_app<A: ApplicationHandler + 'static>(self, mut app: A) {
let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData };
self.elw.p.run(Box::new(move |event| handle_event(&mut app, &target, event)), true);
let event_loop = self.elw.clone();
self.elw.run(Box::new(move |event| handle_event(&mut app, &event_loop, event)), true);
}
pub fn window_target(&self) -> &RootActiveEventLoop {
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.elw
}
@ -83,15 +79,15 @@ impl EventLoop {
}
pub(crate) fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture {
self.elw.request_detailed_monitor_permission().0
self.elw.request_detailed_monitor_permission()
}
pub fn has_detailed_monitor_permission(&self) -> HasMonitorPermissionFuture {
self.elw.p.runner.monitor().has_detailed_monitor_permission_async()
self.elw.runner.monitor().has_detailed_monitor_permission_async()
}
}
fn handle_event<A: ApplicationHandler>(app: &mut A, target: &RootActiveEventLoop, event: Event) {
fn handle_event<A: ApplicationHandler>(app: &mut A, target: &ActiveEventLoop, event: Event) {
match event {
Event::NewEvents(cause) => app.new_events(target, cause),
Event::WindowEvent { window_id, event } => app.window_event(target, window_id, event),

View file

@ -1,3 +1,4 @@
use std::any::Any;
use std::cell::Cell;
use std::clone::Clone;
use std::iter;
@ -5,7 +6,7 @@ use std::rc::Rc;
use web_sys::Element;
use super::super::monitor::{MonitorHandle, MonitorPermissionFuture};
use super::super::monitor::MonitorPermissionFuture;
use super::super::{lock, KeyEventExtra};
use super::device::DeviceId;
use super::runner::{EventWrapper, WeakShared};
@ -15,13 +16,19 @@ use crate::error::{ExternalError, NotSupportedError};
use crate::event::{
DeviceId as RootDeviceId, ElementState, Event, KeyEvent, Touch, TouchPhase, WindowEvent,
};
use crate::event_loop::{ControlFlow, DeviceEvents};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
};
use crate::keyboard::ModifiersState;
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy};
use crate::platform_impl::platform::cursor::CustomCursor;
use crate::platform_impl::platform::r#async::Waker;
use crate::platform_impl::Window;
use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId,
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow,
WindowId as RootWindowId,
};
#[derive(Default)]
@ -67,17 +74,6 @@ impl ActiveEventLoop {
WindowId(self.runner.generate_id())
}
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(self.waker())
}
pub fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: CustomCursor::new(self, source.inner) })
}
pub fn create_custom_cursor_async(&self, source: CustomCursorSource) -> CustomCursorFuture {
CustomCursorFuture(CustomCursor::new_async(self, source.inner))
}
@ -594,52 +590,6 @@ impl ActiveEventLoop {
canvas.on_context_menu();
}
pub fn available_monitors(&self) -> Vec<MonitorHandle> {
self.runner.monitor().available_monitors()
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
self.runner.monitor().primary_monitor()
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new()))
}
pub fn listen_device_events(&self, allowed: DeviceEvents) {
self.runner.listen_device_events(allowed)
}
pub fn system_theme(&self) -> Option<Theme> {
backend::is_dark_mode(self.runner.window()).map(|is_dark_mode| {
if is_dark_mode {
Theme::Dark
} else {
Theme::Light
}
})
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
self.runner.set_control_flow(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
self.runner.control_flow()
}
pub(crate) fn exit(&self) {
self.runner.exit()
}
pub(crate) fn exiting(&self) -> bool {
self.runner.exiting()
}
pub(crate) fn set_poll_strategy(&self, strategy: PollStrategy) {
self.runner.set_poll_strategy(strategy)
}
@ -675,9 +625,92 @@ impl ActiveEventLoop {
pub(crate) fn waker(&self) -> Waker<WeakShared> {
self.runner.waker()
}
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy {
let event_loop_proxy = EventLoopProxy::new(self.waker());
RootEventLoopProxy { event_loop_proxy }
}
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
}
fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: CustomCursor::new(self, source.inner) })
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
Box::new(
self.runner
.monitor()
.available_monitors()
.into_iter()
.map(|inner| RootMonitorHandle { inner }),
)
}
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
self.runner.monitor().primary_monitor().map(|inner| RootMonitorHandle { inner })
}
fn listen_device_events(&self, allowed: DeviceEvents) {
self.runner.listen_device_events(allowed)
}
fn system_theme(&self) -> Option<Theme> {
backend::is_dark_mode(self.runner.window()).map(|is_dark_mode| {
if is_dark_mode {
Theme::Dark
} else {
Theme::Light
}
})
}
fn set_control_flow(&self, control_flow: ControlFlow) {
self.runner.set_control_flow(control_flow)
}
fn control_flow(&self) -> ControlFlow {
self.runner.control_flow()
}
fn exit(&self) {
self.runner.exit()
}
fn exiting(&self) -> bool {
self.runner.exiting()
}
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
RootOwnedDisplayHandle { platform: OwnedDisplayHandle }
}
fn as_any(&self) -> &dyn Any {
self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for ActiveEventLoop {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = rwh_06::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new());
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}