Reverse horizontal scroll direction (#2105)

This commit is contained in:
Emil Ernerfeldt 2022-03-13 14:22:02 +01:00 committed by GitHub
parent 1c68be0631
commit 85baf79d17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 46 additions and 26 deletions

View file

@ -33,6 +33,7 @@ And please only add new entries to the top of this list, right below the `# Unre
- On X11, add mappings for numpad comma, numpad enter, numlock and pause. - On X11, add mappings for numpad comma, numpad enter, numlock and pause.
- On macOS, fix Pinyin IME input by reverting a change that intended to improve IME. - On macOS, fix Pinyin IME input by reverting a change that intended to improve IME.
- On Windows, fix a crash with transparent windows on Windows 11. - On Windows, fix a crash with transparent windows on Windows 11.
- **Breaking:**: Reverse horizontal scrolling sign in `MouseScrollDelta` to match the direction of vertical scrolling. A positive X value now means moving the content to the right. The meaning of vertical scrolling stays the same: a positive Y value means moving the content down.
# 0.26.0 (2021-12-01) # 0.26.0 (2021-12-01)

View file

@ -1,6 +1,6 @@
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;
use winit::{ use winit::{
event::{DeviceEvent, Event, WindowEvent}, event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
window::WindowBuilder, window::WindowBuilder,
}; };
@ -14,29 +14,41 @@ fn main() {
.build(&event_loop) .build(&event_loop)
.unwrap(); .unwrap();
println!(
r"
When using so called 'natural scrolling' (scrolling that acts like on a touch screen), this is what to expect:
Moving your finger downwards on a scroll wheel should make the window move down, and you should see a positive Y scroll value.
When moving fingers on a trackpad down and to the right, you should see positive X and Y deltas, and the window should move down and to the right.
With reverse scrolling, you should see the inverse behavior.
In both cases the example window should move like the content of a scroll area in any other application.
In other words, the deltas indicate the direction in which to move the content (in this case the window)."
);
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait; *control_flow = ControlFlow::Wait;
match event { match event {
Event::WindowEvent { event, .. } => match event { Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
_ => (), WindowEvent::MouseWheel { delta, .. } => match delta {
},
Event::DeviceEvent { event, .. } => match event {
DeviceEvent::MouseWheel { delta } => match delta {
winit::event::MouseScrollDelta::LineDelta(x, y) => { winit::event::MouseScrollDelta::LineDelta(x, y) => {
println!("mouse wheel Line Delta: ({},{})", x, y); println!("mouse wheel Line Delta: ({},{})", x, y);
let pixels_per_line = 120.0; let pixels_per_line = 120.0;
let mut pos = window.outer_position().unwrap(); let mut pos = window.outer_position().unwrap();
pos.x -= (x * pixels_per_line) as i32; pos.x += (x * pixels_per_line) as i32;
pos.y -= (y * pixels_per_line) as i32; pos.y += (y * pixels_per_line) as i32;
window.set_outer_position(pos) window.set_outer_position(pos)
} }
winit::event::MouseScrollDelta::PixelDelta(p) => { winit::event::MouseScrollDelta::PixelDelta(p) => {
println!("mouse wheel Pixel Delta: ({},{})", p.x, p.y); println!("mouse wheel Pixel Delta: ({},{})", p.x, p.y);
let mut pos = window.outer_position().unwrap(); let mut pos = window.outer_position().unwrap();
pos.x -= p.x as i32; pos.x += p.x as i32;
pos.y -= p.y as i32; pos.y += p.y as i32;
window.set_outer_position(pos) window.set_outer_position(pos)
} }
}, },

View file

@ -759,15 +759,23 @@ pub enum MouseScrollDelta {
/// Amount in lines or rows to scroll in the horizontal /// Amount in lines or rows to scroll in the horizontal
/// and vertical directions. /// and vertical directions.
/// ///
/// Positive values indicate movement forward /// Positive values indicate that the content that is being scrolled should move
/// (away from the user) or rightwards. /// right and down (revealing more content left and up).
LineDelta(f32, f32), LineDelta(f32, f32),
/// Amount in pixels to scroll in the horizontal and /// Amount in pixels to scroll in the horizontal and
/// vertical direction. /// vertical direction.
/// ///
/// Scroll events are expressed as a PixelDelta if /// Scroll events are expressed as a PixelDelta if
/// supported by the device (eg. a touchpad) and /// supported by the device (eg. a touchpad) and
/// platform. /// platform.
///
/// Positive values indicate that the content being scrolled should
/// move right/down.
///
/// For a 'natural scrolling' touch pad (that acts like a touch screen)
/// this means moving your fingers right and down should give positive values,
/// and move the content right and down (to reveal more things left and up).
PixelDelta(PhysicalPosition<f64>), PixelDelta(PhysicalPosition<f64>),
} }

View file

@ -193,9 +193,9 @@ pub(super) fn handle_pointer(
// Old seat compatibility. // Old seat compatibility.
match axis { match axis {
// Wayland vertical sign convention is the inverse of winit. // Wayland sign convention is the inverse of winit.
wl_pointer::Axis::VerticalScroll => y -= value as f32, wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32, wl_pointer::Axis::HorizontalScroll => x -= value as f32,
_ => unreachable!(), _ => unreachable!(),
} }
@ -216,9 +216,9 @@ pub(super) fn handle_pointer(
} else { } else {
let (mut x, mut y) = pointer_data.axis_data.axis_buffer.unwrap_or((0.0, 0.0)); let (mut x, mut y) = pointer_data.axis_data.axis_buffer.unwrap_or((0.0, 0.0));
match axis { match axis {
// Wayland vertical sign convention is the inverse of winit. // Wayland sign convention is the inverse of winit.
wl_pointer::Axis::VerticalScroll => y -= value as f32, wl_pointer::Axis::VerticalScroll => y -= value as f32,
wl_pointer::Axis::HorizontalScroll => x += value as f32, wl_pointer::Axis::HorizontalScroll => x -= value as f32,
_ => unreachable!(), _ => unreachable!(),
} }
@ -237,9 +237,9 @@ pub(super) fn handle_pointer(
.unwrap_or((0., 0.)); .unwrap_or((0., 0.));
match axis { match axis {
// Wayland vertical sign convention is the inverse of winit. // Wayland sign convention is the inverse of winit.
wl_pointer::Axis::VerticalScroll => y -= discrete as f32, wl_pointer::Axis::VerticalScroll => y -= discrete as f32,
wl_pointer::Axis::HorizontalScroll => x += discrete as f32, wl_pointer::Axis::HorizontalScroll => x -= discrete as f32,
_ => unreachable!(), _ => unreachable!(),
} }

View file

@ -693,8 +693,8 @@ impl<T: 'static> EventProcessor<T> {
delta: match xev.detail { delta: match xev.detail {
4 => LineDelta(0.0, 1.0), 4 => LineDelta(0.0, 1.0),
5 => LineDelta(0.0, -1.0), 5 => LineDelta(0.0, -1.0),
6 => LineDelta(-1.0, 0.0), 6 => LineDelta(1.0, 0.0),
7 => LineDelta(1.0, 0.0), 7 => LineDelta(-1.0, 0.0),
_ => unreachable!(), _ => unreachable!(),
}, },
phase: TouchPhase::Moved, phase: TouchPhase::Moved,
@ -774,10 +774,10 @@ impl<T: 'static> EventProcessor<T> {
event: MouseWheel { event: MouseWheel {
device_id, device_id,
delta: match info.orientation { delta: match info.orientation {
ScrollOrientation::Horizontal => {
LineDelta(delta as f32, 0.0)
}
// X11 vertical scroll coordinates are opposite to winit's // X11 vertical scroll coordinates are opposite to winit's
ScrollOrientation::Horizontal => {
LineDelta(-delta as f32, 0.0)
}
ScrollOrientation::Vertical => { ScrollOrientation::Vertical => {
LineDelta(0.0, -delta as f32) LineDelta(0.0, -delta as f32)
} }

View file

@ -1000,8 +1000,7 @@ extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
let state = &mut *(state_ptr as *mut ViewState); let state = &mut *(state_ptr as *mut ViewState);
let delta = { let delta = {
// macOS horizontal sign convention is the inverse of winit. let (x, y) = (event.scrollingDeltaX(), event.scrollingDeltaY());
let (x, y) = (event.scrollingDeltaX() * -1.0, event.scrollingDeltaY());
if event.hasPreciseScrollingDeltas() == YES { if event.hasPreciseScrollingDeltas() == YES {
let delta = LogicalPosition::new(x, y).to_physical(state.get_scale_factor()); let delta = LogicalPosition::new(x, y).to_physical(state.get_scale_factor());
MouseScrollDelta::PixelDelta(delta) MouseScrollDelta::PixelDelta(delta)

View file

@ -48,7 +48,7 @@ pub fn mouse_position_by_client(
} }
pub fn mouse_scroll_delta(event: &WheelEvent) -> Option<MouseScrollDelta> { pub fn mouse_scroll_delta(event: &WheelEvent) -> Option<MouseScrollDelta> {
let x = event.delta_x(); let x = -event.delta_x();
let y = -event.delta_y(); let y = -event.delta_y();
match event.delta_mode() { match event.delta_mode() {

View file

@ -1208,7 +1208,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
let value = (wparam >> 16) as i16; let value = (wparam >> 16) as i16;
let value = value as i32; let value = value as i32;
let value = value as f32 / WHEEL_DELTA as f32; let value = -value as f32 / WHEEL_DELTA as f32; // NOTE: inverted! See https://github.com/rust-windowing/winit/pull/2105/
update_modifiers(window, userdata); update_modifiers(window, userdata);