api: refactor ActiveEventLoop into trait

This should help with further extensions because the backend event
loops are used directly now.
This commit is contained in:
Kirill Chibisov 2024-08-06 21:02:53 +03:00 committed by GitHub
parent f5304815a1
commit f07153b8e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1058 additions and 1071 deletions

View file

@ -20,7 +20,7 @@ fn main() -> Result<(), impl std::error::Error> {
}
impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let attributes = Window::default_attributes()
.with_title("parent window")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
@ -35,7 +35,7 @@ fn main() -> Result<(), impl std::error::Error> {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: winit::window::WindowId,
event: WindowEvent,
) {
@ -72,7 +72,7 @@ fn main() -> Result<(), impl std::error::Error> {
}
}
fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window {
fn spawn_child_window(parent: &Window, event_loop: &dyn ActiveEventLoop) -> Window {
let parent = parent.raw_window_handle().unwrap();
let mut window_attributes = Window::default_attributes()
.with_title("child window")

View file

@ -56,7 +56,7 @@ struct ControlFlowDemo {
}
impl ApplicationHandler for ControlFlowDemo {
fn new_events(&mut self, _event_loop: &ActiveEventLoop, cause: StartCause) {
fn new_events(&mut self, _event_loop: &dyn ActiveEventLoop, cause: StartCause) {
info!("new_events: {cause:?}");
self.wait_cancelled = match cause {
@ -65,7 +65,7 @@ impl ApplicationHandler for ControlFlowDemo {
}
}
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title(
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
);
@ -74,7 +74,7 @@ impl ApplicationHandler for ControlFlowDemo {
fn window_event(
&mut self,
_event_loop: &ActiveEventLoop,
_event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
@ -120,7 +120,7 @@ impl ApplicationHandler for ControlFlowDemo {
}
}
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
if self.request_redraw && !self.wait_cancelled && !self.close_requested {
self.window.as_ref().unwrap().request_redraw();
}

View file

@ -22,14 +22,14 @@ fn main() -> std::process::ExitCode {
}
impl ApplicationHandler for PumpDemo {
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title("A fantastic window!");
self.window = Some(event_loop.create_window(window_attributes).unwrap());
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {

View file

@ -22,13 +22,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
impl ApplicationHandler for App {
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
if let Some(window) = self.window.as_ref() {
window.request_redraw();
}
}
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes()
.with_title("Fantastic window number one!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0));
@ -39,7 +39,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {

View file

@ -129,7 +129,7 @@ impl Application {
fn create_window(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
_tab_id: Option<String>,
) -> Result<WindowId, Box<dyn Error>> {
// TODO read-out activation token.
@ -175,7 +175,7 @@ impl Application {
Ok(window_id)
}
fn handle_action_from_proxy(&mut self, _event_loop: &ActiveEventLoop, action: Action) {
fn handle_action_from_proxy(&mut self, _event_loop: &dyn ActiveEventLoop, action: Action) {
match action {
#[cfg(web_platform)]
Action::DumpMonitors => self.dump_monitors(_event_loop),
@ -188,7 +188,7 @@ impl Application {
fn handle_action_with_window(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
action: Action,
) {
@ -286,7 +286,7 @@ impl Application {
}
}
fn dump_monitors(&self, event_loop: &ActiveEventLoop) {
fn dump_monitors(&self, event_loop: &dyn ActiveEventLoop) {
info!("Monitors information");
let primary_monitor = event_loop.primary_monitor();
for monitor in event_loop.available_monitors() {
@ -366,7 +366,7 @@ impl Application {
}
impl ApplicationHandler for Application {
fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) {
fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) {
while let Ok(action) = self.receiver.try_recv() {
self.handle_action_from_proxy(event_loop, action)
}
@ -374,7 +374,7 @@ impl ApplicationHandler for Application {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
@ -516,14 +516,14 @@ impl ApplicationHandler for Application {
fn device_event(
&mut self,
_event_loop: &ActiveEventLoop,
_event_loop: &dyn ActiveEventLoop,
device_id: DeviceId,
event: DeviceEvent,
) {
info!("Device {device_id:?} event: {event:?}");
}
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
info!("Ready to create surfaces");
self.dump_monitors(event_loop);
@ -533,7 +533,7 @@ impl ApplicationHandler for Application {
self.print_help();
}
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
if self.windows.is_empty() {
info!("No windows left, exiting...");
event_loop.exit();
@ -541,7 +541,7 @@ impl ApplicationHandler for Application {
}
#[cfg(not(any(android_platform, ios_platform)))]
fn exiting(&mut self, _event_loop: &ActiveEventLoop) {
fn exiting(&mut self, _event_loop: &dyn ActiveEventLoop) {
// We must drop the context here.
self.context = None;
}
@ -755,7 +755,10 @@ impl WindowState {
/// Custom cursor from an URL.
#[cfg(web_platform)]
fn url_custom_cursor(&mut self, event_loop: &ActiveEventLoop) -> Result<(), Box<dyn Error>> {
fn url_custom_cursor(
&mut self,
event_loop: &dyn ActiveEventLoop,
) -> Result<(), Box<dyn Error>> {
let cursor = event_loop.create_custom_cursor(url_custom_cursor())?;
self.window.set_cursor(cursor);
@ -767,7 +770,7 @@ impl WindowState {
#[cfg(web_platform)]
fn animation_custom_cursor(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
custom_cursors: &[CustomCursor],
) -> Result<(), Box<dyn Error>> {
use std::time::Duration;

View file

@ -18,7 +18,7 @@ fn main() -> Result<(), Box<dyn Error>> {
}
impl ApplicationHandler for XEmbedDemo {
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes()
.with_title("An embedded window!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
@ -29,7 +29,7 @@ fn main() -> Result<(), Box<dyn Error>> {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
@ -44,7 +44,7 @@ fn main() -> Result<(), Box<dyn Error>> {
}
}
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
self.window.as_ref().unwrap().request_redraw();
}
}

View file

@ -12,7 +12,7 @@ pub trait ApplicationHandler {
/// events, such as updating frame timing information for benchmarking or checking the
/// [`StartCause`] to see if a timer set by
/// [`ControlFlow::WaitUntil`][crate::event_loop::ControlFlow::WaitUntil] has elapsed.
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) {
let _ = (event_loop, cause);
}
@ -46,7 +46,7 @@ pub trait ApplicationHandler {
/// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported.
///
/// [`resumed()`]: Self::resumed
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
@ -91,7 +91,7 @@ pub trait ApplicationHandler {
///
/// [`can_create_surfaces()`]: Self::can_create_surfaces
/// [`destroy_surfaces()`]: Self::destroy_surfaces
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop);
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop);
/// Called after a wake up is requested using [`EventLoopProxy::wake_up()`].
///
@ -126,15 +126,15 @@ pub trait ApplicationHandler {
/// impl ApplicationHandler for MyApp {
/// # fn window_event(
/// # &mut self,
/// # _event_loop: &ActiveEventLoop,
/// # _event_loop: &dyn ActiveEventLoop,
/// # _window_id: winit::window::WindowId,
/// # _event: winit::event::WindowEvent,
/// # ) {
/// # }
/// #
/// # fn can_create_surfaces(&mut self, _event_loop: &ActiveEventLoop) {}
/// # fn can_create_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) {}
/// #
/// fn proxy_wake_up(&mut self, _event_loop: &ActiveEventLoop) {
/// fn proxy_wake_up(&mut self, _event_loop: &dyn ActiveEventLoop) {
/// // Iterate current events, since wake-ups may have been merged.
/// //
/// // Note: We take care not to use `recv` or `iter` here, as those are blocking,
@ -180,14 +180,14 @@ pub trait ApplicationHandler {
/// Ok(())
/// }
/// ```
fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) {
fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
/// Emitted when the OS sends an event to a winit window.
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
);
@ -195,7 +195,7 @@ pub trait ApplicationHandler {
/// Emitted when the OS sends an event to a device.
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
device_id: DeviceId,
event: DeviceEvent,
) {
@ -213,7 +213,7 @@ pub trait ApplicationHandler {
///
/// This is not an ideal event to drive application rendering from and instead applications
/// should render in response to [`WindowEvent::RedrawRequested`] events.
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
@ -247,7 +247,7 @@ pub trait ApplicationHandler {
/// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported.
///
/// [`suspended()`]: Self::suspended
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
@ -286,7 +286,7 @@ pub trait ApplicationHandler {
///
/// [`can_create_surfaces()`]: Self::can_create_surfaces
/// [`destroy_surfaces()`]: Self::destroy_surfaces
fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
@ -294,7 +294,7 @@ pub trait ApplicationHandler {
///
/// This is irreversible - if this method is called, it is guaranteed that the event loop
/// will exit right after.
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
@ -322,7 +322,7 @@ pub trait ApplicationHandler {
/// ### Others
///
/// - **macOS / Orbital / Wayland / Web / Windows:** Unsupported.
fn memory_warning(&mut self, event_loop: &ActiveEventLoop) {
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
}
@ -330,29 +330,29 @@ pub trait ApplicationHandler {
#[deny(clippy::missing_trait_methods)]
impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
#[inline]
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) {
(**self).new_events(event_loop, cause);
}
#[inline]
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).resumed(event_loop);
}
#[inline]
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).can_create_surfaces(event_loop);
}
#[inline]
fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) {
fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).proxy_wake_up(event_loop);
}
#[inline]
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
@ -362,7 +362,7 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
#[inline]
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
device_id: DeviceId,
event: DeviceEvent,
) {
@ -370,27 +370,27 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
}
#[inline]
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).about_to_wait(event_loop);
}
#[inline]
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).suspended(event_loop);
}
#[inline]
fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).destroy_surfaces(event_loop);
}
#[inline]
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).exiting(event_loop);
}
#[inline]
fn memory_warning(&mut self, event_loop: &ActiveEventLoop) {
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).memory_warning(event_loop);
}
}
@ -398,29 +398,29 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
#[deny(clippy::missing_trait_methods)]
impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
#[inline]
fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) {
(**self).new_events(event_loop, cause);
}
#[inline]
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).resumed(event_loop);
}
#[inline]
fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).can_create_surfaces(event_loop);
}
#[inline]
fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) {
fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).proxy_wake_up(event_loop);
}
#[inline]
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
@ -430,7 +430,7 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
#[inline]
fn device_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
device_id: DeviceId,
event: DeviceEvent,
) {
@ -438,27 +438,27 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
}
#[inline]
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).about_to_wait(event_loop);
}
#[inline]
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).suspended(event_loop);
}
#[inline]
fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) {
fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).destroy_surfaces(event_loop);
}
#[inline]
fn exiting(&mut self, event_loop: &ActiveEventLoop) {
fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).exiting(event_loop);
}
#[inline]
fn memory_warning(&mut self, event_loop: &ActiveEventLoop) {
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).memory_warning(event_loop);
}
}

View file

@ -59,6 +59,8 @@ changelog entry.
### Changed
- Change `ActiveEventLoop` to be a trait.
- `ApplicationHandler` now uses `dyn ActiveEventLoop`.
- On Web, let events wake up event loop immediately when using `ControlFlow::Poll`.
- Bump MSRV from `1.70` to `1.73`.
- Changed `ApplicationHandler::user_event` to `user_wake_up`, removing the

View file

@ -50,7 +50,7 @@ impl From<CustomCursor> for Cursor {
/// ```no_run
/// # use winit::event_loop::ActiveEventLoop;
/// # use winit::window::Window;
/// # fn scope(event_loop: &ActiveEventLoop, window: &Window) {
/// # fn scope(event_loop: &dyn ActiveEventLoop, window: &Window) {
/// use winit::window::CustomCursor;
///
/// let w = 10;

View file

@ -8,6 +8,7 @@
//!
//! See the root-level documentation for information on how to create and use an event loop to
//! handle events.
use std::any::Any;
use std::fmt;
use std::marker::PhantomData;
#[cfg(any(x11_platform, wayland_platform))]
@ -45,15 +46,6 @@ pub struct EventLoop {
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
}
/// Target that associates windows with an [`EventLoop`].
///
/// This type exists to allow you to create new windows while Winit executes
/// your callback.
pub struct ActiveEventLoop {
pub(crate) p: platform_impl::ActiveEventLoop,
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
}
/// Object that allows building the event loop.
///
/// This is used to make specifying options that affect the whole application
@ -129,12 +121,6 @@ impl fmt::Debug for EventLoop {
}
}
impl fmt::Debug for ActiveEventLoop {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("ActiveEventLoop { .. }")
}
}
/// Set through [`ActiveEventLoop::set_control_flow()`].
///
/// Indicates the desired behavior of the event loop after [`about_to_wait`] is called.
@ -239,14 +225,14 @@ impl EventLoop {
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
/// to the main event loop, possibly from another thread.
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy { event_loop_proxy: self.event_loop.window_target().p.create_proxy() }
self.event_loop.window_target().create_proxy()
}
/// Gets a persistent reference to the underlying platform display.
///
/// See the [`OwnedDisplayHandle`] type for more information.
pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle { platform: self.event_loop.window_target().p.owned_display_handle() }
self.event_loop.window_target().owned_display_handle()
}
/// Change if or when [`DeviceEvent`]s are captured.
@ -260,13 +246,12 @@ impl EventLoop {
allowed = ?allowed
)
.entered();
self.event_loop.window_target().p.listen_device_events(allowed);
self.event_loop.window_target().listen_device_events(allowed)
}
/// Sets the [`ControlFlow`].
pub fn set_control_flow(&self, control_flow: ControlFlow) {
self.event_loop.window_target().p.set_control_flow(control_flow)
self.event_loop.window_target().set_control_flow(control_flow);
}
/// Create custom cursor.
@ -278,14 +263,14 @@ impl EventLoop {
&self,
custom_cursor: CustomCursorSource,
) -> Result<CustomCursor, ExternalError> {
self.event_loop.window_target().p.create_custom_cursor(custom_cursor)
self.event_loop.window_target().create_custom_cursor(custom_cursor)
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for EventLoop {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
rwh_06::HasDisplayHandle::display_handle(self.event_loop.window_target())
rwh_06::HasDisplayHandle::display_handle(self.event_loop.window_target().rwh_06_handle())
}
}
@ -317,12 +302,10 @@ impl AsRawFd for EventLoop {
}
}
impl ActiveEventLoop {
pub trait ActiveEventLoop {
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
/// to the main event loop, possibly from another thread.
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy { event_loop_proxy: self.p.create_proxy() }
}
fn create_proxy(&self) -> EventLoopProxy;
/// Create the window.
///
@ -332,31 +315,17 @@ impl ActiveEventLoop {
///
/// - **Web:** The window is created but not inserted into the Web page automatically. Please
/// see the Web platform module for more information.
#[inline]
pub fn create_window(&self, window_attributes: WindowAttributes) -> Result<Window, OsError> {
let _span = tracing::debug_span!(
"winit::ActiveEventLoop::create_window",
window_attributes = ?window_attributes
)
.entered();
let window = platform_impl::Window::new(&self.p, window_attributes)?;
Ok(Window { window })
}
fn create_window(&self, window_attributes: WindowAttributes) -> Result<Window, OsError>;
/// Create custom cursor.
///
/// ## Platform-specific
///
/// **iOS / Android / Orbital:** Unsupported.
pub fn create_custom_cursor(
fn create_custom_cursor(
&self,
custom_cursor: CustomCursorSource,
) -> Result<CustomCursor, ExternalError> {
let _span = tracing::debug_span!("winit::ActiveEventLoop::create_custom_cursor",).entered();
self.p.create_custom_cursor(custom_cursor)
}
) -> Result<CustomCursor, ExternalError>;
/// Returns the list of all the monitors available on the system.
///
@ -368,13 +337,7 @@ impl ActiveEventLoop {
doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
)]
#[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")]
#[inline]
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
let _span = tracing::debug_span!("winit::ActiveEventLoop::available_monitors",).entered();
#[allow(clippy::useless_conversion)] // false positive on some platforms
self.p.available_monitors().into_iter().map(|inner| MonitorHandle { inner })
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = MonitorHandle>>;
/// Returns the primary monitor of the system.
///
@ -389,12 +352,7 @@ impl ActiveEventLoop {
doc = " [detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
)]
#[cfg_attr(not(any(web_platform, docsrs)), doc = " detailed monitor permissions.")]
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
let _span = tracing::debug_span!("winit::ActiveEventLoop::primary_monitor",).entered();
self.p.primary_monitor().map(|inner| MonitorHandle { inner })
}
fn primary_monitor(&self) -> Option<MonitorHandle>;
/// Change if or when [`DeviceEvent`]s are captured.
///
@ -407,15 +365,7 @@ impl ActiveEventLoop {
/// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported.
///
/// [`DeviceEvent`]: crate::event::DeviceEvent
pub fn listen_device_events(&self, allowed: DeviceEvents) {
let _span = tracing::debug_span!(
"winit::ActiveEventLoop::listen_device_events",
allowed = ?allowed
)
.entered();
self.p.listen_device_events(allowed);
}
fn listen_device_events(&self, allowed: DeviceEvents);
/// Returns the current system theme.
///
@ -424,51 +374,37 @@ impl ActiveEventLoop {
/// ## Platform-specific
///
/// - **iOS / Android / Wayland / x11 / Orbital:** Unsupported.
pub fn system_theme(&self) -> Option<Theme> {
self.p.system_theme()
}
fn system_theme(&self) -> Option<Theme>;
/// Sets the [`ControlFlow`].
pub fn set_control_flow(&self, control_flow: ControlFlow) {
self.p.set_control_flow(control_flow)
}
fn set_control_flow(&self, control_flow: ControlFlow);
/// Gets the current [`ControlFlow`].
pub fn control_flow(&self) -> ControlFlow {
self.p.control_flow()
}
fn control_flow(&self) -> ControlFlow;
/// This exits the event loop.
///
/// See [`exiting`][crate::application::ApplicationHandler::exiting].
pub fn exit(&self) {
let _span = tracing::debug_span!("winit::ActiveEventLoop::exit",).entered();
self.p.exit()
}
fn exit(&self);
/// Returns if the [`EventLoop`] is about to stop.
///
/// See [`exit()`][Self::exit].
pub fn exiting(&self) -> bool {
self.p.exiting()
}
fn exiting(&self) -> bool;
/// Gets a persistent reference to the underlying platform display.
///
/// See the [`OwnedDisplayHandle`] type for more information.
pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle { platform: self.p.owned_display_handle() }
}
}
fn owned_display_handle(&self) -> OwnedDisplayHandle;
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for ActiveEventLoop {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = self.p.raw_display_handle_rwh_06()?;
// SAFETY: The display will never be deallocated while the event loop is alive.
Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) })
}
/// Get the [`ActiveEventLoop`] as [`Any`].
///
/// This is useful for downcasting to a concrete event loop type.
fn as_any(&self) -> &dyn Any;
/// Get the raw-window-handle handle.
#[cfg(feature = "rwh_06")]
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle;
}
/// A proxy for the underlying display handle.
@ -486,7 +422,7 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop {
#[derive(Clone)]
pub struct OwnedDisplayHandle {
#[cfg_attr(not(feature = "rwh_06"), allow(dead_code))]
platform: platform_impl::OwnedDisplayHandle,
pub(crate) platform: platform_impl::OwnedDisplayHandle,
}
impl fmt::Debug for OwnedDisplayHandle {
@ -512,7 +448,7 @@ impl rwh_06::HasDisplayHandle for OwnedDisplayHandle {
/// Control the [`EventLoop`], possibly from a different thread, without referencing it directly.
#[derive(Clone)]
pub struct EventLoopProxy {
event_loop_proxy: platform_impl::EventLoopProxy,
pub(crate) event_loop_proxy: platform_impl::EventLoopProxy,
}
impl EventLoopProxy {

View file

@ -52,11 +52,11 @@
//! }
//!
//! impl ApplicationHandler for App {
//! fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) {
//! fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
//! self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());
//! }
//!
//! fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
//! fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, id: WindowId, event: WindowEvent) {
//! match event {
//! WindowEvent::CloseRequested => {
//! println!("The close button was pressed; stopping");

View file

@ -109,9 +109,11 @@ impl WindowExtAndroid for Window {
}
}
impl ActiveEventLoopExtAndroid for ActiveEventLoop {
impl ActiveEventLoopExtAndroid for &dyn ActiveEventLoop {
fn android_app(&self) -> &AndroidApp {
&self.p.app
let event_loop =
self.as_any().downcast_ref::<crate::platform_impl::ActiveEventLoop>().unwrap();
&event_loop.app
}
}

View file

@ -395,21 +395,37 @@ pub trait ActiveEventLoopExtMacOS {
fn allows_automatic_window_tabbing(&self) -> bool;
}
impl ActiveEventLoopExtMacOS for ActiveEventLoop {
impl ActiveEventLoopExtMacOS for &dyn ActiveEventLoop {
fn hide_application(&self) {
self.p.hide_application()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non macOS event loop on macOS");
event_loop.hide_application()
}
fn hide_other_applications(&self) {
self.p.hide_other_applications()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non macOS event loop on macOS");
event_loop.hide_other_applications()
}
fn set_allows_automatic_window_tabbing(&self, enabled: bool) {
self.p.set_allows_automatic_window_tabbing(enabled);
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non macOS event loop on macOS");
event_loop.set_allows_automatic_window_tabbing(enabled);
}
fn allows_automatic_window_tabbing(&self) -> bool {
self.p.allows_automatic_window_tabbing()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non macOS event loop on macOS");
event_loop.allows_automatic_window_tabbing()
}
}

View file

@ -25,6 +25,8 @@ use std::env;
use crate::error::NotSupportedError;
use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial};
#[cfg(wayland_platform)]
use crate::platform::wayland::ActiveEventLoopExtWayland;
use crate::window::{ActivationToken, Window, WindowAttributes};
/// The variable which is used mostly on X11.
@ -55,16 +57,18 @@ pub trait WindowAttributesExtStartupNotify {
fn with_activation_token(self, token: ActivationToken) -> Self;
}
impl EventLoopExtStartupNotify for ActiveEventLoop {
impl EventLoopExtStartupNotify for &dyn ActiveEventLoop {
fn read_token_from_env(&self) -> Option<ActivationToken> {
match self.p {
#[cfg(wayland_platform)]
crate::platform_impl::ActiveEventLoop::Wayland(_) => env::var(WAYLAND_VAR),
#[cfg(x11_platform)]
crate::platform_impl::ActiveEventLoop::X(_) => env::var(X11_VAR),
#[cfg(x11_platform)]
let _is_wayland = false;
#[cfg(wayland_platform)]
let _is_wayland = self.is_wayland();
if _is_wayland {
env::var(WAYLAND_VAR).ok().map(ActivationToken::_new)
} else {
env::var(X11_VAR).ok().map(ActivationToken::_new)
}
.ok()
.map(ActivationToken::_new)
}
}

View file

@ -24,10 +24,10 @@ pub trait ActiveEventLoopExtWayland {
fn is_wayland(&self) -> bool;
}
impl ActiveEventLoopExtWayland for ActiveEventLoop {
impl ActiveEventLoopExtWayland for &dyn ActiveEventLoop {
#[inline]
fn is_wayland(&self) -> bool {
self.p.is_wayland()
self.as_any().downcast_ref::<crate::platform_impl::wayland::ActiveEventLoop>().is_some()
}
}

View file

@ -94,7 +94,7 @@ pub trait WindowExtWeb {
/// Returns whether using [`CursorGrabMode::Locked`] returns raw, un-accelerated mouse input.
///
/// This is the same as [`ActiveEventLoop::is_cursor_lock_raw()`], and is provided for
/// This is the same as [`ActiveEventLoopExtWeb::is_cursor_lock_raw()`], and is provided for
/// convenience.
///
/// [`CursorGrabMode::Locked`]: crate::window::CursorGrabMode::Locked
@ -344,50 +344,86 @@ pub trait ActiveEventLoopExtWeb {
fn has_detailed_monitor_permission(&self) -> bool;
}
impl ActiveEventLoopExtWeb for ActiveEventLoop {
impl ActiveEventLoopExtWeb for &dyn ActiveEventLoop {
#[inline]
fn create_custom_cursor_async(&self, source: CustomCursorSource) -> CustomCursorFuture {
self.p.create_custom_cursor_async(source)
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.create_custom_cursor_async(source)
}
#[inline]
fn set_poll_strategy(&self, strategy: PollStrategy) {
self.p.set_poll_strategy(strategy);
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.set_poll_strategy(strategy);
}
#[inline]
fn poll_strategy(&self) -> PollStrategy {
self.p.poll_strategy()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.poll_strategy()
}
#[inline]
fn set_wait_until_strategy(&self, strategy: WaitUntilStrategy) {
self.p.set_wait_until_strategy(strategy);
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.set_wait_until_strategy(strategy);
}
#[inline]
fn wait_until_strategy(&self) -> WaitUntilStrategy {
self.p.wait_until_strategy()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.wait_until_strategy()
}
#[inline]
fn is_cursor_lock_raw(&self) -> bool {
self.p.is_cursor_lock_raw()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.is_cursor_lock_raw()
}
#[inline]
fn has_multiple_screens(&self) -> Result<bool, NotSupportedError> {
self.p.has_multiple_screens()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.has_multiple_screens()
}
#[inline]
fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture {
MonitorPermissionFuture(self.p.request_detailed_monitor_permission())
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
MonitorPermissionFuture(event_loop.request_detailed_monitor_permission())
}
#[inline]
fn has_detailed_monitor_permission(&self) -> bool {
self.p.has_detailed_monitor_permission()
let event_loop = self
.as_any()
.downcast_ref::<crate::platform_impl::ActiveEventLoop>()
.expect("non Web event loop on Web");
event_loop.has_detailed_monitor_permission()
}
}
@ -623,7 +659,7 @@ pub trait MonitorHandleExtWeb {
/// [`false`] will always represent the current monitor the browser window is in instead of a
/// specific monitor.
///
/// See [`ActiveEventLoop::request_detailed_monitor_permission()`].
/// See [`ActiveEventLoopExtWeb::request_detailed_monitor_permission()`].
fn is_detailed(&self) -> bool;
}

View file

@ -91,10 +91,10 @@ pub trait ActiveEventLoopExtX11 {
fn is_x11(&self) -> bool;
}
impl ActiveEventLoopExtX11 for ActiveEventLoop {
impl ActiveEventLoopExtX11 for &dyn ActiveEventLoop {
#[inline]
fn is_x11(&self) -> bool {
!self.p.is_wayland()
self.as_any().downcast_ref::<crate::platform_impl::x11::ActiveEventLoop>().is_some()
}
}
@ -187,7 +187,7 @@ pub trait WindowAttributesExtX11 {
/// use winit::window::Window;
/// use winit::event_loop::ActiveEventLoop;
/// use winit::platform::x11::{XWindow, WindowAttributesExtX11};
/// # fn create_window(event_loop: &ActiveEventLoop) -> Result<(), Box<dyn std::error::Error>> {
/// # fn create_window(event_loop: &dyn ActiveEventLoop) -> Result<(), Box<dyn std::error::Error>> {
/// let parent_window_id = std::env::args().nth(1).unwrap().parse::<XWindow>()?;
/// let window_attributes = Window::default_attributes().with_embed_parent_window(parent_window_id);
/// let window = event_loop.create_window(window_attributes)?;

View file

@ -1,7 +1,7 @@
use std::any::Any;
use std::cell::Cell;
use std::collections::VecDeque;
use std::hash::Hash;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
@ -17,12 +17,16 @@ use crate::cursor::Cursor;
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{self, EventLoopError, ExternalError, NotSupportedError};
use crate::event::{self, Force, InnerSizeWriter, StartCause};
use crate::event_loop::{self, ControlFlow, DeviceEvents};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
};
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::Fullscreen;
use crate::window::{
self, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose, ResizeDirection, Theme,
WindowButtons, WindowLevel,
Window as RootWindow, WindowAttributes, WindowButtons, WindowLevel,
};
mod keycodes;
@ -98,7 +102,7 @@ pub struct KeyEventExtra {}
pub struct EventLoop {
pub(crate) android_app: AndroidApp,
window_target: event_loop::ActiveEventLoop,
window_target: ActiveEventLoop,
redraw_flag: SharedFlag,
loop_running: bool, // Dispatched `NewEvents<Init>`
running: bool,
@ -134,18 +138,12 @@ impl EventLoop {
Ok(Self {
android_app: android_app.clone(),
window_target: event_loop::ActiveEventLoop {
p: 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,
},
_marker: PhantomData,
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,
},
redraw_flag,
loop_running: false,
@ -157,6 +155,10 @@ impl EventLoop {
})
}
pub(crate) fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.window_target
}
fn single_iteration<A: ApplicationHandler>(
&mut self,
main_event: Option<MainEvent<'_>>,
@ -168,17 +170,17 @@ impl EventLoop {
let mut pending_redraw = self.pending_redraw;
let mut resized = false;
app.new_events(self.window_target(), cause);
app.new_events(&self.window_target, cause);
if let Some(event) = main_event {
trace!("Handling main event {:?}", event);
match event {
MainEvent::InitWindow { .. } => {
app.can_create_surfaces(self.window_target());
app.can_create_surfaces(&self.window_target);
},
MainEvent::TerminateWindow { .. } => {
app.destroy_surfaces(self.window_target());
app.destroy_surfaces(&self.window_target);
},
MainEvent::WindowResized { .. } => resized = true,
MainEvent::RedrawNeeded { .. } => pending_redraw = true,
@ -189,13 +191,13 @@ impl EventLoop {
HAS_FOCUS.store(true, Ordering::Relaxed);
let window_id = window::WindowId(WindowId);
let event = event::WindowEvent::Focused(true);
app.window_event(self.window_target(), window_id, event);
app.window_event(&self.window_target, window_id, event);
},
MainEvent::LostFocus => {
HAS_FOCUS.store(false, Ordering::Relaxed);
let window_id = window::WindowId(WindowId);
let event = event::WindowEvent::Focused(false);
app.window_event(self.window_target(), window_id, event);
app.window_event(&self.window_target, window_id, event);
},
MainEvent::ConfigChanged { .. } => {
let monitor = MonitorHandle::new(self.android_app.clone());
@ -213,11 +215,11 @@ impl EventLoop {
scale_factor,
};
app.window_event(self.window_target(), window_id, event);
app.window_event(&self.window_target, window_id, event);
}
},
MainEvent::LowMemory => {
app.memory_warning(self.window_target());
app.memory_warning(&self.window_target);
},
MainEvent::Start => {
// XXX: how to forward this state to applications?
@ -276,8 +278,8 @@ impl EventLoop {
},
}
if self.window_target.p.proxy_wake_up.swap(false, Ordering::Relaxed) {
app.proxy_wake_up(self.window_target());
if self.window_target.proxy_wake_up.swap(false, Ordering::Relaxed) {
app.proxy_wake_up(&self.window_target);
}
if self.running {
@ -291,7 +293,7 @@ impl EventLoop {
};
let window_id = window::WindowId(WindowId);
let event = event::WindowEvent::Resized(size);
app.window_event(self.window_target(), window_id, event);
app.window_event(&self.window_target, window_id, event);
}
pending_redraw |= self.redraw_flag.get_and_reset();
@ -299,12 +301,12 @@ impl EventLoop {
pending_redraw = false;
let window_id = window::WindowId(WindowId);
let event = event::WindowEvent::RedrawRequested;
app.window_event(self.window_target(), window_id, event);
app.window_event(&self.window_target, window_id, event);
}
}
// This is always the last event we dispatch before poll again
app.about_to_wait(self.window_target());
app.about_to_wait(&self.window_target);
self.pending_redraw = pending_redraw;
}
@ -361,7 +363,7 @@ impl EventLoop {
force: Some(Force::Normalized(pointer.pressure() as f64)),
});
app.window_event(self.window_target(), window_id, event);
app.window_event(&self.window_target, window_id, event);
}
}
},
@ -404,7 +406,7 @@ impl EventLoop {
is_synthetic: false,
};
app.window_event(self.window_target(), window_id, event);
app.window_event(&self.window_target, window_id, event);
},
}
},
@ -424,7 +426,7 @@ impl EventLoop {
&mut self,
mut app: A,
) -> Result<(), EventLoopError> {
self.window_target.p.clear_exit();
self.window_target.clear_exit();
loop {
match self.pump_app_events(None, &mut app) {
PumpStatus::Exit(0) => {
@ -466,7 +468,7 @@ impl EventLoop {
if self.exiting() {
self.loop_running = false;
app.exiting(self.window_target());
app.exiting(&self.window_target);
PumpStatus::Exit(0)
} else {
@ -484,7 +486,7 @@ impl EventLoop {
self.pending_redraw |= self.redraw_flag.get_and_reset();
timeout = if self.running
&& (self.pending_redraw || self.window_target.p.proxy_wake_up.load(Ordering::Relaxed))
&& (self.pending_redraw || self.window_target.proxy_wake_up.load(Ordering::Relaxed))
{
// If we already have work to do then we don't want to block on the next poll
Some(Duration::ZERO)
@ -517,7 +519,7 @@ impl EventLoop {
self.pending_redraw |= self.redraw_flag.get_and_reset();
if !self.running
|| (!self.pending_redraw
&& !self.window_target.p.proxy_wake_up.load(Ordering::Relaxed))
&& !self.window_target.proxy_wake_up.load(Ordering::Relaxed))
{
return;
}
@ -547,16 +549,12 @@ impl EventLoop {
});
}
pub fn window_target(&self) -> &event_loop::ActiveEventLoop {
&self.window_target
}
fn control_flow(&self) -> ControlFlow {
self.window_target.p.control_flow()
self.window_target.control_flow()
}
fn exiting(&self) -> bool {
self.window_target.p.exiting()
self.window_target.exiting()
}
}
@ -582,65 +580,85 @@ pub struct ActiveEventLoop {
}
impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy { proxy_wake_up: self.proxy_wake_up.clone(), waker: self.app.create_waker() }
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 }
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
Some(MonitorHandle::new(self.app.clone()))
fn create_window(
&self,
window_attributes: WindowAttributes,
) -> Result<RootWindow, error::OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
}
pub fn create_custom_cursor(
fn create_custom_cursor(
&self,
_source: CustomCursorSource,
) -> Result<CustomCursor, ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut v = VecDeque::with_capacity(1);
v.push_back(MonitorHandle::new(self.app.clone()));
v
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
let handle = RootMonitorHandle { inner: MonitorHandle::new(self.app.clone()) };
Box::new(vec![handle].into_iter())
}
#[inline]
pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
Some(RootMonitorHandle { inner: MonitorHandle::new(self.app.clone()) })
}
#[inline]
pub fn system_theme(&self) -> Option<Theme> {
fn system_theme(&self) -> Option<Theme> {
None
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Android(rwh_06::AndroidDisplayHandle::new()))
}
fn listen_device_events(&self, _allowed: DeviceEvents) {}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
fn set_control_flow(&self, control_flow: ControlFlow) {
self.control_flow.set(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
fn control_flow(&self) -> ControlFlow {
self.control_flow.get()
}
pub(crate) fn exit(&self) {
fn exit(&self) {
self.exit.set(true)
}
pub(crate) fn clear_exit(&self) {
self.exit.set(false)
}
pub(crate) fn exiting(&self) -> bool {
fn exiting(&self) -> bool {
self.exit.get()
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
RootOwnedDisplayHandle { platform: OwnedDisplayHandle }
}
fn as_any(&self) -> &dyn Any {
self
}
#[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()) })
}
}

View file

@ -16,7 +16,7 @@ use super::observer::{EventLoopWaker, RunLoop};
use super::{menu, WindowId};
use crate::application::ApplicationHandler;
use crate::event::{StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow};
use crate::event_loop::ControlFlow;
use crate::window::WindowId as RootWindowId;
#[derive(Debug)]
@ -282,7 +282,7 @@ impl ApplicationDelegate {
#[track_caller]
pub fn maybe_queue_with_handler(
&self,
callback: impl FnOnce(&mut dyn ApplicationHandler, &RootActiveEventLoop) + 'static,
callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop) + 'static,
) {
// Most programmer actions in AppKit (e.g. change window fullscreen, set focused, etc.)
// result in an event being queued, and applied at a later point.
@ -302,11 +302,9 @@ impl ApplicationDelegate {
}
#[track_caller]
fn with_handler(
&self,
callback: impl FnOnce(&mut dyn ApplicationHandler, &RootActiveEventLoop),
) {
let event_loop = ActiveEventLoop::new_root(self.retain());
fn with_handler(&self, callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop)) {
let event_loop =
ActiveEventLoop { delegate: self.retain(), mtm: MainThreadMarker::from(self) };
self.ivars().event_handler.handle(callback, &event_loop);
}

View file

@ -2,7 +2,7 @@ use std::cell::RefCell;
use std::{fmt, mem};
use crate::application::ApplicationHandler;
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
use crate::platform_impl::ActiveEventLoop;
#[derive(Default)]
pub(crate) struct EventHandler {
@ -110,8 +110,8 @@ impl EventHandler {
pub(crate) fn handle(
&self,
callback: impl FnOnce(&mut dyn ApplicationHandler, &RootActiveEventLoop),
event_loop: &RootActiveEventLoop,
callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop),
event_loop: &ActiveEventLoop,
) {
match self.inner.try_borrow_mut().as_deref_mut() {
Ok(Some(user_app)) => {

View file

@ -1,7 +1,5 @@
use std::any::Any;
use std::cell::Cell;
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::os::raw::c_void;
use std::panic::{catch_unwind, resume_unwind, RefUnwindSafe, UnwindSafe};
use std::ptr;
@ -25,14 +23,21 @@ use super::app::WinitApplication;
use super::app_state::ApplicationDelegate;
use super::cursor::CustomCursor;
use super::event::dummy_event;
use super::monitor::{self, MonitorHandle};
use super::monitor;
use super::observer::setup_control_flow_observers;
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, ExternalError};
use crate::event_loop::{ActiveEventLoop as RootWindowTarget, ControlFlow, DeviceEvents};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
};
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::macos::ActivationPolicy;
use crate::platform::pump_events::PumpStatus;
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme};
use crate::platform_impl::Window;
use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow,
};
#[derive(Default)]
pub struct PanicInfo {
@ -66,85 +71,15 @@ impl PanicInfo {
#[derive(Debug)]
pub struct ActiveEventLoop {
delegate: Retained<ApplicationDelegate>,
pub(super) delegate: Retained<ApplicationDelegate>,
pub(super) mtm: MainThreadMarker,
}
impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(self.delegate.proxy_wake_up())
}
pub(super) fn new_root(delegate: Retained<ApplicationDelegate>) -> RootWindowTarget {
let mtm = MainThreadMarker::from(&*delegate);
let p = Self { delegate, mtm };
RootWindowTarget { p, _marker: PhantomData }
}
pub(super) fn app_delegate(&self) -> &ApplicationDelegate {
&self.delegate
}
pub fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: CustomCursor::new(source.inner)? })
}
#[inline]
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
monitor::available_monitors()
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
let monitor = monitor::primary_monitor();
Some(monitor)
}
#[inline]
pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
#[inline]
pub fn system_theme(&self) -> Option<Theme> {
let app = NSApplication::sharedApplication(self.mtm);
if app.respondsToSelector(sel!(effectiveAppearance)) {
Some(super::window_delegate::appearance_to_theme(&app.effectiveAppearance()))
} else {
Some(Theme::Light)
}
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::AppKit(rwh_06::AppKitDisplayHandle::new()))
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
self.delegate.set_control_flow(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
self.delegate.control_flow()
}
pub(crate) fn exit(&self) {
self.delegate.exit()
}
pub(crate) fn exiting(&self) -> bool {
self.delegate.exiting()
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
pub(crate) fn hide_application(&self) {
NSApplication::sharedApplication(self.mtm).hide(None)
}
@ -162,6 +97,86 @@ impl ActiveEventLoop {
}
}
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy {
let event_loop_proxy = EventLoopProxy::new(self.delegate.proxy_wake_up());
RootEventLoopProxy { event_loop_proxy }
}
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
}
fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: CustomCursor::new(source.inner)? })
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
Box::new(monitor::available_monitors().into_iter().map(|inner| RootMonitorHandle { inner }))
}
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
let monitor = monitor::primary_monitor();
Some(RootMonitorHandle { inner: monitor })
}
fn listen_device_events(&self, _allowed: DeviceEvents) {}
fn system_theme(&self) -> Option<Theme> {
let app = NSApplication::sharedApplication(self.mtm);
if app.respondsToSelector(sel!(effectiveAppearance)) {
Some(super::window_delegate::appearance_to_theme(&app.effectiveAppearance()))
} else {
Some(Theme::Light)
}
}
fn set_control_flow(&self, control_flow: ControlFlow) {
self.delegate.set_control_flow(control_flow)
}
fn control_flow(&self) -> ControlFlow {
self.delegate.control_flow()
}
fn exit(&self) {
self.delegate.exit()
}
fn exiting(&self) -> bool {
self.delegate.exiting()
}
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
RootOwnedDisplayHandle { platform: OwnedDisplayHandle }
}
fn as_any(&self) -> &dyn Any {
self
}
#[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::RawDisplayHandle::AppKit(rwh_06::AppKitDisplayHandle::new());
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
pub struct EventLoop {
/// Store a reference to the application for convenience.
///
@ -174,7 +189,7 @@ pub struct EventLoop {
/// keep it around here as well.
delegate: Retained<ApplicationDelegate>,
window_target: RootWindowTarget,
window_target: ActiveEventLoop,
panic_info: Rc<PanicInfo>,
}
@ -235,15 +250,12 @@ impl EventLoop {
Ok(EventLoop {
app,
delegate: delegate.clone(),
window_target: RootWindowTarget {
p: ActiveEventLoop { delegate, mtm },
_marker: PhantomData,
},
window_target: ActiveEventLoop { delegate, mtm },
panic_info,
})
}
pub fn window_target(&self) -> &RootWindowTarget {
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.window_target
}

View file

@ -24,6 +24,7 @@ use objc2_foundation::{
use objc2_ui_kit::{UIApplication, UICoordinateSpace, UIView, UIWindow};
use super::window::WinitUIWindow;
use super::ActiveEventLoop;
use crate::dpi::PhysicalSize;
use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow};
@ -43,8 +44,8 @@ macro_rules! bug_assert {
pub(crate) struct EventLoopHandler {
#[allow(clippy::type_complexity)]
pub(crate) handler: Box<dyn FnMut(Event, &RootActiveEventLoop)>,
pub(crate) event_loop: RootActiveEventLoop,
pub(crate) handler: Box<dyn FnMut(Event, &dyn RootActiveEventLoop)>,
pub(crate) event_loop: ActiveEventLoop,
}
impl fmt::Debug for EventLoopHandler {

View file

@ -1,6 +1,5 @@
use std::collections::VecDeque;
use std::any::Any;
use std::ffi::{c_char, c_int, c_void};
use std::marker::PhantomData;
use std::ptr::{self, NonNull};
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
use std::sync::Arc;
@ -21,73 +20,95 @@ use super::app_delegate::AppDelegate;
use super::app_state::{AppState, EventLoopHandler};
use super::{app_state, monitor, MonitorHandle};
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, ExternalError, NotSupportedError};
use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError};
use crate::event::Event;
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
use crate::window::{CustomCursor, CustomCursorSource, Theme};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
};
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform_impl::Window;
use crate::window::{CustomCursor, CustomCursorSource, Theme, Window as RootWindow};
#[derive(Debug)]
pub struct ActiveEventLoop {
pub(crate) struct ActiveEventLoop {
pub(super) mtm: MainThreadMarker,
}
impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(AppState::get_mut(self.mtm).proxy_wake_up())
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy {
let event_loop_proxy = EventLoopProxy::new(AppState::get_mut(self.mtm).proxy_wake_up());
RootEventLoopProxy { event_loop_proxy }
}
pub fn create_custom_cursor(
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<RootWindow, OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
}
fn create_custom_cursor(
&self,
_source: CustomCursorSource,
) -> Result<CustomCursor, ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
monitor::uiscreens(self.mtm)
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
Box::new(monitor::uiscreens(self.mtm).into_iter().map(|inner| RootMonitorHandle { inner }))
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
#[allow(deprecated)]
Some(MonitorHandle::new(UIScreen::mainScreen(self.mtm)))
let monitor = MonitorHandle::new(UIScreen::mainScreen(self.mtm));
Some(RootMonitorHandle { inner: monitor })
}
#[inline]
pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
fn listen_device_events(&self, _allowed: DeviceEvents) {}
#[inline]
pub fn system_theme(&self) -> Option<Theme> {
None
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::UiKit(rwh_06::UiKitDisplayHandle::new()))
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
fn set_control_flow(&self, control_flow: ControlFlow) {
AppState::get_mut(self.mtm).set_control_flow(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
fn system_theme(&self) -> Option<Theme> {
None
}
fn control_flow(&self) -> ControlFlow {
AppState::get_mut(self.mtm).control_flow()
}
pub(crate) fn exit(&self) {
fn exit(&self) {
// https://developer.apple.com/library/archive/qa/qa1561/_index.html
// it is not possible to quit an iOS app gracefully and programmatically
tracing::warn!("`ControlFlow::Exit` ignored on iOS");
}
pub(crate) fn exiting(&self) -> bool {
fn exiting(&self) -> bool {
false
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
RootOwnedDisplayHandle { platform: OwnedDisplayHandle }
}
fn as_any(&self) -> &dyn Any {
self
}
#[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::RawDisplayHandle::UiKit(rwh_06::UiKitDisplayHandle::new());
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
@ -107,7 +128,7 @@ impl OwnedDisplayHandle {
fn map_user_event<'a, A: ApplicationHandler + 'a>(
mut app: A,
proxy_wake_up: Arc<AtomicBool>,
) -> impl FnMut(Event, &RootActiveEventLoop) + 'a {
) -> impl FnMut(Event, &dyn RootActiveEventLoop) + 'a {
move |event, window_target| match event {
Event::NewEvents(cause) => app.new_events(window_target, cause),
Event::WindowEvent { window_id, event } => {
@ -132,7 +153,7 @@ fn map_user_event<'a, A: ApplicationHandler + 'a>(
pub struct EventLoop {
mtm: MainThreadMarker,
window_target: RootActiveEventLoop,
window_target: ActiveEventLoop,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -157,10 +178,7 @@ impl EventLoop {
// this line sets up the main run loop before `UIApplicationMain`
setup_control_flow_observers();
Ok(EventLoop {
mtm,
window_target: RootActiveEventLoop { p: ActiveEventLoop { mtm }, _marker: PhantomData },
})
Ok(EventLoop { mtm, window_target: ActiveEventLoop { mtm } })
}
pub fn run_app<A: ApplicationHandler>(self, app: A) -> ! {
@ -177,8 +195,8 @@ impl EventLoop {
let handler = unsafe {
std::mem::transmute::<
Box<dyn FnMut(Event, &RootActiveEventLoop)>,
Box<dyn FnMut(Event, &RootActiveEventLoop)>,
Box<dyn FnMut(Event, &dyn RootActiveEventLoop)>,
Box<dyn FnMut(Event, &dyn RootActiveEventLoop)>,
>(Box::new(handler))
};
@ -206,7 +224,7 @@ impl EventLoop {
unreachable!()
}
pub fn window_target(&self) -> &RootActiveEventLoop {
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.window_target
}
}

View file

@ -19,8 +19,8 @@ use self::x11::{X11Error, XConnection, XError, XNotSupported};
use crate::application::ApplicationHandler;
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError};
use crate::event_loop::{AsyncRequestSerial, ControlFlow, DeviceEvents};
use crate::error::{EventLoopError, ExternalError, NotSupportedError};
use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial};
use crate::icon::Icon;
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
use crate::keyboard::Key;
@ -31,8 +31,8 @@ pub(crate) use crate::platform_impl::Fullscreen;
#[cfg(x11_platform)]
use crate::utils::Lazy;
use crate::window::{
ActivationToken, Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose,
ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowButtons, WindowLevel,
ActivationToken, Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
WindowButtons, WindowLevel,
};
pub(crate) mod common;
@ -281,23 +281,6 @@ impl VideoModeHandle {
}
impl Window {
#[inline]
pub(crate) fn new(
window_target: &ActiveEventLoop,
attribs: WindowAttributes,
) -> Result<Self, RootOsError> {
match *window_target {
#[cfg(wayland_platform)]
ActiveEventLoop::Wayland(ref window_target) => {
wayland::Window::new(window_target, attribs).map(Window::Wayland)
},
#[cfg(x11_platform)]
ActiveEventLoop::X(ref window_target) => {
x11::Window::new(window_target, attribs).map(Window::X)
},
}
}
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) {
f(self)
}
@ -789,7 +772,7 @@ impl EventLoop {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_app_events(timeout, app))
}
pub fn window_target(&self) -> &crate::event_loop::ActiveEventLoop {
pub fn window_target(&self) -> &dyn ActiveEventLoop {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.window_target())
}
}
@ -812,112 +795,6 @@ impl EventLoopProxy {
}
}
pub enum ActiveEventLoop {
#[cfg(wayland_platform)]
Wayland(wayland::ActiveEventLoop),
#[cfg(x11_platform)]
X(x11::ActiveEventLoop),
}
impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
}
#[inline]
pub fn is_wayland(&self) -> bool {
match *self {
#[cfg(wayland_platform)]
ActiveEventLoop::Wayland(_) => true,
#[cfg(x11_platform)]
_ => false,
}
}
pub fn create_custom_cursor(
&self,
cursor: CustomCursorSource,
) -> Result<CustomCursor, ExternalError> {
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_custom_cursor(cursor))
}
#[inline]
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
match *self {
#[cfg(wayland_platform)]
ActiveEventLoop::Wayland(ref evlp) => {
evlp.available_monitors().map(MonitorHandle::Wayland).collect()
},
#[cfg(x11_platform)]
ActiveEventLoop::X(ref evlp) => {
evlp.available_monitors().map(MonitorHandle::X).collect()
},
}
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
Some(
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.primary_monitor()?; as MonitorHandle),
)
}
#[inline]
pub fn listen_device_events(&self, allowed: DeviceEvents) {
x11_or_wayland!(match self; Self(evlp) => evlp.listen_device_events(allowed))
}
#[inline]
pub fn system_theme(&self) -> Option<Theme> {
None
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle_rwh_06())
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
x11_or_wayland!(match self; Self(evlp) => evlp.set_control_flow(control_flow))
}
pub(crate) fn control_flow(&self) -> ControlFlow {
x11_or_wayland!(match self; Self(evlp) => evlp.control_flow())
}
fn clear_exit(&self) {
x11_or_wayland!(match self; Self(evlp) => evlp.clear_exit())
}
pub(crate) fn exit(&self) {
x11_or_wayland!(match self; Self(evlp) => evlp.exit())
}
pub(crate) fn exiting(&self) -> bool {
x11_or_wayland!(match self; Self(evlp) => evlp.exiting())
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
match self {
#[cfg(x11_platform)]
Self::X(conn) => OwnedDisplayHandle::X(conn.x_connection().clone()),
#[cfg(wayland_platform)]
Self::Wayland(conn) => OwnedDisplayHandle::Wayland(conn.connection.clone()),
}
}
fn set_exit_code(&self, code: i32) {
x11_or_wayland!(match self; Self(evlp) => evlp.set_exit_code(code))
}
fn exit_code(&self) -> Option<i32> {
x11_or_wayland!(match self; Self(evlp) => evlp.exit_code())
}
}
#[derive(Clone)]
#[allow(dead_code)]
pub(crate) enum OwnedDisplayHandle {

View file

@ -1,8 +1,8 @@
//! The event-loop routines.
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::io::Result as IOResult;
use std::marker::PhantomData;
use std::mem;
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::sync::atomic::Ordering;
@ -21,10 +21,8 @@ use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::platform::min_timeout;
use crate::platform_impl::{
ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor,
};
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource};
use crate::platform_impl::{OsError, PlatformCustomCursor};
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme};
mod proxy;
pub mod sink;
@ -55,7 +53,7 @@ pub struct EventLoop {
connection: Connection,
/// Event loop window target.
window_target: RootActiveEventLoop,
active_event_loop: ActiveEventLoop,
// XXX drop after everything else, just to be safe.
/// Calloop's event loop.
@ -132,7 +130,7 @@ impl EventLoop {
.map_err(|error| error.error);
map_err!(result, WaylandError::Calloop)?;
let window_target = ActiveEventLoop {
let active_event_loop = ActiveEventLoop {
connection: connection.clone(),
wayland_dispatcher: wayland_dispatcher.clone(),
event_loop_awakener,
@ -151,10 +149,7 @@ impl EventLoop {
connection,
wayland_dispatcher,
event_loop,
window_target: RootActiveEventLoop {
p: PlatformActiveEventLoop::Wayland(window_target),
_marker: PhantomData,
},
active_event_loop,
};
Ok(event_loop)
@ -168,7 +163,7 @@ impl EventLoop {
&mut self,
mut app: A,
) -> Result<(), EventLoopError> {
self.window_target.p.clear_exit();
self.active_event_loop.clear_exit();
let exit = loop {
match self.pump_app_events(None, &mut app) {
PumpStatus::Exit(0) => {
@ -212,7 +207,7 @@ impl EventLoop {
if let Some(code) = self.exit_code() {
self.loop_running = false;
app.exiting(&self.window_target);
app.exiting(&self.active_event_loop);
PumpStatus::Exit(code)
} else {
@ -300,17 +295,17 @@ impl EventLoop {
let mut buffer_sink = std::mem::take(&mut self.buffer_sink);
let mut window_ids = std::mem::take(&mut self.window_ids);
app.new_events(&self.window_target, cause);
app.new_events(&self.active_event_loop, cause);
// NB: For consistency all platforms must call `can_create_surfaces` even though Wayland
// applications don't themselves have a formal surface destroy/create lifecycle.
if cause == StartCause::Init {
app.can_create_surfaces(&self.window_target);
app.can_create_surfaces(&self.active_event_loop);
}
// Indicate user wake up.
if self.with_state(|state| mem::take(&mut state.proxy_wake_up)) {
app.proxy_wake_up(&self.window_target);
app.proxy_wake_up(&self.active_event_loop);
}
// Drain the pending compositor updates.
@ -337,7 +332,7 @@ impl EventLoop {
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),
};
app.window_event(&self.window_target, root_window_id, event);
app.window_event(&self.active_event_loop, root_window_id, event);
let physical_size = *new_inner_size.lock().unwrap();
drop(new_inner_size);
@ -382,12 +377,12 @@ impl EventLoop {
let window_id = crate::window::WindowId(window_id);
let event = WindowEvent::Resized(physical_size);
app.window_event(&self.window_target, window_id, event);
app.window_event(&self.active_event_loop, window_id, event);
}
if compositor_update.close_window {
let window_id = crate::window::WindowId(window_id);
app.window_event(&self.window_target, window_id, WindowEvent::CloseRequested);
app.window_event(&self.active_event_loop, window_id, WindowEvent::CloseRequested);
}
}
@ -398,10 +393,10 @@ impl EventLoop {
for event in buffer_sink.drain() {
match event {
Event::WindowEvent { window_id, event } => {
app.window_event(&self.window_target, window_id, event)
app.window_event(&self.active_event_loop, window_id, event)
},
Event::DeviceEvent { device_id, event } => {
app.device_event(&self.window_target, device_id, event)
app.device_event(&self.active_event_loop, device_id, event)
},
_ => unreachable!("event which is neither device nor window event."),
}
@ -414,10 +409,10 @@ impl EventLoop {
for event in buffer_sink.drain() {
match event {
Event::WindowEvent { window_id, event } => {
app.window_event(&self.window_target, window_id, event)
app.window_event(&self.active_event_loop, window_id, event)
},
Event::DeviceEvent { device_id, event } => {
app.device_event(&self.window_target, device_id, event)
app.device_event(&self.active_event_loop, device_id, event)
},
_ => unreachable!("event which is neither device nor window event."),
}
@ -457,7 +452,7 @@ impl EventLoop {
if let Some(event) = event {
let window_id = crate::window::WindowId(*window_id);
app.window_event(&self.window_target, window_id, event);
app.window_event(&self.active_event_loop, window_id, event);
}
}
@ -467,7 +462,7 @@ impl EventLoop {
});
// This is always the last event we dispatch before poll again
app.about_to_wait(&self.window_target);
app.about_to_wait(&self.active_event_loop);
// Update the window frames and schedule redraws.
let mut wake_up = false;
@ -496,13 +491,7 @@ impl EventLoop {
// If the user draws from the `AboutToWait` this is likely not required, however
// we can't do much about it.
if wake_up {
match &self.window_target.p {
PlatformActiveEventLoop::Wayland(window_target) => {
window_target.event_loop_awakener.ping();
},
#[cfg(x11_platform)]
PlatformActiveEventLoop::X(_) => unreachable!(),
}
self.active_event_loop.event_loop_awakener.ping();
}
std::mem::swap(&mut self.compositor_updates, &mut compositor_updates);
@ -511,26 +500,17 @@ impl EventLoop {
}
#[inline]
pub fn window_target(&self) -> &RootActiveEventLoop {
&self.window_target
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.active_event_loop
}
fn with_state<'a, U: 'a, F: FnOnce(&'a mut WinitState) -> U>(&'a mut self, callback: F) -> U {
let state = match &mut self.window_target.p {
PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
#[cfg(x11_platform)]
_ => unreachable!(),
};
let state = self.active_event_loop.state.get_mut();
callback(state)
}
fn loop_dispatch<D: Into<Option<std::time::Duration>>>(&mut self, timeout: D) -> IOResult<()> {
let state = match &mut self.window_target.p {
PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
#[cfg(feature = "x11")]
_ => unreachable!(),
};
let state = &mut self.active_event_loop.state.get_mut();
self.event_loop.dispatch(timeout, state).map_err(|error| {
tracing::error!("Error dispatching event loop: {}", error);
@ -539,11 +519,7 @@ impl EventLoop {
}
fn roundtrip(&mut self) -> Result<usize, RootOsError> {
let state = match &mut self.window_target.p {
PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
#[cfg(feature = "x11")]
_ => unreachable!(),
};
let state = &mut self.active_event_loop.state.get_mut();
let mut wayland_source = self.wayland_dispatcher.as_source_mut();
let event_queue = wayland_source.queue();
@ -553,19 +529,19 @@ impl EventLoop {
}
fn control_flow(&self) -> ControlFlow {
self.window_target.p.control_flow()
self.active_event_loop.control_flow()
}
fn exiting(&self) -> bool {
self.window_target.p.exiting()
self.active_event_loop.exiting()
}
fn set_exit_code(&self, code: i32) {
self.window_target.p.set_exit_code(code)
self.active_event_loop.set_exit_code(code)
}
fn exit_code(&self) -> Option<i32> {
self.window_target.p.exit_code()
self.active_event_loop.exit_code()
}
}
@ -608,43 +584,35 @@ pub struct ActiveEventLoop {
pub connection: Connection,
}
impl ActiveEventLoop {
pub(crate) fn create_proxy(&self) -> EventLoopProxy {
self.event_loop_proxy.clone()
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy {
crate::event_loop::EventLoopProxy {
event_loop_proxy: crate::platform_impl::EventLoopProxy::Wayland(
self.event_loop_proxy.clone(),
),
}
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
fn set_control_flow(&self, control_flow: ControlFlow) {
self.control_flow.set(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
fn control_flow(&self) -> ControlFlow {
self.control_flow.get()
}
pub(crate) fn exit(&self) {
fn exit(&self) {
self.exit.set(Some(0))
}
pub(crate) fn clear_exit(&self) {
self.exit.set(None)
}
pub(crate) fn exiting(&self) -> bool {
fn exiting(&self) -> bool {
self.exit.get().is_some()
}
pub(crate) fn set_exit_code(&self, code: i32) {
self.exit.set(Some(code))
}
pub(crate) fn exit_code(&self) -> Option<i32> {
self.exit.get()
}
#[inline]
pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
fn listen_device_events(&self, _allowed: DeviceEvents) {}
pub(crate) fn create_custom_cursor(
fn create_custom_cursor(
&self,
cursor: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
@ -653,17 +621,78 @@ impl ActiveEventLoop {
})
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
use sctk::reexports::client::Proxy;
fn system_theme(&self) -> Option<Theme> {
None
}
Ok(rwh_06::WaylandDisplayHandle::new({
let ptr = self.connection.display().id().as_ptr();
std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null")
})
.into())
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, RootOsError> {
let window = crate::platform_impl::wayland::Window::new(self, window_attributes)?;
let window = crate::platform_impl::Window::Wayland(window);
Ok(crate::window::Window { window })
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
Box::new(
self.state
.borrow()
.output_state
.outputs()
.map(crate::platform_impl::wayland::output::MonitorHandle::new)
.map(crate::platform_impl::MonitorHandle::Wayland)
.map(|inner| crate::monitor::MonitorHandle { inner }),
)
}
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
// There's no primary monitor on Wayland.
None
}
fn owned_display_handle(&self) -> crate::event_loop::OwnedDisplayHandle {
crate::event_loop::OwnedDisplayHandle {
platform: crate::platform_impl::OwnedDisplayHandle::Wayland(self.connection.clone()),
}
}
#[inline(always)]
fn as_any(&self) -> &dyn Any {
self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
}
impl ActiveEventLoop {
fn clear_exit(&self) {
self.exit.set(None)
}
fn set_exit_code(&self, code: i32) {
self.exit.set(Some(code))
}
fn exit_code(&self) -> Option<i32> {
self.exit.get()
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for ActiveEventLoop {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
use sctk::reexports::client::Proxy;
let raw = rwh_06::WaylandDisplayHandle::new({
let ptr = self.connection.display().id().as_ptr();
std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null")
});
Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw.into()) })
}
}

View file

@ -2,23 +2,9 @@ use sctk::output::OutputData;
use sctk::reexports::client::protocol::wl_output::WlOutput;
use sctk::reexports::client::Proxy;
use super::event_loop::ActiveEventLoop;
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
use crate::platform_impl::platform::VideoModeHandle as PlatformVideoModeHandle;
impl ActiveEventLoop {
#[inline]
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
self.state.borrow().output_state.outputs().map(MonitorHandle::new)
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
// There's no primary monitor on Wayland.
None
}
}
#[derive(Clone, Debug)]
pub struct MonitorHandle {
pub(crate) proxy: WlOutput,

View file

@ -25,13 +25,11 @@ use crate::event::{
DeviceEvent, ElementState, Event, Ime, InnerSizeWriter, MouseButton, MouseScrollDelta,
RawKeyEvent, Touch, TouchPhase, WindowEvent,
};
use crate::event_loop::ActiveEventLoop as RootAEL;
use crate::keyboard::ModifiersState;
use crate::platform_impl::common::xkb::{self, XkbState};
use crate::platform_impl::platform::common::xkb::Context;
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest};
use crate::platform_impl::platform::x11::ActiveEventLoop;
use crate::platform_impl::platform::ActiveEventLoop as PlatformActiveEventLoop;
use crate::platform_impl::x11::atoms::*;
use crate::platform_impl::x11::util::cookie::GenericEventCookie;
use crate::platform_impl::x11::{
@ -53,7 +51,7 @@ pub struct EventProcessor {
pub devices: RefCell<HashMap<DeviceId, Device>>,
pub xi2ext: ExtensionInformation,
pub xkbext: ExtensionInformation,
pub target: RootAEL,
pub target: ActiveEventLoop,
pub xkb_context: Context,
// Number of touch events currently in progress
pub num_touch: u32,
@ -75,18 +73,17 @@ pub struct EventProcessor {
impl EventProcessor {
pub(crate) fn process_event<F>(&mut self, xev: &mut XEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
self.process_xevent(xev, &mut callback);
let window_target = Self::window_target_mut(&mut self.target);
// Handle IME requests.
while let Ok(request) = self.ime_receiver.try_recv() {
let ime = match window_target.ime.as_mut() {
let ime = match self.target.ime.as_mut() {
Some(ime) => ime,
None => continue,
};
let ime = ime.get_mut();
match request {
ImeRequest::Position(window_id, x, y) => {
@ -131,9 +128,8 @@ impl EventProcessor {
/// along with an extra copy of the KeyRelease events. This also prevents backspace and
/// arrow keys from being detected twice.
fn filter_event(&mut self, xev: &mut XEvent) -> bool {
let wt = Self::window_target(&self.target);
unsafe {
(wt.xconn.xlib.XFilterEvent)(xev, {
(self.target.xconn.xlib.XFilterEvent)(xev, {
let xev: &XAnyEvent = xev.as_ref();
xev.window
}) == xlib::True
@ -142,7 +138,7 @@ impl EventProcessor {
fn process_xevent<F>(&mut self, xev: &mut XEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let event_type = xev.get_type();
@ -184,9 +180,8 @@ impl EventProcessor {
self.xinput_key_input(xev.as_mut(), state, &mut callback);
},
xlib::GenericEvent => {
let wt = Self::window_target(&self.target);
let xev: GenericEventCookie =
match GenericEventCookie::from_event(wt.xconn.clone(), *xev) {
match GenericEventCookie::from_event(self.target.xconn.clone(), *xev) {
Some(xev) if xev.extension() == self.xi2ext.major_opcode => xev,
_ => return,
};
@ -298,14 +293,10 @@ impl EventProcessor {
}
pub fn poll(&self) -> bool {
let window_target = Self::window_target(&self.target);
let result = unsafe { (window_target.xconn.xlib.XPending)(window_target.xconn.display) };
result != 0
unsafe { (self.target.xconn.xlib.XPending)(self.target.xconn.display) != 0 }
}
pub unsafe fn poll_one_event(&mut self, event_ptr: *mut XEvent) -> bool {
let window_target = Self::window_target(&self.target);
// This function is used to poll and remove a single event
// from the Xlib event queue in a non-blocking, atomic way.
// XCheckIfEvent is non-blocking and removes events from queue.
@ -321,22 +312,19 @@ impl EventProcessor {
1
}
let result = unsafe {
(window_target.xconn.xlib.XCheckIfEvent)(
window_target.xconn.display,
unsafe {
(self.target.xconn.xlib.XCheckIfEvent)(
self.target.xconn.display,
event_ptr,
Some(predicate),
std::ptr::null_mut(),
)
};
result != 0
) != 0
}
}
pub fn init_device(&self, device: xinput::DeviceId) {
let window_target = Self::window_target(&self.target);
let mut devices = self.devices.borrow_mut();
if let Some(info) = DeviceInfo::get(&window_target.xconn, device as _) {
if let Some(info) = DeviceInfo::get(&self.target.xconn, device as _) {
for info in info.iter() {
devices.insert(DeviceId(info.deviceid as _), Device::new(info));
}
@ -349,8 +337,8 @@ impl EventProcessor {
{
let mut deleted = false;
let window_id = WindowId(window_id as _);
let window_target = Self::window_target(&self.target);
let result = window_target
let result = self
.target
.windows
.borrow()
.get(&window_id)
@ -363,53 +351,33 @@ impl EventProcessor {
if deleted {
// Garbage collection
window_target.windows.borrow_mut().remove(&window_id);
self.target.windows.borrow_mut().remove(&window_id);
}
result
}
// NOTE: we avoid `self` to not borrow the entire `self` as not mut.
/// Get the platform window target.
pub fn window_target(window_target: &RootAEL) -> &ActiveEventLoop {
match &window_target.p {
PlatformActiveEventLoop::X(target) => target,
#[cfg(wayland_platform)]
_ => unreachable!(),
}
}
/// Get the platform window target.
pub fn window_target_mut(window_target: &mut RootAEL) -> &mut ActiveEventLoop {
match &mut window_target.p {
PlatformActiveEventLoop::X(target) => target,
#[cfg(wayland_platform)]
_ => unreachable!(),
}
}
fn client_message<F>(&mut self, xev: &XClientMessageEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let atoms = wt.xconn.atoms();
let atoms = self.target.xconn.atoms();
let window = xev.window as xproto::Window;
let window_id = mkwid(window);
if xev.data.get_long(0) as xproto::Atom == wt.wm_delete_window {
if xev.data.get_long(0) as xproto::Atom == self.target.wm_delete_window {
let event = Event::WindowEvent { window_id, event: WindowEvent::CloseRequested };
callback(&self.target, event);
return;
}
if xev.data.get_long(0) as xproto::Atom == wt.net_wm_ping {
if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_ping {
let client_msg = xproto::ClientMessageEvent {
response_type: xproto::CLIENT_MESSAGE_EVENT,
format: xev.format as _,
sequence: xev.serial as _,
window: wt.root,
window: self.target.root,
type_: xev.message_type as _,
data: xproto::ClientMessageData::from({
let [a, b, c, d, e]: [c_long; 5] = xev.data.as_longs().try_into().unwrap();
@ -417,11 +385,12 @@ impl EventProcessor {
}),
};
wt.xconn
self.target
.xconn
.xcb_connection()
.send_event(
false,
wt.root,
self.target.root,
xproto::EventMask::SUBSTRUCTURE_NOTIFY
| xproto::EventMask::SUBSTRUCTURE_REDIRECT,
client_msg.serialize(),
@ -430,7 +399,7 @@ impl EventProcessor {
return;
}
if xev.data.get_long(0) as xproto::Atom == wt.net_wm_sync_request {
if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_sync_request {
let sync_counter_id = match self
.with_window(xev.window as xproto::Window, |window| window.sync_counter_id())
{
@ -448,10 +417,12 @@ impl EventProcessor {
bytemuck::cast::<u32, i32>((xev.data.get_long(3) & 0xffffffff) as u32),
);
wt.xconn
self.target
.xconn
.xcb_connection()
.sync_set_counter(sync_counter_id, Int64 { lo, hi })
.expect_then_ignore_error("Failed to set XSync counter.");
return;
}
@ -526,7 +497,7 @@ impl EventProcessor {
};
// Log this timestamp.
wt.xconn.set_timestamp(time);
self.target.xconn.set_timestamp(time);
// This results in the `SelectionNotify` event below
unsafe {
@ -580,16 +551,15 @@ impl EventProcessor {
fn selection_notify<F>(&mut self, xev: &XSelectionEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let atoms = wt.xconn.atoms();
let atoms = self.target.xconn.atoms();
let window = xev.requestor as xproto::Window;
let window_id = mkwid(window);
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
if xev.property != atoms[XdndSelection] as c_ulong {
return;
@ -614,10 +584,8 @@ impl EventProcessor {
fn configure_notify<F>(&self, xev: &XConfigureEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let xwindow = xev.window as xproto::Window;
let window_id = mkwid(xwindow);
@ -672,7 +640,8 @@ impl EventProcessor {
// We need to convert client area position to window position.
let frame_extents =
shared_state_lock.frame_extents.as_ref().cloned().unwrap_or_else(|| {
let frame_extents = wt.xconn.get_frame_extents_heuristic(xwindow, wt.root);
let frame_extents =
self.target.xconn.get_frame_extents_heuristic(xwindow, self.target.root);
shared_state_lock.frame_extents = Some(frame_extents.clone());
frame_extents
});
@ -703,7 +672,8 @@ impl EventProcessor {
let last_scale_factor = shared_state_lock.last_monitor.scale_factor;
let new_scale_factor = {
let window_rect = util::AaRect::new(new_outer_position, new_inner_size);
let monitor = wt
let monitor = self
.target
.xconn
.get_monitor_for_window(Some(window_rect))
.expect("Failed to find monitor for window");
@ -798,9 +768,7 @@ impl EventProcessor {
/// really have much impact, since on the WMs affected (xmonad, dwm, etc.) the only
/// effect is that we waste some time trying to query unsupported properties.
fn reparent_notify(&self, xev: &XReparentEvent) {
let wt = Self::window_target(&self.target);
wt.xconn.update_cached_wm_info(wt.root);
self.target.xconn.update_cached_wm_info(self.target.root);
self.with_window(xev.window as xproto::Window, |window| {
window.invalidate_cached_frame_extents();
@ -809,7 +777,7 @@ impl EventProcessor {
fn map_notify<F>(&self, xev: &XMapEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let window = xev.window as xproto::Window;
let window_id = mkwid(window);
@ -827,20 +795,18 @@ impl EventProcessor {
fn destroy_notify<F>(&self, xev: &XDestroyWindowEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let window = xev.window as xproto::Window;
let window_id = mkwid(window);
// In the event that the window's been destroyed without being dropped first, we
// cleanup again here.
wt.windows.borrow_mut().remove(&WindowId(window as _));
self.target.windows.borrow_mut().remove(&WindowId(window as _));
// Since all XIM stuff needs to happen from the same thread, we destroy the input
// context here instead of when dropping the window.
if let Some(ime) = wt.ime.as_ref() {
if let Some(ime) = self.target.ime.as_ref() {
ime.borrow_mut()
.remove_context(window as XWindow)
.expect("Failed to destroy input context");
@ -851,10 +817,9 @@ impl EventProcessor {
fn property_notify<F>(&mut self, xev: &XPropertyEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let atoms = wt.x_connection().atoms();
let atoms = self.target.x_connection().atoms();
let atom = xev.atom as xproto::Atom;
if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER)
@ -866,7 +831,7 @@ impl EventProcessor {
fn visibility_notify<F>(&self, xev: &XVisibilityEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let xwindow = xev.window as xproto::Window;
@ -883,7 +848,7 @@ impl EventProcessor {
fn expose<F>(&self, xev: &XExposeEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
// Multiple Expose events may be received for subareas of a window.
// We issue `RedrawRequested` only for the last event of such a series.
@ -899,12 +864,10 @@ impl EventProcessor {
fn xinput_key_input<F>(&mut self, xev: &mut XKeyEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
let window = match self.active_window {
Some(window) => window,
@ -989,12 +952,10 @@ impl EventProcessor {
return;
}
let wt = Self::window_target(&self.target);
if let Some(ic) =
wt.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow))
self.target.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow))
{
let written = wt.xconn.lookup_utf8(ic, xev);
let written = self.target.xconn.lookup_utf8(ic, xev);
if !written.is_empty() {
let event = Event::WindowEvent {
window_id,
@ -1017,15 +978,14 @@ impl EventProcessor {
state: u16,
mut callback: F,
) where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let keymap = match self.xkb_context.keymap_mut() {
Some(keymap) => keymap,
None => return,
};
let wt = Self::window_target(&self.target);
let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
// Use synthetic state since we're replaying the modifier. The user modifier state
// will be restored later.
@ -1046,14 +1006,13 @@ impl EventProcessor {
fn xinput2_button_input<F>(&self, event: &XIDeviceEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let window_id = mkwid(event.event as xproto::Window);
let device_id = mkdid(event.deviceid as xinput::DeviceId);
// Set the timestamp.
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
// Deliver multi-touch events instead of emulated mouse events.
if (event.flags & xinput2::XIPointerEmulated) != 0 {
@ -1099,12 +1058,10 @@ impl EventProcessor {
fn xinput2_mouse_motion<F>(&self, event: &XIDeviceEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
let device_id = mkdid(event.deviceid as xinput::DeviceId);
let window = event.event as xproto::Window;
@ -1174,18 +1131,16 @@ impl EventProcessor {
fn xinput2_mouse_enter<F>(&self, event: &XIEnterEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
let window = event.event as xproto::Window;
let window_id = mkwid(window);
let device_id = mkdid(event.deviceid as xinput::DeviceId);
if let Some(all_info) = DeviceInfo::get(&wt.xconn, super::ALL_DEVICES.into()) {
if let Some(all_info) = DeviceInfo::get(&self.target.xconn, super::ALL_DEVICES.into()) {
let mut devices = self.devices.borrow_mut();
for device_info in all_info.iter() {
// The second expression is need for resetting to work correctly on i3, and
@ -1219,13 +1174,12 @@ impl EventProcessor {
fn xinput2_mouse_left<F>(&self, event: &XILeaveEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let window = event.event as xproto::Window;
// Set the timestamp.
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
// Leave, FocusIn, and FocusOut can be received by a window that's already
// been destroyed, which the user presumably doesn't want to deal with.
@ -1242,15 +1196,14 @@ impl EventProcessor {
fn xinput2_focused<F>(&mut self, xev: &XIFocusInEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let window = xev.event as xproto::Window;
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
if let Some(ime) = wt.ime.as_ref() {
if let Some(ime) = self.target.ime.as_ref() {
ime.borrow_mut().focus(xev.event).expect("Failed to focus input context");
}
@ -1260,7 +1213,7 @@ impl EventProcessor {
self.active_window = Some(window);
wt.update_listen_device_events(true);
self.target.update_listen_device_events(true);
let window_id = mkwid(window);
let position = PhysicalPosition::new(xev.event_x, xev.event_y);
@ -1301,26 +1254,25 @@ impl EventProcessor {
fn xinput2_unfocused<F>(&mut self, xev: &XIFocusOutEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let window = xev.event as xproto::Window;
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
if !self.window_exists(window) {
return;
}
if let Some(ime) = wt.ime.as_ref() {
if let Some(ime) = self.target.ime.as_ref() {
ime.borrow_mut().unfocus(xev.event).expect("Failed to unfocus input context");
}
if self.active_window.take() == Some(window) {
let window_id = mkwid(window);
wt.update_listen_device_events(false);
self.target.update_listen_device_events(false);
// Clear the modifiers when unfocusing the window.
if let Some(xkb_state) = self.xkb_context.state_mut() {
@ -1353,12 +1305,10 @@ impl EventProcessor {
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
let window = xev.event as xproto::Window;
if self.window_exists(window) {
@ -1395,12 +1345,10 @@ impl EventProcessor {
fn xinput2_raw_button_input<F>(&self, xev: &XIRawEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
if xev.flags & xinput2::XIPointerEmulated == 0 {
let event = Event::DeviceEvent {
@ -1413,12 +1361,10 @@ impl EventProcessor {
fn xinput2_raw_mouse_motion<F>(&self, xev: &XIRawEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
let did = mkdid(xev.deviceid as xinput::DeviceId);
@ -1467,12 +1413,10 @@ impl EventProcessor {
fn xinput2_raw_key_input<F>(&mut self, xev: &XIRawEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
let device_id = mkdid(xev.sourceid as xinput::DeviceId);
let keycode = xev.detail as u32;
@ -1488,10 +1432,8 @@ impl EventProcessor {
}
fn xinput2_hierarchy_changed(&mut self, xev: &XIHierarchyEvent) {
let wt = Self::window_target(&self.target);
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
let infos = unsafe { slice::from_raw_parts(xev.info, xev.num_info as usize) };
for info in infos {
if 0 != info.flags & (xinput2::XISlaveAdded | xinput2::XIMasterAdded) {
@ -1505,15 +1447,14 @@ impl EventProcessor {
fn xkb_event<F>(&mut self, xev: &XkbAnyEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
match xev.xkb_type {
xlib::XkbNewKeyboardNotify => {
let xev = unsafe { &*(xev as *const _ as *const xlib::XkbNewKeyboardNotifyEvent) };
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
let keycodes_changed_flag = 0x1;
let geometry_changed_flag = 0x1 << 1;
@ -1524,9 +1465,9 @@ impl EventProcessor {
if xev.device == self.xkb_context.core_keyboard_id
&& (keycodes_changed || geometry_changed)
{
let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
self.xkb_context.set_keymap_from_x11(xcb);
self.xmodmap.reload_from_x_connection(&wt.xconn);
self.xmodmap.reload_from_x_connection(&self.target.xconn);
let window_id = match self.active_window.map(super::mkwid) {
Some(window_id) => window_id,
@ -1540,9 +1481,9 @@ impl EventProcessor {
}
},
xlib::XkbMapNotify => {
let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
self.xkb_context.set_keymap_from_x11(xcb);
self.xmodmap.reload_from_x_connection(&wt.xconn);
self.xmodmap.reload_from_x_connection(&self.target.xconn);
let window_id = match self.active_window.map(super::mkwid) {
Some(window_id) => window_id,
None => return,
@ -1557,7 +1498,7 @@ impl EventProcessor {
let xev = unsafe { &*(xev as *const _ as *const xlib::XkbStateNotifyEvent) };
// Set the timestamp.
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
if let Some(state) = self.xkb_context.state_mut() {
state.update_modifiers(
@ -1589,7 +1530,7 @@ impl EventProcessor {
force: bool,
mut callback: F,
) where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
if let Some(state) = self.xkb_context.state_mut() {
state.update_modifiers(
@ -1615,10 +1556,8 @@ impl EventProcessor {
fn update_mods_from_query<F>(&mut self, window_id: crate::window::WindowId, mut callback: F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
let xkb_state = match self.xkb_context.state_mut() {
Some(xkb_state) => xkb_state,
None => return,
@ -1626,8 +1565,11 @@ impl EventProcessor {
unsafe {
let mut state: XkbStateRec = std::mem::zeroed();
if (wt.xconn.xlib.XkbGetState)(wt.xconn.display, XkbId::USE_CORE_KBD.into(), &mut state)
== xlib::True
if (self.target.xconn.xlib.XkbGetState)(
self.target.xconn.display,
XkbId::USE_CORE_KBD.into(),
&mut state,
) == xlib::True
{
xkb_state.update_modifiers(
state.base_mods as u32,
@ -1650,7 +1592,7 @@ impl EventProcessor {
state: u16,
mut callback: F,
) where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let xkb_mask = self.xkb_mod_mask_from_core(state);
let xkb_state = match self.xkb_context.state_mut() {
@ -1723,7 +1665,7 @@ impl EventProcessor {
///
/// The event won't be sent when the `modifiers` match the previously `sent` modifiers value,
/// unless `force` is passed. The `force` should be passed when the active window changes.
fn send_modifiers<F: FnMut(&RootAEL, Event)>(
fn send_modifiers<F: FnMut(&ActiveEventLoop, Event)>(
&self,
window_id: crate::window::WindowId,
modifiers: ModifiersState,
@ -1742,19 +1684,18 @@ impl EventProcessor {
}
fn handle_pressed_keys<F>(
target: &RootAEL,
target: &ActiveEventLoop,
window_id: crate::window::WindowId,
state: ElementState,
xkb_context: &mut Context,
callback: &mut F,
) where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
// Update modifiers state and emit key events based on which keys are currently pressed.
let window_target = Self::window_target(target);
let xcb = window_target.xconn.xcb_connection().get_raw_xcb_connection();
let xcb = target.xconn.xcb_connection().get_raw_xcb_connection();
let keymap = match xkb_context.keymap_mut() {
Some(keymap) => keymap,
@ -1771,9 +1712,7 @@ impl EventProcessor {
None => return,
};
for keycode in
window_target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET)
{
for keycode in target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET) {
let event = key_processor.process_key_event(keycode as u32, state, false);
let event = Event::WindowEvent {
window_id,
@ -1785,21 +1724,20 @@ impl EventProcessor {
fn process_dpi_change<F>(&self, callback: &mut F)
where
F: FnMut(&RootAEL, Event),
F: FnMut(&ActiveEventLoop, Event),
{
let wt = Self::window_target(&self.target);
wt.xconn.reload_database().expect("failed to reload Xft database");
self.target.xconn.reload_database().expect("failed to reload Xft database");
// In the future, it would be quite easy to emit monitor hotplug events.
let prev_list = {
let prev_list = wt.xconn.invalidate_cached_monitor_list();
let prev_list = self.target.xconn.invalidate_cached_monitor_list();
match prev_list {
Some(prev_list) => prev_list,
None => return,
}
};
let new_list = wt.xconn.available_monitors().expect("Failed to get monitor list");
let new_list = self.target.xconn.available_monitors().expect("Failed to get monitor list");
for new_monitor in new_list {
// Previous list may be empty, in case of disconnecting and
// reconnecting the only one monitor. We still need to emit events in
@ -1809,7 +1747,7 @@ impl EventProcessor {
.find(|prev_monitor| prev_monitor.name == new_monitor.name)
.map(|prev_monitor| prev_monitor.scale_factor);
if Some(new_monitor.scale_factor) != maybe_prev_scale_factor {
for window in wt.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) {
for window in self.target.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) {
window.refresh_dpi_for_monitor(&new_monitor, maybe_prev_scale_factor, |event| {
callback(&self.target, event);
})

View file

@ -1,7 +1,7 @@
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet, VecDeque};
use std::ffi::CStr;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::os::raw::*;
@ -27,14 +27,17 @@ use x11rb::xcb_ffi::ReplyOrIdError;
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, ExternalError, OsError as RootOsError};
use crate::event::{Event, StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
OwnedDisplayHandle as RootOwnedDisplayHandle,
};
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::common::xkb::Context;
use crate::platform_impl::platform::{min_timeout, WindowId};
use crate::platform_impl::{
ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor,
use crate::platform_impl::{OsError, OwnedDisplayHandle, PlatformCustomCursor};
use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowAttributes,
};
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, WindowAttributes};
mod activation;
mod atoms;
@ -310,11 +313,8 @@ impl EventLoop {
// Set initial device event filter.
window_target.update_listen_device_events(true);
let root_window_target =
RootAEL { p: PlatformActiveEventLoop::X(window_target), _marker: PhantomData };
let event_processor = EventProcessor {
target: root_window_target,
target: window_target,
dnd,
devices: Default::default(),
randr_event_offset,
@ -335,9 +335,9 @@ impl EventLoop {
// Register for device hotplug events
// (The request buffer is flushed during `init_device`)
let xconn = &EventProcessor::window_target(&event_processor.target).xconn;
xconn
event_processor
.target
.xconn
.select_xinput_events(
root,
ALL_DEVICES,
@ -345,7 +345,9 @@ impl EventLoop {
)
.expect_then_ignore_error("Failed to register for XInput2 device hotplug events");
xconn
event_processor
.target
.xconn
.select_xkb_events(
0x100, // Use the "core keyboard device"
xkb::EventType::NEW_KEYBOARD_NOTIFY
@ -366,7 +368,7 @@ impl EventLoop {
}
}
pub(crate) fn window_target(&self) -> &RootAEL {
pub(crate) fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.event_processor.target
}
@ -378,7 +380,7 @@ impl EventLoop {
&mut self,
mut app: A,
) -> Result<(), EventLoopError> {
self.event_processor.target.p.clear_exit();
self.event_processor.target.clear_exit();
let exit = loop {
match self.pump_app_events(None, &mut app) {
PumpStatus::Exit(0) => {
@ -397,8 +399,7 @@ impl EventLoop {
// `run_on_demand` calls but if they have only just dropped their
// windows we need to make sure those last requests are sent to the
// X Server.
let wt = EventProcessor::window_target(&self.event_processor.target);
wt.x_connection().sync_with_server().map_err(|x_err| {
self.event_processor.target.x_connection().sync_with_server().map_err(|x_err| {
EventLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err)))))
})?;
@ -576,7 +577,6 @@ impl EventLoop {
event: WindowEvent::RedrawRequested,
} = event
{
let window_target = EventProcessor::window_target(window_target);
window_target.redraw_sender.send(wid);
} else {
match event {
@ -594,21 +594,19 @@ impl EventLoop {
}
fn control_flow(&self) -> ControlFlow {
let window_target = EventProcessor::window_target(&self.event_processor.target);
window_target.control_flow()
self.event_processor.target.control_flow()
}
fn exiting(&self) -> bool {
let window_target = EventProcessor::window_target(&self.event_processor.target);
window_target.exiting()
self.event_processor.target.exiting()
}
fn set_exit_code(&self, code: i32) {
self.window_target().p.set_exit_code(code);
self.event_processor.target.set_exit_code(code);
}
fn exit_code(&self) -> Option<i32> {
self.window_target().p.exit_code()
self.event_processor.target.exit_code()
}
}
@ -625,37 +623,12 @@ impl AsRawFd for EventLoop {
}
impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
self.event_loop_proxy.clone()
}
/// Returns the `XConnection` of this events loop.
#[inline]
pub(crate) fn x_connection(&self) -> &Arc<XConnection> {
&self.xconn
}
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
self.xconn.available_monitors().into_iter().flatten()
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
self.xconn.primary_monitor().ok()
}
pub(crate) fn create_custom_cursor(
&self,
cursor: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor {
inner: PlatformCustomCursor::X(CustomCursor::new(self, cursor.inner)?),
})
}
pub fn listen_device_events(&self, allowed: DeviceEvents) {
self.device_events.set(allowed);
}
/// Update the device event based on window focus.
pub fn update_listen_device_events(&self, focus: bool) {
let device_events = self.device_events.get() == DeviceEvents::Always
@ -690,26 +663,10 @@ impl ActiveEventLoop {
Ok(display_handle.into())
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
self.control_flow.set(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
self.control_flow.get()
}
pub(crate) fn exit(&self) {
self.exit.set(Some(0))
}
pub(crate) fn clear_exit(&self) {
self.exit.set(None)
}
pub(crate) fn exiting(&self) -> bool {
self.exit.get().is_some()
}
pub(crate) fn set_exit_code(&self, code: i32) {
self.exit.set(Some(code))
}
@ -719,6 +676,99 @@ impl ActiveEventLoop {
}
}
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy {
crate::event_loop::EventLoopProxy {
event_loop_proxy: crate::platform_impl::EventLoopProxy::X(
self.event_loop_proxy.clone(),
),
}
}
fn create_window(
&self,
window_attributes: WindowAttributes,
) -> Result<crate::window::Window, RootOsError> {
let window = crate::platform_impl::x11::Window::new(self, window_attributes)?;
let window = crate::platform_impl::Window::X(window);
Ok(crate::window::Window { window })
}
fn create_custom_cursor(
&self,
custom_cursor: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor {
inner: PlatformCustomCursor::X(CustomCursor::new(self, custom_cursor.inner)?),
})
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
Box::new(
self.xconn
.available_monitors()
.into_iter()
.flatten()
.map(crate::platform_impl::MonitorHandle::X)
.map(|inner| crate::monitor::MonitorHandle { inner }),
)
}
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
self.xconn
.primary_monitor()
.ok()
.map(crate::platform_impl::MonitorHandle::X)
.map(|inner| crate::monitor::MonitorHandle { inner })
}
fn system_theme(&self) -> Option<Theme> {
None
}
fn listen_device_events(&self, allowed: DeviceEvents) {
self.device_events.set(allowed);
}
fn set_control_flow(&self, control_flow: ControlFlow) {
self.control_flow.set(control_flow)
}
fn control_flow(&self) -> ControlFlow {
self.control_flow.get()
}
fn exit(&self) {
self.exit.set(Some(0))
}
fn exiting(&self) -> bool {
self.exit.get().is_some()
}
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
let handle = OwnedDisplayHandle::X(self.x_connection().clone());
RootOwnedDisplayHandle { platform: handle }
}
fn as_any(&self) -> &dyn Any {
self
}
#[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 = self.raw_display_handle_rwh_06()?;
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
impl EventLoopProxy {
pub fn wake_up(&self) {
self.ping.ping();

View file

@ -1,6 +1,6 @@
use std::any::Any;
use std::cell::Cell;
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::sync::{mpsc, Arc, Mutex};
use std::time::Instant;
use std::{mem, slice};
@ -19,7 +19,7 @@ use super::{
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, ExternalError, NotSupportedError};
use crate::event::{self, Ime, Modifiers, StartCause};
use crate::event_loop::{self, ControlFlow, DeviceEvents};
use crate::event_loop::{self, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
use crate::keyboard::{
Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode,
PhysicalKey,
@ -273,7 +273,7 @@ impl EventState {
pub struct EventLoop {
windows: Vec<(Arc<RedoxSocket>, EventState)>,
window_target: event_loop::ActiveEventLoop,
window_target: ActiveEventLoop,
user_events_receiver: mpsc::Receiver<()>,
}
@ -306,18 +306,15 @@ impl EventLoop {
Ok(Self {
windows: Vec::new(),
window_target: event_loop::ActiveEventLoop {
p: ActiveEventLoop {
control_flow: Cell::new(ControlFlow::default()),
exit: Cell::new(false),
creates: Mutex::new(VecDeque::new()),
redraws: Arc::new(Mutex::new(VecDeque::new())),
destroys: Arc::new(Mutex::new(VecDeque::new())),
event_socket,
wake_socket,
user_events_sender,
},
_marker: PhantomData,
window_target: ActiveEventLoop {
control_flow: Cell::new(ControlFlow::default()),
exit: Cell::new(false),
creates: Mutex::new(VecDeque::new()),
redraws: Arc::new(Mutex::new(VecDeque::new())),
destroys: Arc::new(Mutex::new(VecDeque::new())),
event_socket,
wake_socket,
user_events_sender,
},
user_events_receiver,
})
@ -327,7 +324,7 @@ impl EventLoop {
window_id: WindowId,
event_option: EventOption,
event_state: &mut EventState,
window_target: &event_loop::ActiveEventLoop,
window_target: &ActiveEventLoop,
app: &mut A,
) {
match event_option {
@ -511,7 +508,7 @@ impl EventLoop {
// Handle window creates.
while let Some(window) = {
let mut creates = self.window_target.p.creates.lock().unwrap();
let mut creates = self.window_target.creates.lock().unwrap();
creates.pop_front()
} {
let window_id = WindowId { fd: window.fd as u64 };
@ -535,7 +532,7 @@ impl EventLoop {
// Handle window destroys.
while let Some(destroy_id) = {
let mut destroys = self.window_target.p.destroys.lock().unwrap();
let mut destroys = self.window_target.destroys.lock().unwrap();
destroys.pop_front()
} {
let window_id = RootWindowId(destroy_id);
@ -584,7 +581,7 @@ impl EventLoop {
.expect("failed to acknowledge resize");
// Require redraw after resize.
let mut redraws = self.window_target.p.redraws.lock().unwrap();
let mut redraws = self.window_target.redraws.lock().unwrap();
if !redraws.contains(&window_id) {
redraws.push_back(window_id);
}
@ -600,7 +597,7 @@ impl EventLoop {
// To avoid deadlocks the redraws lock is not held during event processing.
while let Some(window_id) = {
let mut redraws = self.window_target.p.redraws.lock().unwrap();
let mut redraws = self.window_target.redraws.lock().unwrap();
redraws.pop_front()
} {
app.window_event(
@ -612,11 +609,11 @@ impl EventLoop {
app.about_to_wait(&self.window_target);
if self.window_target.p.exiting() {
if self.window_target.exiting() {
break;
}
let requested_resume = match self.window_target.p.control_flow() {
let requested_resume = match self.window_target.control_flow() {
ControlFlow::Poll => {
start_cause = StartCause::Poll;
continue;
@ -630,7 +627,6 @@ impl EventLoop {
let timeout_socket = TimeSocket::open().unwrap();
self.window_target
.p
.event_socket
.write(&syscall::Event {
id: timeout_socket.0.fd,
@ -658,7 +654,7 @@ impl EventLoop {
// Wait for event if needed.
let mut event = syscall::Event::default();
self.window_target.p.event_socket.read(&mut event).unwrap();
self.window_target.event_socket.read(&mut event).unwrap();
// TODO: handle spurious wakeups (redraw caused wakeup but redraw already handled)
match requested_resume {
@ -679,7 +675,7 @@ impl EventLoop {
Ok(())
}
pub fn window_target(&self) -> &event_loop::ActiveEventLoop {
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.window_target
}
}
@ -721,65 +717,82 @@ pub struct ActiveEventLoop {
user_events_sender: mpsc::SyncSender<()>,
}
impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy {
user_events_sender: self.user_events_sender.clone(),
wake_socket: self.wake_socket.clone(),
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> event_loop::EventLoopProxy {
event_loop::EventLoopProxy {
event_loop_proxy: EventLoopProxy {
user_events_sender: self.user_events_sender.clone(),
wake_socket: self.wake_socket.clone(),
},
}
}
pub fn create_custom_cursor(
fn create_window(
&self,
_source: CustomCursorSource,
window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> {
let window = crate::platform_impl::Window::new(self, window_attributes)?;
Ok(crate::window::Window { window })
}
fn create_custom_cursor(
&self,
_: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
Some(MonitorHandle)
}
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
let mut v = VecDeque::with_capacity(1);
v.push_back(MonitorHandle);
v
v.push_back(crate::monitor::MonitorHandle { inner: MonitorHandle });
Box::new(v.into_iter())
}
#[inline]
pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
#[inline]
pub fn system_theme(&self) -> Option<Theme> {
fn system_theme(&self) -> Option<Theme> {
None
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new()))
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
Some(crate::monitor::MonitorHandle { inner: MonitorHandle })
}
pub fn set_control_flow(&self, control_flow: ControlFlow) {
fn listen_device_events(&self, _allowed: DeviceEvents) {}
fn set_control_flow(&self, control_flow: ControlFlow) {
self.control_flow.set(control_flow)
}
pub fn control_flow(&self) -> ControlFlow {
fn control_flow(&self) -> ControlFlow {
self.control_flow.get()
}
pub(crate) fn exit(&self) {
fn exit(&self) {
self.exit.set(true);
}
pub(crate) fn exiting(&self) -> bool {
fn exiting(&self) -> bool {
self.exit.get()
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
fn owned_display_handle(&self) -> event_loop::OwnedDisplayHandle {
event_loop::OwnedDisplayHandle { platform: OwnedDisplayHandle }
}
fn as_any(&self) -> &dyn Any {
self
}
#[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::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new());
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}

View file

@ -1,11 +1,9 @@
use std::marker::PhantomData;
use super::{backend, device, window, HasMonitorPermissionFuture, MonitorPermissionFuture};
use crate::application::ApplicationHandler;
use crate::error::{EventLoopError, NotSupportedError};
use crate::event::Event;
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
use crate::platform::web::{ActiveEventLoopExtWeb, PollStrategy, WaitUntilStrategy};
use crate::platform::web::{PollStrategy, WaitUntilStrategy};
mod proxy;
pub(crate) mod runner;
@ -16,7 +14,7 @@ pub(crate) use proxy::EventLoopProxy;
pub(crate) use window_target::{ActiveEventLoop, OwnedDisplayHandle};
pub struct EventLoop {
elw: RootActiveEventLoop,
elw: ActiveEventLoop,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -24,16 +22,15 @@ pub(crate) struct PlatformSpecificEventLoopAttributes {}
impl EventLoop {
pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
let elw = RootActiveEventLoop { p: ActiveEventLoop::new(), _marker: PhantomData };
Ok(EventLoop { elw })
Ok(EventLoop { elw: ActiveEventLoop::new() })
}
pub fn run_app<A: ApplicationHandler>(self, mut app: A) -> ! {
let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData };
let event_loop = self.elw.clone();
// SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`.
let handler: Box<dyn FnMut(Event)> =
Box::new(|event| handle_event(&mut app, &target, event));
Box::new(|event| handle_event(&mut app, &event_loop, event));
// SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe
// because this function will never return and all resources not cleaned up by the point we
@ -41,7 +38,7 @@ impl EventLoop {
let handler = unsafe {
std::mem::transmute::<Box<dyn FnMut(Event)>, Box<dyn FnMut(Event) + 'static>>(handler)
};
self.elw.p.run(handler, false);
self.elw.run(handler, false);
// Throw an exception to break out of Rust execution and use unreachable to tell the
// compiler this function won't return, giving it a return type of '!'
@ -53,12 +50,11 @@ impl EventLoop {
}
pub fn spawn_app<A: ApplicationHandler + 'static>(self, mut app: A) {
let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData };
self.elw.p.run(Box::new(move |event| handle_event(&mut app, &target, event)), true);
let event_loop = self.elw.clone();
self.elw.run(Box::new(move |event| handle_event(&mut app, &event_loop, event)), true);
}
pub fn window_target(&self) -> &RootActiveEventLoop {
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.elw
}
@ -83,15 +79,15 @@ impl EventLoop {
}
pub(crate) fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture {
self.elw.request_detailed_monitor_permission().0
self.elw.request_detailed_monitor_permission()
}
pub fn has_detailed_monitor_permission(&self) -> HasMonitorPermissionFuture {
self.elw.p.runner.monitor().has_detailed_monitor_permission_async()
self.elw.runner.monitor().has_detailed_monitor_permission_async()
}
}
fn handle_event<A: ApplicationHandler>(app: &mut A, target: &RootActiveEventLoop, event: Event) {
fn handle_event<A: ApplicationHandler>(app: &mut A, target: &ActiveEventLoop, event: Event) {
match event {
Event::NewEvents(cause) => app.new_events(target, cause),
Event::WindowEvent { window_id, event } => app.window_event(target, window_id, event),

View file

@ -1,3 +1,4 @@
use std::any::Any;
use std::cell::Cell;
use std::clone::Clone;
use std::iter;
@ -5,7 +6,7 @@ use std::rc::Rc;
use web_sys::Element;
use super::super::monitor::{MonitorHandle, MonitorPermissionFuture};
use super::super::monitor::MonitorPermissionFuture;
use super::super::{lock, KeyEventExtra};
use super::device::DeviceId;
use super::runner::{EventWrapper, WeakShared};
@ -15,13 +16,19 @@ use crate::error::{ExternalError, NotSupportedError};
use crate::event::{
DeviceId as RootDeviceId, ElementState, Event, KeyEvent, Touch, TouchPhase, WindowEvent,
};
use crate::event_loop::{ControlFlow, DeviceEvents};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
};
use crate::keyboard::ModifiersState;
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy};
use crate::platform_impl::platform::cursor::CustomCursor;
use crate::platform_impl::platform::r#async::Waker;
use crate::platform_impl::Window;
use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId,
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow,
WindowId as RootWindowId,
};
#[derive(Default)]
@ -67,17 +74,6 @@ impl ActiveEventLoop {
WindowId(self.runner.generate_id())
}
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy::new(self.waker())
}
pub fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: CustomCursor::new(self, source.inner) })
}
pub fn create_custom_cursor_async(&self, source: CustomCursorSource) -> CustomCursorFuture {
CustomCursorFuture(CustomCursor::new_async(self, source.inner))
}
@ -594,52 +590,6 @@ impl ActiveEventLoop {
canvas.on_context_menu();
}
pub fn available_monitors(&self) -> Vec<MonitorHandle> {
self.runner.monitor().available_monitors()
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
self.runner.monitor().primary_monitor()
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new()))
}
pub fn listen_device_events(&self, allowed: DeviceEvents) {
self.runner.listen_device_events(allowed)
}
pub fn system_theme(&self) -> Option<Theme> {
backend::is_dark_mode(self.runner.window()).map(|is_dark_mode| {
if is_dark_mode {
Theme::Dark
} else {
Theme::Light
}
})
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
self.runner.set_control_flow(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
self.runner.control_flow()
}
pub(crate) fn exit(&self) {
self.runner.exit()
}
pub(crate) fn exiting(&self) -> bool {
self.runner.exiting()
}
pub(crate) fn set_poll_strategy(&self, strategy: PollStrategy) {
self.runner.set_poll_strategy(strategy)
}
@ -675,9 +625,92 @@ impl ActiveEventLoop {
pub(crate) fn waker(&self) -> Waker<WeakShared> {
self.runner.waker()
}
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy {
let event_loop_proxy = EventLoopProxy::new(self.waker());
RootEventLoopProxy { event_loop_proxy }
}
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
}
fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: CustomCursor::new(self, source.inner) })
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
Box::new(
self.runner
.monitor()
.available_monitors()
.into_iter()
.map(|inner| RootMonitorHandle { inner }),
)
}
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
self.runner.monitor().primary_monitor().map(|inner| RootMonitorHandle { inner })
}
fn listen_device_events(&self, allowed: DeviceEvents) {
self.runner.listen_device_events(allowed)
}
fn system_theme(&self) -> Option<Theme> {
backend::is_dark_mode(self.runner.window()).map(|is_dark_mode| {
if is_dark_mode {
Theme::Dark
} else {
Theme::Light
}
})
}
fn set_control_flow(&self, control_flow: ControlFlow) {
self.runner.set_control_flow(control_flow)
}
fn control_flow(&self) -> ControlFlow {
self.runner.control_flow()
}
fn exit(&self) {
self.runner.exit()
}
fn exiting(&self) -> bool {
self.runner.exiting()
}
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
RootOwnedDisplayHandle { platform: OwnedDisplayHandle }
}
fn as_any(&self) -> &dyn Any {
self
}
#[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::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new());
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}

View file

@ -3,9 +3,7 @@
mod runner;
use std::cell::Cell;
use std::collections::VecDeque;
use std::ffi::c_void;
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::{Arc, Mutex, MutexGuard};
@ -58,12 +56,16 @@ use super::window::set_skip_taskbar;
use super::SelectedCursor;
use crate::application::ApplicationHandler;
use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::error::{EventLoopError, ExternalError};
use crate::error::{EventLoopError, ExternalError, OsError};
use crate::event::{
Event, Force, Ime, InnerSizeWriter, RawKeyEvent, Touch, TouchPhase, WindowEvent,
};
use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
};
use crate::keyboard::ModifiersState;
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::platform::dark_mode::try_theme;
use crate::platform_impl::platform::dpi::{become_dpi_aware, dpi_to_scale_factor};
@ -80,9 +82,11 @@ use crate::platform_impl::platform::window_state::{
use crate::platform_impl::platform::{
raw_input, util, wrap_device_id, Fullscreen, WindowId, DEVICE_ID,
};
use crate::platform_impl::Window;
use crate::utils::Lazy;
use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId,
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow,
WindowAttributes, WindowId as RootWindowId,
};
pub(crate) struct WindowData {
@ -122,7 +126,7 @@ pub(crate) enum ProcResult {
}
pub struct EventLoop {
window_target: RootAEL,
window_target: ActiveEventLoop,
msg_hook: Option<Box<dyn FnMut(*const c_void) -> bool + 'static>>,
}
@ -174,15 +178,12 @@ impl EventLoop {
);
Ok(EventLoop {
window_target: RootAEL {
p: ActiveEventLoop { thread_id, thread_msg_target, runner_shared },
_marker: PhantomData,
},
window_target: ActiveEventLoop { thread_id, thread_msg_target, runner_shared },
msg_hook: attributes.msg_hook.take(),
})
}
pub fn window_target(&self) -> &RootAEL {
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
&self.window_target
}
@ -194,9 +195,9 @@ impl EventLoop {
&mut self,
mut app: A,
) -> Result<(), EventLoopError> {
self.window_target.p.clear_exit();
self.window_target.clear_exit();
{
let runner = &self.window_target.p.runner_shared;
let runner = &self.window_target.runner_shared;
let event_loop_windows_ref = &self.window_target;
// # Safety
@ -236,7 +237,7 @@ impl EventLoop {
}
};
let runner = &self.window_target.p.runner_shared;
let runner = &self.window_target.runner_shared;
runner.loop_destroyed();
// # Safety
@ -257,7 +258,7 @@ impl EventLoop {
mut app: A,
) -> PumpStatus {
{
let runner = &self.window_target.p.runner_shared;
let runner = &self.window_target.runner_shared;
let event_loop_windows_ref = &self.window_target;
// let user_event_receiver = &self.user_event_receiver;
@ -296,7 +297,7 @@ impl EventLoop {
self.dispatch_peeked_messages();
}
let runner = &self.window_target.p.runner_shared;
let runner = &self.window_target.runner_shared;
let status = if let Some(code) = runner.exit_code() {
runner.loop_destroyed();
@ -358,7 +359,7 @@ impl EventLoop {
}
}
let runner = &self.window_target.p.runner_shared;
let runner = &self.window_target.runner_shared;
// We aim to be consistent with the MacOS backend which has a RunLoop
// observer that will dispatch AboutToWait when about to wait for
@ -420,7 +421,7 @@ impl EventLoop {
/// Dispatch all queued messages via `PeekMessageW`
fn dispatch_peeked_messages(&mut self) {
let runner = &self.window_target.p.runner_shared;
let runner = &self.window_target.runner_shared;
// We generally want to continue dispatching all pending messages
// but we also allow dispatching to be interrupted as a means to
@ -469,81 +470,100 @@ impl EventLoop {
}
fn exit_code(&self) -> Option<i32> {
self.window_target.p.exit_code()
self.window_target.exit_code()
}
}
impl ActiveEventLoop {
pub fn create_proxy(&self) -> EventLoopProxy {
EventLoopProxy { target_window: self.thread_msg_target }
}
#[inline(always)]
pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor {
EventLoopThreadExecutor { thread_id: self.thread_id, target_window: self.thread_msg_target }
}
pub fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: WinCursor::new(&source.inner.0)? })
}
// TODO: Investigate opportunities for caching
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
monitor::available_monitors()
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
let monitor = monitor::primary_monitor();
Some(monitor)
}
#[cfg(feature = "rwh_06")]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Windows(rwh_06::WindowsDisplayHandle::new()))
}
pub fn listen_device_events(&self, allowed: DeviceEvents) {
raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, allowed);
}
pub fn system_theme(&self) -> Option<Theme> {
Some(if super::dark_mode::should_use_dark_mode() { Theme::Dark } else { Theme::Light })
}
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
self.runner_shared.set_control_flow(control_flow)
}
pub(crate) fn control_flow(&self) -> ControlFlow {
self.runner_shared.control_flow()
}
pub(crate) fn exit(&self) {
self.runner_shared.set_exit_code(0)
}
pub(crate) fn exiting(&self) -> bool {
self.runner_shared.exit_code().is_some()
}
pub(crate) fn clear_exit(&self) {
self.runner_shared.clear_exit();
}
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
OwnedDisplayHandle
}
fn exit_code(&self) -> Option<i32> {
self.runner_shared.exit_code()
}
}
impl RootActiveEventLoop for ActiveEventLoop {
fn create_proxy(&self) -> RootEventLoopProxy {
let event_loop_proxy = EventLoopProxy { target_window: self.thread_msg_target };
RootEventLoopProxy { event_loop_proxy }
}
fn create_window(&self, window_attributes: WindowAttributes) -> Result<RootWindow, OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
}
fn create_custom_cursor(
&self,
source: CustomCursorSource,
) -> Result<RootCustomCursor, ExternalError> {
Ok(RootCustomCursor { inner: WinCursor::new(&source.inner.0)? })
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
Box::new(
monitor::available_monitors()
.into_iter()
.map(|inner| crate::monitor::MonitorHandle { inner }),
)
}
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
Some(RootMonitorHandle { inner: monitor::primary_monitor() })
}
fn exiting(&self) -> bool {
self.runner_shared.exit_code().is_some()
}
fn system_theme(&self) -> Option<Theme> {
Some(if super::dark_mode::should_use_dark_mode() { Theme::Dark } else { Theme::Light })
}
fn listen_device_events(&self, allowed: DeviceEvents) {
raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, allowed);
}
fn set_control_flow(&self, control_flow: ControlFlow) {
self.runner_shared.set_control_flow(control_flow)
}
fn control_flow(&self) -> ControlFlow {
self.runner_shared.control_flow()
}
fn exit(&self) {
self.runner_shared.set_exit_code(0)
}
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
RootOwnedDisplayHandle { platform: OwnedDisplayHandle }
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
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::RawDisplayHandle::Windows(rwh_06::WindowsDisplayHandle::new());
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
#[derive(Clone)]
pub(crate) struct OwnedDisplayHandle;
@ -632,7 +652,7 @@ fn dur2timeout(dur: Duration) -> u32 {
impl Drop for EventLoop {
fn drop(&mut self) {
unsafe {
DestroyWindow(self.window_target.p.thread_msg_target);
DestroyWindow(self.window_target.thread_msg_target);
}
}
}

View file

@ -3,8 +3,7 @@ use windows_sys::Win32::Foundation::{HANDLE, HWND};
use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX};
pub(crate) use self::event_loop::{
ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle,
PlatformSpecificEventLoopAttributes,
EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes,
};
pub use self::icon::WinIcon as PlatformIcon;
pub(crate) use self::icon::{SelectedCursor, WinCursor as PlatformCustomCursor, WinIcon};