Repository navigation
Shift-mousewheel for horizontal scroll #75180
Description
Activity
- addedframeworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.a: fidelityMatching the OEM platforms betterMatching the OEM platforms bettera: desktopRunning on desktopRunning on desktopP2Important issues not at the top of the work listImportant issues not at the top of the work list
on Feb 2, 2021 What OS were you testing? Unless I'm misremembering, macOS at least automatically translates this to horizontal scroll events at the OS framework level, so it should work there. I'm not sure how much Linux and Windows do for us.
Reacted by Renan and Rares VancaI tested on Linux and Web.
- addedf: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.
on Feb 2, 2021 CC @Piinks
I think this will be easy to support, we should check the keyboard state here and adjust accordingly:
double _pointerSignalEventDelta(PointerScrollEvent event) {
cc @dkwingsmt who has a really big keyboard revamp underway. :)Reacted by Jared FieldsGiven that the behavior varies by OS, I would actually recommend implementing this in the embeddings rather than the framework.
Reacted by Kate Lovett- addedengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.
on Feb 2, 2021 Makes sense. :)
Tested on MacOS, it does not appear to be supported on that platform either.Update: Magic mouse - no, stepped scroll wheel - yes
That's odd; macOS should definitely be sending the view horizontal scroll events.
Were you testing with a mouse or a trackpad?
That's odd; macOS should definitely be sending the view horizontal scroll events.
Were you testing with a mouse or a trackpad?
Just checked against another mouse, I am guessing the magic mouse is considered a trackpad. Using a stepped wheel mouse it does work. Updated comment above.
Given that the behavior varies by OS, I would actually recommend implementing this in the embeddings rather than the framework.
What if someone wants shift-mousewheel to do something else? Implementing it in the framework seems consistent with our usual approach of making everything configurable.
Reacted by Jared Fields, Yegor and Erik080629 remaining items
I agree, I much preferred doing this in the framework to allow customization, but since we don't control the input from Mac (it appears to flip axes itself when shift is applied before it reaches Flutter), do we add complexity to the framework by re-flipping the signal, or assume the signal from the engine is wrong, or right based on which platform we are on? Or change it in the engine back to the original axis before sending it to the framework?
I can see it causing a lot of confusion if it is not consistent across platforms, after all, it already is. 😂
It would still be very easy to do this in the framework (read: here is a proposal PR I just whipped up #115610) - but adding a workaround for Mac already handling it felt like code smell.
I'd love to fix this finally if we can agree on an approach one way or the other. I think the lack of a clear solution is why this has not been resolved yet. However, many of the concerns above are no longer an issue because trackpad has its own, separate handling now, which is how we ended up circling back to it.
I would very much like to get support for horizontal scrolling on Linux and Windows into the next stable release. It really seems embarrassing that we don't have support for horizontal scrolling. So whatever we do, we should at least implement a first pass at it quickly.
Or change it in the engine back to the original axis before sending it to the framework?
I dislike that macOS is determining our implementation choice here. As Kate suggests, we could flip the direction back on macOS before we send it if shift is down. Then the values coming from the embedder could be consistent across platforms, and we could check in the framework for the shift being down. It might be more complicated than that, though, since we'd also probably have to account for "natural" scroll direction settings being different for horizontal and vertical and flip the sign too in the appropriate cases.
Reacted by Manki KimIs shift-scroll a standard pattern across all OSes? If so, (and I think that's the case currently?) then agreed it'd be nice for this to happen in the framework. We do other event normalisation type tasks in the embedders; there's probably no reason we couldn't do the same for macOS to undo its auto-horizontalisation in the embedder before sending the events to the framework.
Is there anywhere I can read more about what macOS is doing? What exactly is being translated, by whom, from what to what?
I do not know a whole lot about it, but this is what I found in the engine as far as how the scrolling input is bubbled up on Mac: https://github.com/flutter/engine/blob/aeb2cd95b19dfab26bc4ab21137c62783e523d69/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm#L646
We aren't checking in the engine if the shift key is down, so the incoming input has already been flipped from dy to dx.
We receive scroll events via
NSScrollWheelEvents via-[NSView scrollWheel]. These are logical scroll events, not raw hardware events, so as discussed earlier here, if someone holds down shift and scrolls the scroll wheel on a standard mouse, what we get is horizontal scroll deltas. If they've enabled the system setting for reverse scroll, that's already been applied as well.If we want to do everything in the framework instead, we'd either need to:
- find another API that gives us untranslated events (if there is such a thing), or
- attempt to reverse-engineer the behavior and reverse it (if we have enough information)
If we want to do the latter, we would need to be very careful to test a variety of edge cases. E.g., what if someone has a device like a Mighty Mouse that actually has physical horizontal scrolling, holds down shift, and scrolls the ball/wheel horizontally?
We'd also need to make sure that we're either continuing to honor system settings like reverse direction at the embedder level ourselves, or plumbing those into the framework to honor in the framework.
If the system is sending us logical "scroll delta" events, are those distinguishable from hardware "mousewheel + shift" events? I think it would be fine to honour logical events from the system on systems that give those to us, while honoring hardware events on those that do not. The idea is to do the best we can on each platform.
The scroll event system I added when bringing up scroll support initially on desktop doesn't distinguish, but we could potentially add more metadata to the scroll events at the embedder.h level and have each embedding tag the events accordingly.
Right to be clear I mean does the OS distinguish. The embedder itself should as much as possible just pass through the OS data as completely as possible while coercing it into our protocol (so e.g. making sure down events are matched by up events and so on). This may indeed mean adding additional metadata to our events to be able to distinguish the kind of event we get from one platform from those we get on another.
It would be nice if it did add some of the metadata: while working on the Time Picker, I realized that I can "scroll" the dial on the time picker, because a two-finger scroll is considered a drag, just with two fingers: the scroll gesture just adds to the delta, making for a weird interaction. If I knew whether it was part of a scroll or not, I could filter those drags out.
Right to be clear I mean does the OS distinguish.
Right now we have no mechanism in the macOS embedding to receive anything other than preprocessed logical be deltas, so there's nothing to distinguish between.
As mentioned above I don't know offhand if there are other (e.g., CG-level) APIs for anything else.
that sounds about par for the course on mac. But in general that's not unusual. We have this situation with the keyboard APIs too, where each platform does some preprocessing before the embedder does it, and the embedders do their best to provide a coherent unopinionated view of the keyboard so that the framework can then do the best thing on each platform. When you have the precise platform-specific semantic, you pass that through; when you don't, you pass in the ground truth, and the framework implements the semantic directly if available and otherwise does the platform-specific thing with the ground truth.
Reacted by RenanThis thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.- locked as resolved and limited conversation to collaborators
on Mar 3, 2023
On desktop, shift+mousewheel usually means "scroll horizontally". We don't seem to support this.