From bf62103417039827a9541f1c74793bc071295e19 Mon Sep 17 00:00:00 2001 From: Viktor Zoutman Date: Wed, 17 Jun 2020 15:55:52 +0200 Subject: [PATCH] Android run return (#1604) * Initial Draft * Minor clean up * cargo fmt * Removed accidental change * Update CHANGELOG.md Co-authored-by: VZout <=> --- CHANGELOG.md | 1 + src/platform/desktop.rs | 1 + src/platform_impl/android/mod.rs | 135 ++++++++++++++++++++++--------- 3 files changed, 99 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c586be8d..0888252c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/src/platform/desktop.rs b/src/platform/desktop.rs index df801431..abf58b29 100644 --- a/src/platform/desktop.rs +++ b/src/platform/desktop.rs @@ -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" ))] diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index ce26994b..8a5c6940 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -44,6 +44,20 @@ fn poll(poll: Poll) -> Option { pub struct EventLoop { window_target: event_loop::EventLoopWindowTarget, user_queue: Arc>>, + first_event: Option, + 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 EventLoop { @@ -56,42 +70,61 @@ impl EventLoop { _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(self, mut event_handler: F) -> ! + pub fn run(mut self, event_handler: F) -> ! where F: 'static + FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget, &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(&mut self, mut event_handler: F) + where + F: FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget, &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 EventLoop { 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 EventLoop { 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 EventLoop { 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 EventLoop { } 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),