mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-11 05:00:16 +00:00
Replace all X11 mouse events with XI2 equivalents (#11235)
This PR replaces all pointer events on X11 with their XI2 equivalents, which fixes problems with scroll events not being reported when a mouse button is down. Additionally it closes #11206 by resetting the tracked global scroll valulator position with `None` on a leave event to prevent a large scroll delta if scrolling is done outside the window. Lastly, it resolves the bad window issue kvark was having. Release Notes: - Fixed X11 Scroll snapping (#11206 ). --------- Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
5486c3dc93
commit
9a60c0a059
3 changed files with 45 additions and 60 deletions
|
@ -35,7 +35,7 @@ use super::{
|
|||
super::{open_uri_internal, SCROLL_LINES},
|
||||
X11Display, X11WindowStatePtr, XcbAtoms,
|
||||
};
|
||||
use super::{button_of_key, modifiers_from_state};
|
||||
use super::{button_from_mask, button_of_key, modifiers_from_state};
|
||||
use crate::platform::linux::is_within_click_distance;
|
||||
use crate::platform::linux::platform::DOUBLE_CLICK_INTERVAL;
|
||||
|
||||
|
@ -390,16 +390,16 @@ impl X11Client {
|
|||
drop(state);
|
||||
window.handle_input(PlatformInput::KeyUp(crate::KeyUpEvent { keystroke }));
|
||||
}
|
||||
Event::ButtonPress(event) => {
|
||||
Event::XinputButtonPress(event) => {
|
||||
let window = self.get_window(event.event)?;
|
||||
let mut state = self.0.borrow_mut();
|
||||
|
||||
let modifiers = modifiers_from_state(event.state);
|
||||
let modifiers = modifiers_from_xinput_info(event.mods);
|
||||
let position = point(
|
||||
px(event.event_x as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / state.scale_factor),
|
||||
px(event.event_x as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
);
|
||||
if let Some(button) = button_of_key(event.detail) {
|
||||
if let Some(button) = button_of_key(event.detail.try_into().unwrap()) {
|
||||
let click_elapsed = state.last_click.elapsed();
|
||||
|
||||
if click_elapsed < DOUBLE_CLICK_INTERVAL
|
||||
|
@ -426,15 +426,15 @@ impl X11Client {
|
|||
log::warn!("Unknown button press: {event:?}");
|
||||
}
|
||||
}
|
||||
Event::ButtonRelease(event) => {
|
||||
Event::XinputButtonRelease(event) => {
|
||||
let window = self.get_window(event.event)?;
|
||||
let state = self.0.borrow();
|
||||
let modifiers = modifiers_from_state(event.state);
|
||||
let modifiers = modifiers_from_xinput_info(event.mods);
|
||||
let position = point(
|
||||
px(event.event_x as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / state.scale_factor),
|
||||
px(event.event_x as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
);
|
||||
if let Some(button) = button_of_key(event.detail) {
|
||||
if let Some(button) = button_of_key(event.detail.try_into().unwrap()) {
|
||||
let click_count = state.current_count;
|
||||
drop(state);
|
||||
window.handle_input(PlatformInput::MouseUp(crate::MouseUpEvent {
|
||||
|
@ -448,6 +448,7 @@ impl X11Client {
|
|||
Event::XinputMotion(event) => {
|
||||
let window = self.get_window(event.event)?;
|
||||
let state = self.0.borrow();
|
||||
let pressed_button = button_from_mask(event.button_mask[0]);
|
||||
let position = point(
|
||||
px(event.event_x as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
|
@ -464,7 +465,7 @@ impl X11Client {
|
|||
if event.valuator_mask[0] & 3 != 0 {
|
||||
window.handle_input(PlatformInput::MouseMove(crate::MouseMoveEvent {
|
||||
position,
|
||||
pressed_button: None,
|
||||
pressed_button,
|
||||
modifiers,
|
||||
}));
|
||||
}
|
||||
|
@ -524,32 +525,20 @@ impl X11Client {
|
|||
valuator_idx += 1;
|
||||
}
|
||||
}
|
||||
Event::MotionNotify(event) => {
|
||||
Event::XinputLeave(event) => {
|
||||
self.0.borrow_mut().scroll_x = None; // Set last scroll to `None` so that a large delta isn't created if scrolling is done outside the window (the valuator is global)
|
||||
self.0.borrow_mut().scroll_y = None;
|
||||
|
||||
let window = self.get_window(event.event)?;
|
||||
let state = self.0.borrow();
|
||||
let pressed_button = super::button_from_state(event.state);
|
||||
let pressed_button = button_from_mask(event.buttons[0]);
|
||||
let position = point(
|
||||
px(event.event_x as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / state.scale_factor),
|
||||
px(event.event_x as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / u16::MAX as f32 / state.scale_factor),
|
||||
);
|
||||
let modifiers = modifiers_from_state(event.state);
|
||||
drop(state);
|
||||
window.handle_input(PlatformInput::MouseMove(crate::MouseMoveEvent {
|
||||
pressed_button,
|
||||
position,
|
||||
modifiers,
|
||||
}));
|
||||
}
|
||||
Event::LeaveNotify(event) => {
|
||||
let window = self.get_window(event.event)?;
|
||||
let state = self.0.borrow();
|
||||
let pressed_button = super::button_from_state(event.state);
|
||||
let position = point(
|
||||
px(event.event_x as f32 / state.scale_factor),
|
||||
px(event.event_y as f32 / state.scale_factor),
|
||||
);
|
||||
let modifiers = modifiers_from_state(event.state);
|
||||
let modifiers = modifiers_from_xinput_info(event.mods);
|
||||
drop(state);
|
||||
|
||||
window.handle_input(PlatformInput::MouseExited(crate::MouseExitEvent {
|
||||
pressed_button,
|
||||
position,
|
||||
|
|
|
@ -37,12 +37,12 @@ pub(crate) fn modifiers_from_xinput_info(modifier_info: xinput::ModifierInfo) ->
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn button_from_state(state: xproto::KeyButMask) -> Option<MouseButton> {
|
||||
Some(if state.contains(xproto::KeyButMask::BUTTON1) {
|
||||
pub(crate) fn button_from_mask(button_mask: u32) -> Option<MouseButton> {
|
||||
Some(if button_mask & 2 == 2 {
|
||||
MouseButton::Left
|
||||
} else if state.contains(xproto::KeyButMask::BUTTON2) {
|
||||
} else if button_mask & 4 == 4 {
|
||||
MouseButton::Middle
|
||||
} else if state.contains(xproto::KeyButMask::BUTTON3) {
|
||||
} else if button_mask & 8 == 8 {
|
||||
MouseButton::Right
|
||||
} else {
|
||||
return None;
|
||||
|
|
|
@ -16,11 +16,11 @@ use x11rb::{
|
|||
connection::{Connection as _, RequestConnection as _},
|
||||
protocol::{
|
||||
render::{self, ConnectionExt as _},
|
||||
xinput,
|
||||
xproto::{self, ConnectionExt as _},
|
||||
xinput::{self, ConnectionExt as _},
|
||||
xproto::{self, ConnectionExt as _, CreateWindowAux},
|
||||
},
|
||||
resource_manager::Database,
|
||||
wrapper::ConnectionExt,
|
||||
wrapper::ConnectionExt as _,
|
||||
xcb_ffi::XCBConnection,
|
||||
};
|
||||
|
||||
|
@ -262,14 +262,7 @@ impl X11WindowState {
|
|||
| xproto::EventMask::LEAVE_WINDOW
|
||||
| xproto::EventMask::FOCUS_CHANGE
|
||||
| xproto::EventMask::KEY_PRESS
|
||||
| xproto::EventMask::KEY_RELEASE
|
||||
| xproto::EventMask::BUTTON_PRESS
|
||||
| xproto::EventMask::BUTTON_RELEASE
|
||||
| xproto::EventMask::POINTER_MOTION
|
||||
| xproto::EventMask::BUTTON1_MOTION
|
||||
| xproto::EventMask::BUTTON2_MOTION
|
||||
| xproto::EventMask::BUTTON3_MOTION
|
||||
| xproto::EventMask::BUTTON_MOTION,
|
||||
| xproto::EventMask::KEY_RELEASE,
|
||||
);
|
||||
|
||||
xcb_connection
|
||||
|
@ -290,18 +283,6 @@ impl X11WindowState {
|
|||
.check()
|
||||
.unwrap();
|
||||
|
||||
xinput::ConnectionExt::xinput_xi_select_events(
|
||||
&xcb_connection,
|
||||
x_window,
|
||||
&[xinput::EventMask {
|
||||
deviceid: 1,
|
||||
mask: vec![xinput::XIEventMask::MOTION],
|
||||
}],
|
||||
)
|
||||
.unwrap()
|
||||
.check()
|
||||
.unwrap();
|
||||
|
||||
if let Some(titlebar) = params.titlebar {
|
||||
if let Some(title) = titlebar.title {
|
||||
xcb_connection
|
||||
|
@ -326,6 +307,21 @@ impl X11WindowState {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
xcb_connection
|
||||
.xinput_xi_select_events(
|
||||
x_window,
|
||||
&[xinput::EventMask {
|
||||
deviceid: 1,
|
||||
mask: vec![
|
||||
xinput::XIEventMask::MOTION
|
||||
| xinput::XIEventMask::BUTTON_PRESS
|
||||
| xinput::XIEventMask::BUTTON_RELEASE
|
||||
| xinput::XIEventMask::LEAVE,
|
||||
],
|
||||
}],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
xcb_connection.map_window(x_window).unwrap();
|
||||
xcb_connection.flush().unwrap();
|
||||
|
||||
|
|
Loading…
Reference in a new issue