From 40daec89346f44ca733dbcfa74e144a609d9acba Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Tue, 16 Jun 2026 00:20:39 +0200 Subject: [PATCH] fix: Save wayland selection offer to every surface (#7863) In Wayland, when something is copied to the clipboard, an "offer" is given to every "device". WezTerm holds these offers in a 'CopyAndPaste' struct, and reads from the offer when the user presses paste. WezTerm has one 'CopyAndPaste' for each window. When WezTerm receives a data offer, it previously only saved it to one 'CopyAndPaste' based on the active surface id. With this change, it writes it to every CopyAndPaste. Fixes #6685 Replaces #7034 --------- Co-authored-by: XeroOl --- window/src/os/wayland/copy_and_paste.rs | 9 --------- window/src/os/wayland/data_device.rs | 13 +++++++++++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/window/src/os/wayland/copy_and_paste.rs b/window/src/os/wayland/copy_and_paste.rs index ce309fbd3..70bb855af 100644 --- a/window/src/os/wayland/copy_and_paste.rs +++ b/window/src/os/wayland/copy_and_paste.rs @@ -99,15 +99,6 @@ impl CopyAndPaste { } } -impl WaylandState { - pub(super) fn resolve_copy_and_paste(&mut self) -> Option>> { - let active_surface_id = self.active_surface_id.borrow(); - let active_surface_id = active_surface_id.as_ref()?; - let pending = self.surface_to_pending.get(&active_surface_id)?; - Some(Arc::clone(&pending.lock().unwrap().copy_and_paste)) - } -} - pub(super) fn write_selection_to_pipe(fd: WritePipe, text: &str) { if let Err(e) = write_pipe_with_timeout(fd, text.as_bytes()) { log::error!("while sending primary selection to pipe: {}", e); diff --git a/window/src/os/wayland/data_device.rs b/window/src/os/wayland/data_device.rs index 338280e02..8af5194bc 100644 --- a/window/src/os/wayland/data_device.rs +++ b/window/src/os/wayland/data_device.rs @@ -112,8 +112,17 @@ impl DataDeviceHandler for WaylandState { return; } - if let Some(copy_and_paste) = self.resolve_copy_and_paste() { - copy_and_paste.lock().unwrap().confirm_selection(offer); + // The compositor sends the (copy) selection event once per client. + // Broadcast to every window so any of them can paste, regardless + // of which surface was active when the clipboard changed. + // ref: https://github.com/wezterm/wezterm/issues/6685 + for pending_mouse in self.surface_to_pending.values() { + let copy_and_paste = &pending_mouse.lock().unwrap().copy_and_paste; + // Each window gets a clone of the same underlying WlDataOffer handle. + copy_and_paste + .lock() + .unwrap() + .confirm_selection(offer.clone()); } } } -- 2.51.2