From bd9088372a31894bff17ed1720fc5e52db11bb44 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sat, 19 Mar 2022 05:44:39 -0700 Subject: [PATCH] wayland: speculative handling of pointer when seat changes It compiles and launches under weston, so that's promising. I can't test the suspend/resume case on the hardware I have available. refs: #1497 --- docs/changelog.md | 1 + window/src/os/wayland/connection.rs | 17 ++++-------- window/src/os/wayland/copy_and_paste.rs | 8 ++++-- window/src/os/wayland/pointer.rs | 37 +++++++++++++++++++++++-- window/src/os/wayland/window.rs | 6 ++-- 5 files changed, 50 insertions(+), 19 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index a3ea48d51..35f15fe71 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -77,6 +77,7 @@ As features stabilize some brief notes about them will accumulate here. * Fixed lingering hover state in titlebar when the mouse pointer left the window. Thanks to [@davidrios](https://github.com/davidrios)! [#1434](https://github.com/wez/wezterm/issues/1434) * We now respect the difference between `Italic` and `Oblique` font styles when matching fonts. You may explicitly specify `style="Oblique"` rather than using `italic=true` for fonts that offer both italic and oblique variants. [#1646](https://github.com/wez/wezterm/issues/1646) * Hang when clicking a URL would launch the browser for the first time on unix systems [#1721](https://github.com/wez/wezterm/issues/1721) +* Wayland input handling gets broken after suspend/resume. Thanks to [@LawnGnome](https://github.com/LawnGnome)! [#1497](https://github.com/wez/wezterm/issues/1497) ### 20220101-133340-7edc5b5a diff --git a/window/src/os/wayland/connection.rs b/window/src/os/wayland/connection.rs index d11220bfd..2e2914432 100644 --- a/window/src/os/wayland/connection.rs +++ b/window/src/os/wayland/connection.rs @@ -37,7 +37,7 @@ pub struct WaylandConnection { // bottom of this list, and opengl, which depends on everything // must be ahead of the rest. pub(crate) gl_connection: RefCell>>, - pub(crate) pointer: PointerDispatcher, + pub(crate) pointer: RefCell, pub(crate) keyboard_mapper: RefCell>, pub(crate) keyboard_window_id: RefCell>, pub(crate) surface_to_window_id: RefCell>, @@ -132,16 +132,9 @@ impl WaylandConnection { // fires for this seat with has_keyboard = true. seat_keyboards.remove(&seat_data.name); } - if seat_data.has_pointer { - // TODO: ideally do something similar to the keyboard state, - // but the pointer state has a lot of other stuff floating - // around it so it's not so clear cut right now. - log::error!( - "seat {} changed; it has a pointer that is - defunct={} and we don't know what to do about it", - seat_data.name, - seat_data.defunct - ); + if seat_data.has_pointer && !seat_data.defunct { + let conn = Connection::get().unwrap().wayland(); + conn.pointer.borrow_mut().seat_changed(&seat); } }); } @@ -153,7 +146,7 @@ impl WaylandConnection { next_window_id: AtomicUsize::new(1), windows: RefCell::new(HashMap::new()), event_q: RefCell::new(event_q), - pointer: pointer.unwrap(), + pointer: RefCell::new(pointer.unwrap()), seat_listener, gl_connection: RefCell::new(None), keyboard_mapper: RefCell::new(None), diff --git a/window/src/os/wayland/copy_and_paste.rs b/window/src/os/wayland/copy_and_paste.rs index f70f031a4..ffd00f1eb 100644 --- a/window/src/os/wayland/copy_and_paste.rs +++ b/window/src/os/wayland/copy_and_paste.rs @@ -43,8 +43,9 @@ impl CopyAndPaste { pub fn get_clipboard_data(&mut self, clipboard: Clipboard) -> anyhow::Result { let conn = crate::Connection::get().unwrap().wayland(); + let pointer = conn.pointer.borrow(); let primary_selection = if let Clipboard::PrimarySelection = clipboard { - conn.pointer.primary_selection_device.as_ref() + pointer.primary_selection_device.as_ref() } else { None }; @@ -74,11 +75,12 @@ impl CopyAndPaste { pub fn set_clipboard_data(&mut self, clipboard: Clipboard, data: String) { let conn = crate::Connection::get().unwrap().wayland(); + let pointer = conn.pointer.borrow(); let primary_selection = if let Clipboard::PrimarySelection = clipboard { conn.environment .borrow() .get_primary_selection_manager() - .zip(conn.pointer.primary_selection_device.as_ref()) + .zip(pointer.primary_selection_device.as_ref()) } else { None }; @@ -94,6 +96,7 @@ impl CopyAndPaste { .unwrap() .wayland() .pointer + .borrow() .data_device .set_selection(None, 0); } @@ -119,6 +122,7 @@ impl CopyAndPaste { }); source.offer(TEXT_MIME_TYPE.to_string()); conn.pointer + .borrow() .data_device .set_selection(Some(&source), self.last_serial); } diff --git a/window/src/os/wayland/pointer.rs b/window/src/os/wayland/pointer.rs index 080ab3795..40bbd681d 100644 --- a/window/src/os/wayland/pointer.rs +++ b/window/src/os/wayland/pointer.rs @@ -91,7 +91,9 @@ impl Inner { pub struct PointerDispatcher { inner: Arc>, + dev_mgr: Attached, pub(crate) data_device: Main, + selection_manager: Option, pub(crate) primary_selection_device: Option, auto_pointer: ThemedPointer, #[allow(dead_code)] @@ -249,12 +251,15 @@ impl PointerDispatcher { } }); - let primary_selection_device = - selection_manager.map(|m| PrimarySelectionDevice::init_for_seat(&m, seat)); + let primary_selection_device = selection_manager + .as_ref() + .map(|m| PrimarySelectionDevice::init_for_seat(&m, seat)); Ok(Self { inner, + dev_mgr, data_device, + selection_manager, primary_selection_device, themer, auto_pointer, @@ -262,6 +267,34 @@ impl PointerDispatcher { }) } + pub fn seat_changed(&mut self, seat: &WlSeat) { + let inner = Arc::clone(&self.inner); + + let pointer = seat.get_pointer(); + pointer.quick_assign({ + let inner = Arc::clone(&inner); + move |_, evt, _| { + inner.lock().unwrap().handle_event(evt); + } + }); + let data_device = self.dev_mgr.get_data_device(seat); + data_device.quick_assign({ + let inner = Arc::clone(&inner); + move |_device, event, _| { + inner.lock().unwrap().handle_data_event(event, &inner); + } + }); + + let primary_selection_device = self + .selection_manager + .as_ref() + .map(|m| PrimarySelectionDevice::init_for_seat(&m, seat)); + + self.data_device = data_device; + self.primary_selection_device = primary_selection_device; + self.seat = seat.clone(); + } + pub fn add_window(&self, surface: &WlSurface, pending: &Arc>) { let mut inner = self.inner.lock().unwrap(); inner diff --git a/window/src/os/wayland/window.rs b/window/src/os/wayland/window.rs index 27daa4c07..ce0517dff 100644 --- a/window/src/os/wayland/window.rs +++ b/window/src/os/wayland/window.rs @@ -334,7 +334,7 @@ impl WaylandWindow { let copy_and_paste = CopyAndPaste::create(); let pending_mouse = PendingMouse::create(window_id, ©_and_paste); - conn.pointer.add_window(&surface, &pending_mouse); + conn.pointer.borrow().add_window(&surface, &pending_mouse); let inner = Rc::new(RefCell::new(WaylandWindowInner { window_id, @@ -985,7 +985,7 @@ impl WaylandWindowInner { None => return, }; let conn = Connection::get().unwrap().wayland(); - conn.pointer.set_cursor(cursor, None); + conn.pointer.borrow().set_cursor(cursor, None); } fn invalidate(&mut self) { @@ -1035,7 +1035,7 @@ impl WaylandWindowInner { if let Some(window) = self.window.as_ref() { let serial = self.copy_and_paste.lock().unwrap().last_serial; let conn = Connection::get().unwrap().wayland(); - window.start_interactive_move(&conn.pointer.seat, serial); + window.start_interactive_move(&conn.pointer.borrow().seat, serial); } }