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:
Kirill Chibisov 2024-06-24 13:04:55 +03:00 committed by GitHub
parent 7d1287958f
commit ecb887e5c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 675 additions and 966 deletions

View file

@ -21,7 +21,7 @@ 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::{AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed};
use crate::event_loop::{AsyncRequestSerial, ControlFlow, DeviceEvents};
use crate::icon::Icon;
use crate::keyboard::Key;
#[cfg(x11_platform)]
@ -691,27 +691,22 @@ unsafe extern "C" fn x_error_callback(
0
}
pub enum EventLoop<T: 'static> {
pub enum EventLoop {
#[cfg(wayland_platform)]
Wayland(Box<wayland::EventLoop<T>>),
Wayland(Box<wayland::EventLoop>),
#[cfg(x11_platform)]
X(x11::EventLoop<T>),
X(x11::EventLoop),
}
pub enum EventLoopProxy<T: 'static> {
#[derive(Clone)]
pub enum EventLoopProxy {
#[cfg(x11_platform)]
X(x11::EventLoopProxy<T>),
X(x11::EventLoopProxy),
#[cfg(wayland_platform)]
Wayland(wayland::EventLoopProxy<T>),
Wayland(wayland::EventLoopProxy),
}
impl<T: 'static> Clone for EventLoopProxy<T> {
fn clone(&self) -> Self {
x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.clone(); as EventLoopProxy)
}
}
impl<T: 'static> EventLoop<T> {
impl EventLoop {
pub(crate) fn new(
attributes: &PlatformSpecificEventLoopAttributes,
) -> Result<Self, EventLoopError> {
@ -770,12 +765,12 @@ impl<T: 'static> EventLoop<T> {
}
#[cfg(wayland_platform)]
fn new_wayland_any_thread() -> Result<EventLoop<T>, EventLoopError> {
fn new_wayland_any_thread() -> Result<EventLoop, EventLoopError> {
wayland::EventLoop::new().map(|evlp| EventLoop::Wayland(Box::new(evlp)))
}
#[cfg(x11_platform)]
fn new_x11_any_thread() -> Result<EventLoop<T>, EventLoopError> {
fn new_x11_any_thread() -> Result<EventLoop, EventLoopError> {
let xconn = match X11_BACKEND.lock().unwrap().as_ref() {
Ok(xconn) => xconn.clone(),
Err(_) => return Err(EventLoopError::NotSupported(NotSupportedError::new())),
@ -794,22 +789,22 @@ impl<T: 'static> EventLoop<T> {
}
}
pub fn create_proxy(&self) -> EventLoopProxy<T> {
pub fn create_proxy(&self) -> EventLoopProxy {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
}
pub fn run_app<A: ApplicationHandler<T>>(self, app: &mut A) -> Result<(), EventLoopError> {
pub fn run_app<A: ApplicationHandler>(self, app: &mut A) -> Result<(), EventLoopError> {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app(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> {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app_on_demand(app))
}
pub fn pump_app_events<A: ApplicationHandler<T>>(
pub fn pump_app_events<A: ApplicationHandler>(
&mut self,
timeout: Option<Duration>,
app: &mut A,
@ -822,21 +817,21 @@ impl<T: 'static> EventLoop<T> {
}
}
impl<T> AsFd for EventLoop<T> {
impl AsFd for EventLoop {
fn as_fd(&self) -> BorrowedFd<'_> {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.as_fd())
}
}
impl<T> AsRawFd for EventLoop<T> {
impl AsRawFd for EventLoop {
fn as_raw_fd(&self) -> RawFd {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.as_raw_fd())
}
}
impl<T: 'static> EventLoopProxy<T> {
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.send_event(event))
impl EventLoopProxy {
pub fn wake_up(&self) {
x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.wake_up())
}
}

View file

@ -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()
}

View file

@ -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();
}
}

View file

@ -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(..)
}
}

View file

@ -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,
})
}

View file

