Skip to content

Commit

Permalink
add: ActiveEventLoop::create_proxy()
Browse files Browse the repository at this point in the history
Co-authored-by: Kirill Chibisov <[email protected]>
  • Loading branch information
daxpedda and kchibisov authored Jun 29, 2024
1 parent 2e93e48 commit a0d69c7
Show file tree
Hide file tree
Showing 14 changed files with 78 additions and 71 deletions.
4 changes: 4 additions & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ changelog entry.

## Unreleased

### Added

- Add `ActiveEventLoop::create_proxy()`.

### Changed

- On Web, let events wake up event loop immediately when using `ControlFlow::Poll`.
Expand Down
8 changes: 7 additions & 1 deletion src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl EventLoop {
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
/// to the main event loop, possibly from another thread.
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy { event_loop_proxy: self.event_loop.create_proxy() }
EventLoopProxy { event_loop_proxy: self.event_loop.window_target().p.create_proxy() }
}

/// Gets a persistent reference to the underlying platform display.
Expand Down Expand Up @@ -345,6 +345,12 @@ impl AsRawFd for EventLoop {
}

impl ActiveEventLoop {
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
/// to the main event loop, possibly from another thread.
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy { event_loop_proxy: self.p.create_proxy() }
}

/// Create the window.
///
/// Possible causes of error include denied permission, incompatible system, and lack of memory.
Expand Down
22 changes: 10 additions & 12 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ pub struct EventLoop {
android_app: AndroidApp,
window_target: event_loop::ActiveEventLoop,
redraw_flag: SharedFlag,
proxy_wake_up: Arc<AtomicBool>,
loop_running: bool, // Dispatched `NewEvents<Init>`
running: bool,
pending_redraw: bool,
Expand Down Expand Up @@ -145,11 +144,11 @@ impl EventLoop {
&redraw_flag,
android_app.create_waker(),
),
proxy_wake_up,
},
_marker: PhantomData,
},
redraw_flag,
proxy_wake_up,
loop_running: false,
running: false,
pending_redraw: false,
Expand Down Expand Up @@ -278,7 +277,7 @@ impl EventLoop {
},
}

