api: refactor ActiveEventLoop into trait
This should help with further extensions because the backend event loops are used directly now.
This commit is contained in:
parent
f5304815a1
commit
f07153b8e0
33 changed files with 1058 additions and 1071 deletions
|
|
@ -19,8 +19,8 @@ use self::x11::{X11Error, XConnection, XError, XNotSupported};
|
|||
use crate::application::ApplicationHandler;
|
||||
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError};
|
||||
use crate::event_loop::{AsyncRequestSerial, ControlFlow, DeviceEvents};
|
||||
use crate::error::{EventLoopError, ExternalError, NotSupportedError};
|
||||
use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial};
|
||||
use crate::icon::Icon;
|
||||
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
|
||||
use crate::keyboard::Key;
|
||||
|
|
@ -31,8 +31,8 @@ pub(crate) use crate::platform_impl::Fullscreen;
|
|||
#[cfg(x11_platform)]
|
||||
use crate::utils::Lazy;
|
||||
use crate::window::{
|
||||
ActivationToken, Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose,
|
||||
ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowButtons, WindowLevel,
|
||||
ActivationToken, Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
|
||||
WindowButtons, WindowLevel,
|
||||
};
|
||||
|
||||
pub(crate) mod common;
|
||||
|
|
@ -281,23 +281,6 @@ impl VideoModeHandle {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
#[inline]
|
||||
pub(crate) fn new(
|
||||
window_target: &ActiveEventLoop,
|
||||
attribs: WindowAttributes,
|
||||
) -> Result<Self, RootOsError> {
|
||||
match *window_target {
|
||||
#[cfg(wayland_platform)]
|
||||
ActiveEventLoop::Wayland(ref window_target) => {
|
||||
wayland::Window::new(window_target, attribs).map(Window::Wayland)
|
||||
},
|
||||
#[cfg(x11_platform)]
|
||||
ActiveEventLoop::X(ref window_target) => {
|
||||
x11::Window::new(window_target, attribs).map(Window::X)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) {
|
||||
f(self)
|
||||
}
|
||||
|
|
@ -789,7 +772,7 @@ impl EventLoop {
|
|||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_app_events(timeout, app))
|
||||
}
|
||||
|
||||
pub fn window_target(&self) -> &crate::event_loop::ActiveEventLoop {
|
||||
pub fn window_target(&self) -> &dyn ActiveEventLoop {
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.window_target())
|
||||
}
|
||||
}
|
||||
|
|
@ -812,112 +795,6 @@ impl EventLoopProxy {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum ActiveEventLoop {
|
||||
#[cfg(wayland_platform)]
|
||||
Wayland(wayland::ActiveEventLoop),
|
||||
#[cfg(x11_platform)]
|
||||
X(x11::ActiveEventLoop),
|
||||
}
|
||||
|
||||
impl ActiveEventLoop {
|
||||
pub fn create_proxy(&self) -> EventLoopProxy {
|
||||
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_wayland(&self) -> bool {
|
||||
match *self {
|
||||
#[cfg(wayland_platform)]
|
||||
ActiveEventLoop::Wayland(_) => true,
|
||||
#[cfg(x11_platform)]
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_custom_cursor(
|
||||
&self,
|
||||
cursor: CustomCursorSource,
|
||||
) -> Result<CustomCursor, ExternalError> {
|
||||
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_custom_cursor(cursor))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
|
||||
match *self {
|
||||
#[cfg(wayland_platform)]
|
||||
ActiveEventLoop::Wayland(ref evlp) => {
|
||||
evlp.available_monitors().map(MonitorHandle::Wayland).collect()
|
||||
},
|
||||
#[cfg(x11_platform)]
|
||||
ActiveEventLoop::X(ref evlp) => {
|
||||
evlp.available_monitors().map(MonitorHandle::X).collect()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
|
||||
Some(
|
||||
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.primary_monitor()?; as MonitorHandle),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn listen_device_events(&self, allowed: DeviceEvents) {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.listen_device_events(allowed))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn system_theme(&self) -> Option<Theme> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(feature = "rwh_06")]
|
||||
#[inline]
|
||||
pub fn raw_display_handle_rwh_06(
|
||||
&self,
|
||||
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle_rwh_06())
|
||||
}
|
||||
|
||||
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.set_control_flow(control_flow))
|
||||
}
|
||||
|
||||
pub(crate) fn control_flow(&self) -> ControlFlow {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.control_flow())
|
||||
}
|
||||
|
||||
fn clear_exit(&self) {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.clear_exit())
|
||||
}
|
||||
|
||||
pub(crate) fn exit(&self) {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.exit())
|
||||
}
|
||||
|
||||
pub(crate) fn exiting(&self) -> bool {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.exiting())
|
||||
}
|
||||
|
||||
pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle {
|
||||
match self {
|
||||
#[cfg(x11_platform)]
|
||||
Self::X(conn) => OwnedDisplayHandle::X(conn.x_connection().clone()),
|
||||
#[cfg(wayland_platform)]
|
||||
Self::Wayland(conn) => OwnedDisplayHandle::Wayland(conn.connection.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_exit_code(&self, code: i32) {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.set_exit_code(code))
|
||||
}
|
||||
|
||||
fn exit_code(&self) -> Option<i32> {
|
||||
x11_or_wayland!(match self; Self(evlp) => evlp.exit_code())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) enum OwnedDisplayHandle {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
//! The event-loop routines.
|
||||
|
||||
use std::any::Any;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::io::Result as IOResult;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
|
@ -21,10 +21,8 @@ use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent};
|
|||
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::platform::min_timeout;
|
||||
use crate::platform_impl::{
|
||||
ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor,
|
||||
};
|
||||
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource};
|
||||
use crate::platform_impl::{OsError, PlatformCustomCursor};
|
||||
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme};
|
||||
|
||||
mod proxy;
|
||||
pub mod sink;
|
||||
|
|
@ -55,7 +53,7 @@ pub struct EventLoop {
|
|||
connection: Connection,
|
||||
|
||||
/// Event loop window target.
|
||||
window_target: RootActiveEventLoop,
|
||||
active_event_loop: ActiveEventLoop,
|
||||
|
||||
// XXX drop after everything else, just to be safe.
|
||||
/// Calloop's event loop.
|
||||
|
|
@ -132,7 +130,7 @@ impl EventLoop {
|
|||
.map_err(|error| error.error);
|
||||
map_err!(result, WaylandError::Calloop)?;
|
||||
|
||||
let window_target = ActiveEventLoop {
|
||||
let active_event_loop = ActiveEventLoop {
|
||||
connection: connection.clone(),
|
||||
wayland_dispatcher: wayland_dispatcher.clone(),
|
||||
event_loop_awakener,
|
||||
|
|
@ -151,10 +149,7 @@ impl EventLoop {
|
|||
connection,
|
||||
wayland_dispatcher,
|
||||
event_loop,
|
||||
window_target: RootActiveEventLoop {
|
||||
p: PlatformActiveEventLoop::Wayland(window_target),
|
||||
_marker: PhantomData,
|
||||
},
|
||||
active_event_loop,
|
||||
};
|
||||
|
||||
Ok(event_loop)
|
||||
|
|
@ -168,7 +163,7 @@ impl EventLoop {
|
|||
&mut self,
|
||||
mut app: A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
self.window_target.p.clear_exit();
|
||||
self.active_event_loop.clear_exit();
|
||||
let exit = loop {
|
||||
match self.pump_app_events(None, &mut app) {
|
||||
PumpStatus::Exit(0) => {
|
||||
|
|
@ -212,7 +207,7 @@ impl EventLoop {
|
|||
if let Some(code) = self.exit_code() {
|
||||
self.loop_running = false;
|
||||
|
||||
app.exiting(&self.window_target);
|
||||
app.exiting(&self.active_event_loop);
|
||||
|
||||
PumpStatus::Exit(code)
|
||||
} else {
|
||||
|
|
@ -300,17 +295,17 @@ impl EventLoop {
|
|||
let mut buffer_sink = std::mem::take(&mut self.buffer_sink);
|
||||
let mut window_ids = std::mem::take(&mut self.window_ids);
|
||||
|
||||
app.new_events(&self.window_target, cause);
|
||||
app.new_events(&self.active_event_loop, cause);
|
||||
|
||||
// NB: For consistency all platforms must call `can_create_surfaces` even though Wayland
|
||||
// applications don't themselves have a formal surface destroy/create lifecycle.
|
||||
if cause == StartCause::Init {
|
||||
app.can_create_surfaces(&self.window_target);
|
||||
app.can_create_surfaces(&self.active_event_loop);
|
||||
}
|
||||
|
||||
// Indicate user wake up.
|
||||
if self.with_state(|state| mem::take(&mut state.proxy_wake_up)) {
|
||||
app.proxy_wake_up(&self.window_target);
|
||||
app.proxy_wake_up(&self.active_event_loop);
|
||||
}
|
||||
|
||||
// Drain the pending compositor updates.
|
||||
|
|
@ -337,7 +332,7 @@ impl EventLoop {
|
|||
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),
|
||||
};
|
||||
|
||||
app.window_event(&self.window_target, root_window_id, event);
|
||||
app.window_event(&self.active_event_loop, root_window_id, event);
|
||||
|
||||
let physical_size = *new_inner_size.lock().unwrap();
|
||||
drop(new_inner_size);
|
||||
|
|
@ -382,12 +377,12 @@ impl EventLoop {
|
|||
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
let event = WindowEvent::Resized(physical_size);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
app.window_event(&self.active_event_loop, window_id, event);
|
||||
}
|
||||
|
||||
if compositor_update.close_window {
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
app.window_event(&self.window_target, window_id, WindowEvent::CloseRequested);
|
||||
app.window_event(&self.active_event_loop, window_id, WindowEvent::CloseRequested);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -398,10 +393,10 @@ impl EventLoop {
|
|||
for event in buffer_sink.drain() {
|
||||
match event {
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(&self.window_target, window_id, event)
|
||||
app.window_event(&self.active_event_loop, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(&self.window_target, device_id, event)
|
||||
app.device_event(&self.active_event_loop, device_id, event)
|
||||
},
|
||||
_ => unreachable!("event which is neither device nor window event."),
|
||||
}
|
||||
|
|
@ -414,10 +409,10 @@ impl EventLoop {
|
|||
for event in buffer_sink.drain() {
|
||||
match event {
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
app.window_event(&self.window_target, window_id, event)
|
||||
app.window_event(&self.active_event_loop, window_id, event)
|
||||
},
|
||||
Event::DeviceEvent { device_id, event } => {
|
||||
app.device_event(&self.window_target, device_id, event)
|
||||
app.device_event(&self.active_event_loop, device_id, event)
|
||||
},
|
||||
_ => unreachable!("event which is neither device nor window event."),
|
||||
}
|
||||
|
|
@ -457,7 +452,7 @@ impl EventLoop {
|
|||
|
||||
if let Some(event) = event {
|
||||
let window_id = crate::window::WindowId(*window_id);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
app.window_event(&self.active_event_loop, window_id, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -467,7 +462,7 @@ impl EventLoop {
|
|||
});
|
||||
|
||||
// This is always the last event we dispatch before poll again
|
||||
app.about_to_wait(&self.window_target);
|
||||
app.about_to_wait(&self.active_event_loop);
|
||||
|
||||
// Update the window frames and schedule redraws.
|
||||
let mut wake_up = false;
|
||||
|
|
@ -496,13 +491,7 @@ impl EventLoop {
|
|||
// If the user draws from the `AboutToWait` this is likely not required, however
|
||||
// we can't do much about it.
|
||||
if wake_up {
|
||||
match &self.window_target.p {
|
||||
PlatformActiveEventLoop::Wayland(window_target) => {
|
||||
window_target.event_loop_awakener.ping();
|
||||
},
|
||||
#[cfg(x11_platform)]
|
||||
PlatformActiveEventLoop::X(_) => unreachable!(),
|
||||
}
|
||||
self.active_event_loop.event_loop_awakener.ping();
|
||||
}
|
||||
|
||||
std::mem::swap(&mut self.compositor_updates, &mut compositor_updates);
|
||||
|
|
@ -511,26 +500,17 @@ impl EventLoop {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn window_target(&self) -> &RootActiveEventLoop {
|
||||
&self.window_target
|
||||
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
|
||||
&self.active_event_loop
|
||||
}
|
||||
|
||||
fn with_state<'a, U: 'a, F: FnOnce(&'a mut WinitState) -> U>(&'a mut self, callback: F) -> U {
|
||||
let state = match &mut self.window_target.p {
|
||||
PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
|
||||
#[cfg(x11_platform)]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let state = self.active_event_loop.state.get_mut();
|
||||
callback(state)
|
||||
}
|
||||
|
||||
fn loop_dispatch<D: Into<Option<std::time::Duration>>>(&mut self, timeout: D) -> IOResult<()> {
|
||||
let state = match &mut self.window_target.p {
|
||||
PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let state = &mut self.active_event_loop.state.get_mut();
|
||||
|
||||
self.event_loop.dispatch(timeout, state).map_err(|error| {
|
||||
tracing::error!("Error dispatching event loop: {}", error);
|
||||
|
|
@ -539,11 +519,7 @@ impl EventLoop {
|
|||
}
|
||||
|
||||
fn roundtrip(&mut self) -> Result<usize, RootOsError> {
|
||||
let state = match &mut self.window_target.p {
|
||||
PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let state = &mut self.active_event_loop.state.get_mut();
|
||||
|
||||
let mut wayland_source = self.wayland_dispatcher.as_source_mut();
|
||||
let event_queue = wayland_source.queue();
|
||||
|
|
@ -553,19 +529,19 @@ impl EventLoop {
|
|||
}
|
||||
|
||||
fn control_flow(&self) -> ControlFlow {
|
||||
self.window_target.p.control_flow()
|
||||
self.active_event_loop.control_flow()
|
||||
}
|
||||
|
||||
fn exiting(&self) -> bool {
|
||||
self.window_target.p.exiting()
|
||||
self.active_event_loop.exiting()
|
||||
}
|
||||
|
||||
fn set_exit_code(&self, code: i32) {
|
||||
self.window_target.p.set_exit_code(code)
|
||||
self.active_event_loop.set_exit_code(code)
|
||||
}
|
||||
|
||||
fn exit_code(&self) -> Option<i32> {
|
||||
self.window_target.p.exit_code()
|
||||
self.active_event_loop.exit_code()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -608,43 +584,35 @@ pub struct ActiveEventLoop {
|
|||
pub connection: Connection,
|
||||
}
|
||||
|
||||
impl ActiveEventLoop {
|
||||
pub(crate) fn create_proxy(&self) -> EventLoopProxy {
|
||||
self.event_loop_proxy.clone()
|
||||
impl RootActiveEventLoop for ActiveEventLoop {
|
||||
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy {
|
||||
crate::event_loop::EventLoopProxy {
|
||||
event_loop_proxy: crate::platform_impl::EventLoopProxy::Wayland(
|
||||
self.event_loop_proxy.clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||
fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||
self.control_flow.set(control_flow)
|
||||
}
|
||||
|
||||
pub(crate) fn control_flow(&self) -> ControlFlow {
|
||||
fn control_flow(&self) -> ControlFlow {
|
||||
self.control_flow.get()
|
||||
}
|
||||
|
||||
pub(crate) fn exit(&self) {
|
||||
fn exit(&self) {
|
||||
self.exit.set(Some(0))
|
||||
}
|
||||
|
||||
pub(crate) fn clear_exit(&self) {
|
||||
self.exit.set(None)
|
||||
}
|
||||
|
||||
pub(crate) fn exiting(&self) -> bool {
|
||||
fn exiting(&self) -> bool {
|
||||
self.exit.get().is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn set_exit_code(&self, code: i32) {
|
||||
self.exit.set(Some(code))
|
||||
}
|
||||
|
||||
pub(crate) fn exit_code(&self) -> Option<i32> {
|
||||
self.exit.get()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
|
||||
fn listen_device_events(&self, _allowed: DeviceEvents) {}
|
||||
|
||||
pub(crate) fn create_custom_cursor(
|
||||
fn create_custom_cursor(
|
||||
&self,
|
||||
cursor: CustomCursorSource,
|
||||
) -> Result<RootCustomCursor, ExternalError> {
|
||||
|
|
@ -653,17 +621,78 @@ impl ActiveEventLoop {
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "rwh_06")]
|
||||
#[inline]
|
||||
pub fn raw_display_handle_rwh_06(
|
||||
&self,
|
||||
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
|
||||
use sctk::reexports::client::Proxy;
|
||||
fn system_theme(&self) -> Option<Theme> {
|
||||
None
|
||||
}
|
||||
|
||||
Ok(rwh_06::WaylandDisplayHandle::new({
|
||||
let ptr = self.connection.display().id().as_ptr();
|
||||
std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null")
|
||||
})
|
||||
.into())
|
||||
fn create_window(
|
||||
&self,
|
||||
window_attributes: crate::window::WindowAttributes,
|
||||
) -> Result<crate::window::Window, RootOsError> {
|
||||
let window = crate::platform_impl::wayland::Window::new(self, window_attributes)?;
|
||||
let window = crate::platform_impl::Window::Wayland(window);
|
||||
Ok(crate::window::Window { window })
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
|
||||
Box::new(
|
||||
self.state
|
||||
.borrow()
|
||||
.output_state
|
||||
.outputs()
|
||||
.map(crate::platform_impl::wayland::output::MonitorHandle::new)
|
||||
.map(crate::platform_impl::MonitorHandle::Wayland)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner }),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
// There's no primary monitor on Wayland.
|
||||
None
|
||||
}
|
||||
|
||||
fn owned_display_handle(&self) -> crate::event_loop::OwnedDisplayHandle {
|
||||
crate::event_loop::OwnedDisplayHandle {
|
||||
platform: crate::platform_impl::OwnedDisplayHandle::Wayland(self.connection.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "rwh_06")]
|
||||
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveEventLoop {
|
||||
fn clear_exit(&self) {
|
||||
self.exit.set(None)
|
||||
}
|
||||
|
||||
fn set_exit_code(&self, code: i32) {
|
||||
self.exit.set(Some(code))
|
||||
}
|
||||
|
||||
fn exit_code(&self) -> Option<i32> {
|
||||
self.exit.get()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rwh_06")]
|
||||
impl rwh_06::HasDisplayHandle for ActiveEventLoop {
|
||||
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
|
||||
use sctk::reexports::client::Proxy;
|
||||
|
||||
let raw = rwh_06::WaylandDisplayHandle::new({
|
||||
let ptr = self.connection.display().id().as_ptr();
|
||||
std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null")
|
||||
});
|
||||
|
||||
Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw.into()) })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,9 @@ use sctk::output::OutputData;
|
|||
use sctk::reexports::client::protocol::wl_output::WlOutput;
|
||||
use sctk::reexports::client::Proxy;
|
||||
|
||||
use super::event_loop::ActiveEventLoop;
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::platform_impl::platform::VideoModeHandle as PlatformVideoModeHandle;
|
||||
|
||||
impl ActiveEventLoop {
|
||||
#[inline]
|
||||
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
|
||||
self.state.borrow().output_state.outputs().map(MonitorHandle::new)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
|
||||
// There's no primary monitor on Wayland.
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MonitorHandle {
|
||||
pub(crate) proxy: WlOutput,
|
||||
|
|
|
|||
|
|
@ -25,13 +25,11 @@ use crate::event::{
|
|||
DeviceEvent, ElementState, Event, Ime, InnerSizeWriter, MouseButton, MouseScrollDelta,
|
||||
RawKeyEvent, Touch, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::event_loop::ActiveEventLoop as RootAEL;
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::common::xkb::{self, XkbState};
|
||||
use crate::platform_impl::platform::common::xkb::Context;
|
||||
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest};
|
||||
use crate::platform_impl::platform::x11::ActiveEventLoop;
|
||||
use crate::platform_impl::platform::ActiveEventLoop as PlatformActiveEventLoop;
|
||||
use crate::platform_impl::x11::atoms::*;
|
||||
use crate::platform_impl::x11::util::cookie::GenericEventCookie;
|
||||
use crate::platform_impl::x11::{
|
||||
|
|
@ -53,7 +51,7 @@ pub struct EventProcessor {
|
|||
pub devices: RefCell<HashMap<DeviceId, Device>>,
|
||||
pub xi2ext: ExtensionInformation,
|
||||
pub xkbext: ExtensionInformation,
|
||||
pub target: RootAEL,
|
||||
pub target: ActiveEventLoop,
|
||||
pub xkb_context: Context,
|
||||
// Number of touch events currently in progress
|
||||
pub num_touch: u32,
|
||||
|
|
@ -75,18 +73,17 @@ pub struct EventProcessor {
|
|||
impl EventProcessor {
|
||||
pub(crate) fn process_event<F>(&mut self, xev: &mut XEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
self.process_xevent(xev, &mut callback);
|
||||
|
||||
let window_target = Self::window_target_mut(&mut self.target);
|
||||
|
||||
// Handle IME requests.
|
||||
while let Ok(request) = self.ime_receiver.try_recv() {
|
||||
let ime = match window_target.ime.as_mut() {
|
||||
let ime = match self.target.ime.as_mut() {
|
||||
Some(ime) => ime,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let ime = ime.get_mut();
|
||||
match request {
|
||||
ImeRequest::Position(window_id, x, y) => {
|
||||
|
|
@ -131,9 +128,8 @@ impl EventProcessor {
|
|||
/// along with an extra copy of the KeyRelease events. This also prevents backspace and
|
||||
/// arrow keys from being detected twice.
|
||||
fn filter_event(&mut self, xev: &mut XEvent) -> bool {
|
||||
let wt = Self::window_target(&self.target);
|
||||
unsafe {
|
||||
(wt.xconn.xlib.XFilterEvent)(xev, {
|
||||
(self.target.xconn.xlib.XFilterEvent)(xev, {
|
||||
let xev: &XAnyEvent = xev.as_ref();
|
||||
xev.window
|
||||
}) == xlib::True
|
||||
|
|
@ -142,7 +138,7 @@ impl EventProcessor {
|
|||
|
||||
fn process_xevent<F>(&mut self, xev: &mut XEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let event_type = xev.get_type();
|
||||
|
||||
|
|
@ -184,9 +180,8 @@ impl EventProcessor {
|
|||
self.xinput_key_input(xev.as_mut(), state, &mut callback);
|
||||
},
|
||||
xlib::GenericEvent => {
|
||||
let wt = Self::window_target(&self.target);
|
||||
let xev: GenericEventCookie =
|
||||
match GenericEventCookie::from_event(wt.xconn.clone(), *xev) {
|
||||
match GenericEventCookie::from_event(self.target.xconn.clone(), *xev) {
|
||||
Some(xev) if xev.extension() == self.xi2ext.major_opcode => xev,
|
||||
_ => return,
|
||||
};
|
||||
|
|
@ -298,14 +293,10 @@ impl EventProcessor {
|
|||
}
|
||||
|
||||
pub fn poll(&self) -> bool {
|
||||
let window_target = Self::window_target(&self.target);
|
||||
let result = unsafe { (window_target.xconn.xlib.XPending)(window_target.xconn.display) };
|
||||
|
||||
result != 0
|
||||
unsafe { (self.target.xconn.xlib.XPending)(self.target.xconn.display) != 0 }
|
||||
}
|
||||
|
||||
pub unsafe fn poll_one_event(&mut self, event_ptr: *mut XEvent) -> bool {
|
||||
let window_target = Self::window_target(&self.target);
|
||||
// This function is used to poll and remove a single event
|
||||
// from the Xlib event queue in a non-blocking, atomic way.
|
||||
// XCheckIfEvent is non-blocking and removes events from queue.
|
||||
|
|
@ -321,22 +312,19 @@ impl EventProcessor {
|
|||
1
|
||||
}
|
||||
|
||||
let result = unsafe {
|
||||
(window_target.xconn.xlib.XCheckIfEvent)(
|
||||
window_target.xconn.display,
|
||||
unsafe {
|
||||
(self.target.xconn.xlib.XCheckIfEvent)(
|
||||
self.target.xconn.display,
|
||||
event_ptr,
|
||||
Some(predicate),
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
|
||||
result != 0
|
||||
) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_device(&self, device: xinput::DeviceId) {
|
||||
let window_target = Self::window_target(&self.target);
|
||||
let mut devices = self.devices.borrow_mut();
|
||||
if let Some(info) = DeviceInfo::get(&window_target.xconn, device as _) {
|
||||
if let Some(info) = DeviceInfo::get(&self.target.xconn, device as _) {
|
||||
for info in info.iter() {
|
||||
devices.insert(DeviceId(info.deviceid as _), Device::new(info));
|
||||
}
|
||||
|
|
@ -349,8 +337,8 @@ impl EventProcessor {
|
|||
{
|
||||
let mut deleted = false;
|
||||
let window_id = WindowId(window_id as _);
|
||||
let window_target = Self::window_target(&self.target);
|
||||
let result = window_target
|
||||
let result = self
|
||||
.target
|
||||
.windows
|
||||
.borrow()
|
||||
.get(&window_id)
|
||||
|
|
@ -363,53 +351,33 @@ impl EventProcessor {
|
|||
|
||||
if deleted {
|
||||
// Garbage collection
|
||||
window_target.windows.borrow_mut().remove(&window_id);
|
||||
self.target.windows.borrow_mut().remove(&window_id);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// NOTE: we avoid `self` to not borrow the entire `self` as not mut.
|
||||
/// Get the platform window target.
|
||||
pub fn window_target(window_target: &RootAEL) -> &ActiveEventLoop {
|
||||
match &window_target.p {
|
||||
PlatformActiveEventLoop::X(target) => target,
|
||||
#[cfg(wayland_platform)]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the platform window target.
|
||||
pub fn window_target_mut(window_target: &mut RootAEL) -> &mut ActiveEventLoop {
|
||||
match &mut window_target.p {
|
||||
PlatformActiveEventLoop::X(target) => target,
|
||||
#[cfg(wayland_platform)]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn client_message<F>(&mut self, xev: &XClientMessageEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
let atoms = wt.xconn.atoms();
|
||||
let atoms = self.target.xconn.atoms();
|
||||
|
||||
let window = xev.window as xproto::Window;
|
||||
let window_id = mkwid(window);
|
||||
|
||||
if xev.data.get_long(0) as xproto::Atom == wt.wm_delete_window {
|
||||
if xev.data.get_long(0) as xproto::Atom == self.target.wm_delete_window {
|
||||
let event = Event::WindowEvent { window_id, event: WindowEvent::CloseRequested };
|
||||
callback(&self.target, event);
|
||||
return;
|
||||
}
|
||||
|
||||
if xev.data.get_long(0) as xproto::Atom == wt.net_wm_ping {
|
||||
if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_ping {
|
||||
let client_msg = xproto::ClientMessageEvent {
|
||||
response_type: xproto::CLIENT_MESSAGE_EVENT,
|
||||
format: xev.format as _,
|
||||
sequence: xev.serial as _,
|
||||
window: wt.root,
|
||||
window: self.target.root,
|
||||
type_: xev.message_type as _,
|
||||
data: xproto::ClientMessageData::from({
|
||||
let [a, b, c, d, e]: [c_long; 5] = xev.data.as_longs().try_into().unwrap();
|
||||
|
|
@ -417,11 +385,12 @@ impl EventProcessor {
|
|||
}),
|
||||
};
|
||||
|
||||
wt.xconn
|
||||
self.target
|
||||
.xconn
|
||||
.xcb_connection()
|
||||
.send_event(
|
||||
false,
|
||||
wt.root,
|
||||
self.target.root,
|
||||
xproto::EventMask::SUBSTRUCTURE_NOTIFY
|
||||
| xproto::EventMask::SUBSTRUCTURE_REDIRECT,
|
||||
client_msg.serialize(),
|
||||
|
|
@ -430,7 +399,7 @@ impl EventProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
if xev.data.get_long(0) as xproto::Atom == wt.net_wm_sync_request {
|
||||
if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_sync_request {
|
||||
let sync_counter_id = match self
|
||||
.with_window(xev.window as xproto::Window, |window| window.sync_counter_id())
|
||||
{
|
||||
|
|
@ -448,10 +417,12 @@ impl EventProcessor {
|
|||
bytemuck::cast::<u32, i32>((xev.data.get_long(3) & 0xffffffff) as u32),
|
||||
);
|
||||
|
||||
wt.xconn
|
||||
self.target
|
||||
.xconn
|
||||
.xcb_connection()
|
||||
.sync_set_counter(sync_counter_id, Int64 { lo, hi })
|
||||
.expect_then_ignore_error("Failed to set XSync counter.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -526,7 +497,7 @@ impl EventProcessor {
|
|||
};
|
||||
|
||||
// Log this timestamp.
|
||||
wt.xconn.set_timestamp(time);
|
||||
self.target.xconn.set_timestamp(time);
|
||||
|
||||
// This results in the `SelectionNotify` event below
|
||||
unsafe {
|
||||
|
|
@ -580,16 +551,15 @@ impl EventProcessor {
|
|||
|
||||
fn selection_notify<F>(&mut self, xev: &XSelectionEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
let atoms = wt.xconn.atoms();
|
||||
let atoms = self.target.xconn.atoms();
|
||||
|
||||
let window = xev.requestor as xproto::Window;
|
||||
let window_id = mkwid(window);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
if xev.property != atoms[XdndSelection] as c_ulong {
|
||||
return;
|
||||
|
|
@ -614,10 +584,8 @@ impl EventProcessor {
|
|||
|
||||
fn configure_notify<F>(&self, xev: &XConfigureEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
let xwindow = xev.window as xproto::Window;
|
||||
let window_id = mkwid(xwindow);
|
||||
|
||||
|
|
@ -672,7 +640,8 @@ impl EventProcessor {
|
|||
// We need to convert client area position to window position.
|
||||
let frame_extents =
|
||||
shared_state_lock.frame_extents.as_ref().cloned().unwrap_or_else(|| {
|
||||
let frame_extents = wt.xconn.get_frame_extents_heuristic(xwindow, wt.root);
|
||||
let frame_extents =
|
||||
self.target.xconn.get_frame_extents_heuristic(xwindow, self.target.root);
|
||||
shared_state_lock.frame_extents = Some(frame_extents.clone());
|
||||
frame_extents
|
||||
});
|
||||
|
|
@ -703,7 +672,8 @@ impl EventProcessor {
|
|||
let last_scale_factor = shared_state_lock.last_monitor.scale_factor;
|
||||
let new_scale_factor = {
|
||||
let window_rect = util::AaRect::new(new_outer_position, new_inner_size);
|
||||
let monitor = wt
|
||||
let monitor = self
|
||||
.target
|
||||
.xconn
|
||||
.get_monitor_for_window(Some(window_rect))
|
||||
.expect("Failed to find monitor for window");
|
||||
|
|
@ -798,9 +768,7 @@ impl EventProcessor {
|
|||
/// really have much impact, since on the WMs affected (xmonad, dwm, etc.) the only
|
||||
/// effect is that we waste some time trying to query unsupported properties.
|
||||
fn reparent_notify(&self, xev: &XReparentEvent) {
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
wt.xconn.update_cached_wm_info(wt.root);
|
||||
self.target.xconn.update_cached_wm_info(self.target.root);
|
||||
|
||||
self.with_window(xev.window as xproto::Window, |window| {
|
||||
window.invalidate_cached_frame_extents();
|
||||
|
|
@ -809,7 +777,7 @@ impl EventProcessor {
|
|||
|
||||
fn map_notify<F>(&self, xev: &XMapEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let window = xev.window as xproto::Window;
|
||||
let window_id = mkwid(window);
|
||||
|
|
@ -827,20 +795,18 @@ impl EventProcessor {
|
|||
|
||||
fn destroy_notify<F>(&self, xev: &XDestroyWindowEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
let window = xev.window as xproto::Window;
|
||||
let window_id = mkwid(window);
|
||||
|
||||
// In the event that the window's been destroyed without being dropped first, we
|
||||
// cleanup again here.
|
||||
wt.windows.borrow_mut().remove(&WindowId(window as _));
|
||||
self.target.windows.borrow_mut().remove(&WindowId(window as _));
|
||||
|
||||
// Since all XIM stuff needs to happen from the same thread, we destroy the input
|
||||
// context here instead of when dropping the window.
|
||||
if let Some(ime) = wt.ime.as_ref() {
|
||||
if let Some(ime) = self.target.ime.as_ref() {
|
||||
ime.borrow_mut()
|
||||
.remove_context(window as XWindow)
|
||||
.expect("Failed to destroy input context");
|
||||
|
|
@ -851,10 +817,9 @@ impl EventProcessor {
|
|||
|
||||
fn property_notify<F>(&mut self, xev: &XPropertyEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
let atoms = wt.x_connection().atoms();
|
||||
let atoms = self.target.x_connection().atoms();
|
||||
let atom = xev.atom as xproto::Atom;
|
||||
|
||||
if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER)
|
||||
|
|
@ -866,7 +831,7 @@ impl EventProcessor {
|
|||
|
||||
fn visibility_notify<F>(&self, xev: &XVisibilityEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let xwindow = xev.window as xproto::Window;
|
||||
|
||||
|
|
@ -883,7 +848,7 @@ impl EventProcessor {
|
|||
|
||||
fn expose<F>(&self, xev: &XExposeEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
// Multiple Expose events may be received for subareas of a window.
|
||||
// We issue `RedrawRequested` only for the last event of such a series.
|
||||
|
|
@ -899,12 +864,10 @@ impl EventProcessor {
|
|||
|
||||
fn xinput_key_input<F>(&mut self, xev: &mut XKeyEvent, state: ElementState, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let window = match self.active_window {
|
||||
Some(window) => window,
|
||||
|
|
@ -989,12 +952,10 @@ impl EventProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
if let Some(ic) =
|
||||
wt.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow))
|
||||
self.target.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow))
|
||||
{
|
||||
let written = wt.xconn.lookup_utf8(ic, xev);
|
||||
let written = self.target.xconn.lookup_utf8(ic, xev);
|
||||
if !written.is_empty() {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
|
|
@ -1017,15 +978,14 @@ impl EventProcessor {
|
|||
state: u16,
|
||||
mut callback: F,
|
||||
) where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let keymap = match self.xkb_context.keymap_mut() {
|
||||
Some(keymap) => keymap,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let wt = Self::window_target(&self.target);
|
||||
let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
|
||||
// Use synthetic state since we're replaying the modifier. The user modifier state
|
||||
// will be restored later.
|
||||
|
|
@ -1046,14 +1006,13 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_button_input<F>(&self, event: &XIDeviceEvent, state: ElementState, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
let window_id = mkwid(event.event as xproto::Window);
|
||||
let device_id = mkdid(event.deviceid as xinput::DeviceId);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
|
||||
// Deliver multi-touch events instead of emulated mouse events.
|
||||
if (event.flags & xinput2::XIPointerEmulated) != 0 {
|
||||
|
|
@ -1099,12 +1058,10 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_mouse_motion<F>(&self, event: &XIDeviceEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
|
||||
let device_id = mkdid(event.deviceid as xinput::DeviceId);
|
||||
let window = event.event as xproto::Window;
|
||||
|
|
@ -1174,18 +1131,16 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_mouse_enter<F>(&self, event: &XIEnterEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
|
||||
let window = event.event as xproto::Window;
|
||||
let window_id = mkwid(window);
|
||||
let device_id = mkdid(event.deviceid as xinput::DeviceId);
|
||||
|
||||
if let Some(all_info) = DeviceInfo::get(&wt.xconn, super::ALL_DEVICES.into()) {
|
||||
if let Some(all_info) = DeviceInfo::get(&self.target.xconn, super::ALL_DEVICES.into()) {
|
||||
let mut devices = self.devices.borrow_mut();
|
||||
for device_info in all_info.iter() {
|
||||
// The second expression is need for resetting to work correctly on i3, and
|
||||
|
|
@ -1219,13 +1174,12 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_mouse_left<F>(&self, event: &XILeaveEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
let window = event.event as xproto::Window;
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
|
||||
// Leave, FocusIn, and FocusOut can be received by a window that's already
|
||||
// been destroyed, which the user presumably doesn't want to deal with.
|
||||
|
|
@ -1242,15 +1196,14 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_focused<F>(&mut self, xev: &XIFocusInEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
let window = xev.event as xproto::Window;
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
if let Some(ime) = wt.ime.as_ref() {
|
||||
if let Some(ime) = self.target.ime.as_ref() {
|
||||
ime.borrow_mut().focus(xev.event).expect("Failed to focus input context");
|
||||
}
|
||||
|
||||
|
|
@ -1260,7 +1213,7 @@ impl EventProcessor {
|
|||
|
||||
self.active_window = Some(window);
|
||||
|
||||
wt.update_listen_device_events(true);
|
||||
self.target.update_listen_device_events(true);
|
||||
|
||||
let window_id = mkwid(window);
|
||||
let position = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
|
|
@ -1301,26 +1254,25 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_unfocused<F>(&mut self, xev: &XIFocusOutEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
let window = xev.event as xproto::Window;
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
if !self.window_exists(window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(ime) = wt.ime.as_ref() {
|
||||
if let Some(ime) = self.target.ime.as_ref() {
|
||||
ime.borrow_mut().unfocus(xev.event).expect("Failed to unfocus input context");
|
||||
}
|
||||
|
||||
if self.active_window.take() == Some(window) {
|
||||
let window_id = mkwid(window);
|
||||
|
||||
wt.update_listen_device_events(false);
|
||||
self.target.update_listen_device_events(false);
|
||||
|
||||
// Clear the modifiers when unfocusing the window.
|
||||
if let Some(xkb_state) = self.xkb_context.state_mut() {
|
||||
|
|
@ -1353,12 +1305,10 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let window = xev.event as xproto::Window;
|
||||
if self.window_exists(window) {
|
||||
|
|
@ -1395,12 +1345,10 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_raw_button_input<F>(&self, xev: &XIRawEvent, state: ElementState, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
if xev.flags & xinput2::XIPointerEmulated == 0 {
|
||||
let event = Event::DeviceEvent {
|
||||
|
|
@ -1413,12 +1361,10 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_raw_mouse_motion<F>(&self, xev: &XIRawEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let did = mkdid(xev.deviceid as xinput::DeviceId);
|
||||
|
||||
|
|
@ -1467,12 +1413,10 @@ impl EventProcessor {
|
|||
|
||||
fn xinput2_raw_key_input<F>(&mut self, xev: &XIRawEvent, state: ElementState, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let device_id = mkdid(xev.sourceid as xinput::DeviceId);
|
||||
let keycode = xev.detail as u32;
|
||||
|
|
@ -1488,10 +1432,8 @@ impl EventProcessor {
|
|||
}
|
||||
|
||||
fn xinput2_hierarchy_changed(&mut self, xev: &XIHierarchyEvent) {
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
let infos = unsafe { slice::from_raw_parts(xev.info, xev.num_info as usize) };
|
||||
for info in infos {
|
||||
if 0 != info.flags & (xinput2::XISlaveAdded | xinput2::XIMasterAdded) {
|
||||
|
|
@ -1505,15 +1447,14 @@ impl EventProcessor {
|
|||
|
||||
fn xkb_event<F>(&mut self, xev: &XkbAnyEvent, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
match xev.xkb_type {
|
||||
xlib::XkbNewKeyboardNotify => {
|
||||
let xev = unsafe { &*(xev as *const _ as *const xlib::XkbNewKeyboardNotifyEvent) };
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let keycodes_changed_flag = 0x1;
|
||||
let geometry_changed_flag = 0x1 << 1;
|
||||
|
|
@ -1524,9 +1465,9 @@ impl EventProcessor {
|
|||
if xev.device == self.xkb_context.core_keyboard_id
|
||||
&& (keycodes_changed || geometry_changed)
|
||||
{
|
||||
let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
self.xkb_context.set_keymap_from_x11(xcb);
|
||||
self.xmodmap.reload_from_x_connection(&wt.xconn);
|
||||
self.xmodmap.reload_from_x_connection(&self.target.xconn);
|
||||
|
||||
let window_id = match self.active_window.map(super::mkwid) {
|
||||
Some(window_id) => window_id,
|
||||
|
|
@ -1540,9 +1481,9 @@ impl EventProcessor {
|
|||
}
|
||||
},
|
||||
xlib::XkbMapNotify => {
|
||||
let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
self.xkb_context.set_keymap_from_x11(xcb);
|
||||
self.xmodmap.reload_from_x_connection(&wt.xconn);
|
||||
self.xmodmap.reload_from_x_connection(&self.target.xconn);
|
||||
let window_id = match self.active_window.map(super::mkwid) {
|
||||
Some(window_id) => window_id,
|
||||
None => return,
|
||||
|
|
@ -1557,7 +1498,7 @@ impl EventProcessor {
|
|||
let xev = unsafe { &*(xev as *const _ as *const xlib::XkbStateNotifyEvent) };
|
||||
|
||||
// Set the timestamp.
|
||||
wt.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
if let Some(state) = self.xkb_context.state_mut() {
|
||||
state.update_modifiers(
|
||||
|
|
@ -1589,7 +1530,7 @@ impl EventProcessor {
|
|||
force: bool,
|
||||
mut callback: F,
|
||||
) where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
if let Some(state) = self.xkb_context.state_mut() {
|
||||
state.update_modifiers(
|
||||
|
|
@ -1615,10 +1556,8 @@ impl EventProcessor {
|
|||
|
||||
fn update_mods_from_query<F>(&mut self, window_id: crate::window::WindowId, mut callback: F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
|
||||
let xkb_state = match self.xkb_context.state_mut() {
|
||||
Some(xkb_state) => xkb_state,
|
||||
None => return,
|
||||
|
|
@ -1626,8 +1565,11 @@ impl EventProcessor {
|
|||
|
||||
unsafe {
|
||||
let mut state: XkbStateRec = std::mem::zeroed();
|
||||
if (wt.xconn.xlib.XkbGetState)(wt.xconn.display, XkbId::USE_CORE_KBD.into(), &mut state)
|
||||
== xlib::True
|
||||
if (self.target.xconn.xlib.XkbGetState)(
|
||||
self.target.xconn.display,
|
||||
XkbId::USE_CORE_KBD.into(),
|
||||
&mut state,
|
||||
) == xlib::True
|
||||
{
|
||||
xkb_state.update_modifiers(
|
||||
state.base_mods as u32,
|
||||
|
|
@ -1650,7 +1592,7 @@ impl EventProcessor {
|
|||
state: u16,
|
||||
mut callback: F,
|
||||
) where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let xkb_mask = self.xkb_mod_mask_from_core(state);
|
||||
let xkb_state = match self.xkb_context.state_mut() {
|
||||
|
|
@ -1723,7 +1665,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<F: FnMut(&RootAEL, Event)>(
|
||||
fn send_modifiers<F: FnMut(&ActiveEventLoop, Event)>(
|
||||
&self,
|
||||
window_id: crate::window::WindowId,
|
||||
modifiers: ModifiersState,
|
||||
|
|
@ -1742,19 +1684,18 @@ impl EventProcessor {
|
|||
}
|
||||
|
||||
fn handle_pressed_keys<F>(
|
||||
target: &RootAEL,
|
||||
target: &ActiveEventLoop,
|
||||
window_id: crate::window::WindowId,
|
||||
state: ElementState,
|
||||
xkb_context: &mut Context,
|
||||
callback: &mut F,
|
||||
) where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
|
||||
|
||||
// Update modifiers state and emit key events based on which keys are currently pressed.
|
||||
let window_target = Self::window_target(target);
|
||||
let xcb = window_target.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
let xcb = target.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
|
||||
let keymap = match xkb_context.keymap_mut() {
|
||||
Some(keymap) => keymap,
|
||||
|
|
@ -1771,9 +1712,7 @@ impl EventProcessor {
|
|||
None => return,
|
||||
};
|
||||
|
||||
for keycode in
|
||||
window_target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET)
|
||||
{
|
||||
for keycode in target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET) {
|
||||
let event = key_processor.process_key_event(keycode as u32, state, false);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
|
|
@ -1785,21 +1724,20 @@ impl EventProcessor {
|
|||
|
||||
fn process_dpi_change<F>(&self, callback: &mut F)
|
||||
where
|
||||
F: FnMut(&RootAEL, Event),
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let wt = Self::window_target(&self.target);
|
||||
wt.xconn.reload_database().expect("failed to reload Xft database");
|
||||
self.target.xconn.reload_database().expect("failed to reload Xft database");
|
||||
|
||||
// In the future, it would be quite easy to emit monitor hotplug events.
|
||||
let prev_list = {
|
||||
let prev_list = wt.xconn.invalidate_cached_monitor_list();
|
||||
let prev_list = self.target.xconn.invalidate_cached_monitor_list();
|
||||
match prev_list {
|
||||
Some(prev_list) => prev_list,
|
||||
None => return,
|
||||
}
|
||||
};
|
||||
|
||||
let new_list = wt.xconn.available_monitors().expect("Failed to get monitor list");
|
||||
let new_list = self.target.xconn.available_monitors().expect("Failed to get monitor list");
|
||||
for new_monitor in new_list {
|
||||
// Previous list may be empty, in case of disconnecting and
|
||||
// reconnecting the only one monitor. We still need to emit events in
|
||||
|
|
@ -1809,7 +1747,7 @@ impl EventProcessor {
|
|||
.find(|prev_monitor| prev_monitor.name == new_monitor.name)
|
||||
.map(|prev_monitor| prev_monitor.scale_factor);
|
||||
if Some(new_monitor.scale_factor) != maybe_prev_scale_factor {
|
||||
for window in wt.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) {
|
||||
for window in self.target.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) {
|
||||
window.refresh_dpi_for_monitor(&new_monitor, maybe_prev_scale_factor, |event| {
|
||||
callback(&self.target, event);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::any::Any;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::ffi::CStr;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ops::Deref;
|
||||
use std::os::raw::*;
|
||||
|
|
@ -27,14 +27,17 @@ use x11rb::xcb_ffi::ReplyOrIdError;
|
|||
use crate::application::ApplicationHandler;
|
||||
use crate::error::{EventLoopError, ExternalError, OsError as RootOsError};
|
||||
use crate::event::{Event, StartCause, WindowEvent};
|
||||
use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
OwnedDisplayHandle as RootOwnedDisplayHandle,
|
||||
};
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::common::xkb::Context;
|
||||
use crate::platform_impl::platform::{min_timeout, WindowId};
|
||||
use crate::platform_impl::{
|
||||
ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor,
|
||||
use crate::platform_impl::{OsError, OwnedDisplayHandle, PlatformCustomCursor};
|
||||
use crate::window::{
|
||||
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowAttributes,
|
||||
};
|
||||
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, WindowAttributes};
|
||||
|
||||
mod activation;
|
||||
mod atoms;
|
||||
|
|
@ -310,11 +313,8 @@ impl EventLoop {
|
|||
// Set initial device event filter.
|
||||
window_target.update_listen_device_events(true);
|
||||
|
||||
let root_window_target =
|
||||
RootAEL { p: PlatformActiveEventLoop::X(window_target), _marker: PhantomData };
|
||||
|
||||
let event_processor = EventProcessor {
|
||||
target: root_window_target,
|
||||
target: window_target,
|
||||
dnd,
|
||||
devices: Default::default(),
|
||||
randr_event_offset,
|
||||
|
|
@ -335,9 +335,9 @@ impl EventLoop {
|
|||
|
||||
// Register for device hotplug events
|
||||
// (The request buffer is flushed during `init_device`)
|
||||
let xconn = &EventProcessor::window_target(&event_processor.target).xconn;
|
||||
|
||||
xconn
|
||||
event_processor
|
||||
.target
|
||||
.xconn
|
||||
.select_xinput_events(
|
||||
root,
|
||||
ALL_DEVICES,
|
||||
|
|
@ -345,7 +345,9 @@ impl EventLoop {
|
|||
)
|
||||
.expect_then_ignore_error("Failed to register for XInput2 device hotplug events");
|
||||
|
||||
xconn
|
||||
event_processor
|
||||
.target
|
||||
.xconn
|
||||
.select_xkb_events(
|
||||
0x100, // Use the "core keyboard device"
|
||||
xkb::EventType::NEW_KEYBOARD_NOTIFY
|
||||
|
|
@ -366,7 +368,7 @@ impl EventLoop {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn window_target(&self) -> &RootAEL {
|
||||
pub(crate) fn window_target(&self) -> &dyn RootActiveEventLoop {
|
||||
&self.event_processor.target
|
||||
}
|
||||
|
||||
|
|
@ -378,7 +380,7 @@ impl EventLoop {
|
|||
&mut self,
|
||||
mut app: A,
|
||||
) -> Result<(), EventLoopError> {
|
||||
self.event_processor.target.p.clear_exit();
|
||||
self.event_processor.target.clear_exit();
|
||||
let exit = loop {
|
||||
match self.pump_app_events(None, &mut app) {
|
||||
PumpStatus::Exit(0) => {
|
||||
|
|
@ -397,8 +399,7 @@ impl EventLoop {
|
|||
// `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 = EventProcessor::window_target(&self.event_processor.target);
|
||||
wt.x_connection().sync_with_server().map_err(|x_err| {
|
||||
self.event_processor.target.x_connection().sync_with_server().map_err(|x_err| {
|
||||
EventLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err)))))
|
||||
})?;
|
||||
|
||||
|
|
@ -576,7 +577,6 @@ impl EventLoop {
|
|||
event: WindowEvent::RedrawRequested,
|
||||
} = event
|
||||
{
|
||||
let window_target = EventProcessor::window_target(window_target);
|
||||
window_target.redraw_sender.send(wid);
|
||||
} else {
|
||||
match event {
|
||||
|
|
@ -594,21 +594,19 @@ impl EventLoop {
|
|||
}
|
||||
|
||||
fn control_flow(&self) -> ControlFlow {
|
||||
let window_target = EventProcessor::window_target(&self.event_processor.target);
|
||||
window_target.control_flow()
|
||||
self.event_processor.target.control_flow()
|
||||
}
|
||||
|
||||
fn exiting(&self) -> bool {
|
||||
let window_target = EventProcessor::window_target(&self.event_processor.target);
|
||||
window_target.exiting()
|
||||
self.event_processor.target.exiting()
|
||||
}
|
||||
|
||||
fn set_exit_code(&self, code: i32) {
|
||||
self.window_target().p.set_exit_code(code);
|
||||
self.event_processor.target.set_exit_code(code);
|
||||
}
|
||||
|
||||
fn exit_code(&self) -> Option<i32> {
|
||||
self.window_target().p.exit_code()
|
||||
self.event_processor.target.exit_code()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -625,37 +623,12 @@ impl AsRawFd for EventLoop {
|
|||
}
|
||||
|
||||
impl ActiveEventLoop {
|
||||
pub fn create_proxy(&self) -> EventLoopProxy {
|
||||
self.event_loop_proxy.clone()
|
||||
}
|
||||
|
||||
/// Returns the `XConnection` of this events loop.
|
||||
#[inline]
|
||||
pub(crate) fn x_connection(&self) -> &Arc<XConnection> {
|
||||
&self.xconn
|
||||
}
|
||||
|
||||
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
|
||||
self.xconn.available_monitors().into_iter().flatten()
|
||||
}
|
||||
|
||||
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
|
||||
self.xconn.primary_monitor().ok()
|
||||
}
|
||||
|
||||
pub(crate) fn create_custom_cursor(
|
||||
&self,
|
||||
cursor: CustomCursorSource,
|
||||
) -> Result<RootCustomCursor, ExternalError> {
|
||||
Ok(RootCustomCursor {
|
||||
inner: PlatformCustomCursor::X(CustomCursor::new(self, cursor.inner)?),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn listen_device_events(&self, allowed: DeviceEvents) {
|
||||
self.device_events.set(allowed);
|
||||
}
|
||||
|
||||
/// Update the device event based on window focus.
|
||||
pub fn update_listen_device_events(&self, focus: bool) {
|
||||
let device_events = self.device_events.get() == DeviceEvents::Always
|
||||
|
|
@ -690,26 +663,10 @@ impl ActiveEventLoop {
|
|||
Ok(display_handle.into())
|
||||
}
|
||||
|
||||
pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||
self.control_flow.set(control_flow)
|
||||
}
|
||||
|
||||
pub(crate) fn control_flow(&self) -> ControlFlow {
|
||||
self.control_flow.get()
|
||||
}
|
||||
|
||||
pub(crate) fn exit(&self) {
|
||||
self.exit.set(Some(0))
|
||||
}
|
||||
|
||||
pub(crate) fn clear_exit(&self) {
|
||||
self.exit.set(None)
|
||||
}
|
||||
|
||||
pub(crate) fn exiting(&self) -> bool {
|
||||
self.exit.get().is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn set_exit_code(&self, code: i32) {
|
||||
self.exit.set(Some(code))
|
||||
}
|
||||
|
|
@ -719,6 +676,99 @@ impl ActiveEventLoop {
|
|||
}
|
||||
}
|
||||
|
||||
impl RootActiveEventLoop for ActiveEventLoop {
|
||||
fn create_proxy(&self) -> crate::event_loop::EventLoopProxy {
|
||||
crate::event_loop::EventLoopProxy {
|
||||
event_loop_proxy: crate::platform_impl::EventLoopProxy::X(
|
||||
self.event_loop_proxy.clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_window(
|
||||
&self,
|
||||
window_attributes: WindowAttributes,
|
||||
) -> Result<crate::window::Window, RootOsError> {
|
||||
let window = crate::platform_impl::x11::Window::new(self, window_attributes)?;
|
||||
let window = crate::platform_impl::Window::X(window);
|
||||
Ok(crate::window::Window { window })
|
||||
}
|
||||
|
||||
fn create_custom_cursor(
|
||||
&self,
|
||||
custom_cursor: CustomCursorSource,
|
||||
) -> Result<RootCustomCursor, ExternalError> {
|
||||
Ok(RootCustomCursor {
|
||||
inner: PlatformCustomCursor::X(CustomCursor::new(self, custom_cursor.inner)?),
|
||||
})
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
|
||||
Box::new(
|
||||
self.xconn
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(crate::platform_impl::MonitorHandle::X)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner }),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
self.xconn
|
||||
.primary_monitor()
|
||||
.ok()
|
||||
.map(crate::platform_impl::MonitorHandle::X)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner })
|
||||
}
|
||||
|
||||
fn system_theme(&self) -> Option<Theme> {
|
||||
None
|
||||
}
|
||||
|
||||
fn listen_device_events(&self, allowed: DeviceEvents) {
|
||||
self.device_events.set(allowed);
|
||||
}
|
||||
|
||||
fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||
self.control_flow.set(control_flow)
|
||||
}
|
||||
|
||||
fn control_flow(&self) -> ControlFlow {
|
||||
self.control_flow.get()
|
||||
}
|
||||
|
||||
fn exit(&self) {
|
||||
self.exit.set(Some(0))
|
||||
}
|
||||
|
||||
fn exiting(&self) -> bool {
|
||||
self.exit.get().is_some()
|
||||
}
|
||||
|
||||
fn owned_display_handle(&self) -> RootOwnedDisplayHandle {
|
||||
let handle = OwnedDisplayHandle::X(self.x_connection().clone());
|
||||
RootOwnedDisplayHandle { platform: handle }
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "rwh_06")]
|
||||
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rwh_06")]
|
||||
impl rwh_06::HasDisplayHandle for ActiveEventLoop {
|
||||
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
|
||||
let raw = self.raw_display_handle_rwh_06()?;
|
||||
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl EventLoopProxy {
|
||||
pub fn wake_up(&self) {
|
||||
self.ping.ping();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue