api: make OwnedDisplayHandle wrap an opaque type

This will help in case we want to linger the event loop during drop
to prevent use after free in the consumers code.
This commit is contained in:
Kirill Chibisov 2024-11-13 15:29:05 +03:00 committed by GitHub
parent f781e13166
commit 59b1eb5410
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 149 additions and 177 deletions

View file

@ -16,7 +16,10 @@ use crate::cursor::OnlyCursorImage;
use crate::dpi::LogicalSize;
use crate::error::{EventLoopError, OsError, RequestError};
use crate::event::{Event, StartCause, SurfaceSizeWriter, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
use crate::event_loop::{
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
OwnedDisplayHandle as CoreOwnedDisplayHandle,
};
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::platform::min_timeout;
use crate::platform_impl::PlatformCustomCursor;
@ -49,7 +52,7 @@ pub struct EventLoop {
wayland_dispatcher: WaylandDispatcher,
/// Connection to the wayland server.
connection: Connection,
handle: Arc<OwnedDisplayHandle>,
/// Event loop window target.
active_event_loop: ActiveEventLoop,
@ -117,8 +120,9 @@ impl EventLoop {
})
.map_err(|err| os_error!(err))?;
let handle = Arc::new(OwnedDisplayHandle::new(connection));
let active_event_loop = ActiveEventLoop {
connection: connection.clone(),
handle: handle.clone(),
wayland_dispatcher: wayland_dispatcher.clone(),
event_loop_awakener,
event_loop_proxy: EventLoopProxy::new(ping).into(),
@ -133,7 +137,7 @@ impl EventLoop {
compositor_updates: Vec::new(),
buffer_sink: EventSink::default(),
window_ids: Vec::new(),
connection,
handle,
wayland_dispatcher,
event_loop,
active_event_loop,
@ -227,7 +231,7 @@ impl EventLoop {
//
// Checking for flush error is essential to perform an exit with error, since
// once we have a protocol error, we could get stuck retrying...
if self.connection.flush().is_err() {
if self.handle.connection.flush().is_err() {
self.set_exit_code(1);
return;
}
@ -561,8 +565,8 @@ pub struct ActiveEventLoop {
/// Dispatcher of Wayland events.
pub wayland_dispatcher: WaylandDispatcher,
/// Connection to the wayland server.
pub connection: Connection,
/// Handle for the underlying event loop.
pub handle: Arc<OwnedDisplayHandle>,
}
impl RootActiveEventLoop for ActiveEventLoop {
@ -628,10 +632,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
None
}
fn owned_display_handle(&self) -> crate::event_loop::OwnedDisplayHandle {
crate::event_loop::OwnedDisplayHandle {
platform: crate::platform_impl::OwnedDisplayHandle::Wayland(self.connection.clone()),
}
fn owned_display_handle(&self) -> CoreOwnedDisplayHandle {
CoreOwnedDisplayHandle::new(self.handle.clone())
}
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
@ -654,6 +656,22 @@ impl ActiveEventLoop {
}
impl rwh_06::HasDisplayHandle for ActiveEventLoop {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
self.handle.display_handle()
}
}
pub struct OwnedDisplayHandle {
pub(crate) connection: Connection,
}
impl OwnedDisplayHandle {
fn new(connection: Connection) -> Self {
Self { connection }
}
}
impl rwh_06::HasDisplayHandle for OwnedDisplayHandle {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
use sctk::reexports::client::Proxy;

View file

@ -87,7 +87,7 @@ impl Window {
let compositor = state.compositor_state.clone();
let xdg_activation =
state.xdg_activation.as_ref().map(|activation_state| activation_state.global().clone());
let display = event_loop_window_target.connection.display();
let display = event_loop_window_target.handle.connection.display();
let size: Size = attributes.surface_size.unwrap_or(LogicalSize::new(800., 600.).into());
@ -103,7 +103,7 @@ impl Window {
state.xdg_shell.create_window(surface.clone(), default_decorations, &queue_handle);
let mut window_state = WindowState::new(
event_loop_window_target.connection.clone(),
event_loop_window_target.handle.clone(),
&event_loop_window_target.queue_handle,
&state,
size,

View file

@ -10,7 +10,7 @@ use sctk::reexports::client::backend::ObjectId;
use sctk::reexports::client::protocol::wl_seat::WlSeat;
use sctk::reexports::client::protocol::wl_shm::WlShm;
use sctk::reexports::client::protocol::wl_surface::WlSurface;
use sctk::reexports::client::{Connection, Proxy, QueueHandle};
use sctk::reexports::client::{Proxy, QueueHandle};
use sctk::reexports::csd_frame::{
DecorationsFrame, FrameAction, FrameClick, ResizeEdge, WindowState as XdgWindowState,
};
@ -31,6 +31,7 @@ use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur;
use crate::cursor::CustomCursor as RootCustomCursor;
use crate::dpi::{LogicalPosition, LogicalSize, PhysicalSize, Size};
use crate::error::{NotSupportedError, RequestError};
use crate::platform_impl::wayland::event_loop::OwnedDisplayHandle;
use crate::platform_impl::wayland::logical_to_physical_rounded;
use crate::platform_impl::wayland::seat::{
PointerConstraintsState, WinitPointerData, WinitPointerDataExt, ZwpTextInputV3Ext,
@ -52,7 +53,7 @@ const MIN_WINDOW_SIZE: LogicalSize<u32> = LogicalSize::new(2, 1);
/// The state of the window which is being updated from the [`WinitState`].
pub struct WindowState {
/// The connection to Wayland server.
pub connection: Connection,
pub handle: Arc<OwnedDisplayHandle>,
/// The `Shm` to set cursor.
pub shm: WlShm,
@ -161,7 +162,7 @@ pub struct WindowState {
impl WindowState {
/// Create new window state.
pub fn new(
connection: Connection,
handle: Arc<OwnedDisplayHandle>,
queue_handle: &QueueHandle<WinitState>,
winit_state: &WinitState,
initial_size: Size,
@ -183,7 +184,7 @@ impl WindowState {
blur: None,
blur_manager: winit_state.kwin_blur_manager.clone(),
compositor,
connection,
handle,
csd_fails: false,
cursor_grab_mode: GrabState::new(),
selected_cursor: Default::default(),
@ -693,7 +694,7 @@ impl WindowState {
}
self.apply_on_pointer(|pointer, _| {
if pointer.set_cursor(&self.connection, cursor_icon).is_err() {
if pointer.set_cursor(&self.handle.connection, cursor_icon).is_err() {
warn!("Failed to set cursor to {:?}", cursor_icon);
}
})