diff --git a/crates/gpui_linux/src/linux/x11/client.rs b/crates/gpui_linux/src/linux/x11/client.rs index 57871e6ef32b937a7a47662f8022293a57bc3fe2..bc7c9594734d4fae9a8dda4056bc02d515fbab48 100644 --- a/crates/gpui_linux/src/linux/x11/client.rs +++ b/crates/gpui_linux/src/linux/x11/client.rs @@ -214,6 +214,8 @@ pub struct X11ClientState { pointer_device_states: BTreeMap, + pub(crate) supports_xinput_gestures: bool, + pub(crate) common: LinuxCommon, pub(crate) clipboard: Clipboard, pub(crate) clipboard_item: Option, @@ -345,7 +347,8 @@ impl X11Client { // Announce to X server that XInput up to 2.4 is supported. // Version 2.4 is needed for gesture events (GesturePinchBegin/Update/End). - // If the server only supports an older version, gesture events simply won't be delivered. + // The server responds with the highest version it supports; if < 2.4, + // we must not request gesture event masks in XISelectEvents. let xinput_version = get_reply( || "XInput XiQueryVersion failed", xcb_connection.xinput_xi_query_version(2, 4), @@ -354,6 +357,14 @@ impl X11Client { xinput_version.major_version >= 2, "XInput version >= 2 required." ); + let supports_xinput_gestures = xinput_version.major_version > 2 + || (xinput_version.major_version == 2 && xinput_version.minor_version >= 4); + log::info!( + "XInput version: {}.{}, gesture support: {}", + xinput_version.major_version, + xinput_version.minor_version, + supports_xinput_gestures, + ); let pointer_device_states = current_pointer_device_states(&xcb_connection, &BTreeMap::new()).unwrap_or_default(); @@ -535,6 +546,8 @@ impl X11Client { pointer_device_states, + supports_xinput_gestures, + clipboard, clipboard_item: None, xdnd_state: Xdnd::default(), @@ -1593,6 +1606,7 @@ impl LinuxClient for X11Client { let scale_factor = state.scale_factor; let appearance = state.common.appearance; let compositor_gpu = state.compositor_gpu.take(); + let supports_xinput_gestures = state.supports_xinput_gestures; let window = X11Window::new( handle, X11ClientStatePtr(Rc::downgrade(&self.0)), @@ -1608,6 +1622,7 @@ impl LinuxClient for X11Client { scale_factor, appearance, parent_window, + supports_xinput_gestures, )?; check_reply( || "Failed to set XdndAware property", diff --git a/crates/gpui_linux/src/linux/x11/window.rs b/crates/gpui_linux/src/linux/x11/window.rs index 1974cc0bb28f62da4d7dcb3e9fca92b6324470bb..f29ba49fb2498dd49a5f025aad4dc2584a8a8a42 100644 --- a/crates/gpui_linux/src/linux/x11/window.rs +++ b/crates/gpui_linux/src/linux/x11/window.rs @@ -423,6 +423,7 @@ impl X11WindowState { scale_factor: f32, appearance: WindowAppearance, parent_window: Option, + supports_xinput_gestures: bool, ) -> anyhow::Result { let x_screen_index = params .display_id @@ -660,25 +661,27 @@ impl X11WindowState { ), )?; + let mut xi_event_mask = xinput::XIEventMask::MOTION + | xinput::XIEventMask::BUTTON_PRESS + | xinput::XIEventMask::BUTTON_RELEASE + | xinput::XIEventMask::ENTER + | xinput::XIEventMask::LEAVE; + if supports_xinput_gestures { + // x11rb 0.13 doesn't define XIEventMask constants for gesture + // events, so we construct them from the event opcodes (each + // XInput event type N maps to mask bit N). + xi_event_mask |= + xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_BEGIN_EVENT) + | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_UPDATE_EVENT) + | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_END_EVENT); + } check_reply( || "X11 XiSelectEvents failed.", xcb.xinput_xi_select_events( x_window, &[xinput::EventMask { deviceid: XINPUT_ALL_DEVICE_GROUPS, - mask: vec![ - xinput::XIEventMask::MOTION - | xinput::XIEventMask::BUTTON_PRESS - | xinput::XIEventMask::BUTTON_RELEASE - | xinput::XIEventMask::ENTER - | xinput::XIEventMask::LEAVE - // x11rb 0.13 doesn't define XIEventMask constants for gesture - // events, so we construct them from the event opcodes (each - // XInput event type N maps to mask bit N). - | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_BEGIN_EVENT) - | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_UPDATE_EVENT) - | xinput::XIEventMask::from(1u32 << xinput::GESTURE_PINCH_END_EVENT), - ], + mask: vec![xi_event_mask], }], ), )?; @@ -855,6 +858,7 @@ impl X11Window { scale_factor: f32, appearance: WindowAppearance, parent_window: Option, + supports_xinput_gestures: bool, ) -> anyhow::Result { let ptr = X11WindowStatePtr { state: Rc::new(RefCell::new(X11WindowState::new( @@ -872,6 +876,7 @@ impl X11Window { scale_factor, appearance, parent_window, + supports_xinput_gestures, )?)), callbacks: Rc::new(RefCell::new(Callbacks::default())), xcb: xcb.clone(),