On X11, store window target on EventProcessor

Remove the redundant `Rc` to access the window target.
This commit is contained in:
Kirill Chibisov
2024-02-09 05:52:09 +04:00
parent ed600e415a
commit 0135fe51ae
5 changed files with 595 additions and 481 deletions

View File

@@ -498,7 +498,7 @@ impl<'a> KeyEventResults<'a> {
} }
} }
fn physical_key(&mut self) -> PhysicalKey { fn physical_key(&self) -> PhysicalKey {
keymap::raw_keycode_to_physicalkey(self.keycode) keymap::raw_keycode_to_physicalkey(self.keycode)
} }
@@ -553,6 +553,7 @@ impl<'a> KeyEventResults<'a> {
} else { } else {
0 0
}; };
self.keysym_to_key(keysym) self.keysym_to_key(keysym)
.unwrap_or_else(|(key, location)| { .unwrap_or_else(|(key, location)| {
( (
@@ -565,7 +566,7 @@ impl<'a> KeyEventResults<'a> {
}) })
} }
fn keysym_to_key(&mut self, keysym: u32) -> Result<(Key, KeyLocation), (Key, KeyLocation)> { fn keysym_to_key(&self, keysym: u32) -> Result<(Key, KeyLocation), (Key, KeyLocation)> {
let location = super::keymap::keysym_location(keysym); let location = super::keymap::keysym_location(keysym);
let key = super::keymap::keysym_to_key(keysym); let key = super::keymap::keysym_to_key(keysym);
if matches!(key, Key::Unidentified(_)) { if matches!(key, Key::Unidentified(_)) {

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,48 @@
#![cfg(x11_platform)] #![cfg(x11_platform)]
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::os::raw::*;
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::{ptr, slice, str};
pub use self::xdisplay::{XError, XNotSupported};
use calloop::generic::Generic;
use calloop::EventLoop as Loop;
use calloop::{ping::Ping, Readiness};
use libc::{self, setlocale, LC_CTYPE};
use log::warn;
use x11rb::connection::RequestConnection;
use x11rb::errors::{ConnectError, ConnectionError, IdsExhausted, ReplyError};
use x11rb::protocol::xinput::{self, ConnectionExt as _};
use x11rb::protocol::xkb;
use x11rb::protocol::xproto::{self, ConnectionExt as _};
use x11rb::x11_utils::X11Error as LogicalError;
use x11rb::xcb_ffi::ReplyOrIdError;
use super::{common::xkb_state::KbdState, ControlFlow, OsError};
use crate::{
error::{EventLoopError, OsError as RootOsError},
event::{Event, StartCause, WindowEvent},
event_loop::{DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW},
platform::pump_events::PumpStatus,
platform_impl::{
platform::{min_timeout, WindowId},
PlatformSpecificWindowBuilderAttributes,
},
window::WindowAttributes,
};
mod activation; mod activation;
mod atoms; mod atoms;
mod dnd; mod dnd;
@@ -12,72 +55,13 @@ mod window;
mod xdisplay; mod xdisplay;
mod xsettings; mod xsettings;
pub(crate) use self::{
monitor::{MonitorHandle, VideoMode},
window::UnownedWindow,
xdisplay::XConnection,
};
pub use self::xdisplay::{XError, XNotSupported};
use calloop::generic::Generic;
use calloop::EventLoop as Loop;
use calloop::{ping::Ping, Readiness};
use std::{
cell::{Cell, RefCell},
collections::{HashMap, HashSet},
ffi::CStr,
fmt,
mem::MaybeUninit,
ops::Deref,
os::{
raw::*,
unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd},
},
ptr,
rc::Rc,
slice, str,
sync::mpsc::{Receiver, Sender, TryRecvError},
sync::{mpsc, Arc, Weak},
time::{Duration, Instant},
};
use libc::{self, setlocale, LC_CTYPE};
use atoms::*; use atoms::*;
use dnd::{Dnd, DndState};
use x11rb::x11_utils::X11Error as LogicalError; use event_processor::EventProcessor;
use x11rb::{ use ime::{Ime, ImeCreationError, ImeReceiver, ImeRequest, ImeSender};
connection::RequestConnection, pub(crate) use monitor::{MonitorHandle, VideoMode};
protocol::{ use window::UnownedWindow;
xinput::{self, ConnectionExt as _}, pub(crate) use xdisplay::XConnection;
xkb,
xproto::{self, ConnectionExt as _},
},
};
use x11rb::{
errors::{ConnectError, ConnectionError, IdsExhausted, ReplyError},
xcb_ffi::ReplyOrIdError,
};
use self::{
dnd::{Dnd, DndState},
event_processor::EventProcessor,
ime::{Ime, ImeCreationError, ImeReceiver, ImeRequest, ImeSender},
};
use super::{common::xkb_state::KbdState, ControlFlow, OsError};
use crate::{
error::{EventLoopError, OsError as RootOsError},
event::{Event, StartCause, WindowEvent},
event_loop::{DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW},
platform::pump_events::PumpStatus,
platform_impl::{
platform::{min_timeout, WindowId},
PlatformSpecificWindowBuilderAttributes,
},
window::WindowAttributes,
};
// Xinput constants not defined in x11rb // Xinput constants not defined in x11rb
const ALL_DEVICES: u16 = 0; const ALL_DEVICES: u16 = 0;
@@ -169,7 +153,6 @@ pub struct EventLoop<T: 'static> {
user_receiver: PeekableReceiver<T>, user_receiver: PeekableReceiver<T>,
activation_receiver: PeekableReceiver<ActivationToken>, activation_receiver: PeekableReceiver<ActivationToken>,
user_sender: Sender<T>, user_sender: Sender<T>,
target: Rc<RootELW<T>>,
/// The current state of the event loop. /// The current state of the event loop.
state: EventLoopState, state: EventLoopState,
@@ -328,13 +311,13 @@ impl<T: 'static> EventLoop<T> {
// Set initial device event filter. // Set initial device event filter.
window_target.update_listen_device_events(true); window_target.update_listen_device_events(true);
let target = Rc::new(RootELW { let root_window_target = RootELW {
p: super::EventLoopWindowTarget::X(window_target), p: super::EventLoopWindowTarget::X(window_target),
_marker: ::std::marker::PhantomData, _marker: PhantomData,
}); };
let event_processor = EventProcessor { let event_processor = EventProcessor {
target: target.clone(), target: root_window_target,
dnd, dnd,
devices: Default::default(), devices: Default::default(),
randr_event_offset, randr_event_offset,
@@ -353,8 +336,9 @@ impl<T: 'static> EventLoop<T> {
// Register for device hotplug events // Register for device hotplug events
// (The request buffer is flushed during `init_device`) // (The request buffer is flushed during `init_device`)
get_xtarget(&target) let xconn = &EventProcessor::window_target(&event_processor.target).xconn;
.xconn
xconn
.select_xinput_events( .select_xinput_events(
root, root,
ALL_DEVICES, ALL_DEVICES,
@@ -362,8 +346,7 @@ impl<T: 'static> EventLoop<T> {
) )
.expect_then_ignore_error("Failed to register for XInput2 device hotplug events"); .expect_then_ignore_error("Failed to register for XInput2 device hotplug events");
get_xtarget(&target) xconn
.xconn
.select_xkb_events( .select_xkb_events(
0x100, // Use the "core keyboard device" 0x100, // Use the "core keyboard device"
xkb::EventType::NEW_KEYBOARD_NOTIFY xkb::EventType::NEW_KEYBOARD_NOTIFY
@@ -383,7 +366,6 @@ impl<T: 'static> EventLoop<T> {
activation_receiver: PeekableReceiver::from_recv(activation_token_channel), activation_receiver: PeekableReceiver::from_recv(activation_token_channel),
user_receiver: PeekableReceiver::from_recv(user_channel), user_receiver: PeekableReceiver::from_recv(user_channel),
user_sender, user_sender,
target,
state: EventLoopState { state: EventLoopState {
x11_readiness: Readiness::EMPTY, x11_readiness: Readiness::EMPTY,
}, },
@@ -400,7 +382,7 @@ impl<T: 'static> EventLoop<T> {
} }
pub(crate) fn window_target(&self) -> &RootELW<T> { pub(crate) fn window_target(&self) -> &RootELW<T> {
&self.target &self.event_processor.target
} }
pub fn run_on_demand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError> pub fn run_on_demand<F>(&mut self, mut event_handler: F) -> Result<(), EventLoopError>
@@ -429,7 +411,7 @@ impl<T: 'static> EventLoop<T> {
// `run_on_demand` calls but if they have only just dropped their // `run_on_demand` calls but if they have only just dropped their
// windows we need to make sure those last requests are sent to the // windows we need to make sure those last requests are sent to the
// X Server. // X Server.
let wt = get_xtarget(&self.target); let wt = EventProcessor::window_target(&self.event_processor.target);
wt.x_connection().sync_with_server().map_err(|x_err| { wt.x_connection().sync_with_server().map_err(|x_err| {
EventLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err))))) EventLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err)))))
})?; })?;
@@ -552,12 +534,12 @@ impl<T: 'static> EventLoop<T> {
where where
F: FnMut(Event<T>, &RootELW<T>), F: FnMut(Event<T>, &RootELW<T>),
{ {
callback(crate::event::Event::NewEvents(cause), &self.target); callback(Event::NewEvents(cause), &self.event_processor.target);
// NB: For consistency all platforms must emit a 'resumed' event even though X11 // NB: For consistency all platforms must emit a 'resumed' event even though X11
// applications don't themselves have a formal suspend/resume lifecycle. // applications don't themselves have a formal suspend/resume lifecycle.
if cause == StartCause::Init { if cause == StartCause::Init {
callback(crate::event::Event::Resumed, &self.target); callback(Event::Resumed, &self.event_processor.target);
} }
// Process all pending events // Process all pending events
@@ -572,16 +554,16 @@ impl<T: 'static> EventLoop<T> {
}); });
match token { match token {
Some(Ok(token)) => callback( Some(Ok(token)) => {
crate::event::Event::WindowEvent { let event = Event::WindowEvent {
window_id: crate::window::WindowId(window_id), window_id: crate::window::WindowId(window_id),
event: crate::event::WindowEvent::ActivationTokenDone { event: WindowEvent::ActivationTokenDone {
serial, serial,
token: crate::window::ActivationToken::_new(token), token: crate::window::ActivationToken::_new(token),
}, },
}, };
&self.target, callback(event, &self.event_processor.target)
), }
Some(Err(e)) => { Some(Err(e)) => {
log::error!("Failed to get activation token: {}", e); log::error!("Failed to get activation token: {}", e);
} }
@@ -592,7 +574,7 @@ impl<T: 'static> EventLoop<T> {
// Empty the user event buffer // Empty the user event buffer
{ {
while let Ok(event) = self.user_receiver.try_recv() { while let Ok(event) = self.user_receiver.try_recv() {
callback(crate::event::Event::UserEvent(event), &self.target); callback(Event::UserEvent(event), &self.event_processor.target);
} }
} }
@@ -611,14 +593,14 @@ impl<T: 'static> EventLoop<T> {
window_id, window_id,
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
}, },
&self.target, &self.event_processor.target,
); );
} }
} }
// This is always the last event we dispatch before poll again // This is always the last event we dispatch before poll again
{ {
callback(crate::event::Event::AboutToWait, &self.target); callback(Event::AboutToWait, &self.event_processor.target);
} }
} }
@@ -626,40 +608,44 @@ impl<T: 'static> EventLoop<T> {
where where
F: FnMut(Event<T>, &RootELW<T>), F: FnMut(Event<T>, &RootELW<T>),
{ {
let target = &self.target;
let mut xev = MaybeUninit::uninit(); let mut xev = MaybeUninit::uninit();
let wt = get_xtarget(&self.target);
while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } { while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } {
let mut xev = unsafe { xev.assume_init() }; let mut xev = unsafe { xev.assume_init() };
self.event_processor.process_event(&mut xev, |event| { self.event_processor
.process_event(&mut xev, |window_target, event| {
if let Event::WindowEvent { if let Event::WindowEvent {
window_id: crate::window::WindowId(wid), window_id: crate::window::WindowId(wid),
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
} = event } = event
{ {
wt.redraw_sender.send(wid).unwrap(); let window_target = EventProcessor::window_target(window_target);
window_target.redraw_sender.send(wid).unwrap();
} else { } else {
callback(event, target); callback(event, window_target);
} }
}); });
} }
} }
fn control_flow(&self) -> ControlFlow { fn control_flow(&self) -> ControlFlow {
self.target.p.control_flow() let window_target = EventProcessor::window_target(&self.event_processor.target);
window_target.control_flow()
} }
fn exiting(&self) -> bool { fn exiting(&self) -> bool {
self.target.p.exiting() let window_target = EventProcessor::window_target(&self.event_processor.target);
window_target.exiting()
} }
fn set_exit_code(&self, code: i32) { fn set_exit_code(&self, code: i32) {
self.target.p.set_exit_code(code) let window_target = EventProcessor::window_target(&self.event_processor.target);
window_target.set_exit_code(code);
} }
fn exit_code(&self) -> Option<i32> { fn exit_code(&self) -> Option<i32> {
self.target.p.exit_code() let window_target = EventProcessor::window_target(&self.event_processor.target);
window_target.exit_code()
} }
} }
@@ -675,14 +661,6 @@ impl<T> AsRawFd for EventLoop<T> {
} }
} }
pub(crate) fn get_xtarget<T>(target: &RootELW<T>) -> &EventLoopWindowTarget<T> {
match target.p {
super::EventLoopWindowTarget::X(ref target) => target,
#[cfg(wayland_platform)]
_ => unreachable!(),
}
}
impl<T> EventLoopWindowTarget<T> { impl<T> EventLoopWindowTarget<T> {
/// Returns the `XConnection` of this events loop. /// Returns the `XConnection` of this events loop.
#[inline] #[inline]

View File

@@ -118,7 +118,7 @@ impl SharedState {
unsafe impl Send for UnownedWindow {} unsafe impl Send for UnownedWindow {}
unsafe impl Sync for UnownedWindow {} unsafe impl Sync for UnownedWindow {}
pub(crate) struct UnownedWindow { pub struct UnownedWindow {
pub(crate) xconn: Arc<XConnection>, // never changes pub(crate) xconn: Arc<XConnection>, // never changes
xwindow: xproto::Window, // never changes xwindow: xproto::Window, // never changes
#[allow(dead_code)] #[allow(dead_code)]

View File

@@ -22,7 +22,7 @@ use x11rb::{
}; };
/// A connection to an X server. /// A connection to an X server.
pub(crate) struct XConnection { pub struct XConnection {
pub xlib: ffi::Xlib, pub xlib: ffi::Xlib,
pub xcursor: ffi::Xcursor, pub xcursor: ffi::Xcursor,