Skip to content

Commit

Permalink
Merge pull request #2547 from meithecatte/do-not-segfault
Browse files Browse the repository at this point in the history
iced_winit: drop Clipboard before Window
  • Loading branch information
hecrj authored Aug 12, 2024
2 parents 6d6f354 + afa8ad3 commit 8e87d66
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
2 changes: 1 addition & 1 deletion examples/integration/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
33 changes: 25 additions & 8 deletions winit/src/clipboard.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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 }
}
Expand All @@ -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),
},
Expand All @@ -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 => {
Expand Down
2 changes: 1 addition & 1 deletion winit/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ where
}
};

let clipboard = Clipboard::connect(&window);
let clipboard = Clipboard::connect(window.clone());

let finish_boot = async move {
let mut compositor =
Expand Down

0 comments on commit 8e87d66

Please sign in to comment.