Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iced_winit: drop Clipboard before Window #2547

Merged
merged 3 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading