Repository: iced-rs/iced (language: rust)

Issue:
Cannot use mousewheel without shift to scoll a horizontal-only scrollable.
### Is there an existing issue for this?

- [X] I have searched the existing issues.

### Is this issue related to iced?

- [X] My hardware is compatible and my graphics drivers are up-to-date.

### What happened?

I am working on an applicaiton where I have two splits, one scrolling horizontally and one vertically:

![image](https://github.com/iced-rs/iced/assets/21365711/4ac3375f-0c71-47b9-9770-0be4138bc593)

I can scroll the vertical one with the mousewheel just fine, but not the horizontal one. It demands I hold down shift, even though there's no vertical scrollbal present (the scrollable is Horizontal, not Both, so it can only scroll in the one direction anyway). I don't believe I am able to change this behaviour.

### What is the expected behavior?

Shift should be needed only when both scrollbars are present. Otherwise, scrollwheel should just scroll.
Alternatively, I should be able to specify whether I want shift scrolling on a Horizontal scrollable.

### Version

crates.io release

### Operating System

Windows

### Do you have any log output?

_No response_
Cannot use mousewheel without shift to scoll a horizontal-only scrollable.
### Is there an existing issue for this?

- [X] I have searched the existing issues.

### Is this issue related to iced?

- [X] My hardware is compatible and my graphics drivers are up-to-date.

### What happened?

I am working on an applicaiton where I have two splits, one scrolling horizontally and one vertically:

![image](https://github.com/iced-rs/iced/assets/21365711/4ac3375f-0c71-47b9-9770-0be4138bc593)

I can scroll the vertical one with the mousewheel just fine, but not the horizontal one. It demands I hold down shift, even though there's no vertical scrollbal present (the scrollable is Horizontal, not Both, so it can only scroll in the one direction anyway). I don't believe I am able to change this behaviour.

### What is the expected behavior?

Shift should be needed only when both scrollbars are present. Otherwise, scrollwheel should just scroll.
Alternatively, I should be able to specify whether I want shift scrolling on a Horizontal scrollable.

### Version

crates.io release

### Operating System

Windows

### Do you have any log output?

_No response_


Discussion / hints:
What is the state of the art here? The Web does not implement this.
Yeah, horizontal scrolls are pretty rare, they don't show up in windows explorer anymore, terminals, most apps honestly. They're really not developed/looked at much.

The web does not implement this and that's been a problem for ages. Whenever you need to actually make a left/right moving menu, it creates a lot of friction, since web/app navigation is pretty much mouse only. Throwing in a shift key suddenly makes you stop moving when you expect to. Most people don't even know you can do that.

Hence why by now, everyone does little "scroll buttons" that jump x items left/right, and/or they manually implement swipe controls. You've probably seen them all round, the "display 3 elements and swipe/press the arrow on the side to keep scrolling through the next ones" is very common.

For my usecase, that really isn't good enough. I have a section of my app that is exclusively horizontally scrolled by design. I need to be fast and frictionless, and still usable without a hand on the keyboard.

I don't think most people use horizontal scrolls much, so I don't think this would impact people negatively (if at all). For the few that do, it would make the standard of mouse-only navigation a lot smoother. Though if the need arises, at worst we should be able to choose whether we want the shift modifier (I myself don't see why you ever would).
What is the state of the art here? The Web does not implement this.
Yeah, horizontal scrolls are pretty rare, they don't show up in windows explorer anymore, terminals, most apps honestly. They're really not developed/looked at much.

The web does not implement this and that's been a problem for ages. Whenever you need to actually make a left/right moving menu, it creates a lot of friction, since web/app navigation is pretty much mouse only. Throwing in a shift key suddenly makes you stop moving when you expect to. Most people don't even know you can do that.

Hence why by now, everyone does little "scroll buttons" that jump x items left/right, and/or they manually implement swipe controls. You've probably seen them all round, the "display 3 elements and swipe/press the arrow on the side to keep scrolling through the next ones" is very common.

For my usecase, that really isn't good enough. I have a section of my app that is exclusively horizontally scrolled by design. I need to be fast and frictionless, and still usable without a hand on the keyboard.

I don't think most people use horizontal scrolls much, so I don't think this would impact people negatively (if at all). For the few that do, it would make the standard of mouse-only navigation a lot smoother. Though if the need arises, at worst we should be able to choose whether we want the shift modifier (I myself don't see why you ever would).

Fix patch:
diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs
index 47953741b0..c20893403e 100644
--- a/widget/src/scrollable.rs
+++ b/widget/src/scrollable.rs
@@ -706,15 +706,29 @@ where
 
                 let delta = match delta {
                     mouse::ScrollDelta::Lines { x, y } => {
-                        // TODO: Configurable speed/friction (?)
-                        let movement = if !cfg!(target_os = "macos") // macOS automatically inverts the axes when Shift is pressed
-                            && state.keyboard_modifiers.shift()
-                        {
-                            Vector::new(y, x)
-                        } else {
+                        let is_shift_pressed = state.keyboard_modifiers.shift();
+
+                        // macOS automatically inverts the axes when Shift is pressed
+                        let (x, y) =
+                            if cfg!(target_os = "macos") && is_shift_pressed {
+                                (y, x)
+                            } else {
+                                (x, y)
+                            };
+
+                        let is_vertical = match self.direction {
+                            Direction::Vertical(_) => true,
+                            Direction::Horizontal(_) => false,
+                            Direction::Both { .. } => !is_shift_pressed,
+                        };
+
+                        let movement = if is_vertical {
                             Vector::new(x, y)
+                        } else {
+                            Vector::new(y, x)
                         };
 
+                        // TODO: Configurable speed/friction (?)
                         movement * 60.0
                     }
                     mouse::ScrollDelta::Pixels { x, y } => Vector::new(x, y),


Test patch: