2024-08-06 21:02:53 +03:00
|
|
|
use std::any::Any;
|
2022-06-08 11:50:26 -07:00
|
|
|
use std::cell::Cell;
|
|
|
|
|
use std::collections::VecDeque;
|
2022-11-10 16:55:19 +00:00
|
|
|
use std::hash::Hash;
|
|
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
2024-06-24 13:04:55 +03:00
|
|
|
use std::sync::{Arc, Mutex};
|
2022-06-08 11:50:26 -07:00
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
|
|
2023-06-21 18:49:44 +01:00
|
|
|
use android_activity::input::{InputEvent, KeyAction, Keycode, MotionAction};
|
2022-11-10 16:55:19 +00:00
|
|
|
use android_activity::{
|
|
|
|
|
AndroidApp, AndroidAppWaker, ConfigurationRef, InputStatus, MainEvent, Rect,
|
2020-05-06 15:27:49 +02:00
|
|
|
};
|
2024-02-25 19:20:39 -08:00
|
|
|
use tracing::{debug, trace, warn};
|
2022-06-08 11:50:26 -07:00
|
|
|
|
2024-05-20 20:27:36 +04:00
|
|
|
use crate::application::ApplicationHandler;
|
2023-12-25 07:20:52 +01:00
|
|
|
use crate::cursor::Cursor;
|
2022-06-08 11:50:26 -07:00
|
|
|
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
2024-08-06 18:57:03 +02:00
|
|
|
use crate::error::{self, EventLoopError, ExternalError, NotSupportedError};
|
2023-09-22 21:44:39 +02:00
|
|
|
use crate::event::{self, Force, InnerSizeWriter, StartCause};
|
2024-08-06 21:02:53 +03:00
|
|
|
use crate::event_loop::{
|
|
|
|
|
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
|
|
|
|
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
|
|
|
|
|
};
|
|
|
|
|
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
2023-06-18 11:10:13 +01:00
|
|
|
use crate::platform::pump_events::PumpStatus;
|
2023-08-13 23:20:09 +04:00
|
|
|
use crate::platform_impl::Fullscreen;
|
2023-01-29 16:46:46 +01:00
|
|
|
use crate::window::{
|
2024-02-03 07:27:17 +04:00
|
|
|
self, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose, ResizeDirection, Theme,
|
2024-08-06 21:02:53 +03:00
|
|
|
Window as RootWindow, WindowAttributes, WindowButtons, WindowLevel,
|
2019-06-21 11:33:15 -04:00
|
|
|
};
|
|
|
|
|
|
2023-06-21 18:49:44 +01:00
|
|
|
mod keycodes;
|
|
|
|
|
|
2024-02-03 07:27:17 +04:00
|
|
|
pub(crate) use crate::cursor::{
|
|
|
|
|
NoCustomCursor as PlatformCustomCursor, NoCustomCursor as PlatformCustomCursorSource,
|
|
|
|
|
};
|
|
|
|
|
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
|
|
|
|
|
2024-02-28 12:28:26 +01:00
|
|
|
static HAS_FOCUS: AtomicBool = AtomicBool::new(true);
|
2023-01-17 03:30:14 +02:00
|
|
|
|
2023-06-18 11:10:13 +01:00
|
|
|
/// Returns the minimum `Option<Duration>`, taking into account that `None`
|
|
|
|
|
/// equates to an infinite timeout, not a zero timeout (so can't just use
|
|
|
|
|
/// `Option::min`)
|
|
|
|
|
fn min_timeout(a: Option<Duration>, b: Option<Duration>) -> Option<Duration> {
|
|
|
|
|
a.map_or(b, |a_timeout| b.map_or(Some(a_timeout), |b_timeout| Some(a_timeout.min(b_timeout))))
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
struct SharedFlagSetter {
|
|
|
|
|
flag: Arc<AtomicBool>,
|
|
|
|
|
}
|
|
|
|
|
impl SharedFlagSetter {
|
|
|
|
|
pub fn set(&self) -> bool {
|
|
|
|
|
self.flag.compare_exchange(false, true, Ordering::AcqRel, Ordering::Relaxed).is_ok()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct SharedFlag {
|
|
|
|
|
flag: Arc<AtomicBool>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Used for queuing redraws from arbitrary threads. We don't care how many
|
|
|
|
|
// times a redraw is requested (so don't actually need to queue any data,
|
|
|
|
|
// 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 {
|
|
|
|
|
Self { flag: Arc::new(AtomicBool::new(false)) }
|
|
|
|
|
}
|
2024-04-26 19:11:44 +04:00
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
pub fn setter(&self) -> SharedFlagSetter {
|
|
|
|
|
SharedFlagSetter { flag: self.flag.clone() }
|
|
|
|
|
}
|
2024-04-26 19:11:44 +04:00
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
pub fn get_and_reset(&self) -> bool {
|
|
|
|
|
self.flag.swap(false, std::sync::atomic::Ordering::AcqRel)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct RedrawRequester {
|
|
|
|
|
flag: SharedFlagSetter,
|
|
|
|
|
waker: AndroidAppWaker,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RedrawRequester {
|
|
|
|
|
fn new(flag: &SharedFlag, waker: AndroidAppWaker) -> Self {
|
|
|
|
|
RedrawRequester { flag: flag.setter(), waker }
|
|
|
|
|
}
|
2024-04-26 19:11:44 +04:00
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
pub fn request_redraw(&self) {
|
|
|
|
|
if self.flag.set() {
|
|
|
|
|
// Only explicitly try to wake up the main loop when the flag
|
|
|
|
|
// value changes
|
|
|
|
|
self.waker.wake();
|
|
|
|
|
}
|
2017-09-04 12:41:02 +02:00
|
|
|
}
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2023-05-28 20:02:59 +02:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
|
|
|
|
pub struct KeyEventExtra {}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
pub struct EventLoop {
|
2024-07-26 21:49:32 +03:00
|
|
|
pub(crate) android_app: AndroidApp,
|
2024-08-06 21:02:53 +03:00
|
|
|
window_target: ActiveEventLoop,
|
2022-11-10 16:55:19 +00:00
|
|
|
redraw_flag: SharedFlag,
|
2024-06-24 13:04:55 +03:00
|
|
|
loop_running: bool, // Dispatched `NewEvents<Init>`
|
2020-06-17 15:55:52 +02:00
|
|
|
running: bool,
|
2023-06-18 11:10:13 +01:00
|
|
|
pending_redraw: bool,
|
|
|
|
|
cause: StartCause,
|
2023-06-06 23:04:51 +02:00
|
|
|
ignore_volume_keys: bool,
|
2023-08-07 23:56:42 +01:00
|
|
|
combining_accent: Option<char>,
|
2020-06-17 15:55:52 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-08 00:46:28 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
2022-11-10 16:55:19 +00:00
|
|
|
pub(crate) struct PlatformSpecificEventLoopAttributes {
|
|
|
|
|
pub(crate) android_app: Option<AndroidApp>,
|
2023-06-06 23:04:51 +02:00
|
|
|
pub(crate) ignore_volume_keys: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for PlatformSpecificEventLoopAttributes {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self { android_app: Default::default(), ignore_volume_keys: true }
|
|
|
|
|
}
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
2022-02-16 22:09:03 +01:00
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl EventLoop {
|
2023-08-13 23:20:09 +04:00
|
|
|
pub(crate) fn new(
|
|
|
|
|
attributes: &PlatformSpecificEventLoopAttributes,
|
|
|
|
|
) -> Result<Self, EventLoopError> {
|
2024-06-24 13:04:55 +03:00
|
|
|
let proxy_wake_up = Arc::new(AtomicBool::new(false));
|
2022-11-10 16:55:19 +00:00
|
|
|
|
|
|
|
|
let android_app = attributes.android_app.as_ref().expect(
|
|
|
|
|
"An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on \
|
|
|
|
|
Android",
|
|
|
|
|
);
|
|
|
|
|
let redraw_flag = SharedFlag::new();
|
|
|
|
|
|
2023-08-13 23:20:09 +04:00
|
|
|
Ok(Self {
|
2022-11-10 16:55:19 +00:00
|
|
|
android_app: android_app.clone(),
|
2024-08-06 21:02:53 +03:00
|
|
|
window_target: ActiveEventLoop {
|
|
|
|
|
app: android_app.clone(),
|
|
|
|
|
control_flow: Cell::new(ControlFlow::default()),
|
|
|
|
|
exit: Cell::new(false),
|
|
|
|
|
redraw_requester: RedrawRequester::new(&redraw_flag, android_app.create_waker()),
|
|
|
|
|
proxy_wake_up,
|
2020-05-06 15:27:49 +02:00
|
|
|
},
|
2022-11-10 16:55:19 +00:00
|
|
|
redraw_flag,
|
2023-06-18 11:10:13 +01:00
|
|
|
loop_running: false,
|
2020-06-17 15:55:52 +02:00
|
|
|
running: false,
|
2023-06-18 11:10:13 +01:00
|
|
|
pending_redraw: false,
|
|
|
|
|
cause: StartCause::Init,
|
2023-06-06 23:04:51 +02:00
|
|
|
ignore_volume_keys: attributes.ignore_volume_keys,
|
2023-08-07 23:56:42 +01:00
|
|
|
combining_accent: None,
|
2023-08-13 23:20:09 +04:00
|
|
|
})
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
pub(crate) fn window_target(&self) -> &dyn RootActiveEventLoop {
|
|
|
|
|
&self.window_target
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
fn single_iteration<A: ApplicationHandler>(
|
2024-05-20 20:27:36 +04:00
|
|
|
&mut self,
|
|
|
|
|
main_event: Option<MainEvent<'_>>,
|
|
|
|
|
app: &mut A,
|
|
|
|
|
) {
|
2022-11-10 16:55:19 +00:00
|
|
|
trace!("Mainloop iteration");
|
|
|
|
|
|
2023-06-18 11:10:13 +01:00
|
|
|
let cause = self.cause;
|
|
|
|
|
let mut pending_redraw = self.pending_redraw;
|
|
|
|
|
let mut resized = false;
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
app.new_events(&self.window_target, cause);
|
2022-11-10 16:55:19 +00:00
|
|
|
|
|
|
|
|
if let Some(event) = main_event {
|
|
|
|
|
trace!("Handling main event {:?}", event);
|
|
|
|
|
|
|
|
|
|
match event {
|
|
|
|
|
MainEvent::InitWindow { .. } => {
|
2024-08-06 21:02:53 +03:00
|
|
|
app.can_create_surfaces(&self.window_target);
|
2022-11-10 16:55:19 +00:00
|
|
|
},
|
|
|
|
|
MainEvent::TerminateWindow { .. } => {
|
2024-08-06 21:02:53 +03:00
|
|
|
app.destroy_surfaces(&self.window_target);
|
2022-11-10 16:55:19 +00:00
|
|
|
},
|
|
|
|
|
MainEvent::WindowResized { .. } => resized = true,
|
2023-06-18 11:10:13 +01:00
|
|
|
MainEvent::RedrawNeeded { .. } => pending_redraw = true,
|
2022-11-10 16:55:19 +00:00
|
|
|
MainEvent::ContentRectChanged { .. } => {
|
|
|
|
|
warn!("TODO: find a way to notify application of content rect change");
|
|
|
|
|
},
|
|
|
|
|
MainEvent::GainedFocus => {
|
2024-02-28 12:28:26 +01:00
|
|
|
HAS_FOCUS.store(true, Ordering::Relaxed);
|
2024-05-20 20:27:36 +04:00
|
|
|
let window_id = window::WindowId(WindowId);
|
|
|
|
|
let event = event::WindowEvent::Focused(true);
|
2024-08-06 21:02:53 +03:00
|
|
|
app.window_event(&self.window_target, window_id, event);
|
2022-11-10 16:55:19 +00:00
|
|
|
},
|
|
|
|
|
MainEvent::LostFocus => {
|
2024-02-28 12:28:26 +01:00
|
|
|
HAS_FOCUS.store(false, Ordering::Relaxed);
|
2024-05-20 20:27:36 +04:00
|
|
|
let window_id = window::WindowId(WindowId);
|
|
|
|
|
let event = event::WindowEvent::Focused(false);
|
2024-08-06 21:02:53 +03:00
|
|
|
app.window_event(&self.window_target, window_id, event);
|
2022-11-10 16:55:19 +00:00
|
|
|
},
|
|
|
|
|
MainEvent::ConfigChanged { .. } => {
|
|
|
|
|
let monitor = MonitorHandle::new(self.android_app.clone());
|
|
|
|
|
let old_scale_factor = monitor.scale_factor();
|
|
|
|
|
let scale_factor = monitor.scale_factor();
|
|
|
|
|
if (scale_factor - old_scale_factor).abs() < f64::EPSILON {
|
2023-07-31 00:39:01 +04:00
|
|
|
let new_inner_size = Arc::new(Mutex::new(
|
|
|
|
|
MonitorHandle::new(self.android_app.clone()).size(),
|
|
|
|
|
));
|
2024-05-20 20:27:36 +04:00
|
|
|
let window_id = window::WindowId(WindowId);
|
|
|
|
|
let event = event::WindowEvent::ScaleFactorChanged {
|
|
|
|
|
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(
|
|
|
|
|
&new_inner_size,
|
|
|
|
|
)),
|
|
|
|
|
scale_factor,
|
2022-11-10 16:55:19 +00:00
|
|
|
};
|
2024-05-20 20:27:36 +04:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
app.window_event(&self.window_target, window_id, event);
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
MainEvent::LowMemory => {
|
2024-08-06 21:02:53 +03:00
|
|
|
app.memory_warning(&self.window_target);
|
2022-11-10 16:55:19 +00:00
|
|
|
},
|
|
|
|
|
MainEvent::Start => {
|
|
|
|
|
// XXX: how to forward this state to applications?
|
|
|
|
|
warn!("TODO: forward onStart notification to application");
|
|
|
|
|
},
|
|
|
|
|
MainEvent::Resume { .. } => {
|
|
|
|
|
debug!("App Resumed - is running");
|
|
|
|
|
self.running = true;
|
|
|
|
|
},
|
|
|
|
|
MainEvent::SaveState { .. } => {
|
|
|
|
|
// XXX: how to forward this state to applications?
|
|
|
|
|
// XXX: also how do we expose state restoration to apps?
|
|
|
|
|
warn!("TODO: forward saveState notification to application");
|
|
|
|
|
},
|
|
|
|
|
MainEvent::Pause => {
|
|
|
|
|
debug!("App Paused - stopped running");
|
|
|
|
|
self.running = false;
|
|
|
|
|
},
|
|
|
|
|
MainEvent::Stop => {
|
|
|
|
|
// XXX: how to forward this state to applications?
|
|
|
|
|
warn!("TODO: forward onStop notification to application");
|
|
|
|
|
},
|
|
|
|
|
MainEvent::Destroy => {
|
|
|
|
|
// XXX: maybe exit mainloop to drop things before being
|
|
|
|
|
// killed by the OS?
|
|
|
|
|
warn!("TODO: forward onDestroy notification to application");
|
|
|
|
|
},
|
|
|
|
|
MainEvent::InsetsChanged { .. } => {
|
|
|
|
|
// XXX: how to forward this state to applications?
|
|
|
|
|
warn!("TODO: handle Android InsetsChanged notification");
|
|
|
|
|
},
|
|
|
|
|
unknown => {
|
|
|
|
|
trace!("Unknown MainEvent {unknown:?} (ignored)");
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
trace!("No main event to handle");
|
|
|
|
|
}
|
2020-06-17 15:55:52 +02:00
|
|
|
|
2023-08-07 23:56:42 +01:00
|
|
|
// temporarily decouple `android_app` from `self` so we aren't holding
|
|
|
|
|
// a borrow of `self` while iterating
|
|
|
|
|
let android_app = self.android_app.clone();
|
2022-11-10 16:55:19 +00:00
|
|
|
|
2023-08-07 23:56:42 +01:00
|
|
|
// Process input events
|
|
|
|
|
match android_app.input_events_iter() {
|
|
|
|
|
Ok(mut input_iter) => loop {
|
2023-09-07 08:25:04 +02:00
|
|
|
let read_event =
|
2024-05-20 20:27:36 +04:00
|
|
|
input_iter.next(|event| self.handle_input_event(&android_app, event, app));
|
2023-08-07 23:56:42 +01:00
|
|
|
|
|
|
|
|
if !read_event {
|
|
|
|
|
break;
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2023-08-07 23:56:42 +01:00
|
|
|
},
|
|
|
|
|
Err(err) => {
|
2024-02-25 19:20:39 -08:00
|
|
|
tracing::warn!("Failed to get input events iterator: {err:?}");
|
2020-05-06 15:27:49 +02:00
|
|
|
},
|
2023-08-07 23:56:42 +01:00
|
|
|
}
|
2022-11-10 16:55:19 +00:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
if self.window_target.proxy_wake_up.swap(false, Ordering::Relaxed) {
|
|
|
|
|
app.proxy_wake_up(&self.window_target);
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
2020-05-06 15:27:49 +02:00
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
if self.running {
|
|
|
|
|
if resized {
|
|
|
|
|
let size = if let Some(native_window) = self.android_app.native_window().as_ref() {
|
|
|
|
|
let width = native_window.width() as _;
|
|
|
|
|
let height = native_window.height() as _;
|
|
|
|
|
PhysicalSize::new(width, height)
|
|
|
|
|
} else {
|
|
|
|
|
PhysicalSize::new(0, 0)
|
|
|
|
|
};
|
2024-05-20 20:27:36 +04:00
|
|
|
let window_id = window::WindowId(WindowId);
|
|
|
|
|
let event = event::WindowEvent::Resized(size);
|
2024-08-06 21:02:53 +03:00
|
|
|
app.window_event(&self.window_target, window_id, event);
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-18 11:10:13 +01:00
|
|
|
pending_redraw |= self.redraw_flag.get_and_reset();
|
|
|
|
|
if pending_redraw {
|
|
|
|
|
pending_redraw = false;
|
2024-05-20 20:27:36 +04:00
|
|
|
let window_id = window::WindowId(WindowId);
|
|
|
|
|
let event = event::WindowEvent::RedrawRequested;
|
2024-08-06 21:02:53 +03:00
|
|
|
app.window_event(&self.window_target, window_id, event);
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
2020-05-06 15:27:49 +02:00
|
|
|
|
2023-07-28 17:37:56 +01:00
|
|
|
// This is always the last event we dispatch before poll again
|
2024-08-06 21:02:53 +03:00
|
|
|
app.about_to_wait(&self.window_target);
|
2023-09-07 08:25:04 +02:00
|
|
|
|
2023-06-18 11:10:13 +01:00
|
|
|
self.pending_redraw = pending_redraw;
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
fn handle_input_event<A: ApplicationHandler>(
|
2023-08-07 23:56:42 +01:00
|
|
|
&mut self,
|
|
|
|
|
android_app: &AndroidApp,
|
|
|
|
|
event: &InputEvent<'_>,
|
2024-05-20 20:27:36 +04:00
|
|
|
app: &mut A,
|
|
|
|
|
) -> InputStatus {
|
2023-08-07 23:56:42 +01:00
|
|
|
let mut input_status = InputStatus::Handled;
|
|
|
|
|
match event {
|
|
|
|
|
InputEvent::MotionEvent(motion_event) => {
|
|
|
|
|
let window_id = window::WindowId(WindowId);
|
2023-10-03 23:23:18 +02:00
|
|
|
let device_id = event::DeviceId(DeviceId(motion_event.device_id()));
|
2023-08-07 23:56:42 +01:00
|
|
|
|
|
|
|
|
let phase = match motion_event.action() {
|
|
|
|
|
MotionAction::Down | MotionAction::PointerDown => {
|
|
|
|
|
Some(event::TouchPhase::Started)
|
|
|
|
|
},
|
|
|
|
|
MotionAction::Up | MotionAction::PointerUp => Some(event::TouchPhase::Ended),
|
|
|
|
|
MotionAction::Move => Some(event::TouchPhase::Moved),
|
|
|
|
|
MotionAction::Cancel => Some(event::TouchPhase::Cancelled),
|
|
|
|
|
_ => {
|
|
|
|
|
None // TODO mouse events
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
if let Some(phase) = phase {
|
|
|
|
|
let pointers: Box<dyn Iterator<Item = android_activity::input::Pointer<'_>>> =
|
|
|
|
|
match phase {
|
|
|
|
|
event::TouchPhase::Started | event::TouchPhase::Ended => {
|
|
|
|
|
Box::new(std::iter::once(
|
|
|
|
|
motion_event.pointer_at_index(motion_event.pointer_index()),
|
|
|
|
|
))
|
|
|
|
|
},
|
|
|
|
|
event::TouchPhase::Moved | event::TouchPhase::Cancelled => {
|
|
|
|
|
Box::new(motion_event.pointers())
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for pointer in pointers {
|
|
|
|
|
let location =
|
|
|
|
|
PhysicalPosition { x: pointer.x() as _, y: pointer.y() as _ };
|
|
|
|
|
trace!(
|
|
|
|
|
"Input event {device_id:?}, {phase:?}, loc={location:?}, \
|
|
|
|
|
pointer={pointer:?}"
|
|
|
|
|
);
|
2024-05-20 20:27:36 +04:00
|
|
|
|
|
|
|
|
let event = event::WindowEvent::Touch(event::Touch {
|
|
|
|
|
device_id,
|
|
|
|
|
phase,
|
|
|
|
|
location,
|
2024-08-08 00:36:36 +02:00
|
|
|
finger_id: event::FingerId(FingerId(pointer.pointer_id())),
|
2024-05-20 20:27:36 +04:00
|
|
|
force: Some(Force::Normalized(pointer.pressure() as f64)),
|
|
|
|
|
});
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
app.window_event(&self.window_target, window_id, event);
|
2023-08-07 23:56:42 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
InputEvent::KeyEvent(key) => {
|
|
|
|
|
match key.key_code() {
|
|
|
|
|
// Flag 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.
|
2024-04-23 19:51:23 +02:00
|
|
|
Keycode::VolumeUp | Keycode::VolumeDown | Keycode::VolumeMute
|
|
|
|
|
if self.ignore_volume_keys =>
|
|
|
|
|
{
|
|
|
|
|
input_status = InputStatus::Unhandled
|
2023-08-07 23:56:42 +01:00
|
|
|
},
|
|
|
|
|
keycode => {
|
|
|
|
|
let state = match key.action() {
|
|
|
|
|
KeyAction::Down => event::ElementState::Pressed,
|
|
|
|
|
KeyAction::Up => event::ElementState::Released,
|
|
|
|
|
_ => event::ElementState::Released,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let key_char = keycodes::character_map_and_combine_key(
|
|
|
|
|
android_app,
|
|
|
|
|
key,
|
|
|
|
|
&mut self.combining_accent,
|
|
|
|
|
);
|
|
|
|
|
|
2024-05-20 20:27:36 +04:00
|
|
|
let window_id = window::WindowId(WindowId);
|
|
|
|
|
let event = event::WindowEvent::KeyboardInput {
|
|
|
|
|
device_id: event::DeviceId(DeviceId(key.device_id())),
|
|
|
|
|
event: event::KeyEvent {
|
|
|
|
|
state,
|
|
|
|
|
physical_key: keycodes::to_physical_key(keycode),
|
|
|
|
|
logical_key: keycodes::to_logical(key_char, keycode),
|
|
|
|
|
location: keycodes::to_location(keycode),
|
|
|
|
|
repeat: key.repeat_count() > 0,
|
|
|
|
|
text: None,
|
|
|
|
|
platform_specific: KeyEventExtra {},
|
2023-08-07 23:56:42 +01:00
|
|
|
},
|
2024-05-20 20:27:36 +04:00
|
|
|
is_synthetic: false,
|
2023-08-07 23:56:42 +01:00
|
|
|
};
|
2024-05-20 20:27:36 +04:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
app.window_event(&self.window_target, window_id, event);
|
2023-08-07 23:56:42 +01:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
_ => {
|
|
|
|
|
warn!("Unknown android_activity input event {event:?}")
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input_status
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 15:38:09 +02:00
|
|
|
pub fn run_app<A: ApplicationHandler>(mut self, app: A) -> Result<(), EventLoopError> {
|
2024-05-20 20:27:36 +04:00
|
|
|
self.run_app_on_demand(app)
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
pub fn run_app_on_demand<A: ApplicationHandler>(
|
2024-05-20 20:27:36 +04:00
|
|
|
&mut self,
|
2024-07-11 15:38:09 +02:00
|
|
|
mut app: A,
|
2024-05-20 20:27:36 +04:00
|
|
|
) -> Result<(), EventLoopError> {
|
2024-08-06 21:02:53 +03:00
|
|
|
self.window_target.clear_exit();
|
2023-06-18 11:10:13 +01:00
|
|
|
loop {
|
2024-07-11 15:38:09 +02:00
|
|
|
match self.pump_app_events(None, &mut app) {
|
2023-06-18 11:10:13 +01:00
|
|
|
PumpStatus::Exit(0) => {
|
|
|
|
|
break Ok(());
|
|
|
|
|
},
|
|
|
|
|
PumpStatus::Exit(code) => {
|
2023-08-13 23:20:09 +04:00
|
|
|
break Err(EventLoopError::ExitFailure(code));
|
2023-06-18 11:10:13 +01:00
|
|
|
},
|
|
|
|
|
_ => {
|
|
|
|
|
continue;
|
|
|
|
|
},
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
2023-06-18 11:10:13 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
pub fn pump_app_events<A: ApplicationHandler>(
|
2024-05-20 20:27:36 +04:00
|
|
|
&mut self,
|
|
|
|
|
timeout: Option<Duration>,
|
2024-07-11 15:38:09 +02:00
|
|
|
mut app: A,
|
2024-05-20 20:27:36 +04:00
|
|
|
) -> PumpStatus {
|
2023-06-18 11:10:13 +01:00
|
|
|
if !self.loop_running {
|
|
|
|
|
self.loop_running = true;
|
|
|
|
|
|
|
|
|
|
// Reset the internal state for the loop as we start running to
|
|
|
|
|
// ensure consistent behaviour in case the loop runs and exits more
|
|
|
|
|
// than once
|
|
|
|
|
self.pending_redraw = false;
|
|
|
|
|
self.cause = StartCause::Init;
|
|
|
|
|
|
|
|
|
|
// run the initial loop iteration
|
2024-07-11 15:38:09 +02:00
|
|
|
self.single_iteration(None, &mut app);
|
2023-06-18 11:10:13 +01:00
|
|
|
}
|
2022-11-10 16:55:19 +00:00
|
|
|
|
2023-06-18 11:10:13 +01:00
|
|
|
// Consider the possibility that the `StartCause::Init` iteration could
|
|
|
|
|
// request to Exit
|
2023-09-07 08:25:04 +02:00
|
|
|
if !self.exiting() {
|
2024-07-11 15:38:09 +02:00
|
|
|
self.poll_events_with_timeout(timeout, &mut app);
|
2023-06-18 11:10:13 +01:00
|
|
|
}
|
2023-09-07 08:25:04 +02:00
|
|
|
if self.exiting() {
|
2023-06-18 11:10:13 +01:00
|
|
|
self.loop_running = false;
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
app.exiting(&self.window_target);
|
2023-06-18 11:10:13 +01:00
|
|
|
|
2023-09-07 08:25:04 +02:00
|
|
|
PumpStatus::Exit(0)
|
2023-06-18 11:10:13 +01:00
|
|
|
} else {
|
|
|
|
|
PumpStatus::Continue
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-10 16:55:19 +00:00
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
fn poll_events_with_timeout<A: ApplicationHandler>(
|
2024-05-20 20:27:36 +04:00
|
|
|
&mut self,
|
|
|
|
|
mut timeout: Option<Duration>,
|
|
|
|
|
app: &mut A,
|
|
|
|
|
) {
|
2023-06-18 11:10:13 +01:00
|
|
|
let start = Instant::now();
|
|
|
|
|
|
|
|
|
|
self.pending_redraw |= self.redraw_flag.get_and_reset();
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
timeout = if self.running
|
2024-08-06 21:02:53 +03:00
|
|
|
&& (self.pending_redraw || self.window_target.proxy_wake_up.load(Ordering::Relaxed))
|
2024-06-24 13:04:55 +03:00
|
|
|
{
|
|
|
|
|
// If we already have work to do then we don't want to block on the next poll
|
|
|
|
|
Some(Duration::ZERO)
|
|
|
|
|
} else {
|
|
|
|
|
let control_flow_timeout = match self.control_flow() {
|
|
|
|
|
ControlFlow::Wait => None,
|
|
|
|
|
ControlFlow::Poll => Some(Duration::ZERO),
|
|
|
|
|
ControlFlow::WaitUntil(wait_deadline) => {
|
|
|
|
|
Some(wait_deadline.saturating_duration_since(start))
|
|
|
|
|
},
|
2023-06-18 11:10:13 +01:00
|
|
|
};
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
min_timeout(control_flow_timeout, timeout)
|
|
|
|
|
};
|
|
|
|
|
|
2024-05-20 20:27:36 +04:00
|
|
|
let android_app = self.android_app.clone(); // Don't borrow self as part of poll expression
|
|
|
|
|
android_app.poll_events(timeout, |poll_event| {
|
2023-06-18 11:10:13 +01:00
|
|
|
let mut main_event = None;
|
|
|
|
|
|
|
|
|
|
match poll_event {
|
|
|
|
|
android_activity::PollEvent::Wake => {
|
|
|
|
|
// In the X11 backend it's noted that too many false-positive wake ups
|
|
|
|
|
// would cause the event loop to run continuously. They handle this by
|
|
|
|
|
// re-checking for pending events (assuming they cover all
|
|
|
|
|
// valid reasons for a wake up).
|
|
|
|
|
//
|
|
|
|
|
// For now, user_events and redraw_requests are the only reasons to expect
|
|
|
|
|
// a wake up here so we can ignore the wake up if there are no events/requests.
|
|
|
|
|
// We also ignore wake ups while suspended.
|
|
|
|
|
self.pending_redraw |= self.redraw_flag.get_and_reset();
|
|
|
|
|
if !self.running
|
2024-06-29 17:19:09 +02:00
|
|
|
|| (!self.pending_redraw
|
2024-08-06 21:02:53 +03:00
|
|
|
&& !self.window_target.proxy_wake_up.load(Ordering::Relaxed))
|
2023-06-18 11:10:13 +01:00
|
|
|
{
|
|
|
|
|
return;
|
2018-02-15 14:09:14 +01:00
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
},
|
2023-06-18 11:10:13 +01:00
|
|
|
android_activity::PollEvent::Timeout => {},
|
|
|
|
|
android_activity::PollEvent::Main(event) => {
|
|
|
|
|
main_event = Some(event);
|
2019-06-24 12:14:55 -04:00
|
|
|
},
|
2023-06-18 11:10:13 +01:00
|
|
|
unknown_event => {
|
|
|
|
|
warn!("Unknown poll event {unknown_event:?} (ignored)");
|
|
|
|
|
},
|
|
|
|
|
}
|
2022-11-10 16:55:19 +00:00
|
|
|
|
2023-09-07 08:25:04 +02:00
|
|
|
self.cause = match self.control_flow() {
|
2023-06-18 11:10:13 +01:00
|
|
|
ControlFlow::Poll => StartCause::Poll,
|
|
|
|
|
ControlFlow::Wait => StartCause::WaitCancelled { start, requested_resume: None },
|
|
|
|
|
ControlFlow::WaitUntil(deadline) => {
|
|
|
|
|
if Instant::now() < deadline {
|
|
|
|
|
StartCause::WaitCancelled { start, requested_resume: Some(deadline) }
|
|
|
|
|
} else {
|
|
|
|
|
StartCause::ResumeTimeReached { start, requested_resume: deadline }
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
};
|
2022-11-10 16:55:19 +00:00
|
|
|
|
2024-05-20 20:27:36 +04:00
|
|
|
self.single_iteration(main_event, app);
|
2023-06-18 11:10:13 +01:00
|
|
|
});
|
2017-09-04 12:41:02 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-07 08:25:04 +02:00
|
|
|
fn control_flow(&self) -> ControlFlow {
|
2024-08-06 21:02:53 +03:00
|
|
|
self.window_target.control_flow()
|
2023-09-07 08:25:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn exiting(&self) -> bool {
|
2024-08-06 21:02:53 +03:00
|
|
|
self.window_target.exiting()
|
2023-09-07 08:25:04 +02:00
|
|
|
}
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct EventLoopProxy {
|
|
|
|
|
proxy_wake_up: Arc<AtomicBool>,
|
2022-11-10 16:55:19 +00:00
|
|
|
waker: AndroidAppWaker,
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl EventLoopProxy {
|
|
|
|
|
pub fn wake_up(&self) {
|
|
|
|
|
self.proxy_wake_up.store(true, Ordering::Relaxed);
|
2022-11-10 16:55:19 +00:00
|
|
|
self.waker.wake();
|
2017-09-04 12:41:02 +02:00
|
|
|
}
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2024-01-31 17:29:59 +04:00
|
|
|
pub struct ActiveEventLoop {
|
2024-07-26 21:49:32 +03:00
|
|
|
pub(crate) app: AndroidApp,
|
2023-09-07 08:25:04 +02:00
|
|
|
control_flow: Cell<ControlFlow>,
|
|
|
|
|
exit: Cell<bool>,
|
2022-11-10 16:55:19 +00:00
|
|
|
redraw_requester: RedrawRequester,
|
2024-06-29 17:19:09 +02:00
|
|
|
proxy_wake_up: Arc<AtomicBool>,
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
|
|
|
|
|
2024-01-31 17:29:59 +04:00
|
|
|
impl ActiveEventLoop {
|
2024-08-06 21:02:53 +03:00
|
|
|
fn clear_exit(&self) {
|
|
|
|
|
self.exit.set(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RootActiveEventLoop for ActiveEventLoop {
|
|
|
|
|
fn create_proxy(&self) -> RootEventLoopProxy {
|
|
|
|
|
let event_loop_proxy = EventLoopProxy {
|
|
|
|
|
proxy_wake_up: self.proxy_wake_up.clone(),
|
|
|
|
|
waker: self.app.create_waker(),
|
|
|
|
|
};
|
|
|
|
|
RootEventLoopProxy { event_loop_proxy }
|
2024-06-29 17:19:09 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn create_window(
|
|
|
|
|
&self,
|
|
|
|
|
window_attributes: WindowAttributes,
|
|
|
|
|
) -> Result<RootWindow, error::OsError> {
|
|
|
|
|
let window = Window::new(self, window_attributes)?;
|
|
|
|
|
Ok(RootWindow { window })
|
2020-07-04 15:46:41 -04:00
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn create_custom_cursor(
|
2024-08-06 18:57:03 +02:00
|
|
|
&self,
|
|
|
|
|
_source: CustomCursorSource,
|
|
|
|
|
) -> Result<CustomCursor, ExternalError> {
|
|
|
|
|
Err(ExternalError::NotSupported(NotSupportedError::new()))
|
2024-02-03 07:27:17 +04:00
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
|
|
|
|
let handle = RootMonitorHandle { inner: MonitorHandle::new(self.app.clone()) };
|
|
|
|
|
Box::new(vec![handle].into_iter())
|
2020-07-04 15:46:41 -04:00
|
|
|
}
|
2022-07-21 22:22:36 +03:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
|
|
|
|
|
Some(RootMonitorHandle { inner: MonitorHandle::new(self.app.clone()) })
|
|
|
|
|
}
|
2023-09-01 23:14:16 +02:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn system_theme(&self) -> Option<Theme> {
|
2024-08-05 20:51:38 +02:00
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn listen_device_events(&self, _allowed: DeviceEvents) {}
|
2023-09-07 08:25:04 +02:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn set_control_flow(&self, control_flow: ControlFlow) {
|
2023-09-07 08:25:04 +02:00
|
|
|
self.control_flow.set(control_flow)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn control_flow(&self) -> ControlFlow {
|
2023-09-07 08:25:04 +02:00
|
|
|
self.control_flow.get()
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn exit(&self) {
|
2023-09-07 08:25:04 +02:00
|
|
|
self.exit.set(true)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn exiting(&self) -> bool {
|
|
|
|
|
self.exit.get()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
|
|
|
|
|
RootOwnedDisplayHandle { platform: OwnedDisplayHandle }
|
2023-12-22 20:00:20 +04:00
|
|
|
}
|
|
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
|
|
|
self
|
2023-09-07 08:25:04 +02:00
|
|
|
}
|
2024-01-15 11:58:11 -08:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
impl rwh_06::HasDisplayHandle for ActiveEventLoop {
|
|
|
|
|
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
|
|
|
|
|
let raw = rwh_06::AndroidDisplayHandle::new();
|
|
|
|
|
Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw.into()) })
|
2024-01-15 11:58:11 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-08 00:46:28 +02:00
|
|
|
#[derive(Clone, PartialEq, Eq)]
|
2024-01-15 11:58:11 -08:00
|
|
|
pub(crate) struct OwnedDisplayHandle;
|
|
|
|
|
|
|
|
|
|
impl OwnedDisplayHandle {
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn raw_display_handle_rwh_06(
|
|
|
|
|
&self,
|
|
|
|
|
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
|
|
|
|
|
Ok(rwh_06::AndroidDisplayHandle::new().into())
|
|
|
|
|
}
|
2020-07-04 15:46:41 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
2022-11-10 16:55:19 +00:00
|
|
|
pub(crate) struct WindowId;
|
2017-09-04 12:41:02 +02:00
|
|
|
|
2018-12-21 09:51:48 -07:00
|
|
|
impl WindowId {
|
2021-08-30 19:40:02 +02:00
|
|
|
pub const fn dummy() -> Self {
|
2018-12-21 09:51:48 -07:00
|
|
|
WindowId
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-02 14:27:19 +03:00
|
|
|
impl From<WindowId> for u64 {
|
|
|
|
|
fn from(_: WindowId) -> Self {
|
|
|
|
|
0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<u64> for WindowId {
|
|
|
|
|
fn from(_: u64) -> Self {
|
|
|
|
|
Self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
2023-10-03 23:23:18 +02:00
|
|
|
pub struct DeviceId(i32);
|
2017-09-04 12:41:02 +02:00
|
|
|
|
2018-12-21 09:51:48 -07:00
|
|
|
impl DeviceId {
|
2021-08-30 19:40:02 +02:00
|
|
|
pub const fn dummy() -> Self {
|
2023-10-03 23:23:18 +02:00
|
|
|
DeviceId(0)
|
2018-12-21 09:51:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-08 00:36:36 +02:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
|
|
|
pub struct FingerId(i32);
|
|
|
|
|
|
|
|
|
|
impl FingerId {
|
|
|
|
|
pub const fn dummy() -> Self {
|
|
|
|
|
FingerId(0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
2024-01-31 17:29:59 +04:00
|
|
|
pub struct PlatformSpecificWindowAttributes;
|
2017-09-04 12:41:02 +02:00
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
pub(crate) struct Window {
|
|
|
|
|
app: AndroidApp,
|
|
|
|
|
redraw_requester: RedrawRequester,
|
|
|
|
|
}
|
2018-06-14 19:42:18 -04:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
impl Window {
|
2024-01-13 21:36:53 +01:00
|
|
|
pub(crate) fn new(
|
2024-01-31 17:29:59 +04:00
|
|
|
el: &ActiveEventLoop,
|
2020-05-06 15:27:49 +02:00
|
|
|
_window_attrs: window::WindowAttributes,
|
|
|
|
|
) -> Result<Self, error::OsError> {
|
|
|
|
|
// FIXME this ignores requested window attributes
|
2022-11-10 16:55:19 +00:00
|
|
|
|
|
|
|
|
Ok(Self { app: el.app.clone(), redraw_requester: el.redraw_requester.clone() })
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
2018-06-14 19:42:18 -04:00
|
|
|
|
2023-08-14 21:19:57 +02:00
|
|
|
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) {
|
|
|
|
|
f(self)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Self) -> R + Send) -> R {
|
|
|
|
|
f(self)
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn id(&self) -> WindowId {
|
|
|
|
|
WindowId
|
2018-06-14 19:42:18 -04:00
|
|
|
}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2022-09-21 10:04:28 +02:00
|
|
|
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
|
2022-11-10 16:55:19 +00:00
|
|
|
Some(MonitorHandle::new(self.app.clone()))
|
2017-09-04 12:41:02 +02:00
|
|
|
}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
|
|
|
|
|
let mut v = VecDeque::with_capacity(1);
|
2022-11-10 16:55:19 +00:00
|
|
|
v.push_back(MonitorHandle::new(self.app.clone()));
|
2020-05-06 15:27:49 +02:00
|
|
|
v
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
2017-09-07 09:33:46 +01:00
|
|
|
|
2022-09-21 10:04:28 +02:00
|
|
|
pub fn current_monitor(&self) -> Option<MonitorHandle> {
|
2022-11-10 16:55:19 +00:00
|
|
|
Some(MonitorHandle::new(self.app.clone()))
|
2017-09-07 09:33:46 +01:00
|
|
|
}
|
2017-10-17 14:56:38 +03:00
|
|
|
|
2020-01-03 14:52:27 -05:00
|
|
|
pub fn scale_factor(&self) -> f64 {
|
2022-11-10 16:55:19 +00:00
|
|
|
MonitorHandle::new(self.app.clone()).scale_factor()
|
2017-10-17 14:56:38 +03:00
|
|
|
}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn request_redraw(&self) {
|
2022-11-10 16:55:19 +00:00
|
|
|
self.redraw_requester.request_redraw()
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-22 08:08:53 +04:00
|
|
|
pub fn pre_present_notify(&self) {}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
|
|
|
|
|
Err(error::NotSupportedError::new())
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
|
|
|
|
|
Err(error::NotSupportedError::new())
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_outer_position(&self, _position: Position) {
|
|
|
|
|
// no effect
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
|
|
|
|
self.outer_size()
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2023-07-10 04:02:26 +00:00
|
|
|
pub fn request_inner_size(&self, _size: Size) -> Option<PhysicalSize<u32>> {
|
|
|
|
|
Some(self.inner_size())
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn outer_size(&self) -> PhysicalSize<u32> {
|
2022-11-10 16:55:19 +00:00
|
|
|
MonitorHandle::new(self.app.clone()).size()
|
2018-04-16 21:40:30 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_min_inner_size(&self, _: Option<Size>) {}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_max_inner_size(&self, _: Option<Size>) {}
|
2018-03-23 05:35:35 -04:00
|
|
|
|
2022-09-03 21:50:22 +03:00
|
|
|
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_resize_increments(&self, _increments: Option<Size>) {}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_title(&self, _title: &str) {}
|
2018-03-23 05:35:35 -04:00
|
|
|
|
2023-01-15 23:39:36 +03:00
|
|
|
pub fn set_transparent(&self, _transparent: bool) {}
|
|
|
|
|
|
2023-10-08 22:53:15 +03:00
|
|
|
pub fn set_blur(&self, _blur: bool) {}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_visible(&self, _visibility: bool) {}
|
2018-06-14 19:42:18 -04:00
|
|
|
|
2022-02-17 20:44:14 +02:00
|
|
|
pub fn is_visible(&self) -> Option<bool> {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_resizable(&self, _resizeable: bool) {}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2022-02-17 17:03:17 +02:00
|
|
|
pub fn is_resizable(&self) -> bool {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-29 12:03:51 +02:00
|
|
|
pub fn set_enabled_buttons(&self, _buttons: WindowButtons) {}
|
|
|
|
|
|
|
|
|
|
pub fn enabled_buttons(&self) -> WindowButtons {
|
|
|
|
|
WindowButtons::all()
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_minimized(&self, _minimized: bool) {}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2023-01-19 23:39:04 +02:00
|
|
|
pub fn is_minimized(&self) -> Option<bool> {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_maximized(&self, _maximized: bool) {}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2021-01-27 20:01:17 +02:00
|
|
|
pub fn is_maximized(&self) -> bool {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-21 10:04:28 +02:00
|
|
|
pub fn set_fullscreen(&self, _monitor: Option<Fullscreen>) {
|
2020-07-26 21:13:17 +00:00
|
|
|
warn!("Cannot set fullscreen on Android");
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2022-09-21 10:04:28 +02:00
|
|
|
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
2020-05-06 15:27:49 +02:00
|
|
|
None
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_decorations(&self, _decorations: bool) {}
|
2018-06-18 12:32:18 -04:00
|
|
|
|
2022-02-17 15:31:13 +02:00
|
|
|
pub fn is_decorated(&self) -> bool {
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-26 03:50:58 +02:00
|
|
|
pub fn set_window_level(&self, _level: WindowLevel) {}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
|
2017-08-28 00:22:26 +01:00
|
|
|
|
2023-06-22 19:12:14 +00:00
|
|
|
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
|
2020-05-06 15:27:49 +02:00
|
|
|
|
2022-05-07 05:29:25 +03:00
|
|
|
pub fn set_ime_allowed(&self, _allowed: bool) {}
|
|
|
|
|
|
2023-01-29 16:46:46 +01:00
|
|
|
pub fn set_ime_purpose(&self, _purpose: ImePurpose) {}
|
|
|
|
|
|
2021-05-19 18:39:53 +02:00
|
|
|
pub fn focus_window(&self) {}
|
|
|
|
|
|
2020-11-27 03:03:08 +01:00
|
|
|
pub fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {}
|
|
|
|
|
|
2023-12-25 07:20:52 +01:00
|
|
|
pub fn set_cursor(&self, _: Cursor) {}
|
2023-12-16 22:02:17 +02:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> {
|
|
|
|
|
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
|
2017-09-07 09:33:46 +01:00
|
|
|
}
|
|
|
|
|
|
2022-06-13 09:43:14 +03:00
|
|
|
pub fn set_cursor_grab(&self, _: CursorGrabMode) -> Result<(), error::ExternalError> {
|
2020-05-06 15:27:49 +02:00
|
|
|
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
|
2019-04-26 03:09:32 +10:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn set_cursor_visible(&self, _: bool) {}
|
|
|
|
|
|
2021-03-07 10:43:23 +01:00
|
|
|
pub fn drag_window(&self) -> Result<(), error::ExternalError> {
|
|
|
|
|
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-11 18:07:09 +01:00
|
|
|
pub fn drag_resize_window(
|
|
|
|
|
&self,
|
|
|
|
|
_direction: ResizeDirection,
|
|
|
|
|
) -> Result<(), error::ExternalError> {
|
|
|
|
|
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-11 01:16:16 +03:30
|
|
|
#[inline]
|
|
|
|
|
pub fn show_window_menu(&self, _position: Position) {}
|
|
|
|
|
|
2022-04-12 19:10:46 +02:00
|
|
|
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), error::ExternalError> {
|
|
|
|
|
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-14 19:07:39 -07:00
|
|
|
#[cfg(feature = "rwh_06")]
|
2023-10-17 02:08:33 +02:00
|
|
|
// Allow the usage of HasRawWindowHandle inside this function
|
|
|
|
|
#[allow(deprecated)]
|
2023-10-14 19:07:39 -07:00
|
|
|
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
|
2023-10-17 02:08:33 +02:00
|
|
|
use rwh_06::HasRawWindowHandle;
|
|
|
|
|
|
2023-10-14 19:07:39 -07:00
|
|
|
if let Some(native_window) = self.app.native_window().as_ref() {
|
2023-10-17 02:08:33 +02:00
|
|
|
native_window.raw_window_handle()
|
2023-10-14 19:07:39 -07:00
|
|
|
} else {
|
2024-02-25 19:20:39 -08:00
|
|
|
tracing::error!(
|
|
|
|
|
"Cannot get the native window, it's null and will always be null before \
|
|
|
|
|
Event::Resumed and after Event::Suspended. Make sure you only call this function \
|
|
|
|
|
between those events."
|
|
|
|
|
);
|
2023-10-14 19:07:39 -07:00
|
|
|
Err(rwh_06::HandleError::Unavailable)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
pub fn raw_display_handle_rwh_06(
|
|
|
|
|
&self,
|
|
|
|
|
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
|
|
|
|
|
Ok(rwh_06::RawDisplayHandle::Android(rwh_06::AndroidDisplayHandle::new()))
|
2022-07-21 22:22:36 +03:00
|
|
|
}
|
|
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
pub fn config(&self) -> ConfigurationRef {
|
|
|
|
|
self.app.config()
|
2017-12-22 07:50:46 -05:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn content_rect(&self) -> Rect {
|
2022-11-10 16:55:19 +00:00
|
|
|
self.app.content_rect()
|
2018-05-20 10:24:05 -04:00
|
|
|
}
|
2022-10-19 03:34:36 +09:00
|
|
|
|
2022-11-29 11:05:51 +02:00
|
|
|
pub fn set_theme(&self, _theme: Option<Theme>) {}
|
|
|
|
|
|
2022-10-19 03:34:36 +09:00
|
|
|
pub fn theme(&self) -> Option<Theme> {
|
|
|
|
|
None
|
|
|
|
|
}
|
2022-11-03 10:11:37 -07:00
|
|
|
|
2023-09-01 23:14:16 +02:00
|
|
|
pub fn set_content_protected(&self, _protected: bool) {}
|
|
|
|
|
|
2023-01-17 03:30:14 +02:00
|
|
|
pub fn has_focus(&self) -> bool {
|
2024-02-28 12:28:26 +01:00
|
|
|
HAS_FOCUS.load(Ordering::Relaxed)
|
2023-01-17 03:30:14 +02:00
|
|
|
}
|
|
|
|
|
|
2022-11-03 10:11:37 -07:00
|
|
|
pub fn title(&self) -> String {
|
|
|
|
|
String::new()
|
|
|
|
|
}
|
2023-05-28 20:02:59 +02:00
|
|
|
|
|
|
|
|
pub fn reset_dead_keys(&self) {}
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
2018-05-20 10:24:05 -04:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
#[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")
|
2018-05-07 17:36:21 -04:00
|
|
|
}
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
2018-05-07 17:36:21 -04:00
|
|
|
|
2022-11-10 16:55:19 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
|
|
|
pub struct MonitorHandle {
|
|
|
|
|
app: AndroidApp,
|
|
|
|
|
}
|
|
|
|
|
impl PartialOrd for MonitorHandle {
|
2023-07-31 00:39:01 +04:00
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
|
|
Some(self.cmp(other))
|
2022-11-10 16:55:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl Ord for MonitorHandle {
|
|
|
|
|
fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
|
|
|
|
|
std::cmp::Ordering::Equal
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-06 15:27:49 +02:00
|
|
|
|
|
|
|
|
impl MonitorHandle {
|
2022-11-10 16:55:19 +00:00
|
|
|
pub(crate) fn new(app: AndroidApp) -> Self {
|
|
|
|
|
Self { app }
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn name(&self) -> Option<String> {
|
|
|
|
|
Some("Android Device".to_owned())
|
2018-05-17 21:28:30 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn size(&self) -> PhysicalSize<u32> {
|
2022-11-10 16:55:19 +00:00
|
|
|
if let Some(native_window) = self.app.native_window() {
|
|
|
|
|
PhysicalSize::new(native_window.width() as _, native_window.height() as _)
|
2020-05-06 15:27:49 +02:00
|
|
|
} else {
|
|
|
|
|
PhysicalSize::new(0, 0)
|
2019-06-21 11:33:15 -04:00
|
|
|
}
|
2017-08-28 00:22:26 +01:00
|
|
|
}
|
2016-10-31 17:08:55 +01:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn position(&self) -> PhysicalPosition<i32> {
|
|
|
|
|
(0, 0).into()
|
2018-06-16 10:14:12 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn scale_factor(&self) -> f64 {
|
|
|
|
|
self.app.config().density().map(|dpi| dpi as f64 / 160.0).unwrap_or(1.0)
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-08 13:25:56 +03:00
|
|
|
pub fn refresh_rate_millihertz(&self) -> Option<u32> {
|
2022-07-15 14:02:12 -02:30
|
|
|
// FIXME no way to get real refresh rate for now.
|
2022-07-08 13:25:56 +03:00
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-26 22:12:33 +01:00
|
|
|
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
|
2020-05-06 15:27:49 +02:00
|
|
|
let size = self.size().into();
|
|
|
|
|
// FIXME this is not the real refresh rate
|
2022-06-10 13:43:33 +03:00
|
|
|
// (it is guaranteed to support 32 bit color though)
|
2023-12-26 22:12:33 +01:00
|
|
|
std::iter::once(VideoModeHandle {
|
2022-09-21 10:04:28 +02:00
|
|
|
size,
|
|
|
|
|
bit_depth: 32,
|
|
|
|
|
refresh_rate_millihertz: 60000,
|
|
|
|
|
monitor: self.clone(),
|
2022-06-10 13:43:33 +03:00
|
|
|
})
|
2018-06-16 10:14:12 -04:00
|
|
|
}
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
2018-06-16 10:14:12 -04:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
2023-12-26 22:12:33 +01:00
|
|
|
pub struct VideoModeHandle {
|
2020-05-06 15:27:49 +02:00
|
|
|
size: (u32, u32),
|
|
|
|
|
bit_depth: u16,
|
2022-07-08 13:25:56 +03:00
|
|
|
refresh_rate_millihertz: u32,
|
2020-05-06 15:27:49 +02:00
|
|
|
monitor: MonitorHandle,
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-26 22:12:33 +01:00
|
|
|
impl VideoModeHandle {
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn size(&self) -> PhysicalSize<u32> {
|
|
|
|
|
self.size.into()
|
2016-10-31 17:08:55 +01:00
|
|
|
}
|
2019-09-30 17:17:01 +02:00
|
|
|
|
2020-05-06 15:27:49 +02:00
|
|
|
pub fn bit_depth(&self) -> u16 {
|
|
|
|
|
self.bit_depth
|
2019-09-30 17:17:01 +02:00
|
|
|
}
|
2017-07-06 23:33:42 +02:00
|
|
|
|
2022-07-08 13:25:56 +03:00
|
|
|
pub fn refresh_rate_millihertz(&self) -> u32 {
|
|
|
|
|
self.refresh_rate_millihertz
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
2017-09-04 12:41:02 +02:00
|
|
|
|
2022-09-21 10:04:28 +02:00
|
|
|
pub fn monitor(&self) -> MonitorHandle {
|
|
|
|
|
self.monitor.clone()
|
2020-05-06 15:27:49 +02:00
|
|
|
}
|
|
|
|
|
}
|