event_loop: remove generic user event
Let the users wake up the event loop and then they could poll their user sources. Co-authored-by: Mads Marquart <mads@marquart.dk> Co-authored-by: daxpedda <daxpedda@gmail.com>
This commit is contained in:
parent
7d1287958f
commit
ecb887e5c3
44 changed files with 675 additions and 966 deletions
|
|
@ -5,7 +5,6 @@ use std::io::Result as IOResult;
|
|||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
|
|
@ -40,7 +39,7 @@ use super::{logical_to_physical_rounded, DeviceId, WaylandError, WindowId};
|
|||
type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource<WinitState>, WinitState>;
|
||||
|
||||
/// The Wayland event loop.
|
||||
pub struct EventLoop<T: 'static> {
|
||||
pub struct EventLoop {
|
||||
/// Has `run` or `run_on_demand` been called or a call to `pump_events` that starts the loop
|
||||
loop_running: bool,
|
||||
|
||||
|
|
@ -48,13 +47,8 @@ pub struct EventLoop<T: 'static> {
|
|||
compositor_updates: Vec<WindowCompositorUpdate>,
|
||||
window_ids: Vec<WindowId>,
|
||||
|
||||
/// Sender of user events.
|
||||
user_events_sender: calloop::channel::Sender<T>,
|
||||
|
||||
// XXX can't remove RefCell out of here, unless we can plumb generics into the `Window`, which
|
||||
// we don't really want, since it'll break public API by a lot.
|
||||
/// Pending events from the user.
|
||||
pending_user_events: Rc<RefCell<Vec<T>>>,
|
||||
/// Event loop proxy
|
||||
event_loop_proxy: EventLoopProxy,
|
||||
|
||||
/// The Wayland dispatcher to has raw access to the queue when needed, such as
|
||||
/// when creating a new window.
|
||||
|
|
@ -71,8 +65,8 @@ pub struct EventLoop<T: 'static> {
|
|||
event_loop: calloop::EventLoop<'static, WinitState>,
|
||||
}
|
||||
|
||||
impl<T: 'static> EventLoop<T> {
|
||||
pub fn new() -> Result<EventLoop<T>, EventLoopError> {
|
||||
impl EventLoop {
|
||||
pub fn new() -> Result<EventLoop, EventLoopError> {
|
||||
macro_rules! map_err {
|
||||
($e:expr, $err:expr) => {
|
||||
$e.map_err(|error| os_error!($err(error).into()))
|
||||
|
|
@ -115,16 +109,12 @@ impl<T: 'static> EventLoop<T> {
|
|||
)?;
|
||||
|
||||
// Setup the user proxy.
|
||||
let pending_user_events = Rc::new(RefCell::new(Vec::new()));
|
||||
let pending_user_events_clone = pending_user_events.clone();
|
||||
let (user_events_sender, user_events_channel) = calloop::channel::channel();
|
||||
let (ping, ping_source) = calloop::ping::make_ping().unwrap();
|
||||
let result = event_loop
|
||||
.handle()
|
||||
.insert_source(user_events_channel, move |event, _, winit_state: &mut WinitState| {
|
||||
if let calloop::channel::Event::Msg(msg) = event {
|
||||
winit_state.dispatched_events = true;
|
||||
pending_user_events_clone.borrow_mut().push(msg);
|
||||
}
|
||||
.insert_source(ping_source, move |_, _, winit_state: &mut WinitState| {
|
||||
winit_state.dispatched_events = true;
|
||||
winit_state.proxy_wake_up = true;
|
||||
})
|
||||
.map_err(|error| error.error);
|
||||
map_err!(result, WaylandError::Calloop)?;
|
||||
|
|
@ -162,8 +152,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
window_ids: Vec::new(),
|
||||
connection,
|
||||
wayland_dispatcher,
|
||||
user_events_sender,
|
||||
pending_user_events,
|
||||
event_loop_proxy: EventLoopProxy::new(ping),
|
||||
event_loop,
|
||||
window_target: RootActiveEventLoop {
|
||||
p: PlatformActiveEventLoop::Wayland(window_target),
|
||||
|
|
@ -174,11 +163,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
Ok(event_loop)
|
||||
}
|
||||
|
||||
pub fn run_app<A: ApplicationHandler<T>>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
pub fn run_app<A: ApplicationHandler>(mut self, app: &mut A) -> Result<(), EventLoopError> {
|
||||
self.run_app_on_demand(app)
|
||||
}
|
||||
|
||||
pub fn run_app_on_demand<A: ApplicationHandler<T>>(
|
||||
pub fn run_app_on_demand<A: ApplicationHandler>(
|
||||
&mut self,
|
||||
app: &mut A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
|
|
@ -205,7 +194,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
exit
|
||||
}
|
||||
|
||||
pub fn pump_app_events<A: ApplicationHandler<T>>(
|
||||
pub fn pump_app_events<A: ApplicationHandler>(
|
||||
&mut self,
|
||||
timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
|
|
@ -233,7 +222,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn poll_events_with_timeout<A: ApplicationHandler<T>>(
|
||||
pub fn poll_events_with_timeout<A: ApplicationHandler>(
|
||||
&mut self,
|
||||
mut timeout: Option<Duration>,
|
||||
app: &mut A,
|
||||
|
|
@ -302,7 +291,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
self.single_iteration(app, cause);
|
||||
}
|
||||
|
||||
fn single_iteration<A: ApplicationHandler<T>>(&mut self, app: &mut A, cause: StartCause) {
|
||||
fn single_iteration<A: ApplicationHandler>(&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
|
||||
|
|
@ -321,10 +310,9 @@ impl<T: 'static> EventLoop<T> {
|
|||
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(..) {
|
||||
app.user_event(&self.window_target, user_event);
|
||||
// Indicate user wake up.
|
||||
if self.with_state(|state| mem::take(&mut state.proxy_wake_up)) {
|
||||
app.proxy_wake_up(&self.window_target);
|
||||
}
|
||||
|
||||
// Drain the pending compositor updates.
|
||||
|
|
@ -525,8 +513,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
||||
EventLoopProxy::new(self.user_events_sender.clone())
|
||||
pub fn create_proxy(&self) -> EventLoopProxy {
|
||||
self.event_loop_proxy.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -588,13 +576,13 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> AsFd for EventLoop<T> {
|
||||
impl AsFd for EventLoop {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.event_loop.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRawFd for EventLoop<T> {
|
||||
impl AsRawFd for EventLoop {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.event_loop.as_raw_fd()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,19 @@
|
|||
//! An event loop proxy.
|
||||
|
||||
use std::sync::mpsc::SendError;
|
||||
|
||||
use sctk::reexports::calloop::channel::Sender;
|
||||
|
||||
use crate::event_loop::EventLoopClosed;
|
||||
use sctk::reexports::calloop::ping::Ping;
|
||||
|
||||
/// A handle that can be sent across the threads and used to wake up the `EventLoop`.
|
||||
pub struct EventLoopProxy<T: 'static> {
|
||||
user_events_sender: Sender<T>,
|
||||
#[derive(Clone)]
|
||||
pub struct EventLoopProxy {
|
||||
ping: Ping,
|
||||
}
|
||||
|
||||
impl<T: 'static> Clone for EventLoopProxy<T> {
|
||||
fn clone(&self) -> Self {
|
||||
EventLoopProxy { user_events_sender: self.user_events_sender.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> EventLoopProxy<T> {
|
||||
pub fn new(user_events_sender: Sender<T>) -> Self {
|
||||
Self { user_events_sender }
|
||||
impl EventLoopProxy {
|
||||
pub fn new(ping: Ping) -> Self {
|
||||
Self { ping }
|
||||
}
|
||||
|
||||
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
|
||||
self.user_events_sender.send(event).map_err(|SendError(error)| EventLoopClosed(error))
|
||||
pub fn wake_up(&self) {
|
||||
self.ping.ping();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use super::{DeviceId, WindowId};
|
|||
/// to the winit's user.
|
||||
#[derive(Default)]
|
||||
pub struct EventSink {
|
||||
pub window_events: Vec<Event<()>>,
|
||||
pub(crate) window_events: Vec<Event>,
|
||||
}
|
||||
|
||||
impl EventSink {
|
||||
|
|
@ -47,7 +47,7 @@ impl EventSink {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn drain(&mut self) -> Drain<'_, Event<()>> {
|
||||
pub(crate) fn drain(&mut self) -> Drain<'_, Event> {
|
||||
self.window_events.drain(..)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,6 +115,9 @@ pub struct WinitState {
|
|||
/// Whether we have dispatched events to the user thus we want to
|
||||
/// send `AboutToWait` and normally wakeup the user.
|
||||
pub dispatched_events: bool,
|
||||
|
||||
/// Whether the user initiated a wake up.
|
||||
pub proxy_wake_up: bool,
|
||||
}
|
||||
|
||||
impl WinitState {
|
||||
|
|
@ -192,6 +195,7 @@ impl WinitState {
|
|||
loop_handle,
|
||||
// Make it true by default.
|
||||
dispatched_events: true,
|
||||
proxy_wake_up: false,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue