Hacker News new | ask | show | jobs
by sandreas 837 days ago
It isn't... You can see this in an open source JavaScript implementation of kinetic scrolling by Apple called PastryKit[3] using a magic number momentum * 0.9.

The problem is, that on modern Linux environments, there is no clear responsibility for where scroll handling code belongs. Especially Kinetic / Inertial scrolling is handled way different than in macOS.

There is libinput (for handling and redirecting input events)

There is the display server

There is the compositor

There is the window manager

There is the app layer (every App, like Firefox, Gimp,

Currently kinetic scrolling is implemented on the App layer, every app has to handle the scrolling events manually to provide kinetic scrolling. This is not the case in macOS... the kinetic scrolling / rubber banding is handled within the OS.

In my opinion, the scrolling code could belong into the compositor, so that not every app developer has to write code to handle the scrolling, but still prevent unwanted effects like kinetic scrolling transfer between windows. Additionally, the kinetic scrolling approach is not configurable in Gnome... some touchpads / screens are scrolling way to fast, some are too slow...

I filed an issue[1] on cosmic in hope they'll get it right, but I don't have too high hopes that this is of much interest. On Fedora it works ok-ish with a little hack[2] called libinput-config.

[1]: https://github.com/pop-os/cosmic-epoch/issues/204

[2]: https://gitlab.com/warningnonpotablewater/libinput-config.gi...

[3]: https://stackoverflow.com/questions/38619717/need-help-disse...

5 comments

Worth mentioning that before libinput, the synapse driver handled kinetic scroll very well IMO, but AIU the developers removed the device-specific coefficients and other parameters because they said it couldn't be tested and became a mess or something. I remember looking at my Linux (Wayland, gnome3) notebook in anticipation of physical pain, at which point I switched to Mac OS permanently. To this date, I still don't understand why Linux desktop developers had to throw everything away and valued their grand refactorings more than a working desktop, especially when absolutely no new desktop apps are being developed anyway, but I guess that's what you get with a "hobby" (= developer motivation rather than demand driven) OS after all.
While is may be true from a user perspective, this "kinetic scrolling simulation" was removed, because it could lead to unexpected behaviour.

Example: If you where scrolling in a window, the driver kept sending scroll events for a short time to simulate kinetic scrolling. Now, if you moved the cursor to another window, the other window started scrolling, because of the simulated events.

This is not the case on macOS. Changing window focus doesn't change the scrolling. So, while working from a user perspective (in my opionion this would have been better, than NO kinetic scrolling at all), technically, it is a bug / unsolvable behaviour :-), because this problem cannot be solved on the driver level - there is no reference to the current focussed "window" / active element.

That's probably the reason why they thought: This must be solved at App level, which was the worst decision they could make. Putting the effort on the shoulders of App developers instead of solving it at one place leads to so much wasted developer time, that could have been put into new features or solved issues. I was shocked about how nobody seemed to notice that.

However, they are not "hobby" at all. Peter Hutterer is awesome and he understands the problem very well - but as a single developer it's hard to convince a whole community, that partly does not even (want to) understand the problem. And he's responsible for libinput, not for the compositors - so it's clearly not his fault.

I think the problem lies in separated responsibilities. They are trying to keep the projects (driver, compositor, window manager) separated / independent, but in this case, the problem is spanning the whole stack.

> Now, if you moved the cursor to another window, the other window started scrolling, because of the simulated events.

This is such a trivial thing to fix, you just stop sending scroll events when the cursor moves.

Peter has done a great job on libinput for the most part, but he is 100% wrong about inertial scrolling (and button remapping, among a few other things).

> Peter has done a great job on libinput for the most part, but he is 100% wrong about inertial scrolling (and button remapping, among a few other things).

Maybe you're right. However, this should not about individual persons / projects... this is more about that I'm still uncertain, why so many experts cannot get this thing right by just working together finding a suitable solution :-) There must by more than one way of solving this.

I'd argue that he is right about the fact, that the "driver" (libinput) should not send "simulated" events, that are not really there. Whereas the cursor movement should defintely stop the scrolling behaviour, the driver is not the place to care about this, I think it is more a compositor / window manager thing, but I'm not an expert.

However, if he would implement an opt in solution (2 config options) for lets say:

  libinput.simulateKineticScrolling=1
  libinput.kineticScrollingSpeed=0.22
  
a lot of people would be really happy, but this probably is a really dirty hack.
> the "driver" (libinput) should not send "simulated" events

scrolling itself is a simulated event. So is any two-finger gesture that isn't directly represented as an affine transform from one pair of coordinates to another.

that the "driver" (libinput) should not send "simulated" events

As long as they are marked as being synthetic, why not?

If you mark them with a "this is a synthetic event" bit, the compositor/windowmanager has all the information it needs to decide whether or not to ignore the event (because, for example, the pointer moved out of one window and into another).

The driver generates the synthetic events, the compositor/windowmanager decides whether or not to drop them. Done.

Alt + Tab
Putting the effort on the shoulders of App developers instead of solving it at one place leads to so much wasted developer time, that could have been put into new features or solved issues. I was shocked about how nobody seemed to notice that.

However, they are not "hobby" at all. Peter Hutterer is awesome and he understands the problem very well - but as a single developer it's hard to convince a whole community

Wait what?

I'm pretty sure Hutterer was the one who pushed it into the App layer. He's the maintainer of libinput, and refused to do kinetic scroll within libinput (like the libsynapse driver did for X11). If he wanted to do it centrally in libinput there's nobody else to block him from doing that -- he can just do it.

> I'm pretty sure Hutterer was the one who pushed it into the App layer.

I'm not sure what he did and I'm not trying to do fingerpointing. I thought he just pushed it away from libinput stating that it's the wrong place to handle it and wanting to keep libinput as "clean" as possible - even if this might be a questionable argument in this case.

To answer one of your other comments...

> If you mark them with a "this is a synthetic event" bit, the compositor/windowmanager has all the information it needs to decide whether or not to ignore the event (because, for example, the pointer moved out of one window and into another).

Yeah, this would be one of the many possible partial solutions. Don't get me wrong, I'm totally fine with this suggestion, but let's think that through:

libinput implements "simulated" events algorithm for intertial scrolling. It also would probably need a config setting for "speed" or "intensity". Nevertheless, this would not help without changes in at least one of the other layers I mentioned (Compositor, Window Manager, Apps) to either ignore or handle these events. In my opinion the App layer is the wrong place, because so every App developer / maintainer who want's to support inertial scrolling had to implement it AGAIN for his personal app which would create a tremendous amount of additional effort and different implementations acting differently. Not a great user experience...

So, the (additional) implementation has to be done somewhere between libinput and the App layer, which means either compositor or window manager.

Now, if an implementation in one of these layers is inevitable to get it working, why should it be implemented in libinput? Issues would spread over two projects, instead of one and getting pushed back and forth. This is of course my personal opinion.

Instead NOBODY implemented it and App developers and Framework Developers (QT, GTK, etc.) put in the effort to workaround this problem. That just feels wrong to me.

I wish at least one project just had shown good will to do it, in my opinion it would have been better to implement it everywhere (with optional disable) instead of nowhere, but I think it's just a too heated topic to solve it easily :-)

this would not help without changes in at least one of the other layers I mentioned (Compositor, Window Manager, Apps) to either ignore or handle these events

Yes, certainly. But it's basically one or two lines of code with zero configuration knobs:

    if (ev->is_synthetic && focus_changed_since_last_nonsynthetic) return;
Compare this to the current state of affairs, where every toolkit/compositor/app has to reimplement momentum scrolling on its own. That is multiple pages of fairly tricky code and several configuration knobs -- all of them replicated (differently) in each different thing that sits on top of libinput.

why should it be implemented in libinput?

Because libinput is the "narrow waist" in the input stack.

Doing this in libinput puts all the new configuration knobs, and all but one or two lines of code ("if focus changed then drop") in the one place where they can live without having to be duplicated.

Any higher up the stack and you end up replicating this functionality.

Issues would spread over two projects, instead of one and getting pushed back and forth.

I don't think so. If the problem is that a marked-as-synthetic event is/isn't being dropped when it shouldn't/should, that's the problem of some layer above libinput. Any other problem is libinput's. I know nobody wants to own these problems, but we can't make them disappear -- somebody has to own them. If they are owned at or below the libinput layer we can fix each bug once and be done. If we fix them anywhere above the libinput layer we will end up having the same bugs occur in multiple independent implementations and they will have to get fixed independently.