if self.proxy_wake_up.swap(false, Ordering::Relaxed) {
if self.window_target.p.proxy_wake_up.swap(false, Ordering::Relaxed) {
app.proxy_wake_up(self.window_target());
}

Expand Down Expand Up @@ -485,7 +484,7 @@ impl EventLoop {
self.pending_redraw |= self.redraw_flag.get_and_reset();

timeout = if self.running
&& (self.pending_redraw || self.proxy_wake_up.load(Ordering::Relaxed))
&& (self.pending_redraw || self.window_target.p.proxy_wake_up.load(Ordering::Relaxed))
{
// If we already have work to do then we don't want to block on the next poll
Some(Duration::ZERO)
Expand Down Expand Up @@ -517,7 +516,8 @@ impl EventLoop {
// We also ignore wake ups while suspended.
self.pending_redraw |= self.redraw_flag.get_and_reset();
if !self.running
|| (!self.pending_redraw && !self.proxy_wake_up.load(Ordering::Relaxed))
|| (!self.pending_redraw
&& !self.window_target.p.proxy_wake_up.load(Ordering::Relaxed))
{
return;
}
Expand Down Expand Up @@ -551,13 +551,6 @@ impl EventLoop {
&self.window_target
}

pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy {
proxy_wake_up: self.proxy_wake_up.clone(),
waker: self.android_app.create_waker(),
}
}

fn control_flow(&self) -> ControlFlow {
self.window_target.p.control_flow()
}
Expand Down Expand Up @@ -585,9 +578,14 @@ pub struct ActiveEventLoop {
control_flow: Cell<ControlFlow>,
exit: Cell<bool>,
redraw_requester: RedrawRequester,
proxy_wake_up: Arc<AtomicBool>,
}

impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy { proxy_wake_up: self.proxy_wake_up.clone(), waker: self.app.create_waker() }
}

pub fn primary_monitor(&self) -> Option<MonitorHandle> {
Some(MonitorHandle::new(self.app.clone()))
}
Expand Down
7 changes: 5 additions & 2 deletions src/platform_impl/apple/appkit/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,12 @@ impl ApplicationDelegate {
pub(super) fn new(
mtm: MainThreadMarker,
activation_policy: NSApplicationActivationPolicy,
proxy_wake_up: Arc<AtomicBool>,
default_menu: bool,
activate_ignoring_other_apps: bool,
) -> Retained<Self> {
let this = mtm.alloc().set_ivars(AppState {
activation_policy,
proxy_wake_up,
proxy_wake_up: Arc::new(AtomicBool::new(false)),
default_menu,
activate_ignoring_other_apps,
run_loop: RunLoop::main(mtm),
Expand Down Expand Up @@ -179,6 +178,10 @@ impl ApplicationDelegate {
self.ivars().event_handler.set(handler, closure)
}

pub fn proxy_wake_up(&self) -> Arc<AtomicBool> {
self.ivars().proxy_wake_up.clone()
}

/// If `pump_events` is called to progress the event loop then we
/// bootstrap the event loop via `-[NSApplication run]` but will use
/// `CFRunLoopRunInMode` for subsequent calls to `pump_events`.
Expand Down
14 changes: 4 additions & 10 deletions src/platform_impl/apple/appkit/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ pub struct ActiveEventLoop {
}

impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(self.delegate.proxy_wake_up())
}

pub(super) fn new_root(delegate: Retained<ApplicationDelegate>) -> RootWindowTarget {
let mtm = MainThreadMarker::from(&*delegate);
let p = Self { delegate, mtm };
Expand Down Expand Up @@ -166,8 +170,6 @@ pub struct EventLoop {
/// keep it around here as well.
delegate: Retained<ApplicationDelegate>,

proxy_wake_up: Arc<AtomicBool>,

window_target: RootWindowTarget,
panic_info: Rc<PanicInfo>,
}
Expand Down Expand Up @@ -212,12 +214,9 @@ impl EventLoop {
ActivationPolicy::Prohibited => NSApplicationActivationPolicy::Prohibited,
};

let proxy_wake_up = Arc::new(AtomicBool::new(false));

let delegate = ApplicationDelegate::new(
mtm,
activation_policy,
proxy_wake_up.clone(),
attributes.default_menu,
attributes.activate_ignoring_other_apps,
);
Expand All @@ -236,7 +235,6 @@ impl EventLoop {
p: ActiveEventLoop { delegate, mtm },
_marker: PhantomData,
},
proxy_wake_up,
panic_info,
})
}
Expand Down Expand Up @@ -358,10 +356,6 @@ impl EventLoop {
})
})
}

pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(self.proxy_wake_up.clone())
}
}

#[derive(Clone)]
Expand Down
7 changes: 7 additions & 0 deletions src/platform_impl/apple/uikit/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::cell::{RefCell, RefMut};
use std::collections::HashSet;
use std::os::raw::c_void;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex, OnceLock};
use std::time::Instant;
use std::{fmt, mem, ptr};
Expand Down Expand Up @@ -135,6 +136,7 @@ pub(crate) struct AppState {
app_state: Option<AppStateImpl>,
control_flow: ControlFlow,
waker: EventLoopWaker,
proxy_wake_up: Arc<AtomicBool>,
}

impl AppState {
Expand All @@ -158,6 +160,7 @@ impl AppState {
}),
control_flow: ControlFlow::default(),
waker,
proxy_wake_up: Arc::new(AtomicBool::new(false)),
});
}
init_guard(&mut guard);
Expand Down Expand Up @@ -402,6 +405,10 @@ impl AppState {
}
}

pub(crate) fn proxy_wake_up(&self) -> Arc<AtomicBool> {
self.proxy_wake_up.clone()
}

pub(crate) fn set_control_flow(&mut self, control_flow: ControlFlow) {
self.control_flow = control_flow;
}
Expand Down
14 changes: 5 additions & 9 deletions src/platform_impl/apple/uikit/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ pub struct ActiveEventLoop {
}

impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(AppState::get_mut(self.mtm).proxy_wake_up())
}

