api: make EventLoopProxy wrap an opaque type

The proxy is intended to be Clone, thus use `Arc` for it internally and
don't require backends for it to be `Clone`. Use `EventLoopProxyProvider`
to hide the backend's proxy implementation details.

Co-authored-by: daxpedda <daxpedda@gmail.com>
This commit is contained in:
Kirill Chibisov 2024-11-12 10:56:20 +03:00 committed by GitHub
parent ae4c449670
commit 3a60cbaba5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 256 additions and 307 deletions

View file

@ -13,6 +13,7 @@ use std::marker::PhantomData;
#[cfg(any(x11_platform, wayland_platform))] #[cfg(any(x11_platform, wayland_platform))]
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
#[cfg(not(web_platform))] #[cfg(not(web_platform))]
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -452,10 +453,21 @@ impl rwh_06::HasDisplayHandle for OwnedDisplayHandle {
} }
} }
pub(crate) trait EventLoopProxyProvider: Send + Sync {
/// See [`EventLoopProxy::wake_up`] for details.
fn wake_up(&self);
}
/// Control the [`EventLoop`], possibly from a different thread, without referencing it directly. /// Control the [`EventLoop`], possibly from a different thread, without referencing it directly.
#[derive(Clone)] #[derive(Clone)]
pub struct EventLoopProxy { pub struct EventLoopProxy {
pub(crate) event_loop_proxy: platform_impl::EventLoopProxy, pub(crate) proxy: Arc<dyn EventLoopProxyProvider>,
}
impl fmt::Debug for EventLoopProxy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventLoopProxy").finish_non_exhaustive()
}
} }
impl EventLoopProxy { impl EventLoopProxy {
@ -475,13 +487,11 @@ impl EventLoopProxy {
/// ///
/// [#3687]: https://github.com/rust-windowing/winit/pull/3687 /// [#3687]: https://github.com/rust-windowing/winit/pull/3687
pub fn wake_up(&self) { pub fn wake_up(&self) {
self.event_loop_proxy.wake_up(); self.proxy.wake_up();
} }
}
impl fmt::Debug for EventLoopProxy { pub(crate) fn new(proxy: Arc<dyn EventLoopProxyProvider>) -> Self {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Self { proxy }
f.debug_struct("ActiveEventLoop").finish_non_exhaustive()
} }
} }

View file

