pub mod never_return;
pub mod pump_events;
pub mod register;
pub mod run_on_demand;
use std::any::Any;
use std::fmt::{self, Debug};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle};
use crate::Instant;
use crate::application::ApplicationHandler;
use crate::cursor::{CustomCursor, CustomCursorSource};
use crate::data_transfer::{DataTransfer, DataTransferId, DataTransferSend, TransferType};
use crate::error::{EventLoopError, NotSupportedError, RequestError};
use crate::icon::Icon;
use crate::monitor::MonitorHandle;
use crate::window::{Theme, Window, WindowAttributes, WindowId};
pub trait EventLoopProvider: fmt::Debug {
fn run_app<A: ApplicationHandler + 'static>(self, app: A) -> Result<(), EventLoopError>;
fn create_proxy(&self) -> EventLoopProxy;
fn owned_display_handle(&self) -> OwnedDisplayHandle;
fn listen_device_events(&self, allowed: DeviceEvents);
fn set_control_flow(&self, control_flow: ControlFlow);
fn create_custom_cursor(
&self,
custom_cursor: CustomCursorSource,
) -> Result<CustomCursor, RequestError>;
}
pub trait ActiveEventLoop: Any + fmt::Debug {
fn create_proxy(&self) -> EventLoopProxy;
fn create_window(
&self,
window_attributes: WindowAttributes,
) -> Result<Box<dyn Window>, RequestError>;
fn create_custom_cursor(
&self,
custom_cursor: CustomCursorSource,
) -> Result<CustomCursor, RequestError>;
fn available_monitors(&self) -> Box<dyn Iterator<Item = MonitorHandle>>;
fn primary_monitor(&self) -> Option<MonitorHandle>;
fn listen_device_events(&self, allowed: DeviceEvents);
fn system_theme(&self) -> Option<Theme>;
fn set_control_flow(&self, control_flow: ControlFlow);
fn control_flow(&self) -> ControlFlow;
fn exit(&self);
fn exiting(&self) -> bool;
fn owned_display_handle(&self) -> OwnedDisplayHandle;
fn rwh_06_handle(&self) -> &dyn HasDisplayHandle;
fn fetch_data_transfer(
&self,
id: DataTransferId,
type_: &dyn TransferType,
) -> Result<AsyncRequestSerial, RequestError> {
let _ = id;
let _ = type_;
Err(RequestError::NotSupported(NotSupportedError::new(
DATA_TRANSFER_UNSUPPORTED_ERROR_MESSAGE,
)))
}
fn data_transfer(&self, id: DataTransferId) -> Result<Box<dyn DataTransfer>, RequestError> {
let _ = id;
Err(RequestError::NotSupported(NotSupportedError::new(
DATA_TRANSFER_UNSUPPORTED_ERROR_MESSAGE,
)))
}
fn set_valid_dnd_actions(
&self,
id: DataTransferId,
actions: &[DndAction],
) -> Result<(), RequestError> {
let _ = id;
let _ = actions;
Err(RequestError::NotSupported(NotSupportedError::new(
DATA_TRANSFER_UNSUPPORTED_ERROR_MESSAGE,
)))
}
fn start_drag(
&self,
source: WindowId,
send_data: Box<dyn DataTransferSend>,
actions: &[DndAction],
icon: Option<DragIcon>,
) -> Result<DataTransferId, RequestError> {
let _ = source;
let _ = send_data;
let _ = actions;
let _ = icon;
Err(RequestError::NotSupported(NotSupportedError::new(
DATA_TRANSFER_UNSUPPORTED_ERROR_MESSAGE,
)))
}
}
const DATA_TRANSFER_UNSUPPORTED_ERROR_MESSAGE: &str = {
"Cross-application data transfer (e.g. drag-and-drop, clipboard) is unsupported on this \
platform"
};
impl HasDisplayHandle for dyn ActiveEventLoop + '_ {
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
self.rwh_06_handle().display_handle()
}
}
impl_dyn_casting!(ActiveEventLoop);
pub struct DragIcon {
pub icon: Icon,
pub offset_x: i32,
pub offset_y: i32,
}
impl From<Icon> for DragIcon {
fn from(value: Icon) -> Self {
Self { icon: value, offset_x: 0, offset_y: 0 }
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum DndAction {
Move,
Copy,
Link,
Ask,
Private,
}
#[derive(Clone, Debug)]
pub struct EventLoopProxy {
pub(crate) proxy: Arc<dyn EventLoopProxyProvider>,
}
impl EventLoopProxy {
pub fn wake_up(&self) {
self.proxy.wake_up();
}
pub fn new(proxy: Arc<dyn EventLoopProxyProvider>) -> Self {
Self { proxy }
}
}
pub trait EventLoopProxyProvider: Send + Sync + Debug {
fn wake_up(&self);
}
#[derive(Clone)]
pub struct OwnedDisplayHandle {
pub(crate) handle: Arc<dyn HasDisplayHandle + Send + Sync>,
}
impl OwnedDisplayHandle {
pub fn new(handle: Arc<dyn HasDisplayHandle + Send + Sync>) -> Self {
Self { handle }
}
}
impl HasDisplayHandle for OwnedDisplayHandle {
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
self.handle.display_handle()
}
}
impl fmt::Debug for OwnedDisplayHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OwnedDisplayHandle").finish_non_exhaustive()
}
}
impl PartialEq for OwnedDisplayHandle {
fn eq(&self, other: &Self) -> bool {
match (self.display_handle(), other.display_handle()) {
(Ok(lhs), Ok(rhs)) => lhs == rhs,
_ => false,
}
}
}
impl Eq for OwnedDisplayHandle {}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
#[allow(clippy::exhaustive_enums)]
pub enum ControlFlow {
Poll,
#[default]
Wait,
WaitUntil(Instant),
}
impl ControlFlow {
pub fn wait_duration(timeout: Duration) -> Self {
match Instant::now().checked_add(timeout) {
Some(instant) => Self::WaitUntil(instant),
None => Self::Wait,
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(clippy::exhaustive_enums)]
pub enum DeviceEvents {
Always,
#[default]
WhenFocused,
Never,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AsyncRequestSerial {
serial: usize,
}
impl AsyncRequestSerial {
pub fn get() -> Self {
static CURRENT_SERIAL: AtomicUsize = AtomicUsize::new(0);
let serial = CURRENT_SERIAL.fetch_add(1, Ordering::Relaxed);
Self { serial }
}
}