event_loop: remove deprecated run APIs
The APIs are not well suited for the `&dyn ApplicationHandler` model and `Box<dyn EventLoop>` structure, thus remove them.
This commit is contained in:
parent
2b1c8cea1b
commit
3e8fa41073
16 changed files with 544 additions and 587 deletions
|
|
@ -3,50 +3,45 @@
|
|||
fn main() -> Result<(), impl std::error::Error> {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::dpi::{LogicalPosition, LogicalSize, Position};
|
||||
use winit::event::{ElementState, Event, KeyEvent, WindowEvent};
|
||||
use winit::event::{ElementState, KeyEvent, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use winit::raw_window_handle::HasRawWindowHandle;
|
||||
use winit::window::Window;
|
||||
use winit::window::{Window, WindowId};
|
||||
|
||||
#[path = "util/fill.rs"]
|
||||
mod fill;
|
||||
|
||||
fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window {
|
||||
let parent = parent.raw_window_handle().unwrap();
|
||||
let mut window_attributes = Window::default_attributes()
|
||||
.with_title("child window")
|
||||
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
|
||||
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
|
||||
.with_visible(true);
|
||||
// `with_parent_window` is unsafe. Parent window must be a valid window.
|
||||
window_attributes = unsafe { window_attributes.with_parent_window(Some(parent)) };
|
||||
|
||||
event_loop.create_window(window_attributes).unwrap()
|
||||
#[derive(Default)]
|
||||
struct Application {
|
||||
parent_window_id: Option<WindowId>,
|
||||
windows: HashMap<WindowId, Window>,
|
||||
}
|
||||
|
||||
let mut windows = HashMap::new();
|
||||
impl ApplicationHandler for Application {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
let attributes = Window::default_attributes()
|
||||
.with_title("parent window")
|
||||
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
|
||||
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
|
||||
let window = event_loop.create_window(attributes).unwrap();
|
||||
|
||||
let event_loop: EventLoop<()> = EventLoop::new().unwrap();
|
||||
let mut parent_window_id = None;
|
||||
println!("Parent window id: {:?})", window.id());
|
||||
self.parent_window_id = Some(window.id());
|
||||
|
||||
event_loop.run(move |event: Event<()>, event_loop| {
|
||||
match event {
|
||||
Event::Resumed => {
|
||||
let attributes = Window::default_attributes()
|
||||
.with_title("parent window")
|
||||
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
|
||||
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
|
||||
let window = event_loop.create_window(attributes).unwrap();
|
||||
self.windows.insert(window.id(), window);
|
||||
}
|
||||
|
||||
parent_window_id = Some(window.id());
|
||||
|
||||
println!("Parent window id: {parent_window_id:?})");
|
||||
windows.insert(window.id(), window);
|
||||
},
|
||||
Event::WindowEvent { window_id, event } => match event {
|
||||
fn window_event(
|
||||
&mut self,
|
||||
event_loop: &ActiveEventLoop,
|
||||
window_id: winit::window::WindowId,
|
||||
event: WindowEvent,
|
||||
) {
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
windows.clear();
|
||||
self.windows.clear();
|
||||
event_loop.exit();
|
||||
},
|
||||
WindowEvent::CursorEntered { device_id: _ } => {
|
||||
|
|
@ -61,22 +56,38 @@ fn main() -> Result<(), impl std::error::Error> {
|
|||
event: KeyEvent { state: ElementState::Pressed, .. },
|
||||
..
|
||||
} => {
|
||||
let parent_window = windows.get(&parent_window_id.unwrap()).unwrap();
|
||||
let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap();
|
||||
let child_window = spawn_child_window(parent_window, event_loop);
|
||||
let child_id = child_window.id();
|
||||
println!("Child window created with id: {child_id:?}");
|
||||
windows.insert(child_id, child_window);
|
||||
self.windows.insert(child_id, child_window);
|
||||
},
|
||||
WindowEvent::RedrawRequested => {
|
||||
if let Some(window) = windows.get(&window_id) {
|
||||
if let Some(window) = self.windows.get(&window_id) {
|
||||
fill::fill_window(window);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window {
|
||||
let parent = parent.raw_window_handle().unwrap();
|
||||
let mut window_attributes = Window::default_attributes()
|
||||
.with_title("child window")
|
||||
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
|
||||
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
|
||||
.with_visible(true);
|
||||
// `with_parent_window` is unsafe. Parent window must be a valid window.
|
||||
window_attributes = unsafe { window_attributes.with_parent_window(Some(parent)) };
|
||||
|
||||
event_loop.create_window(window_attributes).unwrap()
|
||||
}
|
||||
|
||||
let event_loop: EventLoop<()> = EventLoop::new().unwrap();
|
||||
let mut app = Application::default();
|
||||
event_loop.run_app(&mut app)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "rwh_06", not(any(x11_platform, macos_platform, windows_platform))))]
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@ changelog entry.
|
|||
|
||||
- Reexport `raw-window-handle` versions 0.4 and 0.5 as `raw_window_handle_04` and `raw_window_handle_05`.
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove `EventLoop::run`.
|
||||
- Remove `EventLoopExtRunOnDemand::run_on_demand`.
|
||||
- Remove `EventLoopExtPumpEvents::pump_events`.
|
||||
|
||||
### Fixed
|
||||
|
||||
- On macOS, fix panic on exit when dropping windows outside the event loop.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
`Fn`. The semantics are mostly the same, given that the capture list of the
|
||||
closure is your new `State`. Consider the following code:
|
||||
|
||||
```rust,no_run
|
||||
```rust,no_run,ignore
|
||||
use winit::event::Event;
|
||||
use winit::event_loop::EventLoop;
|
||||
use winit::window::Window;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use web_time::{Duration, Instant};
|
|||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::{EventLoopError, OsError};
|
||||
use crate::event::Event;
|
||||
use crate::monitor::MonitorHandle;
|
||||
use crate::platform_impl;
|
||||
use crate::window::{CustomCursor, CustomCursorSource, Window, WindowAttributes};
|
||||
|
|
@ -152,6 +151,7 @@ impl fmt::Debug for ActiveEventLoop {
|
|||
/// Defaults to [`Wait`].
|
||||
///
|
||||
/// [`Wait`]: Self::Wait
|
||||
/// [`Event::AboutToWait`]: crate::event::Event::AboutToWait
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub enum ControlFlow {
|
||||
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
|
||||
|
|
@ -216,21 +216,6 @@ impl<T> EventLoop<T> {
|
|||
EventLoopBuilder { platform_specific: Default::default(), _p: PhantomData }
|
||||
}
|
||||
|
||||
/// See [`run_app`].
|
||||
///
|
||||
/// [`run_app`]: Self::run_app
|
||||
#[inline]
|
||||
#[deprecated = "use `EventLoop::run_app` instead"]
|
||||
#[cfg(not(all(web_platform, target_feature = "exception-handling")))]
|
||||
pub fn run<F>(self, event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &ActiveEventLoop),
|
||||
{
|
||||
let _span = tracing::debug_span!("winit::EventLoop::run").entered();
|
||||
|
||||
self.event_loop.run(event_handler)
|
||||
}
|
||||
|
||||
/// Run the application with the event loop on the calling thread.
|
||||
///
|
||||
/// See the [`set_control_flow()`] docs on how to change the event loop's behavior.
|
||||
|
|
@ -262,7 +247,7 @@ impl<T> EventLoop<T> {
|
|||
#[inline]
|
||||
#[cfg(not(all(web_platform, target_feature = "exception-handling")))]
|
||||
pub fn run_app<A: ApplicationHandler<T>>(self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
self.event_loop.run(|event, event_loop| dispatch_event_for_app(app, event_loop, event))
|
||||
self.event_loop.run_app(app)
|
||||
}
|
||||
|
||||
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
|
||||
|
|
@ -449,7 +434,7 @@ impl ActiveEventLoop {
|
|||
|
||||
/// This exits the event loop.
|
||||
///
|
||||
/// See [`LoopExiting`][Event::LoopExiting].
|
||||
/// See [`LoopExiting`][crate::event::Event::LoopExiting].
|
||||
pub fn exit(&self) {
|
||||
let _span = tracing::debug_span!("winit::ActiveEventLoop::exit",).entered();
|
||||
|
||||
|
|
@ -618,23 +603,3 @@ impl AsyncRequestSerial {
|
|||
Self { serial }
|
||||
}
|
||||
}
|
||||
|
||||
/// Shim for various run APIs.
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_event_for_app<T: 'static, A: ApplicationHandler<T>>(
|
||||
app: &mut A,
|
||||
event_loop: &ActiveEventLoop,
|
||||
event: Event<T>,
|
||||
) {
|
||||
match event {
|
||||
Event::NewEvents(cause) => app.new_events(event_loop, cause),
|
||||
Event::WindowEvent { window_id, event } => app.window_event(event_loop, window_id, event),
|
||||
Event::DeviceEvent { device_id, event } => app.device_event(event_loop, device_id, event),
|
||||
Event::UserEvent(event) => app.user_event(event_loop, event),
|
||||
Event::Suspended => app.suspended(event_loop),
|
||||
Event::Resumed => app.resumed(event_loop),
|
||||
Event::AboutToWait => app.about_to_wait(event_loop),
|
||||
Event::LoopExiting => app.exiting(event_loop),
|
||||
Event::MemoryWarning => app.memory_warning(event_loop),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::{self, ActiveEventLoop, EventLoop};
|
||||
use crate::event_loop::EventLoop;
|
||||
|
||||
/// Additional methods on [`EventLoop`] for pumping events within an external event loop
|
||||
pub trait EventLoopExtPumpEvents {
|
||||
/// A type provided by the user that can be passed through [`Event::UserEvent`].
|
||||
///
|
||||
/// [`Event::UserEvent`]: crate::event::Event::UserEvent
|
||||
type UserEvent: 'static;
|
||||
|
||||
/// Pump the `EventLoop` to check for and dispatch pending events.
|
||||
|
|
@ -107,30 +108,18 @@ pub trait EventLoopExtPumpEvents {
|
|||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
#[allow(deprecated)]
|
||||
self.pump_events(timeout, |event, event_loop| {
|
||||
event_loop::dispatch_event_for_app(app, event_loop, event)
|
||||
})
|
||||
}
|
||||
|
||||
/// See [`pump_app_events`].
|
||||
///
|
||||
/// [`pump_app_events`]: Self::pump_app_events
|
||||
#[deprecated = "use EventLoopExtPumpEvents::pump_app_events"]
|
||||
fn pump_events<F>(&mut self, timeout: Option<Duration>, event_handler: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<Self::UserEvent>, &ActiveEventLoop);
|
||||
) -> PumpStatus;
|
||||
}
|
||||
|
||||
impl<T> EventLoopExtPumpEvents for EventLoop<T> {
|
||||
type UserEvent = T;
|
||||
|
||||
fn pump_events<F>(&mut self, timeout: Option<Duration>, event_handler: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<Self::UserEvent>, &ActiveEventLoop),
|
||||
{
|
||||
self.event_loop.pump_events(timeout, event_handler)
|
||||
fn pump_app_events<A: ApplicationHandler<Self::UserEvent>>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
self.event_loop.pump_app_events(timeout, app)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::application::ApplicationHandler;
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::{self, ActiveEventLoop, EventLoop};
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoop};
|
||||
|
||||
#[cfg(doc)]
|
||||
use crate::{platform::pump_events::EventLoopExtPumpEvents, window::Window};
|
||||
|
|
@ -9,15 +8,9 @@ use crate::{platform::pump_events::EventLoopExtPumpEvents, window::Window};
|
|||
/// Additional methods on [`EventLoop`] to return control flow to the caller.
|
||||
pub trait EventLoopExtRunOnDemand {
|
||||
/// A type provided by the user that can be passed through [`Event::UserEvent`].
|
||||
type UserEvent: 'static;
|
||||
|
||||
/// See [`run_app_on_demand`].
|
||||
///
|
||||
/// [`run_app_on_demand`]: Self::run_app_on_demand
|
||||
#[deprecated = "use EventLoopExtRunOnDemand::run_app_on_demand"]
|
||||
fn run_on_demand<F>(&mut self, event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<Self::UserEvent>, &ActiveEventLoop);
|
||||
/// [`Event::UserEvent`]: crate::event::Event::UserEvent
|
||||
type UserEvent: 'static;
|
||||
|
||||
/// Run the application with the event loop on the calling thread.
|
||||
///
|
||||
|
|
@ -68,23 +61,18 @@ pub trait EventLoopExtRunOnDemand {
|
|||
fn run_app_on_demand<A: ApplicationHandler<Self::UserEvent>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
#[allow(deprecated)]
|
||||
self.run_on_demand(|event, event_loop| {
|
||||
event_loop::dispatch_event_for_app(app, event_loop, event)
|
||||
})
|
||||
}
|
||||
) -> Result<(), EventLoopError>;
|
||||
}
|
||||
|
||||
impl<T> EventLoopExtRunOnDemand for EventLoop<T> {
|
||||
type UserEvent = T;
|
||||
|
||||
fn run_on_demand<F>(&mut self, event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<Self::UserEvent>, &ActiveEventLoop),
|
||||
{
|
||||
fn run_app_on_demand<A: ApplicationHandler<Self::UserEvent>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
self.event_loop.window_target().clear_exit();
|
||||
self.event_loop.run_on_demand(event_handler)
|
||||
self.event_loop.run_app_on_demand(app)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,7 @@ use web_sys::HtmlCanvasElement;
|
|||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::cursor::CustomCursorSource;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::{self, ActiveEventLoop, EventLoop};
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoop};
|
||||
#[cfg(web_platform)]
|
||||
use crate::platform_impl::CustomCursorFuture as PlatformCustomCursorFuture;
|
||||
use crate::platform_impl::PlatformCustomCursorSource;
|
||||
|
|
@ -156,7 +155,9 @@ impl WindowAttributesExtWebSys for WindowAttributes {
|
|||
|
||||
/// Additional methods on `EventLoop` that are specific to the web.
|
||||
pub trait EventLoopExtWebSys {
|
||||
/// A type provided by the user that can be passed through `Event::UserEvent`.
|
||||
/// A type provided by the user that can be passed through [`Event::UserEvent`].
|
||||
///
|
||||
/// [`Event::UserEvent`]: crate::event::Event::UserEvent
|
||||
type UserEvent: 'static;
|
||||
|
||||
/// Initializes the winit event loop.
|
||||
|
|
@ -182,30 +183,13 @@ pub trait EventLoopExtWebSys {
|
|||
)]
|
||||
/// [^1]: `run_app()` is _not_ available on WASM when the target supports `exception-handling`.
|
||||
fn spawn_app<A: ApplicationHandler<Self::UserEvent> + 'static>(self, app: A);
|
||||
|
||||
/// See [`spawn_app`].
|
||||
///
|
||||
/// [`spawn_app`]: Self::spawn_app
|
||||
#[deprecated = "use EventLoopExtWebSys::spawn_app"]
|
||||
fn spawn<F>(self, event_handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Event<Self::UserEvent>, &ActiveEventLoop);
|
||||
}
|
||||
|
||||
impl<T> EventLoopExtWebSys for EventLoop<T> {
|
||||
type UserEvent = T;
|
||||
|
||||
fn spawn_app<A: ApplicationHandler<Self::UserEvent> + 'static>(self, mut app: A) {
|
||||
self.event_loop.spawn(move |event, event_loop| {
|
||||
event_loop::dispatch_event_for_app(&mut app, event_loop, event)
|
||||
});
|
||||
}
|
||||
|
||||
fn spawn<F>(self, event_handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Event<Self::UserEvent>, &ActiveEventLoop),
|
||||
{
|
||||
self.event_loop.spawn(event_handler)
|
||||
fn spawn_app<A: ApplicationHandler<Self::UserEvent> + 'static>(self, app: A) {
|
||||
self.event_loop.spawn_app(app);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ use android_activity::{
|
|||
};
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error;
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::{self, Force, InnerSizeWriter, StartCause};
|
||||
use crate::event_loop::{self, ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents};
|
||||
use crate::event_loop::{self, ControlFlow, DeviceEvents};
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::Fullscreen;
|
||||
use crate::window::{
|
||||
|
|
@ -197,27 +198,28 @@ impl<T: 'static> EventLoop<T> {
|
|||
})
|
||||
}
|
||||
|
||||
fn single_iteration<F>(&mut self, main_event: Option<MainEvent<'_>>, callback: &mut F)
|
||||
where
|
||||
F: FnMut(event::Event<T>, &RootAEL),
|
||||
{
|
||||
fn single_iteration<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
main_event: Option<MainEvent<'_>>,
|
||||
app: &mut A,
|
||||
) {
|
||||
trace!("Mainloop iteration");
|
||||
|
||||
let cause = self.cause;
|
||||
let mut pending_redraw = self.pending_redraw;
|
||||
let mut resized = false;
|
||||
|
||||
callback(event::Event::NewEvents(cause), self.window_target());
|
||||
app.new_events(self.window_target(), cause);
|
||||
|
||||
if let Some(event) = main_event {
|
||||
trace!("Handling main event {:?}", event);
|
||||
|
||||
match event {
|
||||
MainEvent::InitWindow { .. } => {
|
||||
callback(event::Event::Resumed, self.window_target());
|
||||
app.resumed(self.window_target());
|
||||
},
|
||||
MainEvent::TerminateWindow { .. } => {
|
||||
callback(event::Event::Suspended, self.window_target());
|
||||
app.suspended(self.window_target());
|
||||
},
|
||||
MainEvent::WindowResized { .. } => resized = true,
|
||||
MainEvent::RedrawNeeded { .. } => pending_redraw = true,
|
||||
|
|
@ -226,23 +228,15 @@ impl<T: 'static> EventLoop<T> {
|
|||
},
|
||||
MainEvent::GainedFocus => {
|
||||
HAS_FOCUS.store(true, Ordering::Relaxed);
|
||||
callback(
|
||||
event::Event::WindowEvent {
|
||||
window_id: window::WindowId(WindowId),
|
||||
event: event::WindowEvent::Focused(true),
|
||||
},
|
||||
self.window_target(),
|
||||
);
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::Focused(true);
|
||||
app.window_event(self.window_target(), window_id, event);
|
||||
},
|
||||
MainEvent::LostFocus => {
|
||||
HAS_FOCUS.store(false, Ordering::Relaxed);
|
||||
callback(
|
||||
event::Event::WindowEvent {
|
||||
window_id: window::WindowId(WindowId),
|
||||
event: event::WindowEvent::Focused(false),
|
||||
},
|
||||
self.window_target(),
|
||||
);
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::Focused(false);
|
||||
app.window_event(self.window_target(), window_id, event);
|
||||
},
|
||||
MainEvent::ConfigChanged { .. } => {
|
||||
let monitor = MonitorHandle::new(self.android_app.clone());
|
||||
|
|
@ -252,20 +246,19 @@ impl<T: 'static> EventLoop<T> {
|
|||
let new_inner_size = Arc::new(Mutex::new(
|
||||
MonitorHandle::new(self.android_app.clone()).size(),
|
||||
));
|
||||
let event = event::Event::WindowEvent {
|
||||
window_id: window::WindowId(WindowId),
|
||||
event: event::WindowEvent::ScaleFactorChanged {
|
||||
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(
|
||||
&new_inner_size,
|
||||
)),
|
||||
scale_factor,
|
||||
},
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::ScaleFactorChanged {
|
||||
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(
|
||||
&new_inner_size,
|
||||
)),
|
||||
scale_factor,
|
||||
};
|
||||
callback(event, self.window_target());
|
||||
|
||||
app.window_event(self.window_target(), window_id, event);
|
||||
}
|
||||
},
|
||||
MainEvent::LowMemory => {
|
||||
callback(event::Event::MemoryWarning, self.window_target());
|
||||
app.memory_warning(self.window_target());
|
||||
},
|
||||
MainEvent::Start => {
|
||||
// XXX: how to forward this state to applications?
|
||||
|
|
@ -313,7 +306,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
match android_app.input_events_iter() {
|
||||
Ok(mut input_iter) => loop {
|
||||
let read_event =
|
||||
input_iter.next(|event| self.handle_input_event(&android_app, event, callback));
|
||||
input_iter.next(|event| self.handle_input_event(&android_app, event, app));
|
||||
|
||||
if !read_event {
|
||||
break;
|
||||
|
|
@ -327,7 +320,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
// Empty the user event buffer
|
||||
{
|
||||
while let Ok(event) = self.user_events_receiver.try_recv() {
|
||||
callback(crate::event::Event::UserEvent(event), self.window_target());
|
||||
app.user_event(self.window_target(), event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,39 +333,32 @@ impl<T: 'static> EventLoop<T> {
|
|||
} else {
|
||||
PhysicalSize::new(0, 0)
|
||||
};
|
||||
let event = event::Event::WindowEvent {
|
||||
window_id: window::WindowId(WindowId),
|
||||
event: event::WindowEvent::Resized(size),
|
||||
};
|
||||
callback(event, self.window_target());
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::Resized(size);
|
||||
app.window_event(self.window_target(), window_id, event);
|
||||
}
|
||||
|
||||
pending_redraw |= self.redraw_flag.get_and_reset();
|
||||
if pending_redraw {
|
||||
pending_redraw = false;
|
||||
let event = event::Event::WindowEvent {
|
||||
window_id: window::WindowId(WindowId),
|
||||
event: event::WindowEvent::RedrawRequested,
|
||||
};
|
||||
callback(event, self.window_target());
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::RedrawRequested;
|
||||
app.window_event(self.window_target(), window_id, event);
|
||||
}
|
||||
}
|
||||
|
||||
// This is always the last event we dispatch before poll again
|
||||
callback(event::Event::AboutToWait, self.window_target());
|
||||
app.about_to_wait(self.window_target());
|
||||
|
||||
self.pending_redraw = pending_redraw;
|
||||
}
|
||||
|
||||
fn handle_input_event<F>(
|
||||
fn handle_input_event<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
android_app: &AndroidApp,
|
||||
event: &InputEvent<'_>,
|
||||
callback: &mut F,
|
||||
) -> InputStatus
|
||||
where
|
||||
F: FnMut(event::Event<T>, &RootAEL),
|
||||
{
|
||||
app: &mut A,
|
||||
) -> InputStatus {
|
||||
let mut input_status = InputStatus::Handled;
|
||||
match event {
|
||||
InputEvent::MotionEvent(motion_event) => {
|
||||
|
|
@ -410,17 +396,16 @@ impl<T: 'static> EventLoop<T> {
|
|||
"Input event {device_id:?}, {phase:?}, loc={location:?}, \
|
||||
pointer={pointer:?}"
|
||||
);
|
||||
let event = event::Event::WindowEvent {
|
||||
window_id,
|
||||
event: event::WindowEvent::Touch(event::Touch {
|
||||
device_id,
|
||||
phase,
|
||||
location,
|
||||
id: pointer.pointer_id() as u64,
|
||||
force: Some(Force::Normalized(pointer.pressure() as f64)),
|
||||
}),
|
||||
};
|
||||
callback(event, self.window_target());
|
||||
|
||||
let event = event::WindowEvent::Touch(event::Touch {
|
||||
device_id,
|
||||
phase,
|
||||
location,
|
||||
id: pointer.pointer_id() as u64,
|
||||
force: Some(Force::Normalized(pointer.pressure() as f64)),
|
||||
});
|
||||
|
||||
app.window_event(self.window_target(), window_id, event);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -448,23 +433,22 @@ impl<T: 'static> EventLoop<T> {
|
|||
&mut self.combining_accent,
|
||||
);
|
||||
|
||||
let event = event::Event::WindowEvent {
|
||||
window_id: window::WindowId(WindowId),
|
||||
event: event::WindowEvent::KeyboardInput {
|
||||
device_id: event::DeviceId(DeviceId(key.device_id())),
|
||||
event: event::KeyEvent {
|
||||
state,
|
||||
physical_key: keycodes::to_physical_key(keycode),
|
||||
logical_key: keycodes::to_logical(key_char, keycode),
|
||||
location: keycodes::to_location(keycode),
|
||||
repeat: key.repeat_count() > 0,
|
||||
text: None,
|
||||
platform_specific: KeyEventExtra {},
|
||||
},
|
||||
is_synthetic: false,
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::KeyboardInput {
|
||||
device_id: event::DeviceId(DeviceId(key.device_id())),
|
||||
event: event::KeyEvent {
|
||||
state,
|
||||
physical_key: keycodes::to_physical_key(keycode),
|
||||
logical_key: keycodes::to_logical(key_char, keycode),
|
||||
location: keycodes::to_location(keycode),
|
||||
repeat: key.repeat_count() > 0,
|
||||
text: None,
|
||||
platform_specific: KeyEventExtra {},
|
||||
},
|
||||
is_synthetic: false,
|
||||
};
|
||||
callback(event, self.window_target());
|
||||
|
||||
app.window_event(self.window_target(), window_id, event);
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
@ -476,19 +460,16 @@ impl<T: 'static> EventLoop<T> {
|
|||
input_status
|
||||
}
|
||||
|
||||
pub fn run<F>(mut self, event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(event::Event<T>, &event_loop::ActiveEventLoop),
|
||||
{
|
||||
self.run_on_demand(event_handler)
|
||||
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
self.run_app_on_demand(app)
|
||||
}
|
||||
|
||||
pub fn run_on_demand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(event::Event<T>, &event_loop::ActiveEventLoop),
|
||||
{
|
||||
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
loop {
|
||||
match self.pump_events(None, &mut event_handler) {
|
||||
match self.pump_app_events(None, app) {
|
||||
PumpStatus::Exit(0) => {
|
||||
break Ok(());
|
||||
},
|
||||
|
|
@ -502,10 +483,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, mut callback: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(event::Event<T>, &RootAEL),
|
||||
{
|
||||
pub fn pump_app_events<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
if !self.loop_running {
|
||||
self.loop_running = true;
|
||||
|
||||
|
|
@ -516,18 +498,18 @@ impl<T: 'static> EventLoop<T> {
|
|||
self.cause = StartCause::Init;
|
||||
|
||||
// run the initial loop iteration
|
||||
self.single_iteration(None, &mut callback);
|
||||
self.single_iteration(None, app);
|
||||
}
|
||||
|
||||
// Consider the possibility that the `StartCause::Init` iteration could
|
||||
// request to Exit
|
||||
if !self.exiting() {
|
||||
self.poll_events_with_timeout(timeout, &mut callback);
|
||||
self.poll_events_with_timeout(timeout, app);
|
||||
}
|
||||
if self.exiting() {
|
||||
self.loop_running = false;
|
||||
|
||||
callback(event::Event::LoopExiting, self.window_target());
|
||||
app.exiting(self.window_target());
|
||||
|
||||
PumpStatus::Exit(0)
|
||||
} else {
|
||||
|
|
@ -535,10 +517,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn poll_events_with_timeout<F>(&mut self, mut timeout: Option<Duration>, mut callback: F)
|
||||
where
|
||||
F: FnMut(event::Event<T>, &RootAEL),
|
||||
{
|
||||
fn poll_events_with_timeout<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
mut timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) {
|
||||
let start = Instant::now();
|
||||
|
||||
self.pending_redraw |= self.redraw_flag.get_and_reset();
|
||||
|
|
@ -559,8 +542,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
min_timeout(control_flow_timeout, timeout)
|
||||
};
|
||||
|
||||
let app = self.android_app.clone(); // Don't borrow self as part of poll expression
|
||||
app.poll_events(timeout, |poll_event| {
|
||||
let android_app = self.android_app.clone(); // Don't borrow self as part of poll expression
|
||||
android_app.poll_events(timeout, |poll_event| {
|
||||
let mut main_event = None;
|
||||
|
||||
match poll_event {
|
||||
|
|
@ -601,7 +584,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
},
|
||||
};
|
||||
|
||||
self.single_iteration(main_event, &mut callback);
|
||||
self.single_iteration(main_event, app);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use core_foundation::runloop::{
|
|||
use objc2::ClassType;
|
||||
use objc2_foundation::{MainThreadMarker, NSString};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::{
|
||||
|
|
@ -106,17 +107,28 @@ impl OwnedDisplayHandle {
|
|||
}
|
||||
}
|
||||
|
||||
fn map_user_event<T: 'static>(
|
||||
mut handler: impl FnMut(Event<T>, &RootActiveEventLoop),
|
||||
fn map_user_event<T: 'static, A: ApplicationHandler<T>>(
|
||||
app: &mut A,
|
||||
receiver: mpsc::Receiver<T>,
|
||||
) -> impl FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) {
|
||||
move |event, window_target| match event.map_nonuser_event() {
|
||||
Ok(event) => (handler)(event, window_target),
|
||||
Err(_) => {
|
||||
) -> impl FnMut(Event<HandlePendingUserEvents>, &RootActiveEventLoop) + '_ {
|
||||
move |event, window_target| match event {
|
||||
Event::NewEvents(cause) => app.new_events(window_target, cause),
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(window_target, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(window_target, device_id, event)
|
||||
},
|
||||
Event::UserEvent(_) => {
|
||||
for event in receiver.try_iter() {
|
||||
(handler)(Event::UserEvent(event), window_target);
|
||||
app.user_event(window_target, event);
|
||||
}
|
||||
},
|
||||
Event::Suspended => app.suspended(window_target),
|
||||
Event::Resumed => app.resumed(window_target),
|
||||
Event::AboutToWait => app.about_to_wait(window_target),
|
||||
Event::LoopExiting => app.exiting(window_target),
|
||||
Event::MemoryWarning => app.memory_warning(window_target),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,10 +171,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn run<F>(self, handler: F) -> !
|
||||
where
|
||||
F: FnMut(Event<T>, &RootActiveEventLoop),
|
||||
{
|
||||
pub fn run_app<A: ApplicationHandler<T>>(self, app: &mut A) -> ! {
|
||||
let application = UIApplication::shared(self.mtm);
|
||||
assert!(
|
||||
application.is_none(),
|
||||
|
|
@ -171,7 +180,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
`EventLoop::run_app` calls `UIApplicationMain` on iOS",
|
||||
);
|
||||
|
||||
let handler = map_user_event(handler, self.receiver);
|
||||
let handler = map_user_event(app, self.receiver);
|
||||
|
||||
let handler = unsafe {
|
||||
std::mem::transmute::<
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ use std::{env, fmt};
|
|||
#[cfg(x11_platform)]
|
||||
use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Mutex};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
#[cfg(x11_platform)]
|
||||
use crate::utils::Lazy;
|
||||
use smol_str::SmolStr;
|
||||
|
|
@ -19,12 +21,9 @@ use smol_str::SmolStr;
|
|||
use self::x11::{X11Error, XConnection, XError, XNotSupported};
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootELW, AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed,
|
||||
};
|
||||
use crate::event_loop::{AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed};
|
||||
use crate::icon::Icon;
|
||||
use crate::keyboard::Key;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
#[cfg(x11_platform)]
|
||||
use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook};
|
||||
use crate::window::{
|
||||
|
|
@ -789,25 +788,23 @@ impl<T: 'static> EventLoop<T> {
|
|||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
|
||||
}
|
||||
|
||||
pub fn run<F>(mut self, callback: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(crate::event::Event<T>, &RootELW),
|
||||
{
|
||||
self.run_on_demand(callback)
|
||||
pub fn run_app<A: ApplicationHandler<T>>(self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app(app))
|
||||
}
|
||||
|
||||
pub fn run_on_demand<F>(&mut self, callback: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(crate::event::Event<T>, &RootELW),
|
||||
{
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_on_demand(callback))
|
||||
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app_on_demand(app))
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, callback: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(crate::event::Event<T>, &RootELW),
|
||||
{
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_events(timeout, callback))
|
||||
pub fn pump_app_events<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_app_events(timeout, app))
|
||||
}
|
||||
|
||||
pub fn window_target(&self) -> &crate::event_loop::ActiveEventLoop {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use sctk::reexports::calloop::Error as CalloopError;
|
|||
use sctk::reexports::calloop_wayland_source::WaylandSource;
|
||||
use sctk::reexports::client::{globals, Connection, QueueHandle};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::cursor::OnlyCursorImage;
|
||||
use crate::dpi::LogicalSize;
|
||||
use crate::error::{EventLoopError, OsError as RootOsError};
|
||||
|
|
@ -173,12 +174,16 @@ impl<T: 'static> EventLoop<T> {
|
|||
Ok(event_loop)
|
||||
}
|
||||
|
||||
pub fn run_on_demand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootActiveEventLoop),
|
||||
{
|
||||
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
self.run_app_on_demand(app)
|
||||
}
|
||||
|
||||
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
let exit = loop {
|
||||
match self.pump_events(None, &mut event_handler) {
|
||||
match self.pump_app_events(None, app) {
|
||||
PumpStatus::Exit(0) => {
|
||||
break Ok(());
|
||||
},
|
||||
|
|
@ -200,26 +205,27 @@ impl<T: 'static> EventLoop<T> {
|
|||
exit
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, mut callback: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<T>, &RootActiveEventLoop),
|
||||
{
|
||||
pub fn pump_app_events<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
if !self.loop_running {
|
||||
self.loop_running = true;
|
||||
|
||||
// Run the initial loop iteration.
|
||||
self.single_iteration(&mut callback, StartCause::Init);
|
||||
self.single_iteration(app, StartCause::Init);
|
||||
}
|
||||
|
||||
// Consider the possibility that the `StartCause::Init` iteration could
|
||||
// request to Exit.
|
||||
if !self.exiting() {
|
||||
self.poll_events_with_timeout(timeout, &mut callback);
|
||||
self.poll_events_with_timeout(timeout, app);
|
||||
}
|
||||
if let Some(code) = self.exit_code() {
|
||||
self.loop_running = false;
|
||||
|
||||
callback(Event::LoopExiting, self.window_target());
|
||||
app.exiting(&self.window_target);
|
||||
|
||||
PumpStatus::Exit(code)
|
||||
} else {
|
||||
|
|
@ -227,10 +233,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn poll_events_with_timeout<F>(&mut self, mut timeout: Option<Duration>, mut callback: F)
|
||||
where
|
||||
F: FnMut(Event<T>, &RootActiveEventLoop),
|
||||
{
|
||||
pub fn poll_events_with_timeout<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
mut timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) {
|
||||
let cause = loop {
|
||||
let start = Instant::now();
|
||||
|
||||
|
|
@ -292,13 +299,10 @@ impl<T: 'static> EventLoop<T> {
|
|||
break cause;
|
||||
};
|
||||
|
||||
self.single_iteration(&mut callback, cause);
|
||||
self.single_iteration(app, cause);
|
||||
}
|
||||
|
||||
fn single_iteration<F>(&mut self, callback: &mut F, cause: StartCause)
|
||||
where
|
||||
F: FnMut(Event<T>, &RootActiveEventLoop),
|
||||
{
|
||||
fn single_iteration<A: ApplicationHandler<T>>(&mut self, app: &mut A, cause: StartCause) {
|
||||
// NOTE currently just indented to simplify the diff
|
||||
|
||||
// We retain these grow-only scratch buffers as part of the EventLoop
|
||||
|
|
@ -309,18 +313,18 @@ impl<T: 'static> EventLoop<T> {
|
|||
let mut buffer_sink = std::mem::take(&mut self.buffer_sink);
|
||||
let mut window_ids = std::mem::take(&mut self.window_ids);
|
||||
|
||||
callback(Event::NewEvents(cause), &self.window_target);
|
||||
app.new_events(&self.window_target, cause);
|
||||
|
||||
// NB: For consistency all platforms must emit a 'resumed' event even though Wayland
|
||||
// applications don't themselves have a formal suspend/resume lifecycle.
|
||||
if cause == StartCause::Init {
|
||||
callback(Event::Resumed, &self.window_target);
|
||||
app.resumed(&self.window_target);
|
||||
}
|
||||
|
||||
// Handle pending user events. We don't need back buffer, since we can't dispatch
|
||||
// user events indirectly via callback to the user.
|
||||
for user_event in self.pending_user_events.borrow_mut().drain(..) {
|
||||
callback(Event::UserEvent(user_event), &self.window_target);
|
||||
app.user_event(&self.window_target, user_event);
|
||||
}
|
||||
|
||||
// Drain the pending compositor updates.
|
||||
|
|
@ -341,18 +345,13 @@ impl<T: 'static> EventLoop<T> {
|
|||
let old_physical_size = physical_size;
|
||||
|
||||
let new_inner_size = Arc::new(Mutex::new(physical_size));
|
||||
callback(
|
||||
Event::WindowEvent {
|
||||
window_id: crate::window::WindowId(window_id),
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(
|
||||
&new_inner_size,
|
||||
)),
|
||||
},
|
||||
},
|
||||
&self.window_target,
|
||||
);
|
||||
let root_window_id = crate::window::WindowId(window_id);
|
||||
let event = WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),
|
||||
};
|
||||
|
||||
app.window_event(&self.window_target, root_window_id, event);
|
||||
|
||||
let physical_size = *new_inner_size.lock().unwrap();
|
||||
drop(new_inner_size);
|
||||
|
|
@ -395,23 +394,14 @@ impl<T: 'static> EventLoop<T> {
|
|||
size
|
||||
});
|
||||
|
||||
callback(
|
||||
Event::WindowEvent {
|
||||
window_id: crate::window::WindowId(window_id),
|
||||
event: WindowEvent::Resized(physical_size),
|
||||
},
|
||||
&self.window_target,
|
||||
);
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
let event = WindowEvent::Resized(physical_size);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
|
||||
if compositor_update.close_window {
|
||||
callback(
|
||||
Event::WindowEvent {
|
||||
window_id: crate::window::WindowId(window_id),
|
||||
event: WindowEvent::CloseRequested,
|
||||
},
|
||||
&self.window_target,
|
||||
);
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
app.window_event(&self.window_target, window_id, WindowEvent::CloseRequested);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -420,8 +410,15 @@ impl<T: 'static> EventLoop<T> {
|
|||
buffer_sink.append(&mut state.window_events_sink.lock().unwrap());
|
||||
});
|
||||
for event in buffer_sink.drain() {
|
||||
let event = event.map_nonuser_event().unwrap();
|
||||
callback(event, &self.window_target);
|
||||
match event {
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(&self.window_target, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(&self.window_target, device_id, event)
|
||||
},
|
||||
_ => unreachable!("event which is neither device nor window event."),
|
||||
}
|
||||
}
|
||||
|
||||
// Handle non-synthetic events.
|
||||
|
|
@ -429,8 +426,15 @@ impl<T: 'static> EventLoop<T> {
|
|||
buffer_sink.append(&mut state.events_sink);
|
||||
});
|
||||
for event in buffer_sink.drain() {
|
||||
let event = event.map_nonuser_event().unwrap();
|
||||
callback(event, &self.window_target);
|
||||
match event {
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(&self.window_target, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(&self.window_target, device_id, event)
|
||||
},
|
||||
_ => unreachable!("event which is neither device nor window event."),
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the window ids
|
||||
|
|
@ -466,10 +470,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
});
|
||||
|
||||
if let Some(event) = event {
|
||||
callback(
|
||||
Event::WindowEvent { window_id: crate::window::WindowId(*window_id), event },
|
||||
&self.window_target,
|
||||
);
|
||||
let window_id = crate::window::WindowId(*window_id);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -479,7 +481,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
});
|
||||
|
||||
// This is always the last event we dispatch before poll again
|
||||
callback(Event::AboutToWait, &self.window_target);
|
||||
app.about_to_wait(&self.window_target);
|
||||
|
||||
// Update the window frames and schedule redraws.
|
||||
let mut wake_up = false;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use x11rb::protocol::xproto::{self, ConnectionExt as _};
|
|||
use x11rb::x11_utils::X11Error as LogicalError;
|
||||
use x11rb::xcb_ffi::ReplyOrIdError;
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::{EventLoopError, OsError as RootOsError};
|
||||
use crate::event::{Event, StartCause, WindowEvent};
|
||||
use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents, EventLoopClosed};
|
||||
|
|
@ -379,12 +380,16 @@ impl<T: 'static> EventLoop<T> {
|
|||
&self.event_processor.target
|
||||
}
|
||||
|
||||
pub fn run_on_demand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
self.run_app_on_demand(app)
|
||||
}
|
||||
|
||||
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
let exit = loop {
|
||||
match self.pump_events(None, &mut event_handler) {
|
||||
match self.pump_app_events(None, app) {
|
||||
PumpStatus::Exit(0) => {
|
||||
break Ok(());
|
||||
},
|
||||
|
|
@ -409,26 +414,27 @@ impl<T: 'static> EventLoop<T> {
|
|||
exit
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, mut callback: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
pub fn pump_app_events<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
if !self.loop_running {
|
||||
self.loop_running = true;
|
||||
|
||||
// run the initial loop iteration
|
||||
self.single_iteration(&mut callback, StartCause::Init);
|
||||
self.single_iteration(app, StartCause::Init);
|
||||
}
|
||||
|
||||
// Consider the possibility that the `StartCause::Init` iteration could
|
||||
// request to Exit.
|
||||
if !self.exiting() {
|
||||
self.poll_events_with_timeout(timeout, &mut callback);
|
||||
self.poll_events_with_timeout(timeout, app);
|
||||
}
|
||||
if let Some(code) = self.exit_code() {
|
||||
self.loop_running = false;
|
||||
|
||||
callback(Event::LoopExiting, self.window_target());
|
||||
app.exiting(self.window_target());
|
||||
|
||||
PumpStatus::Exit(code)
|
||||
} else {
|
||||
|
|
@ -442,10 +448,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
|| self.redraw_receiver.has_incoming()
|
||||
}
|
||||
|
||||
pub fn poll_events_with_timeout<F>(&mut self, mut timeout: Option<Duration>, mut callback: F)
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
pub fn poll_events_with_timeout<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
mut timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) {
|
||||
let start = Instant::now();
|
||||
|
||||
let has_pending = self.has_pending();
|
||||
|
|
@ -503,23 +510,20 @@ impl<T: 'static> EventLoop<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
self.single_iteration(&mut callback, cause);
|
||||
self.single_iteration(app, cause);
|
||||
}
|
||||
|
||||
fn single_iteration<F>(&mut self, callback: &mut F, cause: StartCause)
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
callback(Event::NewEvents(cause), &self.event_processor.target);
|
||||
fn single_iteration<A: ApplicationHandler<T>>(&mut self, app: &mut A, cause: StartCause) {
|
||||
app.new_events(&self.event_processor.target, cause);
|
||||
|
||||
// NB: For consistency all platforms must emit a 'resumed' event even though X11
|
||||
// applications don't themselves have a formal suspend/resume lifecycle.
|
||||
if cause == StartCause::Init {
|
||||
callback(Event::Resumed, &self.event_processor.target);
|
||||
app.resumed(&self.event_processor.target)
|
||||
}
|
||||
|
||||
// Process all pending events
|
||||
self.drain_events(callback);
|
||||
self.drain_events(app);
|
||||
|
||||
// Empty activation tokens.
|
||||
while let Ok((window_id, serial)) = self.activation_receiver.try_recv() {
|
||||
|
|
@ -529,14 +533,12 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
match token {
|
||||
Some(Ok(token)) => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id: crate::window::WindowId(window_id),
|
||||
event: WindowEvent::ActivationTokenDone {
|
||||
serial,
|
||||
token: crate::window::ActivationToken::_new(token),
|
||||
},
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
let event = WindowEvent::ActivationTokenDone {
|
||||
serial,
|
||||
token: crate::window::ActivationToken::_new(token),
|
||||
};
|
||||
callback(event, &self.event_processor.target)
|
||||
app.window_event(&self.event_processor.target, window_id, event);
|
||||
},
|
||||
Some(Err(e)) => {
|
||||
tracing::error!("Failed to get activation token: {}", e);
|
||||
|
|
@ -548,7 +550,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
// Empty the user event buffer
|
||||
{
|
||||
while let Ok(event) = self.user_receiver.try_recv() {
|
||||
callback(Event::UserEvent(event), &self.event_processor.target);
|
||||
app.user_event(&self.event_processor.target, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -562,28 +564,24 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
for window_id in windows {
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
callback(
|
||||
Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested },
|
||||
app.window_event(
|
||||
&self.event_processor.target,
|
||||
window_id,
|
||||
WindowEvent::RedrawRequested,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// This is always the last event we dispatch before poll again
|
||||
{
|
||||
callback(Event::AboutToWait, &self.event_processor.target);
|
||||
}
|
||||
app.about_to_wait(&self.event_processor.target);
|
||||
}
|
||||
|
||||
fn drain_events<F>(&mut self, callback: &mut F)
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
fn drain_events<A: ApplicationHandler<T>>(&mut self, app: &mut A) {
|
||||
let mut xev = MaybeUninit::uninit();
|
||||
|
||||
while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } {
|
||||
let mut xev = unsafe { xev.assume_init() };
|
||||
self.event_processor.process_event(&mut xev, |window_target, event| {
|
||||
self.event_processor.process_event(&mut xev, |window_target, event: Event<T>| {
|
||||
if let Event::WindowEvent {
|
||||
window_id: crate::window::WindowId(wid),
|
||||
event: WindowEvent::RedrawRequested,
|
||||
|
|
@ -592,7 +590,15 @@ impl<T: 'static> EventLoop<T> {
|
|||
let window_target = EventProcessor::window_target(window_target);
|
||||
window_target.redraw_sender.send(wid).unwrap();
|
||||
} else {
|
||||
callback(event, window_target);
|
||||
match event {
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(window_target, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(window_target, device_id, event)
|
||||
},
|
||||
_ => unreachable!("event which is neither device nor window event."),
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use super::app_delegate::{ApplicationDelegate, HandlePendingUserEvents};
|
|||
use super::event::dummy_event;
|
||||
use super::monitor::{self, MonitorHandle};
|
||||
use super::observer::setup_control_flow_observers;
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::{
|
||||
|
|
@ -155,17 +156,28 @@ impl ActiveEventLoop {
|
|||
}
|
||||
}
|
||||
|
||||
fn map_user_event<T: 'static>(
|
||||
mut handler: impl FnMut(Event<T>, &RootWindowTarget),
|
||||
fn map_user_event<T: 'static, A: ApplicationHandler<T>>(
|
||||
app: &mut A,
|
||||
receiver: Rc<mpsc::Receiver<T>>,
|
||||
) -> impl FnMut(Event<HandlePendingUserEvents>, &RootWindowTarget) {
|
||||
move |event, window_target| match event.map_nonuser_event() {
|
||||
Ok(event) => (handler)(event, window_target),
|
||||
Err(_) => {
|
||||
) -> impl FnMut(Event<HandlePendingUserEvents>, &RootWindowTarget) + '_ {
|
||||
move |event, window_target| match event {
|
||||
Event::NewEvents(cause) => app.new_events(window_target, cause),
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(window_target, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(window_target, device_id, event)
|
||||
},
|
||||
Event::UserEvent(_) => {
|
||||
for event in receiver.try_iter() {
|
||||
(handler)(Event::UserEvent(event), window_target);
|
||||
app.user_event(window_target, event);
|
||||
}
|
||||
},
|
||||
Event::Suspended => app.suspended(window_target),
|
||||
Event::Resumed => app.resumed(window_target),
|
||||
Event::AboutToWait => app.about_to_wait(window_target),
|
||||
Event::LoopExiting => app.exiting(window_target),
|
||||
Event::MemoryWarning => app.memory_warning(window_target),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -260,22 +272,19 @@ impl<T> EventLoop<T> {
|
|||
&self.window_target
|
||||
}
|
||||
|
||||
pub fn run<F>(mut self, handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootWindowTarget),
|
||||
{
|
||||
self.run_on_demand(handler)
|
||||
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
self.run_app_on_demand(app)
|
||||
}
|
||||
|
||||
// NB: we don't base this on `pump_events` because for `MacOs` we can't support
|
||||
// `pump_events` elegantly (we just ask to run the loop for a "short" amount of
|
||||
// time and so a layered implementation would end up using a lot of CPU due to
|
||||
// redundant wake ups.
|
||||
pub fn run_on_demand<F>(&mut self, handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootWindowTarget),
|
||||
{
|
||||
let handler = map_user_event(handler, self.receiver.clone());
|
||||
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
let handler = map_user_event(app, self.receiver.clone());
|
||||
|
||||
self.delegate.set_event_handler(handler, || {
|
||||
autoreleasepool(|_| {
|
||||
|
|
@ -310,11 +319,12 @@ impl<T> EventLoop<T> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, handler: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<T>, &RootWindowTarget),
|
||||
{
|
||||
let handler = map_user_event(handler, self.receiver.clone());
|
||||
pub fn pump_app_events<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
let handler = map_user_event(app, self.receiver.clone());
|
||||
|
||||
self.delegate.set_event_handler(handler, || {
|
||||
autoreleasepool(|_| {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use orbclient::{
|
|||
};
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::{self, Ime, Modifiers, StartCause};
|
||||
use crate::event_loop::{self, ControlFlow, DeviceEvents};
|
||||
|
|
@ -322,14 +323,13 @@ impl<T: 'static> EventLoop<T> {
|
|||
})
|
||||
}
|
||||
|
||||
fn process_event<F>(
|
||||
fn process_event<A: ApplicationHandler<T>>(
|
||||
window_id: WindowId,
|
||||
event_option: EventOption,
|
||||
event_state: &mut EventState,
|
||||
mut event_handler: F,
|
||||
) where
|
||||
F: FnMut(event::Event<T>),
|
||||
{
|
||||
window_target: &event_loop::ActiveEventLoop,
|
||||
app: &mut A,
|
||||
) {
|
||||
match event_option {
|
||||
EventOption::Key(KeyEvent { character, scancode, pressed }) => {
|
||||
// Convert scancode
|
||||
|
|
@ -371,125 +371,128 @@ impl<T: 'static> EventLoop<T> {
|
|||
key_without_modifiers = logical_key.clone();
|
||||
}
|
||||
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::KeyboardInput {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
event: event::KeyEvent {
|
||||
logical_key,
|
||||
physical_key,
|
||||
location: KeyLocation::Standard,
|
||||
state: element_state(pressed),
|
||||
repeat: false,
|
||||
text,
|
||||
platform_specific: KeyEventExtra {
|
||||
key_without_modifiers,
|
||||
text_with_all_modifiers,
|
||||
},
|
||||
let window_id = RootWindowId(window_id);
|
||||
let event = event::WindowEvent::KeyboardInput {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
event: event::KeyEvent {
|
||||
logical_key,
|
||||
physical_key,
|
||||
location: KeyLocation::Standard,
|
||||
state: element_state(pressed),
|
||||
repeat: false,
|
||||
text,
|
||||
platform_specific: KeyEventExtra {
|
||||
key_without_modifiers,
|
||||
text_with_all_modifiers,
|
||||
},
|
||||
is_synthetic: false,
|
||||
},
|
||||
});
|
||||
is_synthetic: false,
|
||||
};
|
||||
|
||||
app.window_event(window_target, window_id, event);
|
||||
|
||||
// If the state of the modifiers has changed, send the event.
|
||||
if modifiers_before != event_state.keyboard {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::ModifiersChanged(event_state.modifiers()),
|
||||
})
|
||||
app.window_event(
|
||||
window_target,
|
||||
window_id,
|
||||
event::WindowEvent::ModifiersChanged(event_state.modifiers()),
|
||||
);
|
||||
}
|
||||
},
|
||||
EventOption::TextInput(TextInputEvent { character }) => {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::Ime(Ime::Preedit("".into(), None)),
|
||||
});
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::Ime(Ime::Commit(character.into())),
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Ime(Ime::Preedit("".into(), None)),
|
||||
);
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Ime(Ime::Commit(character.into())),
|
||||
);
|
||||
},
|
||||
EventOption::Mouse(MouseEvent { x, y }) => {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::CursorMoved {
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::CursorMoved {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
position: (x, y).into(),
|
||||
},
|
||||
});
|
||||
);
|
||||
},
|
||||
EventOption::MouseRelative(MouseRelativeEvent { dx, dy }) => {
|
||||
event_handler(event::Event::DeviceEvent {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
event: event::DeviceEvent::MouseMotion { delta: (dx as f64, dy as f64) },
|
||||
});
|
||||
app.device_event(
|
||||
window_target,
|
||||
event::DeviceId(DeviceId),
|
||||
event::DeviceEvent::MouseMotion { delta: (dx as f64, dy as f64) },
|
||||
);
|
||||
},
|
||||
EventOption::Button(ButtonEvent { left, middle, right }) => {
|
||||
while let Some((button, state)) = event_state.mouse(left, middle, right) {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::MouseInput {
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::MouseInput {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
state,
|
||||
button,
|
||||
},
|
||||
});
|
||||
);
|
||||
}
|
||||
},
|
||||
EventOption::Scroll(ScrollEvent { x, y }) => {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::MouseWheel {
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::MouseWheel {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
delta: event::MouseScrollDelta::LineDelta(x as f32, y as f32),
|
||||
phase: event::TouchPhase::Moved,
|
||||
},
|
||||
});
|
||||
);
|
||||
},
|
||||
EventOption::Quit(QuitEvent {}) => {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::CloseRequested,
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::CloseRequested,
|
||||
);
|
||||
},
|
||||
EventOption::Focus(FocusEvent { focused }) => {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::Focused(focused),
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Focused(focused),
|
||||
);
|
||||
},
|
||||
EventOption::Move(MoveEvent { x, y }) => {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::Moved((x, y).into()),
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Moved((x, y).into()),
|
||||
);
|
||||
},
|
||||
EventOption::Resize(ResizeEvent { width, height }) => {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::Resized((width, height).into()),
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Resized((width, height).into()),
|
||||
);
|
||||
|
||||
// Acknowledge resize after event loop.
|
||||
event_state.resize_opt = Some((width, height));
|
||||
},
|
||||
// TODO: Screen, Clipboard, Drop
|
||||
EventOption::Hover(HoverEvent { entered }) => {
|
||||
if entered {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::CursorEntered {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
},
|
||||
});
|
||||
let event = if entered {
|
||||
event::WindowEvent::CursorEntered { device_id: event::DeviceId(DeviceId) }
|
||||
} else {
|
||||
event_handler(event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::CursorLeft {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
},
|
||||
});
|
||||
}
|
||||
event::WindowEvent::CursorLeft { device_id: event::DeviceId(DeviceId) }
|
||||
};
|
||||
|
||||
app.window_event(window_target, RootWindowId(window_id), event);
|
||||
},
|
||||
other => {
|
||||
tracing::warn!("unhandled event: {:?}", other);
|
||||
|
|
@ -497,22 +500,13 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run<F>(mut self, mut event_handler_inner: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(event::Event<T>, &event_loop::ActiveEventLoop),
|
||||
{
|
||||
let mut event_handler =
|
||||
move |event: event::Event<T>, window_target: &event_loop::ActiveEventLoop| {
|
||||
event_handler_inner(event, window_target);
|
||||
};
|
||||
|
||||
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
let mut start_cause = StartCause::Init;
|
||||
|
||||
loop {
|
||||
event_handler(event::Event::NewEvents(start_cause), &self.window_target);
|
||||
app.new_events(&self.window_target, start_cause);
|
||||
|
||||
if start_cause == StartCause::Init {
|
||||
event_handler(event::Event::Resumed, &self.window_target);
|
||||
app.resumed(&self.window_target);
|
||||
}
|
||||
|
||||
// Handle window creates.
|
||||
|
|
@ -528,23 +522,15 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
self.windows.push((window, EventState::default()));
|
||||
|
||||
// Send resize event on create to indicate first size.
|
||||
event_handler(
|
||||
event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::Resized((properties.w, properties.h).into()),
|
||||
},
|
||||
&self.window_target,
|
||||
);
|
||||
let window_id = RootWindowId(window_id);
|
||||
|
||||
// Send resize event on create to indicate first position.
|
||||
event_handler(
|
||||
event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::Moved((properties.x, properties.y).into()),
|
||||
},
|
||||
&self.window_target,
|
||||
);
|
||||
// Send resize event on create to indicate first size.
|
||||
let event = event::WindowEvent::Resized((properties.w, properties.h).into());
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
|
||||
// Send moved event on create to indicate first position.
|
||||
let event = event::WindowEvent::Moved((properties.x, properties.y).into());
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
|
||||
// Handle window destroys.
|
||||
|
|
@ -552,14 +538,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
let mut destroys = self.window_target.p.destroys.lock().unwrap();
|
||||
destroys.pop_front()
|
||||
} {
|
||||
event_handler(
|
||||
event::Event::WindowEvent {
|
||||
window_id: RootWindowId(destroy_id),
|
||||
event: event::WindowEvent::Destroyed,
|
||||
},
|
||||
&self.window_target,
|
||||
);
|
||||
|
||||
let window_id = RootWindowId(destroy_id);
|
||||
app.window_event(&self.window_target, window_id, event::WindowEvent::Destroyed);
|
||||
self.windows.retain(|(window, _event_state)| window.fd as u64 != destroy_id.fd);
|
||||
}
|
||||
|
||||
|
|
@ -586,7 +566,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
window_id,
|
||||
orbital_event.to_option(),
|
||||
event_state,
|
||||
|event| event_handler(event, &self.window_target),
|
||||
&self.window_target,
|
||||
app,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -614,7 +595,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
|
||||
while let Ok(event) = self.user_events_receiver.try_recv() {
|
||||
event_handler(event::Event::UserEvent(event), &self.window_target);
|
||||
app.user_event(&self.window_target, event);
|
||||
}
|
||||
|
||||
// To avoid deadlocks the redraws lock is not held during event processing.
|
||||
|
|
@ -622,16 +603,14 @@ impl<T: 'static> EventLoop<T> {
|
|||
let mut redraws = self.window_target.p.redraws.lock().unwrap();
|
||||
redraws.pop_front()
|
||||
} {
|
||||
event_handler(
|
||||
event::Event::WindowEvent {
|
||||
window_id: RootWindowId(window_id),
|
||||
event: event::WindowEvent::RedrawRequested,
|
||||
},
|
||||
app.window_event(
|
||||
&self.window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::RedrawRequested,
|
||||
);
|
||||
}
|
||||
|
||||
event_handler(event::Event::AboutToWait, &self.window_target);
|
||||
app.about_to_wait(&self.window_target);
|
||||
|
||||
if self.window_target.p.exiting() {
|
||||
break;
|
||||
|
|
@ -695,7 +674,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
event_handler(event::Event::LoopExiting, &self.window_target);
|
||||
app.exiting(&self.window_target);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::ActiveEventLoop as RootActiveEventLoop;
|
||||
|
|
@ -31,25 +32,13 @@ impl<T> EventLoop<T> {
|
|||
Ok(EventLoop { elw, user_event_sender, user_event_receiver })
|
||||
}
|
||||
|
||||
pub fn run<F>(self, mut event_handler: F) -> !
|
||||
where
|
||||
F: FnMut(Event<T>, &RootActiveEventLoop),
|
||||
{
|
||||
pub fn run_app<A: ApplicationHandler<T>>(self, app: &mut A) -> ! {
|
||||
let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData };
|
||||
|
||||
// SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`.
|
||||
let handler: Box<dyn FnMut(Event<()>)> = Box::new(|event| {
|
||||
let event = match event.map_nonuser_event() {
|
||||
Ok(event) => event,
|
||||
Err(Event::UserEvent(())) => Event::UserEvent(
|
||||
self.user_event_receiver
|
||||
.try_recv()
|
||||
.expect("handler woken up without user event"),
|
||||
),
|
||||
Err(_) => unreachable!(),
|
||||
};
|
||||
event_handler(event, &target)
|
||||
});
|
||||
let handler: Box<dyn FnMut(Event<()>)> =
|
||||
Box::new(|event| handle_event(app, &target, &self.user_event_receiver, 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
|
||||
// `throw` will leak, making this actually `'static`.
|
||||
|
|
@ -65,24 +54,12 @@ impl<T> EventLoop<T> {
|
|||
unreachable!();
|
||||
}
|
||||
|
||||
pub fn spawn<F>(self, mut event_handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Event<T>, &RootActiveEventLoop),
|
||||
{
|
||||
pub fn spawn_app<A: ApplicationHandler<T> + 'static>(self, mut app: A) {
|
||||
let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData };
|
||||
|
||||
self.elw.p.run(
|
||||
Box::new(move |event| {
|
||||
let event = match event.map_nonuser_event() {
|
||||
Ok(event) => event,
|
||||
Err(Event::UserEvent(())) => Event::UserEvent(
|
||||
self.user_event_receiver
|
||||
.try_recv()
|
||||
.expect("handler woken up without user event"),
|
||||
),
|
||||
Err(_) => unreachable!(),
|
||||
};
|
||||
event_handler(event, &target)
|
||||
handle_event(&mut app, &target, &self.user_event_receiver, event)
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
|
@ -96,3 +73,26 @@ impl<T> EventLoop<T> {
|
|||
&self.elw
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_event<T: 'static, A: ApplicationHandler<T>>(
|
||||
app: &mut A,
|
||||
target: &RootActiveEventLoop,
|
||||
user_event_receiver: &Receiver<T>,
|
||||
event: Event<()>,
|
||||
) {
|
||||
match event {
|
||||
Event::NewEvents(cause) => app.new_events(target, cause),
|
||||
Event::WindowEvent { window_id, event } => app.window_event(target, window_id, event),
|
||||
Event::DeviceEvent { device_id, event } => app.device_event(target, device_id, event),
|
||||
Event::UserEvent(_) => {
|
||||
let event =
|
||||
user_event_receiver.try_recv().expect("user event signaled but not received");
|
||||
app.user_event(target, event);
|
||||
},
|
||||
Event::Suspended => app.suspended(target),
|
||||
Event::Resumed => app.resumed(target),
|
||||
Event::AboutToWait => app.about_to_wait(target),
|
||||
Event::LoopExiting => app.exiting(target),
|
||||
Event::MemoryWarning => app.memory_warning(target),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
|
|||
WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE,
|
||||
};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::error::EventLoopError;
|
||||
use crate::event::{
|
||||
|
|
@ -215,17 +216,14 @@ impl<T: 'static> EventLoop<T> {
|
|||
&self.window_target
|
||||
}
|
||||
|
||||
pub fn run<F>(mut self, event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
self.run_on_demand(event_handler)
|
||||
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
self.run_app_on_demand(app)
|
||||
}
|
||||
|
||||
pub fn run_on_demand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError>
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
{
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
||||
|
|
@ -236,21 +234,32 @@ impl<T: 'static> EventLoop<T> {
|
|||
// returning
|
||||
unsafe {
|
||||
runner.set_event_handler(move |event| {
|
||||
// the shared `EventLoopRunner` is not parameterized
|
||||
// `EventLoopProxy::send_event()` calls `PostMessage`
|
||||
// to wakeup and dispatch a placeholder `UserEvent`,
|
||||
// when we received the placeholder event here, the
|
||||
// real UserEvent(T) should already be put in the
|
||||
// mpsc channel and ready to be pulled
|
||||
let event = match event.map_nonuser_event() {
|
||||
Ok(non_user_event) => non_user_event,
|
||||
Err(_user_event_placeholder) => Event::UserEvent(
|
||||
user_event_receiver
|
||||
match event {
|
||||
Event::NewEvents(cause) => app.new_events(event_loop_windows_ref, cause),
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(event_loop_windows_ref, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(event_loop_windows_ref, device_id, event)
|
||||
},
|
||||
// The shared `EventLoopRunner` is not parameterized
|
||||
// `EventLoopProxy::send_event()` calls `PostMessage`
|
||||
// to wakeup and dispatch a placeholder `UserEvent`,
|
||||
// when we received the placeholder event here, the
|
||||
// real UserEvent(T) should already be put in the
|
||||
// mpsc channel and ready to be pulled
|
||||
Event::UserEvent(_) => {
|
||||
let event = user_event_receiver
|
||||
.try_recv()
|
||||
.expect("user event signaled but not received"),
|
||||
),
|
||||
};
|
||||
event_handler(event, event_loop_windows_ref)
|
||||
.expect("user event signaled but not received");
|
||||
app.user_event(event_loop_windows_ref, event);
|
||||
},
|
||||
Event::Suspended => app.suspended(event_loop_windows_ref),
|
||||
Event::Resumed => app.resumed(event_loop_windows_ref),
|
||||
Event::AboutToWait => app.about_to_wait(event_loop_windows_ref),
|
||||
Event::LoopExiting => app.exiting(event_loop_windows_ref),
|
||||
Event::MemoryWarning => app.memory_warning(event_loop_windows_ref),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -284,10 +293,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pump_events<F>(&mut self, timeout: Option<Duration>, mut event_handler: F) -> PumpStatus
|
||||
where
|
||||
F: FnMut(Event<T>, &RootAEL),
|
||||
{
|
||||
pub fn pump_app_events<A: ApplicationHandler<T>>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
) -> PumpStatus {
|
||||
{
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
let event_loop_windows_ref = &self.window_target;
|
||||
|
|
@ -302,16 +312,34 @@ impl<T: 'static> EventLoop<T> {
|
|||
// event handler.
|
||||
unsafe {
|
||||
runner.set_event_handler(move |event| {
|
||||
let event = match event.map_nonuser_event() {
|
||||
Ok(non_user_event) => non_user_event,
|
||||
Err(_user_event_placeholder) => Event::UserEvent(
|
||||
user_event_receiver
|
||||
.recv()
|
||||
.expect("user event signaled but not received"),
|
||||
),
|
||||
};
|
||||
event_handler(event, event_loop_windows_ref)
|
||||
match event {
|
||||
Event::NewEvents(cause) => app.new_events(event_loop_windows_ref, cause),
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(event_loop_windows_ref, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(event_loop_windows_ref, device_id, event)
|
||||
},
|
||||
// The shared `EventLoopRunner` is not parameterized
|
||||
// `EventLoopProxy::send_event()` calls `PostMessage`
|
||||
// to wakeup and dispatch a placeholder `UserEvent`,
|
||||
// when we received the placeholder event here, the
|
||||
// real UserEvent(T) should already be put in the
|
||||
// mpsc channel and ready to be pulled
|
||||
Event::UserEvent(_) => {
|
||||
let event = user_event_receiver
|
||||
.try_recv()
|
||||
.expect("user event signaled but not received");
|
||||
app.user_event(event_loop_windows_ref, event);
|
||||
},
|
||||
Event::Suspended => app.suspended(event_loop_windows_ref),
|
||||
Event::Resumed => app.resumed(event_loop_windows_ref),
|
||||
Event::AboutToWait => app.about_to_wait(event_loop_windows_ref),
|
||||
Event::LoopExiting => app.exiting(event_loop_windows_ref),
|
||||
Event::MemoryWarning => app.memory_warning(event_loop_windows_ref),
|
||||
}
|
||||
});
|
||||
|
||||
runner.wakeup();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue