Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reverse horizontal scroll direction #2105

Merged
merged 14 commits into from
Mar 13, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- 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)

Expand Down
30 changes: 21 additions & 9 deletions examples/mouse_wheel.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use simple_logger::SimpleLogger;
use winit::{
event::{DeviceEvent, Event, WindowEvent},
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
Expand All @@ -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 the 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)
}
},
Expand Down
12 changes: 10 additions & 2 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<f64>),
}

Expand Down
12 changes: 6 additions & 6 deletions src/platform_impl/linux/wayland/seat/pointer/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(),
}

Expand All @@ -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!(),
}

Expand All @@ -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!(),
}

Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -693,8 +693,8 @@ impl<T: 'static> EventProcessor<T> {
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,
Expand Down
3 changes: 1 addition & 2 deletions src/platform_impl/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,8 +1002,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)
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/web/web_sys/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn mouse_position_by_client(
}

pub fn mouse_scroll_delta(event: &WheelEvent) -> Option<MouseScrollDelta> {
let x = event.delta_x();
let x = -event.delta_x();
let y = -event.delta_y();

match event.delta_mode() {
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,7 @@ unsafe fn public_window_callback_inner<T: 'static>(

let value = (wparam >> 16) as i16;
let value = value as i32;
let value = value as f32 / winuser::WHEEL_DELTA as f32;
let value = -value as f32 / winuser::WHEEL_DELTA as f32;

update_modifiers(window, userdata);

Expand Down