mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-27 12:54:42 +00:00
linux: scrolling improvements (#9103)
This PR adjusts scrolling to be a lot faster on Linux and also makes terminal scrolling work. For Wayland, it makes scrolling faster by handling the `AxisValue120` event (which also allows high-resolution scrolling on supported mice) On X11, changed the 1 line per scroll to 3. ### Different solutions I tried replicating Chromium's scrolling behaviour, but it was inconsistent in X11/Wayland and found it too fast on Wayland. Plus, it also didn't match VSCode, since it seems that they do something different. Release Notes: - Made scrolling faster on Linux - Made terminal scroll on Linux
This commit is contained in:
parent
c0f8581b29
commit
d8e32c3e3c
4 changed files with 68 additions and 10 deletions
|
@ -30,6 +30,8 @@ use crate::{
|
|||
|
||||
use super::x11::X11Client;
|
||||
|
||||
pub(super) const SCROLL_LINES: f64 = 3.0;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct Callbacks {
|
||||
open_urls: Option<Box<dyn FnMut(Vec<String>)>>,
|
||||
|
|
|
@ -14,7 +14,7 @@ use wayland_backend::protocol::WEnum;
|
|||
use wayland_client::globals::{registry_queue_init, GlobalListContents};
|
||||
use wayland_client::protocol::wl_callback::WlCallback;
|
||||
use wayland_client::protocol::wl_output;
|
||||
use wayland_client::protocol::wl_pointer::AxisRelativeDirection;
|
||||
use wayland_client::protocol::wl_pointer::{AxisRelativeDirection, AxisSource};
|
||||
use wayland_client::{
|
||||
delegate_noop,
|
||||
protocol::{
|
||||
|
@ -64,6 +64,7 @@ pub(crate) struct WaylandClientStateInner {
|
|||
repeat: KeyRepeat,
|
||||
modifiers: Modifiers,
|
||||
scroll_direction: f64,
|
||||
axis_source: AxisSource,
|
||||
mouse_location: Option<Point<Pixels>>,
|
||||
button_pressed: Option<MouseButton>,
|
||||
mouse_focused_window: Option<Rc<WaylandWindowState>>,
|
||||
|
@ -97,9 +98,22 @@ pub(crate) struct WaylandClient {
|
|||
qh: Arc<QueueHandle<WaylandClientState>>,
|
||||
}
|
||||
|
||||
const WL_SEAT_VERSION: u32 = 4;
|
||||
const WL_SEAT_MIN_VERSION: u32 = 4;
|
||||
const WL_OUTPUT_VERSION: u32 = 2;
|
||||
|
||||
fn wl_seat_version(version: u32) -> u32 {
|
||||
if version >= wl_pointer::EVT_AXIS_VALUE120_SINCE {
|
||||
wl_pointer::EVT_AXIS_VALUE120_SINCE
|
||||
} else if version >= WL_SEAT_MIN_VERSION {
|
||||
WL_SEAT_MIN_VERSION
|
||||
} else {
|
||||
panic!(
|
||||
"wl_seat below required version: {} < {}",
|
||||
version, WL_SEAT_MIN_VERSION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl WaylandClient {
|
||||
pub(crate) fn new(linux_platform_inner: Rc<LinuxPlatformInner>) -> Self {
|
||||
let conn = Connection::connect_to_env().unwrap();
|
||||
|
@ -114,7 +128,7 @@ impl WaylandClient {
|
|||
"wl_seat" => {
|
||||
globals.registry().bind::<wl_seat::WlSeat, _, _>(
|
||||
global.name,
|
||||
WL_SEAT_VERSION,
|
||||
wl_seat_version(global.version),
|
||||
&qh,
|
||||
(),
|
||||
);
|
||||
|
@ -163,6 +177,7 @@ impl WaylandClient {
|
|||
command: false,
|
||||
},
|
||||
scroll_direction: -1.0,
|
||||
axis_source: AxisSource::Wheel,
|
||||
mouse_location: None,
|
||||
button_pressed: None,
|
||||
mouse_focused_window: None,
|
||||
|
@ -325,10 +340,10 @@ impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for WaylandClientStat
|
|||
wl_registry::Event::Global {
|
||||
name,
|
||||
interface,
|
||||
version: _,
|
||||
version,
|
||||
} => match &interface[..] {
|
||||
"wl_seat" => {
|
||||
registry.bind::<wl_seat::WlSeat, _, _>(name, WL_SEAT_VERSION, qh, ());
|
||||
registry.bind::<wl_seat::WlSeat, _, _>(name, wl_seat_version(version), qh, ());
|
||||
}
|
||||
"wl_output" => {
|
||||
state.outputs.push((
|
||||
|
@ -914,12 +929,49 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientState {
|
|||
_ => -1.0,
|
||||
}
|
||||
}
|
||||
wl_pointer::Event::AxisSource {
|
||||
axis_source: WEnum::Value(axis_source),
|
||||
} => {
|
||||
state.axis_source = axis_source;
|
||||
}
|
||||
wl_pointer::Event::AxisValue120 {
|
||||
axis: WEnum::Value(axis),
|
||||
value120,
|
||||
} => {
|
||||
let focused_window = &state.mouse_focused_window;
|
||||
let mouse_location = &state.mouse_location;
|
||||
if let (Some(focused_window), Some(mouse_location)) =
|
||||
(focused_window, mouse_location)
|
||||
{
|
||||
let value = value120 as f64 * state.scroll_direction;
|
||||
focused_window.handle_input(PlatformInput::ScrollWheel(ScrollWheelEvent {
|
||||
position: *mouse_location,
|
||||
delta: match axis {
|
||||
wl_pointer::Axis::VerticalScroll => {
|
||||
ScrollDelta::Pixels(Point::new(Pixels(0.0), Pixels(value as f32)))
|
||||
}
|
||||
wl_pointer::Axis::HorizontalScroll => {
|
||||
ScrollDelta::Pixels(Point::new(Pixels(value as f32), Pixels(0.0)))
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
modifiers: state.modifiers,
|
||||
touch_phase: TouchPhase::Moved,
|
||||
}))
|
||||
}
|
||||
}
|
||||
wl_pointer::Event::Axis {
|
||||
time,
|
||||
axis: WEnum::Value(axis),
|
||||
value,
|
||||
..
|
||||
} => {
|
||||
if wl_pointer.version() >= wl_pointer::EVT_AXIS_VALUE120_SINCE
|
||||
&& state.axis_source != AxisSource::Continuous
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let focused_window = &state.mouse_focused_window;
|
||||
let mouse_location = &state.mouse_location;
|
||||
if let (Some(focused_window), Some(mouse_location)) =
|
||||
|
@ -938,7 +990,7 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientState {
|
|||
_ => unimplemented!(),
|
||||
},
|
||||
modifiers: state.modifiers,
|
||||
touch_phase: TouchPhase::Started,
|
||||
touch_phase: TouchPhase::Moved,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::{
|
|||
ScrollDelta, Size, TouchPhase, WindowParams,
|
||||
};
|
||||
|
||||
use super::{X11Display, X11Window, X11WindowState, XcbAtoms};
|
||||
use super::{super::SCROLL_LINES, X11Display, X11Window, X11WindowState, XcbAtoms};
|
||||
use calloop::{
|
||||
generic::{FdWrapper, Generic},
|
||||
RegistrationToken,
|
||||
|
@ -221,12 +221,13 @@ impl X11Client {
|
|||
}));
|
||||
} else if event.detail >= 4 && event.detail <= 5 {
|
||||
// https://stackoverflow.com/questions/15510472/scrollwheel-event-in-x11
|
||||
let delta_x = if event.detail == 4 { 1.0 } else { -1.0 };
|
||||
let scroll_direction = if event.detail == 4 { 1.0 } else { -1.0 };
|
||||
let scroll_y = SCROLL_LINES * scroll_direction;
|
||||
window.handle_input(PlatformInput::ScrollWheel(crate::ScrollWheelEvent {
|
||||
position,
|
||||
delta: ScrollDelta::Lines(Point::new(0.0, delta_x)),
|
||||
delta: ScrollDelta::Lines(Point::new(0.0, scroll_y as f32)),
|
||||
modifiers,
|
||||
touch_phase: TouchPhase::default(),
|
||||
touch_phase: TouchPhase::Moved,
|
||||
}));
|
||||
} else {
|
||||
log::warn!("Unknown button press: {event:?}");
|
||||
|
|
|
@ -70,7 +70,10 @@ actions!(
|
|||
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
||||
///Scroll multiplier that is set to 3 by default. This will be removed when I
|
||||
///Implement scroll bars.
|
||||
#[cfg(target_os = "macos")]
|
||||
const SCROLL_MULTIPLIER: f32 = 4.;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
const SCROLL_MULTIPLIER: f32 = 1.;
|
||||
const MAX_SEARCH_LINES: usize = 100;
|
||||
const DEBUG_TERMINAL_WIDTH: Pixels = px(500.);
|
||||
const DEBUG_TERMINAL_HEIGHT: Pixels = px(30.);
|
||||
|
|
Loading…
Reference in a new issue