@ -72,9 +72,9 @@ pub struct EventProcessor {
}
impl EventProcessor {
pub fn process_event<T: 'static, F>(&mut self, xev: &mut XEvent, mut callback: F)
pub(crate) fn process_event<F>(&mut self, xev: &mut XEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
self.process_xevent(xev, &mut callback);
@ -139,9 +139,9 @@ impl EventProcessor {
}
}
fn process_xevent<T: 'static, F>(&mut self, xev: &mut XEvent, mut callback: F)
fn process_xevent<F>(&mut self, xev: &mut XEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let event_type = xev.get_type();
@ -387,9 +387,9 @@ impl EventProcessor {
}
}
fn client_message<T: 'static, F>(&mut self, xev: &XClientMessageEvent, mut callback: F)
fn client_message<F>(&mut self, xev: &XClientMessageEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
let atoms = wt.xconn.atoms();
@ -552,9 +552,9 @@ impl EventProcessor {
}
}
fn selection_notify<T: 'static, F>(&mut self, xev: &XSelectionEvent, mut callback: F)
fn selection_notify<F>(&mut self, xev: &XSelectionEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
let atoms = wt.xconn.atoms();
@ -586,9 +586,9 @@ impl EventProcessor {
}
}
fn configure_notify<T: 'static, F>(&self, xev: &XConfigureEvent, mut callback: F)
fn configure_notify<F>(&self, xev: &XConfigureEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -781,9 +781,9 @@ impl EventProcessor {
});
}
fn map_notify<T: 'static, F>(&self, xev: &XMapEvent, mut callback: F)
fn map_notify<F>(&self, xev: &XMapEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let window = xev.window as xproto::Window;
let window_id = mkwid(window);
@ -799,9 +799,9 @@ impl EventProcessor {
callback(&self.target, event);
}
fn destroy_notify<T: 'static, F>(&self, xev: &XDestroyWindowEvent, mut callback: F)
fn destroy_notify<F>(&self, xev: &XDestroyWindowEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -823,9 +823,9 @@ impl EventProcessor {
callback(&self.target, Event::WindowEvent { window_id, event: WindowEvent::Destroyed });
}
fn property_notify<T: 'static, F>(&mut self, xev: &XPropertyEvent, mut callback: F)
fn property_notify<F>(&mut self, xev: &XPropertyEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
let atoms = wt.x_connection().atoms();
@ -838,9 +838,9 @@ impl EventProcessor {
}
}
fn visibility_notify<T: 'static, F>(&self, xev: &XVisibilityEvent, mut callback: F)
fn visibility_notify<F>(&self, xev: &XVisibilityEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let xwindow = xev.window as xproto::Window;
@ -855,9 +855,9 @@ impl EventProcessor {
});
}
fn expose<T: 'static, F>(&self, xev: &XExposeEvent, mut callback: F)
fn expose<F>(&self, xev: &XExposeEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
// Multiple Expose events may be received for subareas of a window.
// We issue `RedrawRequested` only for the last event of such a series.
@ -871,13 +871,9 @@ impl EventProcessor {
}
}
fn xinput_key_input<T: 'static, F>(
&mut self,
xev: &mut XKeyEvent,
state: ElementState,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
fn xinput_key_input<F>(&mut self, xev: &mut XKeyEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -989,13 +985,13 @@ impl EventProcessor {
}
}
fn send_synthic_modifier_from_core<T: 'static, F>(
fn send_synthic_modifier_from_core<F>(
&mut self,
window_id: crate::window::WindowId,
state: u16,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let keymap = match self.xkb_context.keymap_mut() {
Some(keymap) => keymap,
@ -1022,13 +1018,9 @@ impl EventProcessor {
callback(&self.target, event);
}
fn xinput2_button_input<T: 'static, F>(
&self,
event: &XIDeviceEvent,
state: ElementState,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
fn xinput2_button_input<F>(&self, event: &XIDeviceEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
let window_id = mkwid(event.event as xproto::Window);
@ -1079,9 +1071,9 @@ impl EventProcessor {
callback(&self.target, event);
}
fn xinput2_mouse_motion<T: 'static, F>(&self, event: &XIDeviceEvent, mut callback: F)
fn xinput2_mouse_motion<F>(&self, event: &XIDeviceEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1157,9 +1149,9 @@ impl EventProcessor {
}
}
fn xinput2_mouse_enter<T: 'static, F>(&self, event: &XIEnterEvent, mut callback: F)
fn xinput2_mouse_enter<F>(&self, event: &XIEnterEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1202,9 +1194,9 @@ impl EventProcessor {
}
}
fn xinput2_mouse_left<T: 'static, F>(&self, event: &XILeaveEvent, mut callback: F)
fn xinput2_mouse_left<F>(&self, event: &XILeaveEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
let window = event.event as xproto::Window;
@ -1225,9 +1217,9 @@ impl EventProcessor {
}
}
fn xinput2_focused<T: 'static, F>(&mut self, xev: &XIFocusInEvent, mut callback: F)
fn xinput2_focused<F>(&mut self, xev: &XIFocusInEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
let window = xev.event as xproto::Window;
@ -1284,9 +1276,9 @@ impl EventProcessor {
callback(&self.target, event);
}
fn xinput2_unfocused<T: 'static, F>(&mut self, xev: &XIFocusOutEvent, mut callback: F)
fn xinput2_unfocused<F>(&mut self, xev: &XIFocusOutEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
let window = xev.event as xproto::Window;
@ -1336,13 +1328,9 @@ impl EventProcessor {
}
}
fn xinput2_touch<T: 'static, F>(
&mut self,
xev: &XIDeviceEvent,
phase: TouchPhase,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
where
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1382,13 +1370,9 @@ impl EventProcessor {
}
}
fn xinput2_raw_button_input<T: 'static, F>(
&self,
xev: &XIRawEvent,
state: ElementState,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
fn xinput2_raw_button_input<F>(&self, xev: &XIRawEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1404,9 +1388,9 @@ impl EventProcessor {
}
}
fn xinput2_raw_mouse_motion<T: 'static, F>(&self, xev: &XIRawEvent, mut callback: F)
fn xinput2_raw_mouse_motion<F>(&self, xev: &XIRawEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1464,13 +1448,9 @@ impl EventProcessor {
}
}
fn xinput2_raw_key_input<T: 'static, F>(
&mut self,
xev: &XIRawEvent,
state: ElementState,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
fn xinput2_raw_key_input<F>(&mut self, xev: &XIRawEvent, state: ElementState, mut callback: F)
where
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1490,9 +1470,9 @@ impl EventProcessor {
});
}
fn xinput2_hierarchy_changed<T: 'static, F>(&mut self, xev: &XIHierarchyEvent, mut callback: F)
fn xinput2_hierarchy_changed<F>(&mut self, xev: &XIHierarchyEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1517,9 +1497,9 @@ impl EventProcessor {
}
}
fn xkb_event<T: 'static, F>(&mut self, xev: &XkbAnyEvent, mut callback: F)
fn xkb_event<F>(&mut self, xev: &XkbAnyEvent, mut callback: F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
match xev.xkb_type {
@ -1596,14 +1576,14 @@ impl EventProcessor {
}
}
pub fn update_mods_from_xinput2_event<T: 'static, F>(
pub(crate) fn update_mods_from_xinput2_event<F>(
&mut self,
mods: &XIModifierState,
group: &XIModifierState,
force: bool,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
if let Some(state) = self.xkb_context.state_mut() {
state.update_modifiers(
@ -1627,12 +1607,9 @@ impl EventProcessor {
}
}
fn update_mods_from_query<T: 'static, F>(
&mut self,
window_id: crate::window::WindowId,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
fn update_mods_from_query<F>(&mut self, window_id: crate::window::WindowId, mut callback: F)
where
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
@ -1661,13 +1638,13 @@ impl EventProcessor {
self.send_modifiers(window_id, mods.into(), true, &mut callback)
}
pub fn update_mods_from_core_event<T: 'static, F>(
pub(crate) fn update_mods_from_core_event<F>(
&mut self,
window_id: crate::window::WindowId,
state: u16,
mut callback: F,
) where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let xkb_mask = self.xkb_mod_mask_from_core(state);
let xkb_state = match self.xkb_context.state_mut() {
@ -1740,7 +1717,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<T: 'static, F: FnMut(&RootAEL, Event<T>)>(
fn send_modifiers<F: FnMut(&RootAEL, Event)>(
&self,
window_id: crate::window::WindowId,
modifiers: ModifiersState,
@ -1758,14 +1735,14 @@ impl EventProcessor {
}
}
fn handle_pressed_keys<T: 'static, F>(
fn handle_pressed_keys<F>(
target: &RootAEL,
window_id: crate::window::WindowId,
state: ElementState,
xkb_context: &mut Context,
callback: &mut F,
) where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
@ -1800,9 +1777,9 @@ impl EventProcessor {
}
}
fn process_dpi_change<T: 'static, F>(&self, callback: &mut F)
fn process_dpi_change<F>(&self, callback: &mut F)
where
F: FnMut(&RootAEL, Event<T>),
F: FnMut(&RootAEL, Event),
{
let wt = Self::window_target(&self.target);
wt.xconn.reload_database().expect("failed to reload Xft database");

View file

@ -9,7 +9,7 @@ use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
use std::sync::{Arc, Weak};
use std::time::{Duration, Instant};
use std::{fmt, ptr, slice, str};
use std::{fmt, mem, ptr, slice, str};
use calloop::generic::Generic;
use calloop::ping::Ping;
@ -28,7 +28,7 @@ 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};
use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents};
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::common::xkb::Context;
use crate::platform_impl::platform::{min_timeout, WindowId};
@ -81,12 +81,11 @@ impl<T> Clone for WakeSender<T> {
}
impl<T> WakeSender<T> {
pub fn send(&self, t: T) -> Result<(), EventLoopClosed<T>> {
let res = self.sender.send(t).map_err(|e| EventLoopClosed(e.0));
pub fn send(&self, t: T) {
let res = self.sender.send(t);
if res.is_ok() {
self.waker.ping();
}
res
}
}
@ -141,15 +140,13 @@ pub struct ActiveEventLoop {
device_events: Cell<DeviceEvents>,
}
pub struct EventLoop<T: 'static> {
pub struct EventLoop {
loop_running: bool,
event_loop: Loop<'static, EventLoopState>,
waker: calloop::ping::Ping,
event_processor: EventProcessor,
redraw_receiver: PeekableReceiver<WindowId>,
user_receiver: PeekableReceiver<T>,
activation_receiver: PeekableReceiver<ActivationToken>,
user_sender: Sender<T>,
event_loop_proxy: EventLoopProxy,
/// The current state of the event loop.
state: EventLoopState,
@ -160,20 +157,13 @@ type ActivationToken = (WindowId, crate::event_loop::AsyncRequestSerial);
struct EventLoopState {
/// The latest readiness state for the x11 file descriptor
x11_readiness: Readiness,
/// User requested a wake up.
proxy_wake_up: bool,
}
pub struct EventLoopProxy<T: 'static> {
user_sender: WakeSender<T>,
}
impl<T: 'static> Clone for EventLoopProxy<T> {
fn clone(&self) -> Self {
EventLoopProxy { user_sender: self.user_sender.clone() }
}
}
impl<T: 'static> EventLoop<T> {
pub(crate) fn new(xconn: Arc<XConnection>) -> EventLoop<T> {
impl EventLoop {
pub(crate) fn new(xconn: Arc<XConnection>) -> EventLoop {
let root = xconn.default_root().root;
let atoms = xconn.atoms();
@ -277,7 +267,16 @@ impl<T: 'static> EventLoop<T> {
let (activation_token_sender, activation_token_channel) = mpsc::channel();
// Create a channel for sending user events.
let (user_sender, user_channel) = mpsc::channel();
let (user_waker, user_waker_source) =
calloop::ping::make_ping().expect("Failed to create user event loop waker.");
event_loop
.handle()
.insert_source(user_waker_source, move |_, _, state| {
// No extra handling is required, we just need to wake-up.
state.proxy_wake_up = true;
})
.expect("Failed to register the event loop waker source");
let event_loop_proxy = EventLoopProxy::new(user_waker);
let xkb_context =
Context::from_x11_xkb(xconn.xcb_connection().get_raw_xcb_connection()).unwrap();
@ -358,31 +357,27 @@ impl<T: 'static> EventLoop<T> {
EventLoop {
loop_running: false,
event_loop,
waker,
event_processor,
redraw_receiver: PeekableReceiver::from_recv(redraw_channel),
activation_receiver: PeekableReceiver::from_recv(activation_token_channel),
user_receiver: PeekableReceiver::from_recv(user_channel),
user_sender,
state: EventLoopState { x11_readiness: Readiness::EMPTY },
event_loop_proxy,
state: EventLoopState { x11_readiness: Readiness::EMPTY, proxy_wake_up: false },
}
}
pub fn create_proxy(&self) -> EventLoopProxy<T> {
EventLoopProxy {
user_sender: WakeSender { sender: self.user_sender.clone(), waker: self.waker.clone() },
}
pub fn create_proxy(&self) -> EventLoopProxy {
self.event_loop_proxy.clone()
}
pub(crate) fn window_target(&self) -> &RootAEL {
&self.event_processor.target
}
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> {
@ -412,7 +407,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,
@ -442,11 +437,11 @@ impl<T: 'static> EventLoop<T> {
fn has_pending(&mut self) -> bool {
self.event_processor.poll()
|| self.user_receiver.has_incoming()
|| self.state.proxy_wake_up
|| self.redraw_receiver.has_incoming()
}
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,
@ -511,7 +506,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) {
app.new_events(&self.event_processor.target, cause);
// NB: For consistency all platforms must emit a 'resumed' event even though X11
@ -546,10 +541,8 @@ impl<T: 'static> EventLoop<T> {
}
// Empty the user event buffer
{
while let Ok(event) = self.user_receiver.try_recv() {
app.user_event(&self.event_processor.target, event);
}
if mem::take(&mut self.state.proxy_wake_up) {
app.proxy_wake_up(&self.event_processor.target);
}
// Empty the redraw requests
@ -574,19 +567,19 @@ impl<T: 'static> EventLoop<T> {
app.about_to_wait(&self.event_processor.target);
}
fn drain_events<A: ApplicationHandler<T>>(&mut self, app: &mut A) {
fn drain_events<A: ApplicationHandler>(&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: Event<T>| {
self.event_processor.process_event(&mut xev, |window_target, event: Event| {
if let Event::WindowEvent {
window_id: crate::window::WindowId(wid),
event: WindowEvent::RedrawRequested,
} = event
{
let window_target = EventProcessor::window_target(window_target);
window_target.redraw_sender.send(wid).unwrap();
window_target.redraw_sender.send(wid);
} else {
match event {
Event::WindowEvent { window_id, event } => {
@ -623,13 +616,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()
}
@ -729,9 +722,9 @@ impl ActiveEventLoop {
}
}
impl<T: 'static> EventLoopProxy<T> {
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
self.user_sender.send(event).map_err(|e| EventLoopClosed(e.0))
impl EventLoopProxy {
pub fn wake_up(&self) {
self.ping.ping();
}
}
@ -815,6 +808,17 @@ impl Drop for Window {
}
}
#[derive(Clone)]
pub struct EventLoopProxy {
ping: Ping,
}
impl EventLoopProxy {
fn new(ping: Ping) -> Self {
Self { ping }
}
}
/// Generic sum error type for X11 errors.
#[derive(Debug)]
pub enum X11Error {

View file

@ -876,11 +876,11 @@ impl UnownedWindow {
/// Refresh the API for the given monitor.
#[inline]
pub(super) fn refresh_dpi_for_monitor<T: 'static>(
pub(super) fn refresh_dpi_for_monitor(
&self,
new_monitor: &X11MonitorHandle,
maybe_prev_scale_factor: Option<f64>,
mut callback: impl FnMut(Event<T>),
mut callback: impl FnMut(Event),
) {
// Check if the self is on this monitor
let monitor = self.shared_state_lock().last_monitor.clone();
@ -1805,9 +1805,7 @@ impl UnownedWindow {
#[inline]
pub fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> {
let serial = AsyncRequestSerial::get();
self.activation_sender
.send((self.id(), serial))
.expect("activation token channel should never be closed");
self.activation_sender.send((self.id(), serial));
Ok(serial)
}
@ -1818,7 +1816,7 @@ impl UnownedWindow {
#[inline]
pub fn request_redraw(&self) {
self.redraw_sender.send(WindowId(self.xwindow as _)).unwrap();
self.redraw_sender.send(WindowId(self.xwindow as _));
}
#[inline]