diff options
author | 2024-08-12 03:18:48 +0200 | |
---|---|---|
committer | 2024-08-12 03:18:48 +0200 | |
commit | 8e87d664d43f458024400d0ec6c26066a4554798 (patch) | |
tree | d3c8e000d333b2611a49849ace6238b0170ab66c /winit/src | |
parent | 6d6f354b425def8b4ab269cdd22cfb2328ce8591 (diff) | |
parent | afa8ad3b11818c431ea8c40fc4af10de528d9a8f (diff) | |
download | iced-8e87d664d43f458024400d0ec6c26066a4554798.tar.gz iced-8e87d664d43f458024400d0ec6c26066a4554798.tar.bz2 iced-8e87d664d43f458024400d0ec6c26066a4554798.zip |
Merge pull request #2547 from meithecatte/do-not-segfault
iced_winit: drop Clipboard before Window
Diffstat (limited to 'winit/src')
-rw-r--r-- | winit/src/clipboard.rs | 33 | ||||
-rw-r--r-- | winit/src/program.rs | 2 |
2 files changed, 26 insertions, 9 deletions
diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index 5237ca01..7ae646fc 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -1,6 +1,8 @@ //! Access the clipboard. use crate::core::clipboard::Kind; +use std::sync::Arc; +use winit::window::Window; /// A buffer for short-term storage and transfer within and between /// applications. @@ -10,18 +12,33 @@ 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<Window>, + }, Unavailable, } impl Clipboard { /// Creates a new [`Clipboard`] for the given window. - pub fn connect(window: &winit::window::Window) -> Clipboard { + pub fn connect(window: Arc<Window>) -> Clipboard { + // SAFETY: The window handle will stay alive throughout the entire + // lifetime of the `window_clipboard::Clipboard` because we hold + // the `Arc<Window>` together with `State`, and enum variant fields + // get dropped in declaration order. #[allow(unsafe_code)] - let state = unsafe { window_clipboard::Clipboard::connect(window) } - .ok() - .map(State::Connected) - .unwrap_or(State::Unavailable); + 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 +54,7 @@ impl Clipboard { /// Reads the current content of the [`Clipboard`] as text. pub fn read(&self, kind: Kind) -> Option<String> { 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 +65,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 3d709b7e..139b2b8f 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 = |