Skip to content
Open
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
24 changes: 17 additions & 7 deletions crates/egui-winit/src/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ pub struct Clipboard {
}

impl Clipboard {
/// Construct a new instance
pub fn new(_raw_display_handle: Option<RawDisplayHandle>) -> Self {
/// Construct a new instance.
///
/// # Safety
///
/// If `raw_display_handle` is `Some`, the display handle must remain valid for the
/// entire lifetime of the returned `Clipboard` instance.
#[expect(unsafe_code)]
pub unsafe fn new(_raw_display_handle: Option<RawDisplayHandle>) -> Self {
Self {
#[cfg(all(
not(any(target_os = "android", target_os = "ios")),
Expand All @@ -47,7 +53,8 @@ impl Clipboard {
),
feature = "smithay-clipboard"
))]
smithay: init_smithay_clipboard(_raw_display_handle),
// SAFETY: The caller guarantees that the display handle remains valid.
smithay: unsafe { init_smithay_clipboard(_raw_display_handle) },

clipboard: Default::default(),
}
Expand Down Expand Up @@ -162,6 +169,10 @@ fn init_arboard() -> Option<arboard::Clipboard> {
}
}

/// # Safety
///
/// The display handle in `raw_display_handle` must remain valid for the
/// lifetime of the returned `Clipboard`.
#[cfg(all(
any(
target_os = "linux",
Expand All @@ -172,16 +183,15 @@ fn init_arboard() -> Option<arboard::Clipboard> {
),
feature = "smithay-clipboard"
))]
fn init_smithay_clipboard(
#[expect(unsafe_code)]
unsafe fn init_smithay_clipboard(
raw_display_handle: Option<RawDisplayHandle>,
) -> Option<smithay_clipboard::Clipboard> {
#![expect(clippy::undocumented_unsafe_blocks)]

profiling::function_scope!();

if let Some(RawDisplayHandle::Wayland(display)) = raw_display_handle {
log::trace!("Initializing smithay clipboard…");
#[expect(unsafe_code)]
// SAFETY: The caller guarantees that the display handle remains valid.
Some(unsafe { smithay_clipboard::Clipboard::new(display.display.as_ptr()) })
} else {
#[cfg(feature = "wayland")]
Expand Down
13 changes: 9 additions & 4 deletions crates/egui-winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ impl State {
..Default::default()
};

// SAFETY: The display handle is obtained from `display_target` which the caller
// is responsible for keeping alive. Winit display handles remain valid for the
// duration of the event loop, which outlives any `State` instance.
#[expect(unsafe_code)]
let clipboard = unsafe {
clipboard::Clipboard::new(display_target.display_handle().ok().map(|h| h.as_raw()))
};

let mut slf = Self {
egui_ctx,
viewport_id,
Expand All @@ -133,10 +141,7 @@ impl State {
pointer_pos_in_points: None,
any_pointer_button_down: false,
current_cursor_icon: None,

clipboard: clipboard::Clipboard::new(
display_target.display_handle().ok().map(|h| h.as_raw()),
),
clipboard,

simulate_touch_screen: false,
pointer_touch_id: None,
Expand Down