@ -18,7 +18,8 @@ use crate::error::{EventLoopError, NotSupportedError, RequestError};
use crate::event::{self, DeviceId, FingerId, Force, StartCause, SurfaceSizeWriter}; use crate::event::{self, DeviceId, FingerId, Force, StartCause, SurfaceSizeWriter};
use crate::event_loop::{ use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
OwnedDisplayHandle as RootOwnedDisplayHandle,
}; };
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::pump_events::PumpStatus; use crate::platform::pump_events::PumpStatus;
@ -131,12 +132,13 @@ impl EventLoop {
pub(crate) fn new( pub(crate) fn new(
attributes: &PlatformSpecificEventLoopAttributes, attributes: &PlatformSpecificEventLoopAttributes,
) -> Result<Self, EventLoopError> { ) -> Result<Self, EventLoopError> {
let proxy_wake_up = Arc::new(AtomicBool::new(false));
let android_app = attributes.android_app.as_ref().expect( let android_app = attributes.android_app.as_ref().expect(
"An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on \ "An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on \
Android", Android",
); );
let event_loop_proxy = Arc::new(EventLoopProxy::new(android_app.create_waker()));
let redraw_flag = SharedFlag::new(); let redraw_flag = SharedFlag::new();
Ok(Self { Ok(Self {
@ -147,7 +149,7 @@ impl EventLoop {
control_flow: Cell::new(ControlFlow::default()), control_flow: Cell::new(ControlFlow::default()),
exit: Cell::new(false), exit: Cell::new(false),
redraw_requester: RedrawRequester::new(&redraw_flag, android_app.create_waker()), redraw_requester: RedrawRequester::new(&redraw_flag, android_app.create_waker()),
proxy_wake_up, event_loop_proxy,
}, },
redraw_flag, redraw_flag,
loop_running: false, loop_running: false,
@ -276,7 +278,7 @@ impl EventLoop {
}, },
} }
if self.window_target.proxy_wake_up.swap(false, Ordering::Relaxed) { if self.window_target.event_loop_proxy.wake_up.swap(false, Ordering::Relaxed) {
app.proxy_wake_up(&self.window_target); app.proxy_wake_up(&self.window_target);
} }
@ -562,7 +564,8 @@ impl EventLoop {
self.pending_redraw |= self.redraw_flag.get_and_reset(); self.pending_redraw |= self.redraw_flag.get_and_reset();
timeout = if self.running timeout = if self.running
&& (self.pending_redraw || self.window_target.proxy_wake_up.load(Ordering::Relaxed)) && (self.pending_redraw
|| self.window_target.event_loop_proxy.wake_up.load(Ordering::Relaxed))
{ {
// If we already have work to do then we don't want to block on the next poll // If we already have work to do then we don't want to block on the next poll
Some(Duration::ZERO) Some(Duration::ZERO)
@ -595,7 +598,7 @@ impl EventLoop {
self.pending_redraw |= self.redraw_flag.get_and_reset(); self.pending_redraw |= self.redraw_flag.get_and_reset();
if !self.running if !self.running
|| (!self.pending_redraw || (!self.pending_redraw
&& !self.window_target.proxy_wake_up.load(Ordering::Relaxed)) && !self.window_target.event_loop_proxy.wake_up.load(Ordering::Relaxed))
{ {
return; return;
} }
@ -634,15 +637,20 @@ impl EventLoop {
} }
} }
#[derive(Clone)]
pub struct EventLoopProxy { pub struct EventLoopProxy {
proxy_wake_up: Arc<AtomicBool>, wake_up: AtomicBool,
waker: AndroidAppWaker, waker: AndroidAppWaker,
} }
impl EventLoopProxy { impl EventLoopProxy {
pub fn wake_up(&self) { fn new(waker: AndroidAppWaker) -> Self {
self.proxy_wake_up.store(true, Ordering::Relaxed); Self { wake_up: AtomicBool::new(false), waker }
}
}
impl EventLoopProxyProvider for EventLoopProxy {
fn wake_up(&self) {
self.wake_up.store(true, Ordering::Relaxed);
self.waker.wake(); self.waker.wake();
} }
} }
@ -652,7 +660,7 @@ pub struct ActiveEventLoop {
control_flow: Cell<ControlFlow>, control_flow: Cell<ControlFlow>,
exit: Cell<bool>, exit: Cell<bool>,
redraw_requester: RedrawRequester, redraw_requester: RedrawRequester,
proxy_wake_up: Arc<AtomicBool>, event_loop_proxy: Arc<EventLoopProxy>,
} }
impl ActiveEventLoop { impl ActiveEventLoop {
@ -662,12 +670,8 @@ impl ActiveEventLoop {
} }
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy { fn create_proxy(&self) -> CoreEventLoopProxy {
let event_loop_proxy = EventLoopProxy { CoreEventLoopProxy::new(self.event_loop_proxy.clone())
proxy_wake_up: self.proxy_wake_up.clone(),
waker: self.app.create_waker(),
};
RootEventLoopProxy { event_loop_proxy }
} }
fn create_window( fn create_window(

View file

@ -1,7 +1,7 @@
use std::cell::{Cell, OnceCell, RefCell}; use std::cell::{Cell, OnceCell, RefCell};
use std::mem; use std::mem;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; use std::sync::atomic::Ordering as AtomicOrdering;
use std::sync::Arc; use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
@ -9,7 +9,7 @@ use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy};
use objc2_foundation::{MainThreadMarker, NSNotification}; use objc2_foundation::{MainThreadMarker, NSNotification};
use super::super::event_handler::EventHandler; use super::super::event_handler::EventHandler;
use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo}; use super::event_loop::{stop_app_immediately, ActiveEventLoop, EventLoopProxy, PanicInfo};
use super::menu; use super::menu;
use super::observer::{EventLoopWaker, RunLoop}; use super::observer::{EventLoopWaker, RunLoop};
use crate::application::ApplicationHandler; use crate::application::ApplicationHandler;
@ -24,7 +24,7 @@ pub(super) struct AppState {
default_menu: bool, default_menu: bool,
activate_ignoring_other_apps: bool, activate_ignoring_other_apps: bool,
run_loop: RunLoop, run_loop: RunLoop,
proxy_wake_up: Arc<AtomicBool>, event_loop_proxy: Arc<EventLoopProxy>,
event_handler: EventHandler, event_handler: EventHandler,
stop_on_launch: Cell<bool>, stop_on_launch: Cell<bool>,
stop_before_wait: Cell<bool>, stop_before_wait: Cell<bool>,
@ -72,7 +72,7 @@ impl AppState {
let this = Rc::new(AppState { let this = Rc::new(AppState {
mtm, mtm,
activation_policy, activation_policy,
proxy_wake_up: Arc::new(AtomicBool::new(false)), event_loop_proxy: Arc::new(EventLoopProxy::new()),
default_menu, default_menu,
activate_ignoring_other_apps, activate_ignoring_other_apps,
run_loop: RunLoop::main(mtm), run_loop: RunLoop::main(mtm),
@ -165,8 +165,8 @@ impl AppState {
self.event_handler.set(handler, closure) self.event_handler.set(handler, closure)
} }
pub fn proxy_wake_up(&self) -> Arc<AtomicBool> { pub fn event_loop_proxy(&self) -> &Arc<EventLoopProxy> {
self.proxy_wake_up.clone() &self.event_loop_proxy
} }
/// If `pump_events` is called to progress the event loop then we /// If `pump_events` is called to progress the event loop then we
@ -350,7 +350,7 @@ impl AppState {
return; return;
} }
if self.proxy_wake_up.swap(false, AtomicOrdering::Relaxed) { if self.event_loop_proxy.wake_up.swap(false, AtomicOrdering::Relaxed) {
self.with_handler(|app, event_loop| app.proxy_wake_up(event_loop)); self.with_handler(|app, event_loop| app.proxy_wake_up(event_loop));
} }

View file

@ -5,7 +5,6 @@ use std::panic::{catch_unwind, resume_unwind, RefUnwindSafe, UnwindSafe};
use std::ptr; use std::ptr;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use core_foundation::base::{CFIndex, CFRelease}; use core_foundation::base::{CFIndex, CFRelease};
@ -32,7 +31,8 @@ use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, RequestError}; use crate::error::{EventLoopError, RequestError};
use crate::event_loop::{ use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
OwnedDisplayHandle as RootOwnedDisplayHandle,
}; };
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::macos::ActivationPolicy; use crate::platform::macos::ActivationPolicy;
@ -95,9 +95,8 @@ impl ActiveEventLoop {
} }
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy { fn create_proxy(&self) -> CoreEventLoopProxy {
let event_loop_proxy = EventLoopProxy::new(self.app_state.proxy_wake_up()); CoreEventLoopProxy::new(self.app_state.event_loop_proxy().clone())
RootEventLoopProxy { event_loop_proxy }
} }
fn create_window( fn create_window(
@ -436,8 +435,9 @@ pub fn stop_app_on_panic<F: FnOnce() -> R + UnwindSafe, R>(
} }
} }
#[derive(Debug)]
pub struct EventLoopProxy { pub struct EventLoopProxy {
proxy_wake_up: Arc<AtomicBool>, pub(crate) wake_up: AtomicBool,
source: CFRunLoopSourceRef, source: CFRunLoopSourceRef,
} }
@ -452,14 +452,8 @@ impl Drop for EventLoopProxy {
} }
} }
impl Clone for EventLoopProxy {
fn clone(&self) -> Self {
EventLoopProxy::new(self.proxy_wake_up.clone())
}
}
impl EventLoopProxy { impl EventLoopProxy {
fn new(proxy_wake_up: Arc<AtomicBool>) -> Self { pub(crate) fn new() -> Self {
unsafe { unsafe {
// just wake up the eventloop // just wake up the eventloop
extern "C" fn event_loop_proxy_handler(_: *const c_void) {} extern "C" fn event_loop_proxy_handler(_: *const c_void) {}
@ -483,14 +477,16 @@ impl EventLoopProxy {
CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes);
CFRunLoopWakeUp(rl); CFRunLoopWakeUp(rl);
EventLoopProxy { proxy_wake_up, source } EventLoopProxy { wake_up: AtomicBool::new(false), source }
} }
} }
}
pub fn wake_up(&self) { impl EventLoopProxyProvider for EventLoopProxy {
self.proxy_wake_up.store(true, AtomicOrdering::Relaxed); fn wake_up(&self) {
self.wake_up.store(true, AtomicOrdering::Relaxed);
unsafe { unsafe {
// let the main thread know there's a new event // Let the main thread know there's a new event.
CFRunLoopSourceSignal(self.source); CFRunLoopSourceSignal(self.source);
let rl = CFRunLoopGetMain(); let rl = CFRunLoopGetMain();
CFRunLoopWakeUp(rl); CFRunLoopWakeUp(rl);

View file

@ -17,8 +17,7 @@ mod window_delegate;
pub(crate) use self::cursor::CustomCursor as PlatformCustomCursor; 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::{physicalkey_to_scancode, scancode_to_physicalkey, KeyEventExtra};
pub(crate) use self::event_loop::{ pub(crate) use self::event_loop::{
ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, ActiveEventLoop, EventLoop, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes,
PlatformSpecificEventLoopAttributes,
}; };
pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle}; pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle};
pub(crate) use self::window::Window; pub(crate) use self::window::Window;

View file

@ -3,7 +3,7 @@
use std::cell::{OnceCell, RefCell, RefMut}; use std::cell::{OnceCell, RefCell, RefMut};
use std::collections::HashSet; use std::collections::HashSet;
use std::os::raw::c_void; use std::os::raw::c_void;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex, OnceLock}; use std::sync::{Arc, Mutex, OnceLock};
use std::time::Instant; use std::time::Instant;
use std::{mem, ptr}; use std::{mem, ptr};
@ -24,7 +24,7 @@ use objc2_ui_kit::{UIApplication, UICoordinateSpace, UIView, UIWindow};
use super::super::event_handler::EventHandler; use super::super::event_handler::EventHandler;
use super::window::WinitUIWindow; use super::window::WinitUIWindow;
use super::ActiveEventLoop; use super::{ActiveEventLoop, EventLoopProxy};
use crate::application::ApplicationHandler; use crate::application::ApplicationHandler;
use crate::dpi::PhysicalSize; use crate::dpi::PhysicalSize;
use crate::event::{Event, StartCause, SurfaceSizeWriter, WindowEvent}; use crate::event::{Event, StartCause, SurfaceSizeWriter, WindowEvent};
@ -139,7 +139,7 @@ pub(crate) struct AppState {
app_state: Option<AppStateImpl>, app_state: Option<AppStateImpl>,
control_flow: ControlFlow, control_flow: ControlFlow,
waker: EventLoopWaker, waker: EventLoopWaker,
proxy_wake_up: Arc<AtomicBool>, event_loop_proxy: Arc<EventLoopProxy>,
} }
impl AppState { impl AppState {
@ -164,7 +164,7 @@ impl AppState {
}), }),
control_flow: ControlFlow::default(), control_flow: ControlFlow::default(),
waker, waker,
proxy_wake_up: Arc::new(AtomicBool::new(false)), event_loop_proxy: Arc::new(EventLoopProxy::new()),
}); });
} }
init_guard(&mut guard); init_guard(&mut guard);
@ -376,8 +376,8 @@ impl AppState {
} }
} }
pub(crate) fn proxy_wake_up(&self) -> Arc<AtomicBool> { pub fn event_loop_proxy(&self) -> &Arc<EventLoopProxy> {
self.proxy_wake_up.clone() &self.event_loop_proxy
} }
pub(crate) fn set_control_flow(&mut self, control_flow: ControlFlow) { pub(crate) fn set_control_flow(&mut self, control_flow: ControlFlow) {
@ -543,10 +543,10 @@ fn handle_user_events(mtm: MainThreadMarker) {
if processing_redraws { if processing_redraws {
bug!("user events attempted to be sent out while `ProcessingRedraws`"); bug!("user events attempted to be sent out while `ProcessingRedraws`");
} }
let proxy_wake_up = this.proxy_wake_up.clone(); let event_loop_proxy = this.event_loop_proxy().clone();
drop(this); drop(this);
if proxy_wake_up.swap(false, Ordering::Relaxed) { if event_loop_proxy.wake_up.swap(false, Ordering::Relaxed) {
handle_event(mtm, Event::UserWakeUp); handle_event(mtm, Event::UserWakeUp);
} }
@ -578,7 +578,7 @@ fn handle_user_events(mtm: MainThreadMarker) {
} }
} }
if proxy_wake_up.swap(false, Ordering::Relaxed) { if event_loop_proxy.wake_up.swap(false, Ordering::Relaxed) {
handle_event(mtm, Event::UserWakeUp); handle_event(mtm, Event::UserWakeUp);
} }
} }

