From f92e01e913480e1450696f3d37af4bff09f661d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 11 Aug 2024 22:33:17 +0200 Subject: [PATCH 1/3] iced_winit: drop Clipboard before Window Fixes #2482, avoids nasal daemons --- winit/src/clipboard.rs | 31 +++++++++++++++++++++++-------- winit/src/program.rs | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index 5237ca0152..f8b90777bf 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -1,6 +1,8 @@ //! Access the clipboard. use crate::core::clipboard::Kind; +use winit::window::Window; +use std::sync::Arc; /// A buffer for short-term storage and transfer within and between /// applications. @@ -10,18 +12,31 @@ pub struct Clipboard { } enum State { - Connected(window_clipboard::Clipboard), + Connected { + clipboard: window_clipboard::Clipboard, + // Held until drop to satisfy the safety invariants of + // `window_clipboard::Clipboard`. + // + // Note that the field ordering is load-bearing. + #[allow(dead_code)] + window: Arc, + }, Unavailable, } impl Clipboard { /// Creates a new [`Clipboard`] for the given window. - pub fn connect(window: &winit::window::Window) -> Clipboard { + pub fn connect(window: Arc) -> Clipboard { #[allow(unsafe_code)] - let state = unsafe { window_clipboard::Clipboard::connect(window) } - .ok() - .map(State::Connected) - .unwrap_or(State::Unavailable); + // SAFETY: The window handle will stay alive throughout the entire + // lifetime of the `window_clipboard::Clipboard` because we hold + // the `Arc` together with `State`, and enum variant fields + // get dropped in declaration order. + let clipboard = unsafe { window_clipboard::Clipboard::connect(&window) }; + let state = match clipboard { + Ok(clipboard) => State::Connected { clipboard, window }, + Err(_) => State::Unavailable, + }; Clipboard { state } } @@ -37,7 +52,7 @@ impl Clipboard { /// Reads the current content of the [`Clipboard`] as text. pub fn read(&self, kind: Kind) -> Option { match &self.state { - State::Connected(clipboard) => match kind { + State::Connected { clipboard, .. } => match kind { Kind::Standard => clipboard.read().ok(), Kind::Primary => clipboard.read_primary().and_then(Result::ok), }, @@ -48,7 +63,7 @@ impl Clipboard { /// Writes the given text contents to the [`Clipboard`]. pub fn write(&mut self, kind: Kind, contents: String) { match &mut self.state { - State::Connected(clipboard) => { + State::Connected { clipboard, .. } => { let result = match kind { Kind::Standard => clipboard.write(contents), Kind::Primary => { diff --git a/winit/src/program.rs b/winit/src/program.rs index 3d709b7ef9..139b2b8fb8 100644 --- a/winit/src/program.rs +++ b/winit/src/program.rs @@ -307,7 +307,7 @@ where } }; - let clipboard = Clipboard::connect(&window); + let clipboard = Clipboard::connect(window.clone()); let finish_boot = async move { let mut compositor = From 7decbb3d5d0e72fd4667840568411bcb867feca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Mon, 12 Aug 2024 03:07:11 +0200 Subject: [PATCH 2/3] Fix formatting in `iced_winit::clipboard` --- winit/src/clipboard.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index f8b90777bf..7ae646fc78 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -1,8 +1,8 @@ //! Access the clipboard. use crate::core::clipboard::Kind; -use winit::window::Window; use std::sync::Arc; +use winit::window::Window; /// A buffer for short-term storage and transfer within and between /// applications. @@ -27,12 +27,14 @@ enum State { impl Clipboard { /// Creates a new [`Clipboard`] for the given window. pub fn connect(window: Arc) -> Clipboard { - #[allow(unsafe_code)] // SAFETY: The window handle will stay alive throughout the entire // lifetime of the `window_clipboard::Clipboard` because we hold // the `Arc` together with `State`, and enum variant fields // get dropped in declaration order. - let clipboard = unsafe { window_clipboard::Clipboard::connect(&window) }; + #[allow(unsafe_code)] + let clipboard = + unsafe { window_clipboard::Clipboard::connect(&window) }; + let state = match clipboard { Ok(clipboard) => State::Connected { clipboard, window }, Err(_) => State::Unavailable, From afa8ad3b11818c431ea8c40fc4af10de528d9a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Mon, 12 Aug 2024 03:10:46 +0200 Subject: [PATCH 3/3] Fix `integration` example --- examples/integration/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index 9818adf378..5b64cbd1f5 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -68,7 +68,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { Size::new(physical_size.width, physical_size.height), window.scale_factor(), ); - let clipboard = Clipboard::connect(&window); + let clipboard = Clipboard::connect(window.clone()); let backend = wgpu::util::backend_bits_from_env().unwrap_or_default();