On Wayland, make the CSD frame double click reliable

It was discovered that on GNOME the click sometimes being swallowed
by the mutter's `wl_pointer::enter/leave` sequences. This was happening
due to `xdg_toplevel::move` making the pointer to leave the surface.

To make handling of that more robust, we could start the
`xdg_toplevel::move` when the actual pointer motion is being performed.

Links: https://github.com/alacritty/alacritty/issues/7011
Links: https://gitlab.gnome.org/GNOME/mutter/-/issues/2669#note_1790825
This commit is contained in:
Kirill Chibisov 2023-07-15 08:09:28 +00:00 committed by GitHub
parent 97434d8d80
commit b166e1ff13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 4 deletions

View file

@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre
# Unreleased # Unreleased
- On Wayland, make double clicking and moving the CSD frame more reliable.
- On macOS, add tabbing APIs on `WindowExtMacOS` and `EventLoopWindowTargetExtMacOS`. - On macOS, add tabbing APIs on `WindowExtMacOS` and `EventLoopWindowTargetExtMacOS`.
- **Breaking:** Rename `Window::set_inner_size` to `Window::request_inner_size` and indicate if the size was applied immediately. - **Breaking:** Rename `Window::set_inner_size` to `Window::request_inner_size` and indicate if the size was applied immediately.
- On X11, fix false positive flagging of key repeats when pressing different keys with no release between presses. - On X11, fix false positive flagging of key repeats when pressing different keys with no release between presses.

View file

@ -68,7 +68,7 @@ impl PointerHandler for WinitState {
if parent_surface != surface => if parent_surface != surface =>
{ {
if let Some(icon) = if let Some(icon) =
window.frame_point_moved(surface, event.position.0, event.position.1) window.frame_point_moved(seat, surface, event.position.0, event.position.1)
{ {
if let Some(pointer) = seat_state.pointer.as_ref() { if let Some(pointer) = seat_state.pointer.as_ref() {
let surface = pointer let surface = pointer

View file

@ -127,6 +127,11 @@ pub struct WindowState {
viewport: Option<WpViewport>, viewport: Option<WpViewport>,
fractional_scale: Option<WpFractionalScaleV1>, fractional_scale: Option<WpFractionalScaleV1>,
/// Whether the client side decorations have pending move operations.
///
/// The value is the serial of the event triggered moved.
has_pending_move: Option<u32>,
} }
/// The state of the cursor grabs. /// The state of the cursor grabs.
@ -279,7 +284,7 @@ impl WindowState {
FrameAction::Maximize => self.window.set_maximized(), FrameAction::Maximize => self.window.set_maximized(),
FrameAction::UnMaximize => self.window.unset_maximized(), FrameAction::UnMaximize => self.window.unset_maximized(),
FrameAction::Close => WinitState::queue_close(updates, window_id), FrameAction::Close => WinitState::queue_close(updates, window_id),
FrameAction::Move => self.window.move_(seat, serial), FrameAction::Move => self.has_pending_move = Some(serial),
FrameAction::Resize(edge) => self.window.resize(seat, serial, edge), FrameAction::Resize(edge) => self.window.resize(seat, serial, edge),
FrameAction::ShowMenu(x, y) => self.window.show_window_menu(seat, serial, (x, y)), FrameAction::ShowMenu(x, y) => self.window.show_window_menu(seat, serial, (x, y)),
}; };
@ -294,9 +299,26 @@ impl WindowState {
} }
// Move the point over decorations. // Move the point over decorations.
pub fn frame_point_moved(&mut self, surface: &WlSurface, x: f64, y: f64) -> Option<&str> { pub fn frame_point_moved(
&mut self,
seat: &WlSeat,
surface: &WlSurface,
x: f64,
y: f64,
) -> Option<&str> {
// Take the serial if we had any, so it doesn't stick around.
let serial = self.has_pending_move.take();
if let Some(frame) = self.frame.as_mut() { if let Some(frame) = self.frame.as_mut() {
frame.click_point_moved(surface, x, y) let cursor = frame.click_point_moved(surface, x, y);
// If we have a cursor change, that means that cursor is over the decorations,
// so try to apply move.
if let Some(serial) = cursor.is_some().then_some(serial).flatten() {
self.window.move_(seat, serial);
None
} else {
cursor
}
} else { } else {
None None
} }
@ -419,6 +441,7 @@ impl WindowState {
resizable: true, resizable: true,
viewport, viewport,
window: ManuallyDrop::new(window), window: ManuallyDrop::new(window),
has_pending_move: None,
} }
} }