On Android, change default implementation to ignore volume keys and let operating system handle them (#2748)

This commit is contained in:
Robin Thunström 2023-06-06 23:04:51 +02:00 committed by GitHub
parent ab46aa5b79
commit 4a36741f9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 57 deletions

View file

@ -8,6 +8,8 @@ And please only add new entries to the top of this list, right below the `# Unre
# Unreleased # Unreleased
- On Android, changed default behavior of Android to ignore volume keys letting the operating system handle them.
- On Android, added `EventLoopBuilderExtAndroid::handle_volume_keys` to indicate that the application will handle the volume keys manually.
- **Breaking:** Rename `DeviceEventFilter` to `DeviceEvents` reversing the behavior of variants. - **Breaking:** Rename `DeviceEventFilter` to `DeviceEvents` reversing the behavior of variants.
- **Breaking:** Rename `EventLoopWindowTarget::set_device_event_filter` to `listen_device_events`. - **Breaking:** Rename `EventLoopWindowTarget::set_device_event_filter` to `listen_device_events`.
- On X11, fix `EventLoopWindowTarget::listen_device_events` effect being reversed. - On X11, fix `EventLoopWindowTarget::listen_device_events` effect being reversed.

View file

@ -42,6 +42,11 @@ pub trait EventLoopBuilderExtAndroid {
/// ///
/// This must be called on Android since the `AndroidApp` is not global state. /// This must be called on Android since the `AndroidApp` is not global state.
fn with_android_app(&mut self, app: AndroidApp) -> &mut Self; fn with_android_app(&mut self, app: AndroidApp) -> &mut Self;
/// Calling this will mark the volume keys to be manually handled by the application
///
/// Default is to let the operating system handle the volume keys
fn handle_volume_keys(&mut self) -> &mut Self;
} }
impl<T> EventLoopBuilderExtAndroid for EventLoopBuilder<T> { impl<T> EventLoopBuilderExtAndroid for EventLoopBuilder<T> {
@ -49,6 +54,11 @@ impl<T> EventLoopBuilderExtAndroid for EventLoopBuilder<T> {
self.platform_specific.android_app = Some(app); self.platform_specific.android_app = Some(app);
self self
} }
fn handle_volume_keys(&mut self) -> &mut Self {
self.platform_specific.ignore_volume_keys = false;
self
}
} }
/// Re-export of the `android_activity` API /// Re-export of the `android_activity` API

View file

@ -138,11 +138,22 @@ pub struct EventLoop<T: 'static> {
user_events_sender: mpsc::Sender<T>, user_events_sender: mpsc::Sender<T>,
user_events_receiver: PeekableReceiver<T>, //must wake looper whenever something gets sent user_events_receiver: PeekableReceiver<T>, //must wake looper whenever something gets sent
running: bool, running: bool,
ignore_volume_keys: bool,
} }
#[derive(Default, Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub(crate) struct PlatformSpecificEventLoopAttributes { pub(crate) struct PlatformSpecificEventLoopAttributes {
pub(crate) android_app: Option<AndroidApp>, pub(crate) android_app: Option<AndroidApp>,
pub(crate) ignore_volume_keys: bool,
}
impl Default for PlatformSpecificEventLoopAttributes {
fn default() -> Self {
Self {
android_app: Default::default(),
ignore_volume_keys: true,
}
}
} }
fn sticky_exit_callback<T, F>( fn sticky_exit_callback<T, F>(
@ -192,6 +203,7 @@ impl<T: 'static> EventLoop<T> {
user_events_sender, user_events_sender,
user_events_receiver: PeekableReceiver::from_recv(user_events_receiver), user_events_receiver: PeekableReceiver::from_recv(user_events_receiver),
running: false, running: false,
ignore_volume_keys: attributes.ignore_volume_keys,
} }
} }
@ -327,8 +339,8 @@ impl<T: 'static> EventLoop<T> {
} }
// Process input events // Process input events
self.android_app.input_events(|event| { self.android_app.input_events(|event| {
let mut input_status = InputStatus::Handled;
match event { match event {
InputEvent::MotionEvent(motion_event) => { InputEvent::MotionEvent(motion_event) => {
let window_id = window::WindowId(WindowId); let window_id = window::WindowId(WindowId);
@ -395,6 +407,18 @@ impl<T: 'static> EventLoop<T> {
} }
} }
InputEvent::KeyEvent(key) => { InputEvent::KeyEvent(key) => {
match key.key_code() {
// Flagg keys related to volume as unhandled. While winit does not have a way for applications
// to configure what keys to flag as handled, this appears to be a good default until winit
// can be configured.
ndk::event::Keycode::VolumeUp |
ndk::event::Keycode::VolumeDown |
ndk::event::Keycode::VolumeMute => {
if self.ignore_volume_keys {
input_status = InputStatus::Unhandled
}
},
_ => {
let state = match key.action() { let state = match key.action() {
KeyAction::Down => event::ElementState::Pressed, KeyAction::Down => event::ElementState::Pressed,
KeyAction::Up => event::ElementState::Released, KeyAction::Up => event::ElementState::Released,
@ -448,14 +472,13 @@ impl<T: 'static> EventLoop<T> {
callback, callback,
); );
} }
}
}
_ => { _ => {
warn!("Unknown android_activity input event {event:?}") warn!("Unknown android_activity input event {event:?}")
} }
} }
input_status
// Assume all events are handled, while Winit doesn't currently give a way for
// applications to report whether they handled an input event.
InputStatus::Handled
}); });
// Empty the user event buffer // Empty the user event buffer