View file

@ -1,7 +1,6 @@
use std::ffi::{c_char, c_int, c_void}; use std::ffi::{c_char, c_int, c_void};
use std::ptr::{self, NonNull}; use std::ptr::{self, NonNull};
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
use std::sync::Arc;
use core_foundation::base::{CFIndex, CFRelease}; use core_foundation::base::{CFIndex, CFRelease};
use core_foundation::runloop::{ use core_foundation::runloop::{
@ -29,7 +28,8 @@ use crate::error::{EventLoopError, NotSupportedError, RequestError};
use crate::event::Event; use crate::event::Event;
use crate::event_loop::{ use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
OwnedDisplayHandle as RootOwnedDisplayHandle,
}; };
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform_impl::Window; use crate::platform_impl::Window;
@ -41,9 +41,8 @@ pub(crate) struct ActiveEventLoop {
} }
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy { fn create_proxy(&self) -> CoreEventLoopProxy {
let event_loop_proxy = EventLoopProxy::new(AppState::get_mut(self.mtm).proxy_wake_up()); CoreEventLoopProxy::new(AppState::get_mut(self.mtm).event_loop_proxy().clone())
RootEventLoopProxy { event_loop_proxy }
} }
fn create_window( fn create_window(
@ -289,19 +288,13 @@ impl EventLoop {
} }
pub struct EventLoopProxy { pub struct EventLoopProxy {
proxy_wake_up: Arc<AtomicBool>, pub(crate) wake_up: AtomicBool,
source: CFRunLoopSourceRef, source: CFRunLoopSourceRef,
} }
unsafe impl Send for EventLoopProxy {} unsafe impl Send for EventLoopProxy {}
unsafe impl Sync for EventLoopProxy {} unsafe impl Sync for EventLoopProxy {}
impl Clone for EventLoopProxy {
fn clone(&self) -> EventLoopProxy {
EventLoopProxy::new(self.proxy_wake_up.clone())
}
}
impl Drop for EventLoopProxy { impl Drop for EventLoopProxy {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
@ -312,7 +305,7 @@ impl Drop for EventLoopProxy {
} }
impl EventLoopProxy { impl EventLoopProxy {
fn new(proxy_wake_up: Arc<AtomicBool>) -> EventLoopProxy { pub(crate) fn new() -> EventLoopProxy {
unsafe { unsafe {
// just wake up the eventloop // just wake up the eventloop
extern "C" fn event_loop_proxy_handler(_: *const c_void) {} extern "C" fn event_loop_proxy_handler(_: *const c_void) {}
@ -336,12 +329,14 @@ impl EventLoopProxy {
CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes);
CFRunLoopWakeUp(rl); CFRunLoopWakeUp(rl);
EventLoopProxy { proxy_wake_up, source } EventLoopProxy { wake_up: AtomicBool::new(false), source }
} }
} }
}
pub fn wake_up(&self) { impl EventLoopProxyProvider for EventLoopProxy {
self.proxy_wake_up.store(true, AtomicOrdering::Relaxed); fn wake_up(&self) {
self.wake_up.store(true, AtomicOrdering::Relaxed);
unsafe { unsafe {
// let the main thread know there's a new event // let the main thread know there's a new event
CFRunLoopSourceSignal(self.source); CFRunLoopSourceSignal(self.source);

View file

@ -277,14 +277,6 @@ pub enum EventLoop {
X(x11::EventLoop), X(x11::EventLoop),
} }
#[derive(Clone)]
pub enum EventLoopProxy {
#[cfg(x11_platform)]
X(x11::EventLoopProxy),
#[cfg(wayland_platform)]
Wayland(wayland::EventLoopProxy),
}
impl EventLoop { impl EventLoop {
pub(crate) fn new( pub(crate) fn new(
attributes: &PlatformSpecificEventLoopAttributes, attributes: &PlatformSpecificEventLoopAttributes,
@ -404,12 +396,6 @@ impl AsRawFd for EventLoop {
} }
} }
impl EventLoopProxy {
pub fn wake_up(&self) {
x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.wake_up())
}
}
#[derive(Clone)] #[derive(Clone)]
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) enum OwnedDisplayHandle { pub(crate) enum OwnedDisplayHandle {

View file

@ -25,12 +25,13 @@ use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme}
mod proxy; mod proxy;
pub mod sink; pub mod sink;
pub use proxy::EventLoopProxy; use proxy::EventLoopProxy;
use sink::EventSink; use sink::EventSink;
use super::state::{WindowCompositorUpdate, WinitState}; use super::state::{WindowCompositorUpdate, WinitState};
use super::window::state::FrameCallbackState; use super::window::state::FrameCallbackState;
use super::{logical_to_physical_rounded, WindowId}; use super::{logical_to_physical_rounded, WindowId};
pub use crate::event_loop::EventLoopProxy as CoreEventLoopProxy;
type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource<WinitState>, WinitState>; type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource<WinitState>, WinitState>;
@ -120,7 +121,7 @@ impl EventLoop {
connection: connection.clone(), connection: connection.clone(),
wayland_dispatcher: wayland_dispatcher.clone(), wayland_dispatcher: wayland_dispatcher.clone(),
event_loop_awakener, event_loop_awakener,
event_loop_proxy: EventLoopProxy::new(ping), event_loop_proxy: EventLoopProxy::new(ping).into(),
queue_handle, queue_handle,
control_flow: Cell::new(ControlFlow::default()), control_flow: Cell::new(ControlFlow::default()),
exit: Cell::new(None), exit: Cell::new(None),
@ -539,7 +540,7 @@ impl AsRawFd for EventLoop {
pub struct ActiveEventLoop { pub struct ActiveEventLoop {
/// Event loop proxy /// Event loop proxy
event_loop_proxy: EventLoopProxy, event_loop_proxy: CoreEventLoopProxy,
/// The event loop wakeup source. /// The event loop wakeup source.
pub event_loop_awakener: calloop::ping::Ping, pub event_loop_awakener: calloop::ping::Ping,
@ -565,12 +566,8 @@ pub struct ActiveEventLoop {
} }
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy { fn create_proxy(&self) -> CoreEventLoopProxy {
crate::event_loop::EventLoopProxy { self.event_loop_proxy.clone()
event_loop_proxy: crate::platform_impl::EventLoopProxy::Wayland(
self.event_loop_proxy.clone(),
),
}
} }
fn set_control_flow(&self, control_flow: ControlFlow) { fn set_control_flow(&self, control_flow: ControlFlow) {

View file

@ -1,19 +1,30 @@
//! An event loop proxy. //! An event loop proxy.
use std::sync::Arc;
use sctk::reexports::calloop::ping::Ping; use sctk::reexports::calloop::ping::Ping;
use crate::event_loop::{EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider};
/// A handle that can be sent across the threads and used to wake up the `EventLoop`. /// A handle that can be sent across the threads and used to wake up the `EventLoop`.
#[derive(Clone)]
pub struct EventLoopProxy { pub struct EventLoopProxy {
ping: Ping, ping: Ping,
} }
impl EventLoopProxyProvider for EventLoopProxy {
fn wake_up(&self) {
self.ping.ping();
}
}
impl EventLoopProxy { impl EventLoopProxy {
pub fn new(ping: Ping) -> Self { pub fn new(ping: Ping) -> Self {
Self { ping } Self { ping }
} }
}
pub fn wake_up(&self) { impl From<EventLoopProxy> for CoreEventLoopProxy {
self.ping.ping(); fn from(value: EventLoopProxy) -> Self {
CoreEventLoopProxy::new(Arc::new(value))
} }
} }

View file

@ -1,6 +1,6 @@
//! Winit's Wayland backend. //! Winit's Wayland backend.
pub use event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy}; pub use event_loop::{ActiveEventLoop, EventLoop};
pub use output::{MonitorHandle, VideoModeHandle}; pub use output::{MonitorHandle, VideoModeHandle};
use sctk::reexports::client::protocol::wl_surface::WlSurface; use sctk::reexports::client::protocol::wl_surface::WlSurface;
use sctk::reexports::client::Proxy; use sctk::reexports::client::Proxy;

View file

@ -27,6 +27,7 @@ use crate::error::{EventLoopError, RequestError};
use crate::event::{DeviceId, Event, StartCause, WindowEvent}; use crate::event::{DeviceId, Event, StartCause, WindowEvent};
use crate::event_loop::{ use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
OwnedDisplayHandle as RootOwnedDisplayHandle, OwnedDisplayHandle as RootOwnedDisplayHandle,
}; };
use crate::platform::pump_events::PumpStatus; use crate::platform::pump_events::PumpStatus;
@ -139,7 +140,7 @@ pub struct ActiveEventLoop {
windows: RefCell<HashMap<WindowId, Weak<UnownedWindow>>>, windows: RefCell<HashMap<WindowId, Weak<UnownedWindow>>>,
redraw_sender: WakeSender<WindowId>, redraw_sender: WakeSender<WindowId>,
activation_sender: WakeSender<ActivationToken>, activation_sender: WakeSender<ActivationToken>,
event_loop_proxy: EventLoopProxy, event_loop_proxy: CoreEventLoopProxy,
device_events: Cell<DeviceEvents>, device_events: Cell<DeviceEvents>,
} }
@ -306,7 +307,7 @@ impl EventLoop {
sender: activation_token_sender, // not used again so no clone sender: activation_token_sender, // not used again so no clone
waker: waker.clone(), waker: waker.clone(),
}, },
event_loop_proxy, event_loop_proxy: event_loop_proxy.into(),
device_events: Default::default(), device_events: Default::default(),
}; };
@ -675,12 +676,8 @@ impl ActiveEventLoop {
} }
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy { fn create_proxy(&self) -> CoreEventLoopProxy {
crate::event_loop::EventLoopProxy { self.event_loop_proxy.clone()
event_loop_proxy: crate::platform_impl::EventLoopProxy::X(
self.event_loop_proxy.clone(),
),
}
} }
fn create_window( fn create_window(
@ -759,12 +756,6 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop {
} }
} }
impl EventLoopProxy {
pub fn wake_up(&self) {
self.ping.ping();
}
}
struct DeviceInfo<'a> { struct DeviceInfo<'a> {
xconn: &'a XConnection, xconn: &'a XConnection,
info: *const ffi::XIDeviceInfo, info: *const ffi::XIDeviceInfo,
@ -807,12 +798,24 @@ pub struct EventLoopProxy {
ping: Ping, ping: Ping,
} }
impl EventLoopProxyProvider for EventLoopProxy {
fn wake_up(&self) {
self.ping.ping();
}
}
impl EventLoopProxy { impl EventLoopProxy {
fn new(ping: Ping) -> Self { fn new(ping: Ping) -> Self {
Self { ping } Self { ping }
} }
} }
impl From<EventLoopProxy> for CoreEventLoopProxy {
fn from(value: EventLoopProxy) -> Self {
CoreEventLoopProxy::new(Arc::new(value))
}
}
/// Generic sum error type for X11 errors. /// Generic sum error type for X11 errors.
#[derive(Debug)] #[derive(Debug)]
pub enum X11Error { pub enum X11Error {

View file

@ -18,7 +18,10 @@ use super::{
use crate::application::ApplicationHandler; use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, NotSupportedError, RequestError}; use crate::error::{EventLoopError, NotSupportedError, RequestError};
use crate::event::{self, Ime, Modifiers, StartCause}; use crate::event::{self, Ime, Modifiers, StartCause};
use crate::event_loop::{self, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents}; use crate::event_loop::{
self, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
};
use crate::keyboard::{ use crate::keyboard::{
Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode, Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode,
PhysicalKey, PhysicalKey,
@ -286,8 +289,7 @@ impl EventLoop {
let event_socket = let event_socket =
Arc::new(RedoxSocket::event().map_err(|error| os_error!(format!("{error}")))?); Arc::new(RedoxSocket::event().map_err(|error| os_error!(format!("{error}")))?);
let wake_socket = let wake_socket = TimeSocket::open().map_err(|error| os_error!(format!("{error}")))?;
Arc::new(TimeSocket::open().map_err(|error| os_error!(format!("{error}")))?);
event_socket event_socket
.write(&syscall::Event { .write(&syscall::Event {
@ -306,8 +308,7 @@ impl EventLoop {
redraws: Arc::new(Mutex::new(VecDeque::new())), redraws: Arc::new(Mutex::new(VecDeque::new())),
destroys: Arc::new(Mutex::new(VecDeque::new())), destroys: Arc::new(Mutex::new(VecDeque::new())),
event_socket, event_socket,
wake_socket, event_loop_proxy: Arc::new(EventLoopProxy { wake_socket, user_events_sender }),
user_events_sender,
}, },
user_events_receiver, user_events_receiver,
}) })
@ -664,11 +665,11 @@ impl EventLoop {
pub struct EventLoopProxy { pub struct EventLoopProxy {
user_events_sender: mpsc::SyncSender<()>, user_events_sender: mpsc::SyncSender<()>,
wake_socket: Arc<TimeSocket>, pub(super) wake_socket: TimeSocket,
} }
impl EventLoopProxy { impl EventLoopProxyProvider for EventLoopProxy {
pub fn wake_up(&self) { fn wake_up(&self) {
// When we fail to send the event it means that we haven't woken up to read the previous // When we fail to send the event it means that we haven't woken up to read the previous
// event. // event.
if self.user_events_sender.try_send(()).is_ok() { if self.user_events_sender.try_send(()).is_ok() {
@ -677,15 +678,6 @@ impl EventLoopProxy {
} }
} }
impl Clone for EventLoopProxy {
fn clone(&self) -> Self {
Self {
user_events_sender: self.user_events_sender.clone(),
wake_socket: self.wake_socket.clone(),
}
}
}
impl Unpin for EventLoopProxy {} impl Unpin for EventLoopProxy {}
pub struct ActiveEventLoop { pub struct ActiveEventLoop {
@ -695,18 +687,12 @@ pub struct ActiveEventLoop {
pub(super) redraws: Arc<Mutex<VecDeque<WindowId>>>, pub(super) redraws: Arc<Mutex<VecDeque<WindowId>>>,
pub(super) destroys: Arc<Mutex<VecDeque<WindowId>>>, pub(super) destroys: Arc<Mutex<VecDeque<WindowId>>>,
pub(super) event_socket: Arc<RedoxSocket>, pub(super) event_socket: Arc<RedoxSocket>,
pub(super) wake_socket: Arc<TimeSocket>, pub(super) event_loop_proxy: Arc<EventLoopProxy>,
user_events_sender: mpsc::SyncSender<()>,
} }
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> event_loop::EventLoopProxy { fn create_proxy(&self) -> CoreEventLoopProxy {
event_loop::EventLoopProxy { CoreEventLoopProxy::new(self.event_loop_proxy.clone())
event_loop_proxy: EventLoopProxy {
user_events_sender: self.user_events_sender.clone(),
wake_socket: self.wake_socket.clone(),
},
}
} }
fn create_window( fn create_window(

View file

@ -5,7 +5,7 @@ use std::{fmt, str};
use smol_str::SmolStr; use smol_str::SmolStr;
pub(crate) use self::event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle}; pub(crate) use self::event_loop::{ActiveEventLoop, EventLoop, OwnedDisplayHandle};
use crate::dpi::{PhysicalPosition, PhysicalSize}; use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::keyboard::Key; use crate::keyboard::Key;
mod event_loop; mod event_loop;

View file

@ -1,7 +1,8 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, TimeSocket, WindowProperties}; use super::event_loop::EventLoopProxy;
use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, WindowProperties};
use crate::cursor::Cursor; use crate::cursor::Cursor;
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{NotSupportedError, RequestError}; use crate::error::{NotSupportedError, RequestError};
@ -23,7 +24,7 @@ pub struct Window {
window_socket: Arc<RedoxSocket>, window_socket: Arc<RedoxSocket>,
redraws: Arc<Mutex<VecDeque<WindowId>>>, redraws: Arc<Mutex<VecDeque<WindowId>>>,
destroys: Arc<Mutex<VecDeque<WindowId>>>, destroys: Arc<Mutex<VecDeque<WindowId>>>,
wake_socket: Arc<TimeSocket>, event_loop_proxy: Arc<EventLoopProxy>,
} }
impl Window { impl Window {
@ -113,13 +114,13 @@ impl Window {
creates.push_back(window_socket.clone()); creates.push_back(window_socket.clone());
} }
el.wake_socket.wake().unwrap(); el.event_loop_proxy.wake_socket.wake().unwrap();
Ok(Self { Ok(Self {
window_socket, window_socket,
redraws: el.redraws.clone(), redraws: el.redraws.clone(),
destroys: el.destroys.clone(), destroys: el.destroys.clone(),
wake_socket: el.wake_socket.clone(), event_loop_proxy: el.event_loop_proxy.clone(),
}) })
} }
@ -184,7 +185,7 @@ impl CoreWindow for Window {
if !redraws.contains(&window_id) { if !redraws.contains(&window_id) {
redraws.push_back(window_id); redraws.push_back(window_id);
self.wake_socket.wake().unwrap(); self.event_loop_proxy.wake_socket.wake().unwrap();
} }
} }
@ -475,6 +476,6 @@ impl Drop for Window {
destroys.push_back(self.id()); destroys.push_back(self.id());
} }
self.wake_socket.wake().unwrap(); self.event_loop_proxy.wake_socket.wake().unwrap();
} }
} }

View file

@ -6,15 +6,13 @@ mod channel;
mod concurrent_queue; mod concurrent_queue;
mod dispatcher; mod dispatcher;
mod notifier; mod notifier;
mod waker;
mod wrapper; mod wrapper;
use atomic_waker::AtomicWaker; pub(crate) use atomic_waker::AtomicWaker;
use concurrent_queue::{ConcurrentQueue, PushError}; use concurrent_queue::{ConcurrentQueue, PushError};
pub use self::abortable::{AbortHandle, Abortable, DropAbortHandle}; pub use self::abortable::{AbortHandle, Abortable, DropAbortHandle};
pub use self::channel::{channel, Receiver, Sender}; pub use self::channel::{channel, Receiver, Sender};
pub use self::dispatcher::{DispatchRunner, Dispatcher}; pub use self::dispatcher::{DispatchRunner, Dispatcher};
pub use self::notifier::{Notified, Notifier}; pub use self::notifier::{Notified, Notifier};
pub use self::waker::{Waker, WakerSpawner}; pub(crate) use self::wrapper::Wrapper;
use self::wrapper::Wrapper;

View file

@ -1,117 +0,0 @@
use std::future;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::task::Poll;
use super::super::main_thread::MainThreadMarker;
use super::{AtomicWaker, Wrapper};
pub struct WakerSpawner<T: 'static>(Wrapper<Handler<T>, Sender, ()>);
pub struct Waker<T: 'static>(Wrapper<Handler<T>, Sender, ()>);
struct Handler<T> {
value: T,
handler: fn(&T, bool),
}
#[derive(Clone)]
struct Sender(Arc<Inner>);
impl<T> WakerSpawner<T> {
pub fn new(main_thread: MainThreadMarker, value: T, handler: fn(&T, bool)) -> Self {
let inner = Arc::new(Inner {
awoken: AtomicBool::new(false),
waker: AtomicWaker::new(),
closed: AtomicBool::new(false),
});
let handler = Handler { value, handler };
let sender = Sender(Arc::clone(&inner));
Self(Wrapper::new(
main_thread,
handler,
|handler, _| {
let handler = handler.borrow();
let handler = handler.as_ref().unwrap();
(handler.handler)(&handler.value, true);
},
{
let inner = Arc::clone(&inner);
move |handler| async move {
while future::poll_fn(|cx| {
if inner.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
inner.waker.register(cx.waker());
if inner.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
if inner.closed.load(Ordering::Relaxed) {
return Poll::Ready(false);
}
Poll::Pending
}
}
})
.await
{
let handler = handler.borrow();
let handler = handler.as_ref().unwrap();
(handler.handler)(&handler.value, false);
}
}
},
sender,
|inner, _| {
inner.0.awoken.store(true, Ordering::Relaxed);
inner.0.waker.wake();
},
))
}
pub fn waker(&self) -> Waker<T> {
Waker(self.0.clone())
}
pub fn take(&self) -> bool {
debug_assert!(
MainThreadMarker::new().is_some(),
"this should only be called from the main thread"
);
self.0.with_sender_data(|inner| inner.0.awoken.swap(false, Ordering::Relaxed))
}
}
impl<T> Drop for WakerSpawner<T> {
fn drop(&mut self) {
self.0.with_sender_data(|inner| {
inner.0.closed.store(true, Ordering::Relaxed);
inner.0.waker.wake();
});
}
}
impl<T> Waker<T> {
pub fn wake(&self) {
self.0.send(())
}
}
impl<T> Clone for Waker<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
struct Inner {
awoken: AtomicBool,
waker: AtomicWaker,
closed: AtomicBool,
}

View file

@ -10,7 +10,6 @@ pub(crate) mod runner;
mod state; mod state;
mod window_target; mod window_target;
pub(crate) use proxy::EventLoopProxy;
pub(crate) use window_target::{ActiveEventLoop, OwnedDisplayHandle}; pub(crate) use window_target::{ActiveEventLoop, OwnedDisplayHandle};
pub struct EventLoop { pub struct EventLoop {

View file

@ -1,17 +1,101 @@
use super::runner::WeakShared; use std::future;
use crate::platform_impl::platform::r#async::Waker; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::task::Poll;
#[derive(Clone)] use super::super::main_thread::MainThreadMarker;
pub struct EventLoopProxy { use crate::event_loop::EventLoopProxyProvider;
runner: Waker<WeakShared>, use crate::platform_impl::web::event_loop::runner::WeakShared;
use crate::platform_impl::web::r#async::{AtomicWaker, Wrapper};
pub struct EventLoopProxy(Wrapper<WeakShared, Arc<State>, ()>);
struct State {
awoken: AtomicBool,
waker: AtomicWaker,
closed: AtomicBool,
} }
impl EventLoopProxy { impl EventLoopProxy {
pub fn new(runner: Waker<WeakShared>) -> Self { pub fn new(main_thread: MainThreadMarker, runner: WeakShared) -> Self {
Self { runner } let state = Arc::new(State {
awoken: AtomicBool::new(false),
waker: AtomicWaker::new(),
closed: AtomicBool::new(false),
});
Self(Wrapper::new(
main_thread,
runner,
|runner, _| {
let runner = runner.borrow();
let runner = runner.as_ref().unwrap();
if let Some(runner) = runner.upgrade() {
runner.send_proxy_wake_up(true);
}
},
{
let state = Arc::clone(&state);
move |runner| async move {
while future::poll_fn(|cx| {
if state.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
state.waker.register(cx.waker());
if state.awoken.swap(false, Ordering::Relaxed) {
Poll::Ready(true)
} else {
if state.closed.load(Ordering::Relaxed) {
return Poll::Ready(false);
}
Poll::Pending
}
}
})
.await
{
let runner = runner.borrow();
let runner = runner.as_ref().unwrap();
if let Some(runner) = runner.upgrade() {
runner.send_proxy_wake_up(false);
}
}
}
},
state,
|state, _| {
state.awoken.store(true, Ordering::Relaxed);
state.waker.wake();
},
))
} }
pub fn wake_up(&self) { pub fn take(&self) -> bool {
self.runner.wake(); debug_assert!(
MainThreadMarker::new().is_some(),
"this should only be called from the main thread"
);
self.0.with_sender_data(|state| state.awoken.swap(false, Ordering::Relaxed))
}
}
impl Drop for EventLoopProxy {
fn drop(&mut self) {
self.0.with_sender_data(|state| {
state.closed.store(true, Ordering::Relaxed);
state.waker.wake();
});
}
}
impl EventLoopProxyProvider for EventLoopProxy {
fn wake_up(&self) {
self.0.send(())
} }
} }

View file

@ -3,6 +3,7 @@ use std::collections::{HashSet, VecDeque};
use std::iter; use std::iter;
use std::ops::Deref; use std::ops::Deref;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use std::sync::Arc;
use wasm_bindgen::prelude::Closure; use wasm_bindgen::prelude::Closure;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
@ -13,13 +14,14 @@ use super::super::event;
use super::super::main_thread::MainThreadMarker; use super::super::main_thread::MainThreadMarker;
use super::super::monitor::MonitorHandler; use super::super::monitor::MonitorHandler;
use super::backend; use super::backend;
use super::proxy::EventLoopProxy;
use super::state::State; use super::state::State;
use crate::dpi::PhysicalSize; use crate::dpi::PhysicalSize;
use crate::event::{DeviceEvent, ElementState, Event, RawKeyEvent, StartCause, WindowEvent}; use crate::event::{DeviceEvent, ElementState, Event, RawKeyEvent, StartCause, WindowEvent};
use crate::event_loop::{ControlFlow, DeviceEvents}; use crate::event_loop::{ControlFlow, DeviceEvents};
use crate::platform::web::{PollStrategy, WaitUntilStrategy}; use crate::platform::web::{PollStrategy, WaitUntilStrategy};
use crate::platform_impl::platform::backend::EventListenerHandle; use crate::platform_impl::platform::backend::EventListenerHandle;
use crate::platform_impl::platform::r#async::{DispatchRunner, Waker, WakerSpawner}; use crate::platform_impl::platform::r#async::DispatchRunner;
use crate::platform_impl::platform::window::Inner; use crate::platform_impl::platform::window::Inner;
use crate::window::WindowId; use crate::window::WindowId;
@ -37,7 +39,7 @@ type OnEventHandle<T> = RefCell<Option<EventListenerHandle<dyn FnMut(T)>>>;
struct Execution { struct Execution {
main_thread: MainThreadMarker, main_thread: MainThreadMarker,
proxy_spawner: WakerSpawner<WeakShared>, event_loop_proxy: Arc<EventLoopProxy>,
control_flow: Cell<ControlFlow>, control_flow: Cell<ControlFlow>,
poll_strategy: Cell<PollStrategy>, poll_strategy: Cell<PollStrategy>,
wait_until_strategy: Cell<WaitUntilStrategy>, wait_until_strategy: Cell<WaitUntilStrategy>,
@ -140,12 +142,7 @@ impl Shared {
let document = window.document().expect("Failed to obtain document"); let document = window.document().expect("Failed to obtain document");
Shared(Rc::<Execution>::new_cyclic(|weak| { Shared(Rc::<Execution>::new_cyclic(|weak| {
let proxy_spawner = let proxy_spawner = EventLoopProxy::new(main_thread, WeakShared(weak.clone()));
WakerSpawner::new(main_thread, WeakShared(weak.clone()), |runner, local| {
if let Some(runner) = runner.upgrade() {
runner.send_proxy_wake_up(local);
}
});
let monitor = MonitorHandler::new( let monitor = MonitorHandler::new(
main_thread, main_thread,
@ -156,7 +153,7 @@ impl Shared {
Execution { Execution {
main_thread, main_thread,
proxy_spawner, event_loop_proxy: Arc::new(proxy_spawner),
control_flow: Cell::new(ControlFlow::default()), control_flow: Cell::new(ControlFlow::default()),
poll_strategy: Cell::new(PollStrategy::default()), poll_strategy: Cell::new(PollStrategy::default()),
wait_until_strategy: Cell::new(WaitUntilStrategy::default()), wait_until_strategy: Cell::new(WaitUntilStrategy::default()),
@ -653,7 +650,7 @@ impl Shared {
// Pre-fetch `UserEvent`s to avoid having to wait until the next event loop cycle. // Pre-fetch `UserEvent`s to avoid having to wait until the next event loop cycle.
events.extend( events.extend(
self.0 self.0
.proxy_spawner .event_loop_proxy
.take() .take()
.then_some(Event::UserWakeUp) .then_some(Event::UserWakeUp)
.map(EventWrapper::from), .map(EventWrapper::from),
@ -818,8 +815,8 @@ impl Shared {
self.0.wait_until_strategy.get() self.0.wait_until_strategy.get()
} }
pub(crate) fn waker(&self) -> Waker<WeakShared> { pub(crate) fn event_loop_proxy(&self) -> &Arc<EventLoopProxy> {
self.0.proxy_spawner.waker() &self.0.event_loop_proxy
} }
pub(crate) fn weak(&self) -> WeakShared { pub(crate) fn weak(&self) -> WeakShared {

View file

@ -2,13 +2,14 @@ use std::cell::Cell;
use std::clone::Clone; use std::clone::Clone;
use std::iter; use std::iter;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
use web_sys::Element; use web_sys::Element;
use super::super::monitor::MonitorPermissionFuture; use super::super::monitor::MonitorPermissionFuture;
use super::super::{lock, KeyEventExtra}; use super::super::{lock, KeyEventExtra};
use super::runner::{EventWrapper, WeakShared}; use super::runner::EventWrapper;
use super::{backend, runner, EventLoopProxy}; use super::{backend, runner};
use crate::error::{NotSupportedError, RequestError}; use crate::error::{NotSupportedError, RequestError};
use crate::event::{ElementState, Event, KeyEvent, TouchPhase, WindowEvent}; use crate::event::{ElementState, Event, KeyEvent, TouchPhase, WindowEvent};
use crate::event_loop::{ use crate::event_loop::{
@ -19,7 +20,7 @@ use crate::keyboard::ModifiersState;
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy}; use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy};
use crate::platform_impl::platform::cursor::CustomCursor; use crate::platform_impl::platform::cursor::CustomCursor;
use crate::platform_impl::platform::r#async::Waker; use crate::platform_impl::web::event_loop::proxy::EventLoopProxy;
use crate::platform_impl::Window; use crate::platform_impl::Window;
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId}; use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId};
@ -476,15 +477,15 @@ impl ActiveEventLoop {
self.runner.monitor().has_detailed_monitor_permission() self.runner.monitor().has_detailed_monitor_permission()
} }
pub(crate) fn waker(&self) -> Waker<WeakShared> { pub(crate) fn event_loop_proxy(&self) -> Arc<EventLoopProxy> {
self.runner.waker() self.runner.event_loop_proxy().clone()
} }
} }
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy { fn create_proxy(&self) -> RootEventLoopProxy {
let event_loop_proxy = EventLoopProxy::new(self.waker()); let event_loop_proxy = self.event_loop_proxy();
RootEventLoopProxy { event_loop_proxy } RootEventLoopProxy::new(event_loop_proxy)
} }
fn create_window( fn create_window(

View file

@ -38,8 +38,7 @@ pub(crate) use cursor::{
}; };
pub(crate) use self::event_loop::{ pub(crate) use self::event_loop::{
ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, ActiveEventLoop, EventLoop, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes,
PlatformSpecificEventLoopAttributes,
}; };
pub(crate) use self::keyboard::KeyEventExtra; pub(crate) use self::keyboard::KeyEventExtra;
pub(crate) use self::monitor::{ pub(crate) use self::monitor::{

View file

@ -69,7 +69,8 @@ use crate::event::{
}; };
use crate::event_loop::{ use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, EventLoopProxy as RootEventLoopProxy, EventLoopProxyProvider,
OwnedDisplayHandle as RootOwnedDisplayHandle,
}; };
use crate::keyboard::ModifiersState; use crate::keyboard::ModifiersState;
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
@ -462,7 +463,7 @@ impl ActiveEventLoop {
impl RootActiveEventLoop for ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy { fn create_proxy(&self) -> RootEventLoopProxy {
let event_loop_proxy = EventLoopProxy { target_window: self.thread_msg_target }; let event_loop_proxy = EventLoopProxy { target_window: self.thread_msg_target };
RootEventLoopProxy { event_loop_proxy } RootEventLoopProxy::new(Arc::new(event_loop_proxy))
} }
fn create_window( fn create_window(
@ -802,15 +803,14 @@ impl EventLoopThreadExecutor {
type ThreadExecFn = Box<Box<dyn FnMut()>>; type ThreadExecFn = Box<Box<dyn FnMut()>>;
#[derive(Clone)]
pub struct EventLoopProxy { pub struct EventLoopProxy {
target_window: HWND, target_window: HWND,
} }
unsafe impl Send for EventLoopProxy {} unsafe impl Send for EventLoopProxy {}
impl EventLoopProxy { impl EventLoopProxyProvider for EventLoopProxy {
pub fn wake_up(&self) { fn wake_up(&self) {
unsafe { PostMessageW(self.target_window, USER_EVENT_MSG_ID.get(), 0, 0) }; unsafe { PostMessageW(self.target_window, USER_EVENT_MSG_ID.get(), 0, 0) };
} }
} }

View file

@ -3,7 +3,7 @@ use windows_sys::Win32::Foundation::HWND;
use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX}; use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX};
pub(crate) use self::event_loop::{ pub(crate) use self::event_loop::{
EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, EventLoop, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes,
}; };
pub use self::icon::WinIcon as PlatformIcon; pub use self::icon::WinIcon as PlatformIcon;
pub(crate) use self::icon::{SelectedCursor, WinCursor as PlatformCustomCursor, WinIcon}; pub(crate) use self::icon::{SelectedCursor, WinCursor as PlatformCustomCursor, WinIcon};