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)
}
@@ -553,6 +553,7 @@ impl<'a> KeyEventResults<'a> {
} else {
0
};
self.keysym_to_key(keysym)
.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 key = super::keymap::keysym_to_key(keysym);
if matches!(key, Key::Unidentified(_)) {

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,48 @@
#![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 atoms;
mod dnd;
@@ -12,72 +55,13 @@ mod window;
mod xdisplay;
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 x11rb::x11_utils::X11Error as LogicalError;
use x11rb::{
connection::RequestConnection,
protocol::{
xinput::{self, ConnectionExt as _},
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,
};
use dnd::{Dnd, DndState};
use event_processor::EventProcessor;
use ime::{Ime, ImeCreationError, ImeReceiver, ImeRequest, ImeSender};
pub(crate) use monitor::{MonitorHandle, VideoMode};
use window::UnownedWindow;
pub(crate) use xdisplay::XConnection;
// Xinput constants not defined in x11rb
const ALL_DEVICES: u16 = 0;
@@ -169,7 +153,6 @@ pub struct EventLoop<T: 'static> {
user_receiver: PeekableReceiver<T>,
activation_receiver: PeekableReceiver<ActivationToken>,
user_sender: Sender<T>,
target: Rc<RootELW<T>>,
/// The current state of the event loop.
state: EventLoopState,
@@ -328,13 +311,13 @@ impl<T: 'static> EventLoop<T> {
// Set initial device event filter.
window_target.update_listen_device_events(true);
let target = Rc::new(RootELW {
let root_window_target = RootELW {
p: super::EventLoopWindowTarget::X(window_target),
_marker: ::std::marker::PhantomData,
});
_marker: PhantomData,
};
let event_processor = EventProcessor {
target: target.clone(),
target: root_window_target,
dnd,
devices: Default::default(),
randr_event_offset,
@@ -353,8 +336,9 @@ impl<T: 'static> EventLoop<T> {
// Register for device hotplug events
// (The request buffer is flushed during `init_device`)
get_xtarget(&target)
.xconn
let xconn = &EventProcessor::window_target(&event_processor.target).xconn;
xconn
.select_xinput_events(
root,
ALL_DEVICES,
@@ -362,8 +346,7 @@ impl<T: 'static> EventLoop<T> {
)
.expect_then_ignore_error("Failed to register for XInput2 device hotplug events");
get_xtarget(&target)
.xconn
xconn
.select_xkb_events(
0x100, // Use the "core keyboard device"
xkb::EventType::NEW_KEYBOARD_NOTIFY
@@ -383,7 +366,6 @@ impl<T: 'static> EventLoop<T> {
activation_receiver: PeekableReceiver::from_recv(activation_token_channel),
user_receiver: PeekableReceiver::from_recv(user_channel),
user_sender,
target,
state: EventLoopState {
x11_readiness: Readiness::EMPTY,
},
@@ -400,7 +382,7 @@ impl<T: 'static> EventLoop<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>
@@ -429,7 +411,7 @@ impl<T: 'static> EventLoop<T> {
// `run_on_demand` calls but if they have only just dropped their
// windows we need to make sure those last requests are sent to the
// X Server.
let wt = get_xtarget(&self.target);
let wt = EventProcessor::window_target(&self.event_processor.target);
wt.x_connection().sync_with_server().map_err(|x_err| {
EventLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err)))))
})?;
@@ -552,12 +534,12 @@ impl<T: 'static> EventLoop<T> {
where
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
// applications don't themselves have a formal suspend/resume lifecycle.
if cause == StartCause::Init {
callback(crate::event::Event::Resumed, &self.target);
callback(Event::Resumed, &self.event_processor.target);
}
// Process all pending events
@@ -572,16 +554,16 @@ impl<T: 'static> EventLoop<T> {
});
match token {
Some(Ok(token)) => callback(
crate::event::Event::WindowEvent {
Some(Ok(token)) => {
let event = Event::WindowEvent {
window_id: crate::window::WindowId(window_id),
event: crate::event::WindowEvent::ActivationTokenDone {
event: WindowEvent::ActivationTokenDone {
serial,
token: crate::window::ActivationToken::_new(token),
},
},
&self.target,
),
};
callback(event, &self.event_processor.target)
}
Some(Err(e)) => {
log::error!("Failed to get activation token: {}", e);
}
@@ -592,7 +574,7 @@ impl<T: 'static> EventLoop<T> {
// Empty the user event buffer
{
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,
event: WindowEvent::RedrawRequested,
},
&self.target,
&self.event_processor.target,
);
}
}
// 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
F: FnMut(Event<T>, &RootELW<T>),
{
let target = &self.target;
let mut xev = MaybeUninit::uninit();
let wt = get_xtarget(&self.target);
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, |event| {
if let Event::WindowEvent {
window_id: crate::window::WindowId(wid),
event: WindowEvent::RedrawRequested,
} = event
{
wt.redraw_sender.send(wid).unwrap();
} else {
callback(event, target);
}
});
self.event_processor
.process_event(&mut xev, |window_target, 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();
} else {
callback(event, window_target);
}
});
}
}
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 {
self.target.p.exiting()
let window_target = EventProcessor::window_target(&self.event_processor.target);
window_target.exiting()
}
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> {
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> {
/// Returns the `XConnection` of this events loop.
#[inline]

View File

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

View File

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