1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 22:42:48 +03:00

Fix copy mode on Wayland

On Wayland, copy mode often doesn't actually update the clipboard.
Specifically, it only works one time after a pointer enter or pointer
button event, then doesn't work again until the next event.

This is because the Wayland protocol serial number in
CopyAndPaste::last_serial is only updated by pointer enter and pointer
button events. So, subsequent copies using only the keyboard reuse the
same serial number and get ignored. last_serial used to be updated for
keyboard events, too, but that was (accidentally?) dropped in commit
0a00ffe98b.

Commit 0a00ffe98b also added another
last_serial to WaylandConnection which is updated for keyboard events
but isn't used anywhere as far as I can tell.

So, to fix this bug, let's get rid of CopyAndPaste::last_serial and
replace it with WaylandConnection::last_serial, which is now updated for
pointer and keyboard events.

closes: #3843
This commit is contained in:
Omar Sandoval 2023-07-03 08:23:13 -07:00 committed by Wez Furlong
parent f376468f46
commit 7373a4990b
3 changed files with 12 additions and 21 deletions

View File

@ -16,13 +16,11 @@ use crate::Clipboard;
#[derive(Default)]
pub struct CopyAndPaste {
data_offer: Option<WlDataOffer>,
pub(crate) last_serial: u32,
}
impl std::fmt::Debug for CopyAndPaste {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
fmt.debug_struct("CopyAndPaste")
.field("last_serial", &self.last_serial)
.field("data_offer", &self.data_offer.is_some())
.finish()
}
@ -35,12 +33,6 @@ impl CopyAndPaste {
Arc::new(Mutex::new(Default::default()))
}
pub fn update_last_serial(&mut self, serial: u32) {
if serial != 0 {
self.last_serial = serial;
}
}
pub fn get_clipboard_data(&mut self, clipboard: Clipboard) -> anyhow::Result<FileDescriptor> {
let conn = crate::Connection::get().unwrap().wayland();
let pointer = conn.pointer.borrow();
@ -75,6 +67,7 @@ impl CopyAndPaste {
pub fn set_clipboard_data(&mut self, clipboard: Clipboard, data: String) {
let conn = crate::Connection::get().unwrap().wayland();
let last_serial = *conn.last_serial.borrow();
let pointer = conn.pointer.borrow();
let primary_selection = if let Clipboard::PrimarySelection = clipboard {
conn.environment
@ -105,7 +98,7 @@ impl CopyAndPaste {
}
},
);
device.set_selection(&Some(source), self.last_serial)
device.set_selection(&Some(source), last_serial)
}
None => {
let source = conn
@ -122,7 +115,7 @@ impl CopyAndPaste {
conn.pointer
.borrow()
.data_device
.set_selection(Some(&source), self.last_serial);
.set_selection(Some(&source), last_serial);
}
}
}
@ -130,12 +123,14 @@ impl CopyAndPaste {
pub fn handle_data_offer(&mut self, event: DataOfferEvent, offer: WlDataOffer) {
match event {
DataOfferEvent::Offer { mime_type } => {
let conn = crate::Connection::get().unwrap().wayland();
let last_serial = *conn.last_serial.borrow();
if mime_type == TEXT_MIME_TYPE {
offer.accept(self.last_serial, Some(mime_type));
offer.accept(last_serial, Some(mime_type));
self.data_offer.replace(offer);
} else {
// Refuse other mime types
offer.accept(self.last_serial, None);
offer.accept(last_serial, None);
}
}
DataOfferEvent::SourceActions { .. } | DataOfferEvent::Action { .. } => {

View File

@ -141,10 +141,8 @@ impl PendingMouse {
pub fn queue(&mut self, evt: PointerEvent) -> bool {
match evt {
PointerEvent::Enter { serial, .. } => {
self.copy_and_paste
.lock()
.unwrap()
.update_last_serial(serial);
let conn = WaylandConnection::get().unwrap().wayland();
*conn.last_serial.borrow_mut() = serial;
self.in_window = true;
false
}
@ -169,10 +167,8 @@ impl PendingMouse {
serial,
..
} => {
self.copy_and_paste
.lock()
.unwrap()
.update_last_serial(serial);
let conn = WaylandConnection::get().unwrap().wayland();
*conn.last_serial.borrow_mut() = serial;
fn linux_button(b: u32) -> Option<MousePress> {
// See BTN_LEFT and friends in <linux/input-event-codes.h>
match b {

View File

@ -1176,8 +1176,8 @@ impl WaylandWindowInner {
fn request_drag_move(&self) {
if let Some(window) = self.window.as_ref() {
let serial = self.copy_and_paste.lock().unwrap().last_serial;
let conn = Connection::get().unwrap().wayland();
let serial = *conn.last_serial.borrow();
window.start_interactive_move(&conn.pointer.borrow().seat, serial);
}
}