event_loop: remove generic user event

Let the users wake up the event loop and then they could poll their
user sources.

Co-authored-by: Mads Marquart <mads@marquart.dk>
Co-authored-by: daxpedda <daxpedda@gmail.com>
This commit is contained in:
Kirill Chibisov 2024-06-24 13:04:55 +03:00 committed by GitHub
parent 7d1287958f
commit ecb887e5c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 675 additions and 966 deletions

View file

@ -3,7 +3,7 @@ use std::collections::VecDeque;
use std::hash::Hash;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{mpsc, Arc, Mutex};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use android_activity::input::{InputEvent, KeyAction, Keycode, MotionAction};
@ -42,41 +42,6 @@ fn min_timeout(a: Option<Duration>, b: Option<Duration>) -> Option<Duration> {
a.map_or(b, |a_timeout| b.map_or(Some(a_timeout), |b_timeout| Some(a_timeout.min(b_timeout))))
}
struct PeekableReceiver<T> {
recv: mpsc::Receiver<T>,
first: Option<T>,
}
impl<T> PeekableReceiver<T> {
pub fn from_recv(recv: mpsc::Receiver<T>) -> Self {
Self { recv, first: None }
}
pub fn has_incoming(&mut self) -> bool {
if self.first.is_some() {
return true;
}
match self.recv.try_recv() {
Ok(v) => {
self.first = Some(v);
true
},
Err(mpsc::TryRecvError::Empty) => false,
Err(mpsc::TryRecvError::Disconnected) => {
warn!("Channel was disconnected when checking incoming");
false
},
}
}
pub fn try_recv(&mut self) -> Result<T, mpsc::TryRecvError> {
if let Some(first) = self.first.take() {
return Ok(first);
}
self.recv.try_recv()
}
}
#[derive(Clone)]
struct SharedFlagSetter {
flag: Arc<AtomicBool>,
@ -132,13 +97,12 @@ impl RedrawRequester {
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra {}
pub struct EventLoop<T: 'static> {
pub struct EventLoop {
android_app: AndroidApp,
window_target: event_loop::ActiveEventLoop,
redraw_flag: SharedFlag,
user_events_sender: mpsc::Sender<T>,
user_events_receiver: PeekableReceiver<T>, // must wake looper whenever something gets sent
loop_running: bool, // Dispatched `NewEvents<Init>`
proxy_wake_up: Arc<AtomicBool>,
loop_running: bool, // Dispatched `NewEvents<Init>`
running: bool,
pending_redraw: bool,
cause: StartCause,
@ -158,11 +122,11 @@ impl Default for PlatformSpecificEventLoopAttributes {
}
}
impl<T: 'static> EventLoop<T> {
impl EventLoop {
pub(crate) fn new(
attributes: &PlatformSpecificEventLoopAttributes,
) -> Result<Self, EventLoopError> {
let (user_events_sender, user_events_receiver) = mpsc::channel();
let proxy_wake_up = Arc::new(AtomicBool::new(false));
let android_app = attributes.android_app.as_ref().expect(
"An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on \
@ -185,8 +149,7 @@ impl<T: 'static> EventLoop<T> {
_marker: PhantomData,
},
redraw_flag,
user_events_sender,
user_events_receiver: PeekableReceiver::from_recv(user_events_receiver),
proxy_wake_up,
loop_running: false,
running: false,
pending_redraw: false,
@ -196,7 +159,7 @@ impl<T: 'static> EventLoop<T> {
})
}
fn single_iteration<A: ApplicationHandler<T>>(
fn single_iteration<A: ApplicationHandler>(
&mut self,
main_event: Option<MainEvent<'_>>,
app: &mut A,
@ -315,11 +278,8 @@ impl<T: 'static> EventLoop<T> {
},
}
// Empty the user event buffer
{
while let Ok(event) = self.user_events_receiver.try_recv() {
app.user_event(self.window_target(), event);
}
if self.proxy_wake_up.swap(false, Ordering::Relaxed) {
app.proxy_wake_up(self.window_target());
}
if self.running {
@ -351,7 +311,7 @@ impl<T: 'static> EventLoop<T> {
self.pending_redraw = pending_redraw;
}
fn handle_input_event<A: ApplicationHandler<T>>(
fn handle_input_event<A: ApplicationHandler>(
&mut self,
android_app: &AndroidApp,
event: &InputEvent<'_>,
@ -458,11 +418,11 @@ impl<T: 'static> EventLoop<T> {
input_status
}
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
pub fn run_app<A: ApplicationHandler>(mut self, app: &mut A) -> Result<(), EventLoopError> {
self.run_app_on_demand(app)
}
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
pub fn run_app_on_demand<A: ApplicationHandler>(
&mut self,
app: &mut A,
) -> Result<(), EventLoopError> {
@ -481,7 +441,7 @@ impl<T: 'static> EventLoop<T> {
}
}
pub fn pump_app_events<A: ApplicationHandler<T>>(
pub fn pump_app_events<A: ApplicationHandler>(
&mut self,
timeout: Option<Duration>,
app: &mut A,
@ -515,7 +475,7 @@ impl<T: 'static> EventLoop<T> {
}
}
fn poll_events_with_timeout<A: ApplicationHandler<T>>(
fn poll_events_with_timeout<A: ApplicationHandler>(
&mut self,
mut timeout: Option<Duration>,
app: &mut A,
@ -524,22 +484,23 @@ impl<T: 'static> EventLoop<T> {
self.pending_redraw |= self.redraw_flag.get_and_reset();
timeout =
if self.running && (self.pending_redraw || self.user_events_receiver.has_incoming()) {
// If we already have work to do then we don't want to block on the next poll
Some(Duration::ZERO)
} else {
let control_flow_timeout = match self.control_flow() {
ControlFlow::Wait => None,
ControlFlow::Poll => Some(Duration::ZERO),
ControlFlow::WaitUntil(wait_deadline) => {
Some(wait_deadline.saturating_duration_since(start))
},
};
min_timeout(control_flow_timeout, timeout)
timeout = if self.running
&& (self.pending_redraw || self.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)
} else {
let control_flow_timeout = match self.control_flow() {
ControlFlow::Wait => None,
ControlFlow::Poll => Some(Duration::ZERO),
ControlFlow::WaitUntil(wait_deadline) => {
Some(wait_deadline.saturating_duration_since(start))
},
};
min_timeout(control_flow_timeout, timeout)
};
let android_app = self.android_app.clone(); // Don't borrow self as part of poll expression
android_app.poll_events(timeout, |poll_event| {
let mut main_event = None;
@ -556,7 +517,7 @@ impl<T: 'static> EventLoop<T> {
// We also ignore wake ups while suspended.
self.pending_redraw |= self.redraw_flag.get_and_reset();
if !self.running
|| (!self.pending_redraw && !self.user_events_receiver.has_incoming())
|| (!self.pending_redraw && !self.proxy_wake_up.load(Ordering::Relaxed))
{
return;
}
@ -590,9 +551,9 @@ impl<T: 'static> EventLoop<T> {
&self.window_target
}
pub fn create_proxy(&self) -> EventLoopProxy<T> {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy {
user_events_sender: self.user_events_sender.clone(),
proxy_wake_up: self.proxy_wake_up.clone(),
waker: self.android_app.create_waker(),
}
}
@ -606,25 +567,16 @@ impl<T: 'static> EventLoop<T> {
}
}
pub struct EventLoopProxy<T: 'static> {
user_events_sender: mpsc::Sender<T>,
#[derive(Clone)]
pub struct EventLoopProxy {
proxy_wake_up: Arc<AtomicBool>,
waker: AndroidAppWaker,
}
impl<T: 'static> Clone for EventLoopProxy<T> {
fn clone(&self) -> Self {
EventLoopProxy {
user_events_sender: self.user_events_sender.clone(),
waker: self.waker.clone(),
}
}
}
impl<T> EventLoopProxy<T> {
pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed<T>> {
self.user_events_sender.send(event).map_err(|err| event_loop::EventLoopClosed(err.0))?;
impl EventLoopProxy {
pub fn wake_up(&self) {
self.proxy_wake_up.store(true, Ordering::Relaxed);
self.waker.wake();
Ok(())
}
}