mirror of
https://github.com/rust-mobile/android-activity.git
synced 2026-07-04 05:47:26 +00:00
Support changing window manager params
This enables support for changing the various WindowManager parameters documented here: https://developer.android.com/reference/android/view/WindowManager.LayoutParams either via NativeActivity_setWindowFlags or GameActivity_setWindowFlags Fixes: #25
This commit is contained in:
@@ -23,7 +23,7 @@ use ndk::asset::AssetManager;
|
||||
use ndk::configuration::Configuration;
|
||||
use ndk::native_window::NativeWindow;
|
||||
|
||||
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect};
|
||||
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect, WindowManagerFlags};
|
||||
|
||||
mod ffi;
|
||||
|
||||
@@ -309,6 +309,17 @@ impl AndroidAppInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_window_flags(
|
||||
&self,
|
||||
add_flags: WindowManagerFlags,
|
||||
remove_flags: WindowManagerFlags,
|
||||
) {
|
||||
unsafe {
|
||||
let activity = (*self.native_app.as_ptr()).activity;
|
||||
ffi::GameActivity_setWindowFlags(activity, add_flags.bits(), remove_flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable_motion_axis(&mut self, axis: Axis) {
|
||||
unsafe { ffi::GameActivityPointerAxes_enableAxis(axis as i32) }
|
||||
}
|
||||
|
||||
+197
-1
@@ -6,6 +6,8 @@ use std::time::Duration;
|
||||
use ndk::asset::AssetManager;
|
||||
use ndk::native_window::NativeWindow;
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
compile_error!("android-activity only supports compiling for Android");
|
||||
|
||||
@@ -170,9 +172,174 @@ pub enum PollEvent<'a> {
|
||||
}
|
||||
|
||||
use activity_impl::AndroidAppInner;
|
||||
|
||||
pub use activity_impl::AndroidAppWaker;
|
||||
|
||||
bitflags! {
|
||||
/// Flags for [`AndroidApp::set_window_flags`]
|
||||
/// as per the [android.view.WindowManager.LayoutParams Java API](https://developer.android.com/reference/android/view/WindowManager.LayoutParams)
|
||||
pub struct WindowManagerFlags: u32 {
|
||||
/// As long as this window is visible to the user, allow the lock
|
||||
/// screen to activate while the screen is on. This can be used
|
||||
/// independently, or in combination with
|
||||
/// [`Self::KEEP_SCREEN_ON`] and/or [`Self::SHOW_WHEN_LOCKED`]
|
||||
const ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001;
|
||||
|
||||
/// Everything behind this window will be dimmed. */
|
||||
const DIM_BEHIND = 0x00000002;
|
||||
|
||||
/// Blur everything behind this window.
|
||||
#[deprecated = "Blurring is no longer supported"]
|
||||
const BLUR_BEHIND = 0x00000004;
|
||||
|
||||
/// This window won't ever get key input focus, so the
|
||||
/// user can not send key or other button events to it. Those will
|
||||
/// instead go to whatever focusable window is behind it. This flag
|
||||
/// will also enable [`Self::NOT_TOUCH_MODAL`] whether or not
|
||||
/// that is explicitly set.
|
||||
///
|
||||
/// Setting this flag also implies that the window will not need to
|
||||
/// interact with
|
||||
/// a soft input method, so it will be Z-ordered and positioned
|
||||
/// independently of any active input method (typically this means it
|
||||
/// gets Z-ordered on top of the input method, so it can use the full
|
||||
/// screen for its content and cover the input method if needed. You
|
||||
/// can use [`Self::ALT_FOCUSABLE_IM`] to modify this
|
||||
/// behavior.
|
||||
const NOT_FOCUSABLE = 0x00000008;
|
||||
|
||||
/// This window can never receive touch events.
|
||||
const NOT_TOUCHABLE = 0x00000010;
|
||||
|
||||
/// Even when this window is focusable (if
|
||||
/// [`Self::NOT_FOCUSABLE`] is not set), allow any pointer
|
||||
/// events outside of the window to be sent to the windows behind it.
|
||||
/// Otherwise it will consume all pointer events itself, regardless of
|
||||
/// whether they are inside of the window.
|
||||
const NOT_TOUCH_MODAL = 0x00000020;
|
||||
|
||||
/// When set, if the device is asleep when the touch
|
||||
/// screen is pressed, you will receive this first touch event. Usually
|
||||
/// the first touch event is consumed by the system since the user can
|
||||
/// not see what they are pressing on.
|
||||
#[deprecated]
|
||||
const TOUCHABLE_WHEN_WAKING = 0x00000040;
|
||||
|
||||
/// As long as this window is visible to the user, keep
|
||||
/// the device's screen turned on and bright.
|
||||
const KEEP_SCREEN_ON = 0x00000080;
|
||||
|
||||
/// Place the window within the entire screen, ignoring
|
||||
/// decorations around the border (such as the status bar). The
|
||||
/// window must correctly position its contents to take the screen
|
||||
/// decoration into account.
|
||||
const LAYOUT_IN_SCREEN = 0x00000100;
|
||||
|
||||
/// Allows the window to extend outside of the screen.
|
||||
const LAYOUT_NO_LIMITS = 0x00000200;
|
||||
|
||||
/// Hide all screen decorations (such as the status
|
||||
/// bar) while this window is displayed. This allows the window to
|
||||
/// use the entire display space for itself -- the status bar will
|
||||
/// be hidden when an app window with this flag set is on the top
|
||||
/// layer. A fullscreen window will ignore a value of
|
||||
/// [`Self::SOFT_INPUT_ADJUST_RESIZE`] the window will stay
|
||||
/// fullscreen and will not resize.
|
||||
const FULLSCREEN = 0x00000400;
|
||||
|
||||
/// Override [`Self::FULLSCREEN`] and force the
|
||||
/// screen decorations (such as the status bar) to be shown.
|
||||
const FORCE_NOT_FULLSCREEN = 0x00000800;
|
||||
/// Turn on dithering when compositing this window to
|
||||
/// the screen.
|
||||
#[deprecated="This flag is no longer used"]
|
||||
const DITHER = 0x00001000;
|
||||
|
||||
/// Treat the content of the window as secure, preventing
|
||||
/// it from appearing in screenshots or from being viewed on non-secure
|
||||
/// displays.
|
||||
const SECURE = 0x00002000;
|
||||
|
||||
/// A special mode where the layout parameters are used
|
||||
/// to perform scaling of the surface when it is composited to the
|
||||
/// screen.
|
||||
const SCALED = 0x00004000;
|
||||
|
||||
/// Intended for windows that will often be used when the user is
|
||||
/// holding the screen against their face, it will aggressively
|
||||
/// filter the event stream to prevent unintended presses in this
|
||||
/// situation that may not be desired for a particular window, when
|
||||
/// such an event stream is detected, the application will receive
|
||||
/// a `AMOTION_EVENT_ACTION_CANCEL` to indicate this so
|
||||
/// applications can handle this accordingly by taking no action on
|
||||
/// the event until the finger is released.
|
||||
const IGNORE_CHEEK_PRESSES = 0x00008000;
|
||||
|
||||
/// A special option only for use in combination with
|
||||
/// [`Self::LAYOUT_IN_SCREEN`]. When requesting layout in
|
||||
/// the screen your window may appear on top of or behind screen decorations
|
||||
/// such as the status bar. By also including this flag, the window
|
||||
/// manager will report the inset rectangle needed to ensure your
|
||||
/// content is not covered by screen decorations.
|
||||
const LAYOUT_INSET_DECOR = 0x00010000;
|
||||
|
||||
/// Invert the state of [`Self::NOT_FOCUSABLE`] with
|
||||
/// respect to how this window interacts with the current method.
|
||||
/// That is, if [`Self::NOT_FOCUSABLE`] is set and this flag is set,
|
||||
/// then the window will behave as if it needs to interact with the
|
||||
/// input method and thus be placed behind/away from it; if
|
||||
/// [`Self::NOT_FOCUSABLE`] is not set and this flag is set,
|
||||
/// then the window will behave as if it doesn't need to interact
|
||||
/// with the input method and can be placed to use more space and
|
||||
/// cover the input method.
|
||||
const ALT_FOCUSABLE_IM = 0x00020000;
|
||||
|
||||
/// If you have set [`Self::NOT_TOUCH_MODAL`], you
|
||||
/// can set this flag to receive a single special MotionEvent with
|
||||
/// the action
|
||||
/// `AMOTION_EVENT_ACTION_OUTSIDE` for
|
||||
/// touches that occur outside of your window. Note that you will not
|
||||
/// receive the full down/move/up gesture, only the location of the
|
||||
/// first down as an `AMOTION_EVENT_ACTION_OUTSIDE`.
|
||||
const WATCH_OUTSIDE_TOUCH = 0x00040000;
|
||||
|
||||
/// Special flag to let windows be shown when the screen
|
||||
/// is locked. This will let application windows take precedence over
|
||||
/// key guard or any other lock screens. Can be used with
|
||||
/// [`Self::KEEP_SCREEN_ON`] to turn screen on and display
|
||||
/// windows directly before showing the key guard window. Can be used with
|
||||
/// [`Self::DISMISS_KEYGUARD`] to automatically fully
|
||||
/// dismiss non-secure key guards. This flag only applies to the top-most
|
||||
/// full-screen window.
|
||||
const SHOW_WHEN_LOCKED = 0x00080000;
|
||||
|
||||
/// Ask that the system wallpaper be shown behind
|
||||
/// your window. The window surface must be translucent to be able
|
||||
/// to actually see the wallpaper behind it; this flag just ensures
|
||||
/// that the wallpaper surface will be there if this window actually
|
||||
/// has translucent regions.
|
||||
const SHOW_WALLPAPER = 0x00100000;
|
||||
|
||||
/// When set as a window is being added or made
|
||||
/// visible, once the window has been shown then the system will
|
||||
/// poke the power manager's user activity (as if the user had woken
|
||||
/// up the device) to turn the screen on.
|
||||
const TURN_SCREEN_ON = 0x00200000;
|
||||
|
||||
/// When set the window will cause the key guard to
|
||||
/// be dismissed, only if it is not a secure lock key guard. Because such
|
||||
/// a key guard is not needed for security, it will never re-appear if
|
||||
/// the user navigates to another window (in contrast to
|
||||
/// [`Self::SHOW_WHEN_LOCKED`], which will only temporarily
|
||||
/// hide both secure and non-secure key guards but ensure they reappear
|
||||
/// when the user moves to another UI that doesn't hide them).
|
||||
/// If the key guard is currently active and is secure (requires an
|
||||
/// unlock pattern) then the user will still need to confirm it before
|
||||
/// seeing this window, unless [`Self::SHOW_WHEN_LOCKED`] has
|
||||
/// also been set.
|
||||
const DISMISS_KEYGUARD = 0x00400000;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AndroidApp {
|
||||
pub(crate) inner: Arc<RwLock<AndroidAppInner>>,
|
||||
@@ -251,6 +418,26 @@ impl AndroidApp {
|
||||
self.inner.read().unwrap().asset_manager()
|
||||
}
|
||||
|
||||
/// Change the window flags of the given activity.
|
||||
///
|
||||
/// Note that some flags must be set before the window decoration is created,
|
||||
/// see
|
||||
/// `<https://developer.android.com/reference/android/view/Window#setFlags(int,%20int)>`.
|
||||
pub fn set_window_flags(
|
||||
&self,
|
||||
add_flags: WindowManagerFlags,
|
||||
remove_flags: WindowManagerFlags,
|
||||
) {
|
||||
self.inner
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_window_flags(add_flags, remove_flags);
|
||||
}
|
||||
|
||||
/// Enable additional input axis
|
||||
///
|
||||
/// To reduce overhead, by default only [`input::Axis::X`] and [`input::Axis::Y`] are enabled
|
||||
/// and other axis should be enabled explicitly.
|
||||
pub fn enable_motion_axis(&self, axis: input::Axis) {
|
||||
self.inner.write().unwrap().enable_motion_axis(axis);
|
||||
}
|
||||
@@ -259,6 +446,15 @@ impl AndroidApp {
|
||||
self.inner.write().unwrap().disable_motion_axis(axis);
|
||||
}
|
||||
|
||||
/// Query and process all out-standing input event
|
||||
///
|
||||
/// Applications are generally either expected to call this in-sync with their rendering or
|
||||
/// in response to a [`MainEvent::InputAvailable`] event being delivered. _Note though that your
|
||||
/// application is will only be delivered a single [`MainEvent::InputAvailable`] event between calls
|
||||
/// to this API._
|
||||
///
|
||||
/// To reduce overhead, by default only [`input::Axis::X`] and [`input::Axis::Y`] are enabled
|
||||
/// and other axis should be enabled explicitly via [`Self::enable_motion_axis`].
|
||||
pub fn input_events<'b, F>(&self, callback: F)
|
||||
where
|
||||
F: FnMut(&input::InputEvent),
|
||||
|
||||
@@ -21,7 +21,7 @@ use ndk::configuration::Configuration;
|
||||
use ndk::input_queue::InputQueue;
|
||||
use ndk::native_window::NativeWindow;
|
||||
|
||||
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect};
|
||||
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect, WindowManagerFlags};
|
||||
|
||||
mod ffi;
|
||||
|
||||
@@ -353,6 +353,22 @@ impl AndroidAppInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_window_flags(
|
||||
&self,
|
||||
add_flags: WindowManagerFlags,
|
||||
remove_flags: WindowManagerFlags,
|
||||
) {
|
||||
let na = self.native_activity();
|
||||
let na_mut = na as *mut ndk_sys::ANativeActivity;
|
||||
unsafe {
|
||||
ffi::ANativeActivity_setWindowFlags(
|
||||
na_mut.cast(),
|
||||
add_flags.bits(),
|
||||
remove_flags.bits(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable_motion_axis(&self, _axis: input::Axis) {
|
||||
// NOP - The InputQueue API doesn't let us optimize which axis values are read
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user