pub fn create_custom_cursor(&self, source: CustomCursorSource) -> CustomCursor {
let _ = source.inner;
CustomCursor { inner: super::PlatformCustomCursor }
Expand Down Expand Up @@ -134,7 +138,6 @@ fn map_user_event<A: ApplicationHandler>(

pub struct EventLoop {
mtm: MainThreadMarker,
proxy_wake_up: Arc<AtomicBool>,
window_target: RootActiveEventLoop,
}

Expand All @@ -160,11 +163,8 @@ impl EventLoop {
// this line sets up the main run loop before `UIApplicationMain`
setup_control_flow_observers();

let proxy_wake_up = Arc::new(AtomicBool::new(false));

Ok(EventLoop {
mtm,
proxy_wake_up,
window_target: RootActiveEventLoop { p: ActiveEventLoop { mtm }, _marker: PhantomData },
})
}
Expand All @@ -179,7 +179,7 @@ impl EventLoop {
`EventLoop::run_app` calls `UIApplicationMain` on iOS",
);

let handler = map_user_event(app, self.proxy_wake_up.clone());
let handler = map_user_event(app, AppState::get_mut(self.mtm).proxy_wake_up());

let handler = unsafe {
std::mem::transmute::<
Expand Down Expand Up @@ -212,10 +212,6 @@ impl EventLoop {
unreachable!()
}

pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(self.proxy_wake_up.clone())
}

pub fn window_target(&self) -> &RootActiveEventLoop {
&self.window_target
}
Expand Down
8 changes: 4 additions & 4 deletions src/platform_impl/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,10 +789,6 @@ impl EventLoop {
}
}

pub fn create_proxy(&self) -> EventLoopProxy {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
}

pub fn run_app<A: ApplicationHandler>(self, app: &mut A) -> Result<(), EventLoopError> {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app(app))
}
Expand Down Expand Up @@ -843,6 +839,10 @@ pub enum ActiveEventLoop {
}

impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
}

#[inline]
pub fn is_wayland(&self) -> bool {
match *self {
Expand Down
17 changes: 8 additions & 9 deletions src/platform_impl/linux/wayland/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ pub struct EventLoop {
compositor_updates: Vec<WindowCompositorUpdate>,
window_ids: Vec<WindowId>,

/// Event loop proxy
event_loop_proxy: EventLoopProxy,

/// The Wayland dispatcher to has raw access to the queue when needed, such as
/// when creating a new window.
wayland_dispatcher: WaylandDispatcher,
Expand Down Expand Up @@ -139,6 +136,7 @@ impl EventLoop {
connection: connection.clone(),
wayland_dispatcher: wayland_dispatcher.clone(),
event_loop_awakener,
event_loop_proxy: EventLoopProxy::new(ping),
queue_handle,
control_flow: Cell::new(ControlFlow::default()),
exit: Cell::new(None),
Expand All @@ -152,7 +150,6 @@ impl EventLoop {
window_ids: Vec::new(),
connection,
wayland_dispatcher,
event_loop_proxy: EventLoopProxy::new(ping),
event_loop,
window_target: RootActiveEventLoop {
p: PlatformActiveEventLoop::Wayland(window_target),
Expand Down Expand Up @@ -512,11 +509,6 @@ impl EventLoop {
std::mem::swap(&mut self.window_ids, &mut window_ids);
}

#[inline]
pub fn create_proxy(&self) -> EventLoopProxy {
self.event_loop_proxy.clone()
}

#[inline]
pub fn window_target(&self) -> &RootActiveEventLoop {
&self.window_target
Expand Down Expand Up @@ -589,6 +581,9 @@ impl AsRawFd for EventLoop {
}

pub struct ActiveEventLoop {
/// Event loop proxy
event_loop_proxy: EventLoopProxy,

/// The event loop wakeup source.
pub event_loop_awakener: calloop::ping::Ping,

Expand All @@ -613,6 +608,10 @@ pub struct ActiveEventLoop {
}

impl ActiveEventLoop {
pub(crate) fn create_proxy(&self) -> EventLoopProxy {
self.event_loop_proxy.clone()
}

pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
self.control_flow.set(control_flow)
}
Expand Down
Loading

0 comments on commit a0d69c7

Please sign in to comment.