use std::time::Duration;
use std::{os::unix::prelude::RawFd, sync::Arc};
use std::hash::Hash;
use std::ops::Deref;
use ndk::asset::AssetManager;
use ndk::configuration::Configuration;
use ndk::looper::FdEvent;
use ndk::native_window::NativeWindow;
#[cfg(not(target_os = "android"))]
compile_error!("android-activity only supports compiling for Android");
#[cfg(all(feature = "game-activity", feature = "native-activity"))]
compile_error!("The \"game-activity\" and \"native-activity\" features cannot be enabled at the same time");
#[cfg(all(not(any(feature = "game-activity", feature = "native-activity")), not(doc)))]
compile_error!("Either \"game-activity\" or \"native-activity\" must be enabled as features");
#[cfg(any(feature="native-activity", doc))]
mod native_activity;
#[cfg(any(feature="native-activity", doc))]
use native_activity as activity_impl;
#[cfg(feature="game-activity")]
mod game_activity;
#[cfg(feature="game-activity")]
use game_activity as activity_impl;
pub use activity_impl::input;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Rect {
pub left: i32,
pub top: i32,
pub right: i32,
pub bottom: i32,
}
pub struct NativeWindowRef {
inner: NativeWindow
}
impl NativeWindowRef {
pub fn new(native_window: &NativeWindow) -> Self {
unsafe { ndk_sys::ANativeWindow_acquire(native_window.ptr().as_ptr()); }
Self { inner: native_window.clone() }
}
}
impl Drop for NativeWindowRef {
fn drop(&mut self) {
unsafe { ndk_sys::ANativeWindow_release(self.inner.ptr().as_ptr()) }
}
}
impl Deref for NativeWindowRef {
type Target = NativeWindow;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
pub type StateSaver<'a> = activity_impl::StateSaver<'a>;
pub type StateLoader<'a> = activity_impl::StateLoader<'a>;
#[non_exhaustive]
#[derive(Debug)]
pub enum MainEvent<'a> {
#[non_exhaustive]
InitWindow { },
#[non_exhaustive]
TerminateWindow {},
#[non_exhaustive]
WindowResized {},
#[non_exhaustive]
RedrawNeeded {},
ContentRectChanged,
GainedFocus,
LostFocus,
ConfigChanged,
LowMemory,
Start,
#[non_exhaustive]
Resume { loader: StateLoader<'a> },
#[non_exhaustive]
SaveState { saver: StateSaver<'a> },
Pause,
Stop,
Destroy,
#[non_exhaustive]
InsetsChanged {},
}
#[derive(Debug)]
#[non_exhaustive]
pub enum PollEvent<'a> {
Wake,
Timeout,
Main(MainEvent<'a>),
#[non_exhaustive]
FdEvent { ident: i32, fd: RawFd, events: FdEvent, data: *mut std::ffi::c_void },
Error
}
use activity_impl::AndroidAppInner;
pub use activity_impl::AndroidAppWaker;
#[derive(Debug, Clone)]
pub struct AndroidApp {
pub(crate) inner: Arc<AndroidAppInner>
}
impl PartialEq for AndroidApp {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl Eq for AndroidApp {}
impl Hash for AndroidApp {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.inner).hash(state);
}
}
impl AndroidApp {
#[cfg_attr(docsrs, doc(cfg(feature = "native-activity")))]
#[cfg(feature = "native-activity")]
pub(crate) fn native_activity(&self) -> *const ndk_sys::ANativeActivity {
self.inner.native_activity()
}
pub fn native_window<'a>(&self) -> Option<NativeWindowRef> {
self.inner.native_window()
}
pub fn poll_events<F>(&self, timeout: Option<Duration>, callback: F)
where F: FnMut(PollEvent)
{
self.inner.poll_events(timeout, callback);
}
pub fn create_waker(&self) -> activity_impl::AndroidAppWaker {
self.inner.create_waker()
}
pub fn config(&self) -> Configuration {
self.inner.config()
}
pub fn content_rect(&self) -> Rect {
self.inner.content_rect()
}
pub fn asset_manager(&self) -> AssetManager {
self.inner.asset_manager()
}
pub fn enable_motion_axis(&self, axis: input::Axis) {
self.inner.enable_motion_axis(axis);
}
pub fn disable_motion_axis(&self, axis: input::Axis) {
self.inner.disable_motion_axis(axis);
}
pub fn input_events<'b, F>(&self, callback: F)
where F: FnMut(&input::InputEvent)
{
self.inner.input_events(callback);
}
pub fn sdk_version() -> i32 {
let mut prop = android_properties::getprop("ro.build.version.sdk");
if let Some(val) = prop.value() {
i32::from_str_radix(&val, 10).expect("Failed to parse ro.build.version.sdk property")
} else {
panic!("Couldn't read ro.build.version.sdk system property");
}
}
pub fn internal_data_path(&self) -> Option<std::path::PathBuf> {
self.inner.internal_data_path()
}
pub fn external_data_path(&self) -> Option<std::path::PathBuf> {
self.inner.external_data_path()
}
pub fn obb_path(&self) -> Option<std::path::PathBuf> {
self.inner.obb_path()
}
}