in my opinion it would have been better to implement it everywhere (with optional disable) instead of nowhere

I don't agree with this either. This "multiple reimplementations of the exact same thing" is becoming entrenched! We could get stuck in this situation, permanently. This isn't a question like "what should a titlebar look like" where different toolkits can legitimately have different opinions about it.

In my opinion the App layer is the wrong place

I agree.

Some part of this has to be done somewhere at-or-above the compositor layer, since those are the only layers that are aware of focus changes. Unfortunately there seems to be no traction for e.g. wayland to require that all compositors do this. So the replication gets amplified even further by pushing it up into every compositor or toolkit. That's why it's so important to limit the size of the bit that gets pushed up the stack to being two lines of code.

Perhaps a viable compromise would be to insert a new layer above libinput. For argument's sake, call it "libgesture" (*). It's responsible for consuming libinput events and emitting synthetic events like momentum scrolling. It would have exactly the same API as libinput, except events would have an additional `is_synthetic` field. I've actually built something similar to this (but at the kernel evdev level) for my own use.

Perhaps that would make everybody happy.

(*) This is unrelated to `libei` -- I have this sinking feeling that many apps (especially chromium) will reject any event that smells "emulated" to them "because muh bots" or something stupid like that. Trying to use libei for this is likely to backfire once the chromium devs decide that "emulated" means "bad for Web Environment Integrity". The indicator for gesture-synthesized events like momentum scrolling really needs to be completely separate from any marker indicating that the event was in any way emulated.*

Very convincing pitch

> Perhaps a viable compromise would be to insert a new layer above libinput.

Since I think this probably will never get integrated in libinput, this might be the best solution for everyone - also opt in. Unfortunately I don't think anyone is ever gonna implement it in a way that everyone can agree on.

However, if someone would implement patches for libinput as well as e.g. mutter that work flawlessly, are documented and gain acceptance, this would put a lot of pressure on all other projects to integrate this.

If you have such patches and they are open source, you surely would have my support. I would definetely use it...

> I filed an issue[1] on cosmic in hope they'll get it right, but I don't have too high hopes that this is of much interest.

That's insane but you're right. Firefox on Ubuntu had awful trackpad scrolling 10 years ago and it's still bad. How do you make an OS where the main pointing device on half of the market sucks and assign that low priority?

> How do you make an OS where the main pointing device on half of the market sucks and assign that low priority?

Because Linux isn't "an OS". It's a kernel made by one set of developers, combined with a bunch of operating systems made by a second set of developers, which pick and choose compositors/window managers/etc. often made by a third set of developers. Each of these sets of developers are pretty good at solving bugs that live entirely in their "domain", but when there's an issue which crosses these interface boundaries, there is nobody to "assign priority", never mind actually work to fix it.

(Not to mention, systemd demonstrates that trying to solve these kinds of pan-system problems earns you little gratitude but tons of vociferous hatred, so people are not inclined to do it.)

That's why I mentioned Ubuntu; if anyone has incentive and resources to contribute to all these projects and get smooth scrolling working it's Canonical. If _they_ can't, I guess that means the whole community is screwed on that side. Maybe it's going to work 20 years from now, when we've moved on from trackpads to AI voice interfaces.
In 20 years there will be so much baggage to fix that we’ll be at the same point we are now “ugh but you have to rewrite everything from the ground up and update so many programs…”
That's what I think is the problem. And exactly the reason I thought cosmic could get this right. There is a lot of promising decisions in this project, but maybe it'll take a while to work as expected :-)
I've been using Firefox on Ubuntu from 2009 to 2022, 08.10 to 22.04, then switched to Debian, but I never noticed any problem. I always used X11, a laptop, touchpad and two finger scrolling. Maybe is it a Wayland thing? Or it is very subjective.
Noticing a problem and having smooth / improved scrolling are two different things. I think you can only notice the difference if you've ever used a macOS device with a trackpad for more than 2 weeks and then switched back to either Windows or Linux. It's just feels HORRIBILE for some people (like me).

The interesting thing: Some Distributions have smooth scrolling (or interial scrolling / kinetic scrolling) by default (Fedora, Ubuntu) and some don't. Those who have enabled it, have no speed setting, so most of the time it's way to fast. I tinkered around a very long time with libinput-config to get it right and now it's acceptable. But it is still waaay better on macOS.

It is NOT a hardware issue though. I tried "hackintosh" on my T460s, and the touchpad experience is nearly as good as on a MacBook, so it is mostly software / OS.

Smooth scrolling is something completely different, having to do with mousewheels.

Please don't perpetuate the awful terminological confusion around this issue.

Try enabling "XINPUT2" in firefox, you'd be surprised what a difference it makes
I gave it a try. The difference is that XINPUT2 scroll has inertia: I start scrolling, remove the fingers from the touchpad and it keeps scrolling for a while. If I want to stop when I see something interesting I have to click or it will scroll away. That adds an extra action that must performed at the right time. I don't think I like that because this is not a videogame and Firefox is not supposed to challenge my abilities. I prefer the current behavior: it scrolls until I stop sliding my fingers on the touchpad. Then I have to move them up to the top of the touch pad and start again but I can scroll all the front page of HN in a single motion and it gives me time to check what I'm looking at, especially on longer pages (this comment thread.)

Anyway, it's nice to have different settings that suit different people.

Try it for some longer time. Scrolling on Macbook becomes subconscious. I don't think about it anymore. I don't even notice that I am moving my fingers. The scroll pane just moves where I want it to move. Simulating the behavior of physical objects allows our minds to reuse what it learned about the physical world. That is imho a very powerful user interface metaphor. But beware, this is just an anecdote.
There are two other problems I thought about later:

1) It's too fast. My Android phone also scrolls like XINPUT2 but it's got a smaller acceleration. But maybe it's what you say about getting used to it.

2) That would work in Firefox and every other window would still scroll in the other way. That's really bad and works against getting used to a specific scrolling behavior. I don't get it: the scrolling behavior should be managed at a level below every application. All the scrollbars should behave in only one way, except the random application that implements its own logic because of some important reason. So I would expect a system wide setting for XINPUT2 or traditional scrolling.

> I start scrolling, remove the fingers from the touchpad and it keeps scrolling for a while

If you want it to not scroll further you need to stop scrolling before lifting you fingers. That should be pretty easy to get used to.

The pointing device doesn't suck, just the defaults (and probably the graphical configuration tools - I always use CLI and editing config files but most open-source GUIs are horrible). If you're willing to spend 5-10 minutes tweaking, you can get exactly the same performance or better just by playing around with some settings.
You're right, after tinkering around I also found settings that are ok. But that's only part of it. There are so many things that just work better on macOS, e.g. the "tap-to-stop" or "vertical-scrolling".

I also think that the App developers should not have to shoulder this. App developers have way better things to do than care about touchpad events... like fixing issues and developing new features. I don't see where smooth scrolling should be an App feature...

That's only going to affect part of your apps though. Last I checked, Firefox on Ubuntu finally had a kind of pixel-perfect scrolling, but it wasn't smooth and didn't keep momentum if you let go of the trackpad while scrolling fast. That just feels bad, even after getting used to it.

And Qt apps will scroll differently than the GNOME project's apps which will scroll differently than other Gtk apps. It really feels disorganized and unfinished.

This doesn't help me. I have zero confidence I can do any of this.
> There is the display server

> There is the compositor

> There is the window manager

What kind of Schrodinger Way11 world is that? X11 has display server and window manager (and window manager doesn't deal with mouse movement), and Wayland has a compositor.

I just meant to point out the complexity of the transition Linux has gone through... The transition from X11 to Wayland is still a thing and most Environments / Window Managers still use code from both technologies.

However, you are right, there is no such thing like display server AND compositor.

> and window manager doesn't deal with mouse movement

And that's causing one of the problems I described above, when changing window focus while scrolling. The driver just sends scrolling events, regardless of the window focus, so it keeps scrolling, when you trying to "simulate" kinetic scrolling.

Slight correction: macOS handles the kinetic scrolling, but rubber banding is handled by the app itself.
Oh, that was new to me. Thanks...
This explains a lot. Thanks so much! This is a rabbit hole I didn’t want to go in a few years back. Some people would say they had issues, others didn’t. Would’ve taken me a lot of time to figure out that we all may be talking about different DEs, apps, etc.