Linux: Add support for MouseButton::Navigate in GPUI (wayland and x11) (#7996)

Release Notes:

- N/A

Based on wgpu implementation (which I wrote).

---------

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
bbb651 2024-02-19 18:09:53 -08:00 committed by GitHub
parent b00b65b330
commit 0422d43798
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 18 deletions

View File

@ -30,11 +30,11 @@ use xkbcommon::xkb::{Keycode, KEYMAP_COMPILE_NO_FLAGS};
use crate::platform::linux::client::Client; use crate::platform::linux::client::Client;
use crate::platform::linux::wayland::window::{WaylandDecorationState, WaylandWindow}; use crate::platform::linux::wayland::window::{WaylandDecorationState, WaylandWindow};
use crate::platform::{LinuxPlatformInner, PlatformWindow}; use crate::platform::{LinuxPlatformInner, PlatformWindow};
use crate::ScrollDelta;
use crate::{ use crate::{
platform::linux::wayland::window::WaylandWindowState, AnyWindowHandle, DisplayId, KeyDownEvent, platform::linux::wayland::window::WaylandWindowState, AnyWindowHandle, DisplayId, KeyDownEvent,
KeyUpEvent, Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, KeyUpEvent, Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
Pixels, PlatformDisplay, PlatformInput, Point, ScrollWheelEvent, TouchPhase, WindowOptions, NavigationDirection, Pixels, PlatformDisplay, PlatformInput, Point, ScrollDelta,
ScrollWheelEvent, TouchPhase, WindowOptions,
}; };
const MIN_KEYCODE: u32 = 8; // used to convert evdev scancode to xkb scancode const MIN_KEYCODE: u32 = 8; // used to convert evdev scancode to xkb scancode
@ -495,13 +495,24 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
} }
} }
fn linux_button_to_gpui(button: u32) -> MouseButton { fn linux_button_to_gpui(button: u32) -> Option<MouseButton> {
match button { // These values are coming from <linux/input-event-codes.h>.
0x110 => MouseButton::Left, const BTN_LEFT: u32 = 0x110;
0x111 => MouseButton::Right, const BTN_RIGHT: u32 = 0x111;
0x112 => MouseButton::Middle, const BTN_MIDDLE: u32 = 0x112;
_ => unimplemented!(), // todo!(linux) const BTN_SIDE: u32 = 0x113;
} const BTN_EXTRA: u32 = 0x114;
const BTN_FORWARD: u32 = 0x115;
const BTN_BACK: u32 = 0x116;
Some(match button {
BTN_LEFT => MouseButton::Left,
BTN_RIGHT => MouseButton::Right,
BTN_MIDDLE => MouseButton::Middle,
BTN_BACK | BTN_SIDE => MouseButton::Navigate(NavigationDirection::Back),
BTN_FORWARD | BTN_EXTRA => MouseButton::Navigate(NavigationDirection::Forward),
_ => return None,
})
} }
impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientState { impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientState {
@ -555,16 +566,17 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientState {
.. ..
} => { } => {
let focused_window = &state.mouse_focused_window; let focused_window = &state.mouse_focused_window;
let mouse_location = &state.mouse_location; let mouse_location = state.mouse_location;
if let (Some(focused_window), Some(mouse_location)) = let button = linux_button_to_gpui(button);
(focused_window, mouse_location) if let (Some(focused_window), Some(mouse_location), Some(button)) =
(focused_window, mouse_location, button)
{ {
match button_state { match button_state {
wl_pointer::ButtonState::Pressed => { wl_pointer::ButtonState::Pressed => {
state.button_pressed = Some(linux_button_to_gpui(button)); state.button_pressed = Some(button);
focused_window.handle_input(PlatformInput::MouseDown(MouseDownEvent { focused_window.handle_input(PlatformInput::MouseDown(MouseDownEvent {
button: linux_button_to_gpui(button), button,
position: *mouse_location, position: mouse_location,
modifiers: state.modifiers, modifiers: state.modifiers,
click_count: 1, click_count: 1,
})); }));
@ -572,8 +584,8 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientState {
wl_pointer::ButtonState::Released => { wl_pointer::ButtonState::Released => {
state.button_pressed = None; state.button_pressed = None;
focused_window.handle_input(PlatformInput::MouseUp(MouseUpEvent { focused_window.handle_input(PlatformInput::MouseUp(MouseUpEvent {
button: linux_button_to_gpui(button), button,
position: *mouse_location, position: mouse_location,
modifiers: Modifiers::default(), modifiers: Modifiers::default(),
click_count: 1, click_count: 1,
})); }));

View File

@ -1,12 +1,14 @@
use xcb::x; use xcb::x;
use crate::{Modifiers, MouseButton}; use crate::{Modifiers, MouseButton, NavigationDirection};
pub(crate) fn button_of_key(detail: x::Button) -> Option<MouseButton> { pub(crate) fn button_of_key(detail: x::Button) -> Option<MouseButton> {
Some(match detail { Some(match detail {
1 => MouseButton::Left, 1 => MouseButton::Left,
2 => MouseButton::Middle, 2 => MouseButton::Middle,
3 => MouseButton::Right, 3 => MouseButton::Right,
8 => MouseButton::Navigate(NavigationDirection::Back),
9 => MouseButton::Navigate(NavigationDirection::Forward),
_ => return None, _ => return None,
}) })
} }