From 85baf79d179128614dd450c171524f04bdd06f4d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 13 Mar 2022 14:22:02 +0100 Subject: [PATCH] Reverse horizontal scroll direction (#2105) --- CHANGELOG.md | 1 + examples/mouse_wheel.rs | 30 +++++++++++++------ src/event.rs | 12 ++++++-- .../linux/wayland/seat/pointer/handlers.rs | 12 ++++---- .../linux/x11/event_processor.rs | 10 +++---- src/platform_impl/macos/view.rs | 3 +- src/platform_impl/web/web_sys/event.rs | 2 +- src/platform_impl/windows/event_loop.rs | 2 +- 8 files changed, 46 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ea561ee..9ad24fcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 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. +- **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) diff --git a/examples/mouse_wheel.rs b/examples/mouse_wheel.rs index e61b64af..105944a3 100644 --- a/examples/mouse_wheel.rs +++ b/examples/mouse_wheel.rs @@ -1,6 +1,6 @@ use simple_logger::SimpleLogger; use winit::{ - event::{DeviceEvent, Event, WindowEvent}, + event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; @@ -14,29 +14,41 @@ fn main() { .build(&event_loop) .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| { *control_flow = ControlFlow::Wait; match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - _ => (), - }, - Event::DeviceEvent { event, .. } => match event { - DeviceEvent::MouseWheel { delta } => match delta { + WindowEvent::MouseWheel { delta, .. } => match delta { winit::event::MouseScrollDelta::LineDelta(x, y) => { println!("mouse wheel Line Delta: ({},{})", x, y); let pixels_per_line = 120.0; let mut pos = window.outer_position().unwrap(); - pos.x -= (x * pixels_per_line) as i32; - pos.y -= (y * pixels_per_line) as i32; + pos.x += (x * pixels_per_line) as i32; + pos.y += (y * pixels_per_line) as i32; window.set_outer_position(pos) } winit::event::MouseScrollDelta::PixelDelta(p) => { println!("mouse wheel Pixel Delta: ({},{})", p.x, p.y); let mut pos = window.outer_position().unwrap(); - pos.x -= p.x as i32; - pos.y -= p.y as i32; + pos.x += p.x as i32; + pos.y += p.y as i32; window.set_outer_position(pos) } }, diff --git a/src/event.rs b/src/event.rs index 6660e006..5afb0ebf 100644 --- a/src/event.rs +++ b/src/event.rs @@ -759,15 +759,23 @@ pub enum MouseScrollDelta { /// Amount in lines or rows to scroll in the horizontal /// and vertical directions. /// - /// Positive values indicate movement forward - /// (away from the user) or rightwards. + /// Positive values indicate that the content that is being scrolled should move + /// right and down (revealing more content left and up). LineDelta(f32, f32), + /// Amount in pixels to scroll in the horizontal and /// vertical direction. /// /// Scroll events are expressed as a PixelDelta if /// supported by the device (eg. a touchpad) and /// 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), } diff --git a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs index 56c64799..c5e605fe 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs @@ -193,9 +193,9 @@ pub(super) fn handle_pointer( // Old seat compatibility. 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::HorizontalScroll => x += value as f32, + wl_pointer::Axis::HorizontalScroll => x -= value as f32, _ => unreachable!(), } @@ -216,9 +216,9 @@ pub(super) fn handle_pointer( } else { let (mut x, mut y) = pointer_data.axis_data.axis_buffer.unwrap_or((0.0, 0.0)); 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::HorizontalScroll => x += value as f32, + wl_pointer::Axis::HorizontalScroll => x -= value as f32, _ => unreachable!(), } @@ -237,9 +237,9 @@ pub(super) fn handle_pointer( .unwrap_or((0., 0.)); 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::HorizontalScroll => x += discrete as f32, + wl_pointer::Axis::HorizontalScroll => x -= discrete as f32, _ => unreachable!(), } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 17f9436f..be269ce3 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -693,8 +693,8 @@ impl EventProcessor { delta: match xev.detail { 4 => LineDelta(0.0, 1.0), 5 => LineDelta(0.0, -1.0), - 6 => LineDelta(-1.0, 0.0), - 7 => LineDelta(1.0, 0.0), + 6 => LineDelta(1.0, 0.0), + 7 => LineDelta(-1.0, 0.0), _ => unreachable!(), }, phase: TouchPhase::Moved, @@ -774,10 +774,10 @@ impl EventProcessor { event: MouseWheel { device_id, delta: match info.orientation { - ScrollOrientation::Horizontal => { - LineDelta(delta as f32, 0.0) - } // X11 vertical scroll coordinates are opposite to winit's + ScrollOrientation::Horizontal => { + LineDelta(-delta as f32, 0.0) + } ScrollOrientation::Vertical => { LineDelta(0.0, -delta as f32) } diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 192e4936..7046e458 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -1000,8 +1000,7 @@ extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) { let state = &mut *(state_ptr as *mut ViewState); let delta = { - // macOS horizontal sign convention is the inverse of winit. - let (x, y) = (event.scrollingDeltaX() * -1.0, event.scrollingDeltaY()); + let (x, y) = (event.scrollingDeltaX(), event.scrollingDeltaY()); if event.hasPreciseScrollingDeltas() == YES { let delta = LogicalPosition::new(x, y).to_physical(state.get_scale_factor()); MouseScrollDelta::PixelDelta(delta) diff --git a/src/platform_impl/web/web_sys/event.rs b/src/platform_impl/web/web_sys/event.rs index fb6c52d3..7dfbd8cf 100644 --- a/src/platform_impl/web/web_sys/event.rs +++ b/src/platform_impl/web/web_sys/event.rs @@ -48,7 +48,7 @@ pub fn mouse_position_by_client( } pub fn mouse_scroll_delta(event: &WheelEvent) -> Option { - let x = event.delta_x(); + let x = -event.delta_x(); let y = -event.delta_y(); match event.delta_mode() { diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 7cb36f95..c0366ecb 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1208,7 +1208,7 @@ unsafe fn public_window_callback_inner( let value = (wparam >> 16) as i16; 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);