Android run return (#1604)

* Initial Draft

* Minor clean up

* cargo fmt

* Removed accidental change

* Update CHANGELOG.md

Co-authored-by: VZout <=>
This commit is contained in:
Viktor Zoutman 2020-06-17 15:55:52 +02:00 committed by GitHub
parent 4b1b314ce2
commit bf62103417
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 99 additions and 38 deletions

View file

@ -5,6 +5,7 @@
- On Wayland, fix deadlock when calling to `set_inner_size` from a callback.
- On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`.
- On android added support for `run_return`.
- On MacOS, Fixed fullscreen and dialog support for `run_return`.
# 0.22.2 (2020-05-16)

View file

@ -1,6 +1,7 @@
#![cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "android",
target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"
))]

View file

@ -44,6 +44,20 @@ fn poll(poll: Poll) -> Option<EventSource> {
pub struct EventLoop<T: 'static> {
window_target: event_loop::EventLoopWindowTarget<T>,
user_queue: Arc<Mutex<VecDeque<T>>>,
first_event: Option<EventSource>,
start_cause: event::StartCause,
looper: ThreadLooper,
running: bool,
}
macro_rules! call_event_handler {
( $event_handler:expr, $window_target:expr, $cf:expr, $event:expr ) => {{
if $cf != ControlFlow::Exit {
$event_handler($event, $window_target, &mut $cf);
} else {
$event_handler($event, $window_target, &mut ControlFlow::Exit);
}
}};
}
impl<T: 'static> EventLoop<T> {
@ -56,42 +70,61 @@ impl<T: 'static> EventLoop<T> {
_marker: std::marker::PhantomData,
},
user_queue: Default::default(),
first_event: None,
start_cause: event::StartCause::Init,
looper: ThreadLooper::for_thread().unwrap(),
running: false,
}
}
pub fn run<F>(self, mut event_handler: F) -> !
pub fn run<F>(mut self, event_handler: F) -> !
where
F: 'static
+ FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
{
let mut cf = ControlFlow::default();
let mut first_event = None;
let mut start_cause = event::StartCause::Init;
let looper = ThreadLooper::for_thread().unwrap();
let mut running = false;
self.run_return(event_handler);
::std::process::exit(0);
}
loop {
event_handler(
event::Event::NewEvents(start_cause),
pub fn run_return<F>(&mut self, mut event_handler: F)
where
F: FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
{
let mut control_flow = ControlFlow::default();
'event_loop: loop {
call_event_handler!(
event_handler,
self.window_target(),
&mut cf,
control_flow,
event::Event::NewEvents(self.start_cause)
);
let mut redraw = false;
let mut resized = false;
match first_event.take() {
match self.first_event.take() {
Some(EventSource::Callback) => match ndk_glue::poll_events().unwrap() {
Event::WindowCreated => {
event_handler(event::Event::Resumed, self.window_target(), &mut cf);
call_event_handler!(
event_handler,
self.window_target(),
control_flow,
event::Event::Resumed
);
}
Event::WindowResized => resized = true,
Event::WindowRedrawNeeded => redraw = true,
Event::WindowDestroyed => {
event_handler(event::Event::Suspended, self.window_target(), &mut cf);
call_event_handler!(
event_handler,
self.window_target(),
control_flow,
event::Event::Suspended
);
}
Event::Pause => running = false,
Event::Resume => running = true,
Event::Pause => self.running = false,
Event::Resume => self.running = true,
Event::ConfigChanged => {
let am = ndk_glue::native_activity().asset_manager();
let config = Configuration::from_asset_manager(&am);
@ -107,7 +140,12 @@ impl<T: 'static> EventLoop<T> {
scale_factor,
},
};
event_handler(event, self.window_target(), &mut cf);
call_event_handler!(
event_handler,
self.window_target(),
control_flow,
event
);
}
}
_ => {}
@ -147,7 +185,12 @@ impl<T: 'static> EventLoop<T> {
force: None,
}),
};
event_handler(event, self.window_target(), &mut cf);
call_event_handler!(
event_handler,
self.window_target(),
control_flow,
event
);
}
}
InputEvent::KeyEvent(_) => {} // TODO
@ -160,50 +203,66 @@ impl<T: 'static> EventLoop<T> {
Some(EventSource::User) => {
let mut user_queue = self.user_queue.lock().unwrap();
while let Some(event) = user_queue.pop_front() {
event_handler(
event::Event::UserEvent(event),
call_event_handler!(
event_handler,
self.window_target(),
&mut cf,
control_flow,
event::Event::UserEvent(event)
);
}
}
None => {}
None => {
control_flow = ControlFlow::Exit;
}
}
event_handler(
event::Event::MainEventsCleared,
call_event_handler!(
event_handler,
self.window_target(),
&mut cf,
control_flow,
event::Event::MainEventsCleared
);
if resized && running {
if resized && self.running {
let size = MonitorHandle.size();
let event = event::Event::WindowEvent {
window_id: window::WindowId(WindowId),
event: event::WindowEvent::Resized(size),
};
event_handler(event, self.window_target(), &mut cf);
call_event_handler!(event_handler, self.window_target(), control_flow, event);
}
if redraw && running {
if redraw && self.running {
let event = event::Event::RedrawRequested(window::WindowId(WindowId));
event_handler(event, self.window_target(), &mut cf);
call_event_handler!(event_handler, self.window_target(), control_flow, event);
}
event_handler(
event::Event::RedrawEventsCleared,
call_event_handler!(
event_handler,
self.window_target(),
&mut cf,
control_flow,
event::Event::RedrawEventsCleared
);
match cf {
ControlFlow::Exit => panic!(),
match control_flow {
ControlFlow::Exit => {
self.first_event = poll(
self.looper
.poll_once_timeout(Duration::from_millis(0))
.unwrap(),
);
self.start_cause = event::StartCause::WaitCancelled {
start: Instant::now(),
requested_resume: None,
};
break 'event_loop;
}
ControlFlow::Poll => {
start_cause = event::StartCause::Poll;
self.start_cause = event::StartCause::Poll;
}
ControlFlow::Wait => {
first_event = poll(looper.poll_all().unwrap());
start_cause = event::StartCause::WaitCancelled {
self.first_event = poll(self.looper.poll_all().unwrap());
self.start_cause = event::StartCause::WaitCancelled {
start: Instant::now(),
requested_resume: None,
}
@ -215,8 +274,8 @@ impl<T: 'static> EventLoop<T> {
} else {
instant - start
};
first_event = poll(looper.poll_all_timeout(duration).unwrap());
start_cause = if first_event.is_some() {
self.first_event = poll(self.looper.poll_all_timeout(duration).unwrap());
self.start_cause = if self.first_event.is_some() {
event::StartCause::WaitCancelled {
start,
requested_resume: Some(instant),