Move Android backend to winit-android (#4250)
This commit is contained in:
parent
04482d5a2e
commit
b1f8d778a1
11 changed files with 102 additions and 76 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
|
@ -1,6 +1,5 @@
|
|||
# Android
|
||||
/src/platform/android.rs @MarijnS95
|
||||
/src/platform_impl/android @MarijnS95
|
||||
/winit-android @MarijnS95
|
||||
|
||||
# Apple (AppKit + UIKit)
|
||||
/src/platform/ios.rs @madsmtm
|
||||
|
|
|
|||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
|
@ -182,6 +182,10 @@ jobs:
|
|||
- name: Test winit core
|
||||
run: cargo test -p winit-core
|
||||
|
||||
- name: Test winit Android
|
||||
if: contains(matrix.platform.target, 'android')
|
||||
run: cargo $CMD test -p winit-android --target=${{ matrix.platform.target }} --features native-activity --no-run
|
||||
|
||||
- name: Test winit Orbital
|
||||
if: contains(matrix.platform.target, 'redox')
|
||||
run: cargo test -p winit-orbital
|
||||
|
|
|
|||
12
Cargo.toml
12
Cargo.toml
|
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members = ["dpi", "winit-core", "winit-orbital"]
|
||||
members = ["dpi", "winit-*"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
|
|
@ -12,6 +12,7 @@ rust-version = "1.80"
|
|||
# Workspace dependencies.
|
||||
# `winit` has no version here to allow using it in dev deps for docs.
|
||||
winit = { path = "." }
|
||||
winit-android = { version = "0.0.0", path = "winit-android" }
|
||||
winit-core = { version = "0.0.0", path = "winit-core" }
|
||||
winit-orbital = { version = "0.0.0", path = "winit-orbital" }
|
||||
|
||||
|
|
@ -149,9 +150,10 @@ targets = [
|
|||
|
||||
# Features are documented in either `lib.rs` or under `winit::platform`.
|
||||
[features]
|
||||
android-game-activity = ["android-activity/game-activity"]
|
||||
android-native-activity = ["android-activity/native-activity"]
|
||||
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
|
||||
|
||||
android-game-activity = ["winit-android/game-activity"]
|
||||
android-native-activity = ["winit-android/native-activity"]
|
||||
mint = ["dpi/mint"]
|
||||
serde = [
|
||||
"dep:serde",
|
||||
|
|
@ -197,10 +199,8 @@ tracing-subscriber = { workspace = true, features = ["env-filter"] }
|
|||
[target.'cfg(not(target_os = "android"))'.dev-dependencies]
|
||||
softbuffer.workspace = true
|
||||
|
||||
# Android
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android-activity.workspace = true
|
||||
ndk.workspace = true
|
||||
winit-android.workspace = true
|
||||
|
||||
# AppKit or UIKit
|
||||
[target.'cfg(target_vendor = "apple")'.dependencies]
|
||||
|
|
|
|||
|
|
@ -328,6 +328,26 @@ impl winit_core::event_loop::run_on_demand::EventLoopExtRunOnDemand for EventLoo
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(android_platform)]
|
||||
impl winit_android::EventLoopExtAndroid for EventLoop {
|
||||
fn android_app(&self) -> &winit_android::activity::AndroidApp {
|
||||
&self.event_loop.android_app
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(android_platform)]
|
||||
impl winit_android::EventLoopBuilderExtAndroid for EventLoopBuilder {
|
||||
fn with_android_app(&mut self, app: winit_android::activity::AndroidApp) -> &mut Self {
|
||||
self.platform_specific.android_app = Some(app);
|
||||
self
|
||||
}
|
||||
|
||||
fn handle_volume_keys(&mut self) -> &mut Self {
|
||||
self.platform_specific.ignore_volume_keys = false;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// ```compile_error
|
||||
/// use winit::event_loop::run_on_demand::EventLoopExtRunOnDemand;
|
||||
/// use winit::event_loop::EventLoop;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
//! Only the modules corresponding to the platform you're compiling to will be available.
|
||||
|
||||
#[cfg(android_platform)]
|
||||
pub mod android;
|
||||
pub use winit_android as android;
|
||||
#[cfg(ios_platform)]
|
||||
pub mod ios;
|
||||
#[cfg(macos_platform)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#[cfg(android_platform)]
|
||||
mod android;
|
||||
pub(crate) use winit_android as platform;
|
||||
#[cfg(target_vendor = "apple")]
|
||||
mod apple;
|
||||
#[cfg(any(x11_platform, wayland_platform))]
|
||||
|
|
@ -11,8 +11,6 @@ mod web;
|
|||
#[cfg(windows_platform)]
|
||||
mod windows;
|
||||
|
||||
#[cfg(android_platform)]
|
||||
use self::android as platform;
|
||||
#[cfg(target_vendor = "apple")]
|
||||
use self::apple as platform;
|
||||
#[cfg(any(x11_platform, wayland_platform))]
|
||||
|
|
|
|||
35
winit-android/Cargo.toml
Normal file
35
winit-android/Cargo.toml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
[package]
|
||||
description = "Winit's Android backend"
|
||||
documentation = "https://docs.rs/winit-android"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
name = "winit-android"
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
|
||||
[features]
|
||||
game-activity = ["android-activity/game-activity"]
|
||||
native-activity = ["android-activity/native-activity"]
|
||||
serde = ["dep:serde", "bitflags/serde", "smol_str/serde", "dpi/serde", "winit-core/serde"]
|
||||
|
||||
[dependencies]
|
||||
bitflags.workspace = true
|
||||
dpi.workspace = true
|
||||
rwh_06.workspace = true
|
||||
serde = { workspace = true, optional = true }
|
||||
smol_str.workspace = true
|
||||
tracing.workspace = true
|
||||
winit-core.workspace = true
|
||||
|
||||
# Platform-specific
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android-activity.workspace = true
|
||||
ndk.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
winit.workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["serde", "native-activity"]
|
||||
targets = ["aarch64-linux-android"]
|
||||
1
winit-android/README.md
Symbolic link
1
winit-android/README.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../README.md
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
|
@ -26,7 +27,7 @@ use winit_core::window::{
|
|||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
mod keycodes;
|
||||
use crate::keycodes;
|
||||
|
||||
static HAS_FOCUS: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
|
|
@ -42,7 +43,7 @@ struct SharedFlagSetter {
|
|||
flag: Arc<AtomicBool>,
|
||||
}
|
||||
impl SharedFlagSetter {
|
||||
pub fn set(&self) -> bool {
|
||||
fn set(&self) -> bool {
|
||||
self.flag.compare_exchange(false, true, Ordering::AcqRel, Ordering::Relaxed).is_ok()
|
||||
}
|
||||
}
|
||||
|
|
@ -57,21 +58,21 @@ struct SharedFlag {
|
|||
// we just need to know at the start of a main loop iteration if a redraw
|
||||
// was queued and be able to read and clear the state atomically)
|
||||
impl SharedFlag {
|
||||
pub fn new() -> Self {
|
||||
fn new() -> Self {
|
||||
Self { flag: Arc::new(AtomicBool::new(false)) }
|
||||
}
|
||||
|
||||
pub fn setter(&self) -> SharedFlagSetter {
|
||||
fn setter(&self) -> SharedFlagSetter {
|
||||
SharedFlagSetter { flag: self.flag.clone() }
|
||||
}
|
||||
|
||||
pub fn get_and_reset(&self) -> bool {
|
||||
fn get_and_reset(&self) -> bool {
|
||||
self.flag.swap(false, std::sync::atomic::Ordering::AcqRel)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RedrawRequester {
|
||||
struct RedrawRequester {
|
||||
flag: SharedFlagSetter,
|
||||
waker: AndroidAppWaker,
|
||||
}
|
||||
|
|
@ -87,7 +88,7 @@ impl RedrawRequester {
|
|||
RedrawRequester { flag: flag.setter(), waker }
|
||||
}
|
||||
|
||||
pub fn request_redraw(&self) {
|
||||
fn request_redraw(&self) {
|
||||
if self.flag.set() {
|
||||
// Only explicitly try to wake up the main loop when the flag
|
||||
// value changes
|
||||
|
|
@ -98,7 +99,7 @@ impl RedrawRequester {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct EventLoop {
|
||||
pub(crate) android_app: AndroidApp,
|
||||
pub android_app: AndroidApp,
|
||||
window_target: ActiveEventLoop,
|
||||
redraw_flag: SharedFlag,
|
||||
loop_running: bool, // Dispatched `NewEvents<Init>`
|
||||
|
|
@ -111,9 +112,9 @@ pub struct EventLoop {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct PlatformSpecificEventLoopAttributes {
|
||||
pub(crate) android_app: Option<AndroidApp>,
|
||||
pub(crate) ignore_volume_keys: bool,
|
||||
pub struct PlatformSpecificEventLoopAttributes {
|
||||
pub android_app: Option<AndroidApp>,
|
||||
pub ignore_volume_keys: bool,
|
||||
}
|
||||
|
||||
impl Default for PlatformSpecificEventLoopAttributes {
|
||||
|
|
@ -126,9 +127,7 @@ impl Default for PlatformSpecificEventLoopAttributes {
|
|||
const GLOBAL_WINDOW: WindowId = WindowId::from_raw(0);
|
||||
|
||||
impl EventLoop {
|
||||
pub(crate) fn new(
|
||||
attributes: &PlatformSpecificEventLoopAttributes,
|
||||
) -> Result<Self, EventLoopError> {
|
||||
pub fn new(attributes: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
|
||||
let android_app = attributes.android_app.as_ref().expect(
|
||||
"An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on \
|
||||
Android",
|
||||
|
|
@ -158,7 +157,7 @@ impl EventLoop {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn window_target(&self) -> &dyn RootActiveEventLoop {
|
||||
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
|
||||
&self.window_target
|
||||
}
|
||||
|
||||
|
|
@ -751,7 +750,7 @@ impl rwh_06::HasDisplayHandle for OwnedDisplayHandle {
|
|||
pub struct PlatformSpecificWindowAttributes;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Window {
|
||||
pub struct Window {
|
||||
app: AndroidApp,
|
||||
redraw_requester: RedrawRequester,
|
||||
}
|
||||
|
|
@ -766,11 +765,11 @@ impl Window {
|
|||
Ok(Self { app: el.app.clone(), redraw_requester: el.redraw_requester.clone() })
|
||||
}
|
||||
|
||||
pub fn config(&self) -> ConfigurationRef {
|
||||
pub(crate) fn config(&self) -> ConfigurationRef {
|
||||
self.app.config()
|
||||
}
|
||||
|
||||
pub fn content_rect(&self) -> Rect {
|
||||
pub(crate) fn content_rect(&self) -> Rect {
|
||||
self.app.content_rect()
|
||||
}
|
||||
|
||||
|
|
@ -999,16 +998,6 @@ impl CoreWindow for Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct OsError;
|
||||
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
impl Display for OsError {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(fmt, "Android OS Error")
|
||||
}
|
||||
}
|
||||
|
||||
fn screen_size(app: &AndroidApp) -> PhysicalSize<u32> {
|
||||
if let Some(native_window) = app.native_window() {
|
||||
PhysicalSize::new(native_window.width() as _, native_window.height() as _)
|
||||
|
|
@ -69,10 +69,19 @@
|
|||
//! logging as above).
|
||||
//! 4. Pass a clone of the `AndroidApp` that your application receives to Winit when building your
|
||||
//! event loop (as shown above).
|
||||
#![cfg(target_os = "android")]
|
||||
|
||||
mod event_loop;
|
||||
mod keycodes;
|
||||
|
||||
use winit_core::event_loop::ActiveEventLoop as CoreActiveEventLoop;
|
||||
use winit_core::window::Window as CoreWindow;
|
||||
|
||||
use self::activity::{AndroidApp, ConfigurationRef, Rect};
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
|
||||
use crate::window::Window;
|
||||
pub use crate::event_loop::{
|
||||
ActiveEventLoop, EventLoop, EventLoopProxy, PlatformSpecificEventLoopAttributes,
|
||||
PlatformSpecificWindowAttributes, Window,
|
||||
};
|
||||
|
||||
/// Additional methods on [`EventLoop`] that are specific to Android.
|
||||
pub trait EventLoopExtAndroid {
|
||||
|
|
@ -80,12 +89,6 @@ pub trait EventLoopExtAndroid {
|
|||
fn android_app(&self) -> &AndroidApp;
|
||||
}
|
||||
|
||||
impl EventLoopExtAndroid for EventLoop {
|
||||
fn android_app(&self) -> &AndroidApp {
|
||||
&self.event_loop.android_app
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional methods on [`ActiveEventLoop`] that are specific to Android.
|
||||
pub trait ActiveEventLoopExtAndroid {
|
||||
/// Get the [`AndroidApp`] which was used to create this event loop.
|
||||
|
|
@ -99,21 +102,21 @@ pub trait WindowExtAndroid {
|
|||
fn config(&self) -> ConfigurationRef;
|
||||
}
|
||||
|
||||
impl WindowExtAndroid for dyn Window + '_ {
|
||||
impl WindowExtAndroid for dyn CoreWindow + '_ {
|
||||
fn content_rect(&self) -> Rect {
|
||||
let window = self.cast_ref::<crate::platform_impl::Window>().unwrap();
|
||||
let window = self.cast_ref::<Window>().unwrap();
|
||||
window.content_rect()
|
||||
}
|
||||
|
||||
fn config(&self) -> ConfigurationRef {
|
||||
let window = self.cast_ref::<crate::platform_impl::Window>().unwrap();
|
||||
let window = self.cast_ref::<Window>().unwrap();
|
||||
window.config()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveEventLoopExtAndroid for dyn ActiveEventLoop + '_ {
|
||||
impl ActiveEventLoopExtAndroid for dyn CoreActiveEventLoop + '_ {
|
||||
fn android_app(&self) -> &AndroidApp {
|
||||
let event_loop = self.cast_ref::<crate::platform_impl::ActiveEventLoop>().unwrap();
|
||||
let event_loop = self.cast_ref::<ActiveEventLoop>().unwrap();
|
||||
&event_loop.app
|
||||
}
|
||||
}
|
||||
|
|
@ -130,18 +133,6 @@ pub trait EventLoopBuilderExtAndroid {
|
|||
fn handle_volume_keys(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl EventLoopBuilderExtAndroid for EventLoopBuilder {
|
||||
fn with_android_app(&mut self, app: AndroidApp) -> &mut Self {
|
||||
self.platform_specific.android_app = Some(app);
|
||||
self
|
||||
}
|
||||
|
||||
fn handle_volume_keys(&mut self) -> &mut Self {
|
||||
self.platform_specific.ignore_volume_keys = false;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-export of the `android_activity` API
|
||||
///
|
||||
/// Winit re-exports the `android_activity` API for convenience so that most
|
||||
|
|
@ -170,16 +161,5 @@ pub mod activity {
|
|||
// feature enabled, so we avoid inlining it so that they're forced to view
|
||||
// it on the crate's own docs.rs page.
|
||||
#[doc(no_inline)]
|
||||
#[cfg(android_platform)]
|
||||
pub use android_activity::*;
|
||||
|
||||
#[cfg(not(android_platform))]
|
||||
#[doc(hidden)]
|
||||
pub struct Rect;
|
||||
#[cfg(not(android_platform))]
|
||||
#[doc(hidden)]
|
||||
pub struct ConfigurationRef;
|
||||
#[cfg(not(android_platform))]
|
||||
#[doc(hidden)]
|
||||
pub struct AndroidApp;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue