After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 774430 - Scrolling with touchpad combines smooth and rough movement
Scrolling with touchpad combines smooth and rough movement
Status: RESOLVED OBSOLETE
Product: gtk+
Classification: Platform
Component: .General
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
: 792151 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2016-11-14 20:31 UTC by Egmont Koblinger
Modified: 2018-05-02 17:46 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Egmont Koblinger 2016-11-14 20:31:47 UTC
Forwarding from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=843642:

"When scrolling in Gnome Terminal using a high resolution method like two-finger
scroll on a touchpad or button scroll with a trackpoint, for every few lines of
smooth movement, there is a jump of another few lines. The expected behaviour
would be one or the other, preferably smooth scrolling, but not both.

I speculate that Gnome Terminal reacts to both real XInput 2.1 scroll events and
emulated button 4-7 events.

[snip]
ii  gnome-terminal-data                          3.22.0-3
ii  libgtk-3-0                                   3.22.2-1
ii  libvte-2.91-0                                0.46.0-1"

Also the same as https://sourceforge.net/p/roxterm/bugs/127/:

"GTK3's smooth scrolling (which is available on e.g. touchpads) causes the view to jump.

Every 5 lines that are scrolled smoothly, it jumps ahead an additional 4-5 lines. i.e. the progression is 1-1-1-1-4-1-1-1-1-4 which is not very smooth at all."
Comment 1 Egmont Koblinger 2016-11-14 20:36:09 UTC
I could reproduce this behavior in roxterm with vte up to (excluding) commit 0612f40 (vte-0.43-ish, bug 734920: use input-only window).

I could never and still cannot reproduce this behavior in gnome-terminal.

I use my laptop's touchpad all the time with two-finger scrolling, I don't have a standard mouse / trackball / anything else.
Comment 2 Egmont Koblinger 2016-11-14 20:43:26 UTC
Copying over from the roxterm bug, to keep it all at one place:

I played a bit with 0.42 ./configure --enable-debug; followed by VTE_DEBUG=events roxterm.

vte_terminal_scroll(), which is a static method and is only used when being assigned to widget_class->scroll_event, is usually being called with event->direction being GDK_SCROLL_SMOOTH (that's okay), and is also sometimes being called with GDK_SCROLL_UP/DOWN which is totally mysterious to me. The latter one does not necessarily occur at the same time when a SMOOTH scroll event actually happens to scroll by a line.

> [someone else] I suspect that smooth scrolling is activated in parallel with regular scrolling.

Yup, it seems so. But why, and whose fault is it???
Comment 3 Egmont Koblinger 2016-11-14 20:52:42 UTC
Checking the obvious: scroll_event's handler always returns TRUE. So it's not that Gtk+ calls it again with the rough version because with the smooth coordinates it reported it didn't handle them.
Comment 4 Egmont Koblinger 2016-11-15 10:14:55 UTC
Random thoughts:

- Seems like a really tricky, hard to catch bug, with a lots of seemingly independent things making a difference:

 -- Input-only window makes a difference;

 -- gnome-terminal vs. roxterm makes a difference;

 -- does not occur to all users. In fact, smooth scrolling feature has been there for 3 years now (bug 710426 / commit 7efb04f) and we've only seen 2 reports of this obviously freaking annoying behavior. This suggests to me that the bug only occurs for a tiny fraction of users;

 -- so probably it depends on a certain version of some lib, or a certain user or system configuration, maybe the touchpad driver (synaptics vs. evdev vs. mouse), maybe even the hardware;

 -- reminder for myself: I've just switched to a new laptop, I should re-check if the behavior with vte-0.42/0.44 + roxterm is still the same for me.

- This really sounds like a Gtk+ or X11 bug to me, accidentally triggered by the constellation of some irrelevant things in vte and roxterm/g-t: vte should not receive the non-smooth events at all. Should we reassign to Gtk+ to see what they say?

- We _could_ easily work it around in vte: after seeing a smooth event we could ignore the subsequent one or two non-smooth events (maybe even with an expiration time). The only minor drawback would be is if that if the user switches between a touchpad and a mouse, the first one or two mouse wheel scrolls would be swallowed. That being said, I'd strongly prefer not to have this nasty workaround in vte and get the actual bug fixed.
Comment 5 Egmont Koblinger 2016-11-15 10:39:34 UTC
So... brand new laptop, brand new Yakkety installation, brand new Unity 7 (I did not migrate my previous configs). roxterm and roxterm-data installed from Xenial repo.

Roxterm's behavior is still the same. The faulty behavior is reproducible up to (excluding) the "use input-only window" vte commit.
Comment 6 Egmont Koblinger 2016-11-15 21:20:03 UTC
Reassigning... Gtk+ folks and Carlos, could you please take a look?
Comment 7 Carlos Garnacho 2016-11-16 13:08:18 UTC
I can't reproduce with neither gnome-terminal nor roxterm, running Fedora here.

But this is how scroll events (are supposed to) work:

- Xserver reports both smooth and discrete events, for compatibility with old clients. "xinput test-xi2" can be used to see this behavior. Depending on the device being used, there will be an "is emulated" flag set on the events that are made up out of the other kind.

- In GDK, your X11 toplevel window listens to both sets of events, and propagates both, but preserving the "is emulated" flag
  https://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkdevicemanager-xi2.c#n1654
  https://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkdevicemanager-xi2.c#n1535

- In GDK client-side windows code, depending on the event mask of the window beneath the pointer (the input-only window in this case), one set of events or the other will be discarded.
  https://git.gnome.org/browse/gtk+/tree/gdk/gdkwindow.c#n8387
  Note that if the discrete scroll events are not emulated, they will be propagated anyway despite the window/widget preferring smooth scroll. This is so older devices/drivers/Xservers can still trigger scrolling despite widgets adding only the smooth scroll mask.

I actually see nothing really uncommon in how vte is doing things... I'd suggest trying with gtk+ 3.22 from git to discard distro patches, and double check how scroll events are dealt with in the places I pointed out if you can still reproduce.

Another thing worth checking (just to discard Xserver bugs/distro patches/whatnot) is looking in "xinput text-xi2" that the 4-7 button events generated contain "flags: emulated". If they are not flagged as such, it could produce a similar effect to what you see, although everywhere, not just vte.
Comment 8 Ben Gamari 2017-01-05 02:59:38 UTC
I can confirm that `xinput test-xi2` shows that the RawButton[Press,Release] events indeed have the emulated flag on my Debian 8 system afflicted with this issue.
Comment 9 Cosimo Lupo 2017-10-07 22:08:23 UTC
Hello,

I'm experiencing the same issue (i.e. smooth scrolling combined with rough jumps every 4-5 lines when scrolling with two fingers on my touchpad) in another application written on top on VTE called Tilix: https://github.com/gnunn1/tilix

The Linux distro I'm using is Debian Buster (testing branch).

Note that the same happens with gnome terminal, so it must not be a Tilix-specific issue.

It is quite annoying, since the terminal is the application I use most of the time.

Please let me know if I can do anything to debug the issue.

Thank you.

Cosimo
Comment 10 Egmont Koblinger 2017-10-17 11:32:21 UTC
(In reply to Cosimo Lupo from comment #9)

> Please let me know if I can do anything to debug the issue.

Well, if you could go through Carlos's comment and check each step (comapring what he says should happen to what actually happens) that would be awesome. This requires you to modify various pieces of software (add some trivial debug statements). This bug looks like one that probably requires deeper understanding of multiple components, so it's probably not an easy or straightforward task.

Unfortunately I have very limited time to work on VTE, and I can only reproduce this particular bug with the combination of an older VTE and an abandoned app. We've hardly seen people complaining about this true usability nightmare, suggesting that it only occurs for a few people. All these combined, sadly it's not on my radar to work on this.
Comment 11 Cosimo Lupo 2017-10-17 13:15:07 UTC
(In reply to Egmont Koblinger from comment #10)

Thanks for replying.

You know, I just found a solution to this problem, although I have no idea why this solves the problem :)

Basically, the bug disappeared after I run im-config to set ibus as the input method in ~/.xinputrc. I was trying to fix another unrelated issue, namely the  CTRL+SHIFT+U shortcut (to input arbitrary unicodes) which wasn't working as I expected.
After I restarted, the touchpad scrolling issue in the Terminal was gone! I can now smooth-scroll without any more jumps :D

im-config is telling me that my system has two available input methods: ibus and xim. I presume the system's default method is set to xim, because after setting it to ibus for the my user, the bug disappeared.

Most importantly, as soon as I restored the system default input method, by undoing what im-config had done and restarting... the terminal scrolling bug was back.

I have no idea why, but this is a good-enough fix for me.

I'll leave it to you to figure out why using xim as input method would produce such bug, or why using ibus would solve it.

Thanks!
Comment 12 Egmont Koblinger 2018-01-02 22:59:32 UTC
FYI: Yet another duplicate report, with a screencast:
https://bugs.launchpad.net/terminator/+bug/1740954
Comment 13 Egmont Koblinger 2018-01-03 08:42:28 UTC
*** Bug 792151 has been marked as a duplicate of this bug. ***
Comment 14 Nathaniel Smith 2018-01-04 02:07:55 UTC
I'm also affected by this bug, and Egmont asked me to report on my IM settings. I've never done anything to tweak this and I don't even have im-config installed, so I guess I have the default xim?

I *can* report that my laptop has two different devices that generate pixel-wise scrolling events: a synaptics touchpad and a thinkpad trackpoint. I see the same jumpy behavior on both of them, so that's some evidence against it being a device driver bug.

The bug is totally consistent (and totally annoying) for me, and I've dealt with GTK+/GDK/X.org internals in a previous life, so I'm happy to go spelunking to help track it down. What I'm not so familiar with is how the gnome-terminal/VTE/scrolling stack is put together -- can anyone give me some tips on which components I should be trying to instrument and debug? Where is the actual scrolling happening?
Comment 15 Egmont Koblinger 2018-01-04 12:22:46 UTC
(In reply to Nathaniel Smith from comment #14)
>  so I'm happy to go spelunking to help track it down.

That would be absolutely awesome and highly appreciated!

> What I'm not so familiar with is how the gnome-terminal/VTE/scrolling
> stack is put together

Scrolling is handled "manually" by VTE (I mean there's no GtkScrollWhatever involved). gnome-terminal _should_ be irrelevant in the game, although having seen a different behavior in gnome-terminal vs. roxterm you can never be sure. (It's gnome-terminal displaying the scrollbar but I guess that's irrelevant, I guess this bug occurs even if the scrollbar is turned off.)

VTE ships one or two test apps, the simplest would be if you could reproduce the issue with one of them. Then you wouldn't need to fiddle with custom installation locations, LD_LIBRARY_PATH integration with gnome-terminal and such.

You can get VTE from git or tarball. If you pass --enable-debug to ./configure or ./autogen.sh then you can turn on debugging messages via the env var e.g. «DEBUG=events,misc».

From 0.38 to 0.46 there were two test apps: ./src/testvte (source: src/vteapp.c) and ./src/vte-2.91 (source: src/app.vala).

Somewhere during the 0.47 devel cycle the latter one was moved to ./bindings/vala/vte-2.91 (source: bindings/vala/app.c).

During 0.51 (current devel cycle) both of these were dropped and a new one appeared: ./src/app/vte-2.91 (source: src/app/app.cc).

I recommend not to cross these boundaries back-n-forth within a single git clone, otherwise you might easily end up with stale test apps that can easily totally confuse you. (By the way, do «echo $VTE_VERSION» to double check that the desired version of the library is used.) Use separate source directory trees for significantly different versions isntead.

Please try if you can reproduce the issue with any of these test apps, if not then I'll help you with gnome-terminal integration.

As for the VTE library itself: in the 0.43 days it received per-pixel "smooth scrolling" feature (a9b0b4c, Oct 24 2015; confusingly exactly two years earlier it received yet another feature that we called "smooth scrolling" at that time: 7efb04f, Oct 23 2013, forget about this older one.)

Shortly afterwards, also in the 0.43 series was the "input-only window" change (0612f40, Dec 26 2015) that made a difference for me with Roxterm. Apart from these, and the aforementioned changes in the test apps, I don't think there were any more relevant changes in the vte library.

As for the source code, all that matters to you should be in the (bloated) src/vte.cc, especially wherever you see the variable m_mouse_smooth_scroll_delta (in earlier vte versions without the m_ prefix). This variable accumulates the amount of scroll we received but haven't acted on yet. Also check here for GDK_SCROLL_UP, GDK_SCROLL_DOWN and GDK_SCROLL_SMOOTH. Normally only either the first two or only the last one should be seen, but with the buggy behavior you'll see both kinds of events arriving.

Let me mention two more variables with counterintuitive names that may or may not be of any interest to you.

insert_delta belongs purely to the emulation logic, regardless of how the viewport is scrolled back. Its value is: assuming the scrollbar's "normal" (bottom) position, the index of the topmost visible row relative to the beginning of VTE's lifetime. In other words, (if you don't resize the window) it's number of times the contents have scrolled by a line.

scroll_delta is a similar concept, but for the current view: the current topmost visible row's index, whereas row indices are again counted from 0 from VTE's birth. It used to be a integer, but with super smooth scrolling it was converted to a double, but still a difference of 1.0 stands for one entire row of text.

scroll_delta == insert_delta if and only if the scrollbar is at the "normal" (bottom) position, otherwise scroll_data is smaller by the number of rows you scrolled back with.

I hope these are enough for a start, let me know if you have any questions!
Comment 16 Egmont Koblinger 2018-01-04 12:25:23 UTC
> turn on debugging messages via the env var e.g. «DEBUG=events,misc».

Oops typo, the env var is called VTE_DEBUG !!
Comment 17 Nathaniel Smith 2018-01-06 02:05:25 UTC
Well, here's an initial result: I can indeed reproduce the problem with the src/app/vte-2.91 from current git, and with VTE_DEBUG=events,misc it does show a mixture of "Smooth scroll by ..." lines, + the occasional "Scroll up" line, which seems to confirm the hypothesis that VTE is somehow processing both smooth scroll events and old-style discrete scroll events.

Log excerpt:

Match hilite update (838, 376) -> 76, 641
No matches grid[625,0 .. 625,0].
Smooth scroll by 0.000000, delta now at 0.000000
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.142813, delta now at -0.142813
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 640
No matches grid[624,0 .. 624,0].
Smooth scroll by -0.085688, delta now at -0.085688
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 640
No matches grid[624,0 .. 624,0].
Smooth scroll by -0.114250, delta now at -0.114250
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 640
No matches grid[623,0 .. 623,0].
Smooth scroll by -0.085688, delta now at -0.085688
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 639
No matches grid[623,0 .. 623,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 639
No matches grid[623,0 .. 623,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 639
No matches grid[623,0 .. 623,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 639
No matches grid[623,0 .. 623,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 639
No matches grid[623,0 .. 623,0].
Smooth scroll by -0.085688, delta now at -0.085688
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 639
No matches grid[622,0 .. 622,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 638
No matches grid[622,0 .. 622,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 638
No matches grid[622,0 .. 622,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 638
No matches grid[622,0 .. 622,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 638
No matches grid[622,0 .. 622,0].
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Scroll up
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 635
No matches grid[618,0 .. 618,0].
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 634
No matches grid[618,0 .. 618,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 634
No matches grid[618,0 .. 618,0].
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 634
No matches grid[618,0 .. 618,0].
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 634
No matches grid[618,0 .. 618,0].
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.314189, delta now at -0.314189
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 633
No matches grid[617,0 .. 617,0].
Smooth scroll by -0.114250, delta now at -0.114250
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.114250, delta now at -0.114250
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 632
No matches grid[616,0 .. 616,0].
Smooth scroll by -0.057125, delta now at -0.057125
Scroll speed is 3 lines per non-smooth scroll unit
Smooth scroll by -0.028563, delta now at -0.028563
Scroll speed is 3 lines per non-smooth scroll unit
Scroll up
Scroll speed is 3 lines per non-smooth scroll unit
Match hilite update (838, 376) -> 76, 629
No matches grid[613,0 .. 613,0].
Smooth scroll by -0.028563, delta now at -0.028563
Comment 18 Nathaniel Smith 2018-01-06 03:06:28 UTC
In comment 7,  Carlos Garnacho wrote:

> - In GDK client-side windows code, depending on the event mask of the window beneath the pointer (the input-only window in this case), one set of events or the other will be discarded.
>   https://git.gnome.org/browse/gtk+/tree/gdk/gdkwindow.c#n8387
> Note that if the discrete scroll events are not emulated, they will be propagated anyway despite the window/widget preferring smooth scroll. This is so older devices/drivers/Xservers can still trigger scrolling despite widgets adding only the smooth scroll mask.

It looks like this isn't working correctly. VteTerminalPrivate::widget_scroll is receiving GDK_SCROLL_SMOOTH events for which gdk_event_get_pointer_emulated(event) returns false, i.e., these are the real smooth scroll events, and it's *also* receiving GDK_SCROLL_UP/DOWN events for which gdk_event_get_pointer_emulated(event) returns true, i.e., these are the fake events created for backwards compatibility with applications that don't know about smooth scrolling, *and* GDK/GTK+ know that that's the case, so it should be discarding them instead of sending them to VTE. Yet here they are.

A quick hack would be to add a call like

if (gdk_event_get_pointer_emulated(event))
    return

at the top of VteTerminalPrivate::widget_scroll. And I checked that if I hack this in through some gdb breakpoint trickery, then it does indeed fix the scrolling problem. But the bigger question is why GDK/GTK+ is delivering emulated scroll events, when according to Carlos's comment that shouldn't be happening...
Comment 19 Nathaniel Smith 2018-01-06 05:26:17 UTC
OK, I got a bit further, but now I'm stuck and probably need some help from a GDK/GTK+ expert.

I'm looking at Debian's gtk+3.0-3.22.26 source package, because gtk+ is a bit daunting to git clone and build :-). I could if really necessary.

What I think I know:

When new events arrive, they're placed in a queue, and then _gdk_windowing_got_event is invoked, and it has a chance to mess around with the queue. After it runs, whatever events are left in the queue are delivered by calling gtk_main_do_event.

When it sees one of our nasty GDK_SCROLL_{UP,DOWN} non-smooth scroll events, _gdk_windowing_got_event invokes proxy_button_event. The motivation here is a bit obscure to me, but there's a check in proxy_pointer_event that seems specifically designed to catch them:

https://github.com/GNOME/gtk/blob/01c349995cb3a63879aaf8852fb1c3ed3947bd74/gdk/gdkwindow.c#L9608-L9614

(linking to github because I don't know how to make a stable link to a specific revision on git.gnome.org/browse. Note that that's the head of the 3-22 branch! Master seems to have been refactored somehow.)

That branch fires because (a) this is a GDK_SCROLL event, (b) evmask & GDK_SMOOTH_SCROLL_MASK != 0, because our application has smooth scroll handling enabled, (c) source_event->scroll.direction != GDK_SCROLL_SMOOTH, because this is an emulated GDK_SCROLL_{UP,DOWN} event, not a smooth scrolling event, and (d) gdk_event_get_pointer_emulated(source_event) is true, because this is an emulated event.

Because all those things are true, proxy_button_event returns FALSE, which tells _gdk_windowing_got_event that it should... *not* discard the event from the queue! Instead it keeps the event in the queue and delivers it to the application! And indeed, if I single-step through after the 'return FALSE', then the event does eventually go through gtk_main_do_event -> gtk_propagate_event -> (eventually) VteTerminalPrivate::widget_scroll.

I really don't understand how this is intended to work, or what the logic in proxy_button_event is even trying to do.
Comment 20 Nathaniel Smith 2018-01-06 07:16:34 UTC
It looks like all that proxy_button_event code got deleted in March. From the commit message it sounds like the original idea was that it was supposed to do some coordinate transformations before passing things to gtk_main_do_event, but gtk_main_do_event is now clever enough to understand the original untranslated coordinates, so the code wasn't actually doing anything:

https://github.com/GNOME/gtk/commit/f57f48d61fca9c8caaa393fcb71a2548bdd278e6#diff-fd6ecdddff262f16904b12e351b36465

This is consistent with my observation that the code doesn't seem to be doing anything :-). Still, I'm very puzzled now, because AFAICT that is the code that Carlos pointed to back in comment 7 and said it was responsible for filtering out emulated scroll events. So... who *is* responsible for filtering out emulated scroll events now? Surely someone is doing it, or otherwise scrolling would be broken for everyone in every app, not just me and a few other random people in VTE apps only.

But I've been searching for the code that might do this, and coming up totally empty... in current GTK+ master, I reviewed every call to gdk_event_get_pointer_emulated (there are only a handful), and none of them seems related to this.
Comment 21 Egmont Koblinger 2018-01-06 09:37:59 UTC
(In reply to Nathaniel Smith from comment #19)
> (linking to github because I don't know how to make a stable link to a
> specific revision on git.gnome.org/browse.

At https://git.gnome.org/browse/gtk+/, pick the branch or tag, or particular commit under the "log" tab first. Then switch to the "tree" tab and locate the file.

> Note that that's the head of the
> 3-22 branch! Master seems to have been refactored somehow.)

head is work-in-progress GTK+ v4 (3.9x). I'd be truly surprised if VTE worked with that. 3-22 is the active head of GTK+ v3, so you're looking at the right place.
Comment 22 Egmont Koblinger 2018-01-06 09:39:01 UTC
(In reply to Egmont Koblinger from comment #21)

> head is work-in-progress GTK+ v4 (3.9x).

Sorry, I meant to say:
*master* is work-in-progress GTK+ v4 (3.9x).
Comment 23 Egmont Koblinger 2018-01-06 09:50:49 UTC
(In reply to Nathaniel Smith from comment #18)

> A quick hack would be to add a call like
> 
> if (gdk_event_get_pointer_emulated(event))
>     return
> 
> at the top of VteTerminalPrivate::widget_scroll.

How robust would it be currently, as well as against future changes?

If there's ever another extension not immediately supported by VTE, it'd generate emulated events, wouldn't it, just like I assume touchpad's rough events were emulated ones until VTE began asking for smooth ones. Bug 769696 may perhaps also be slightly relevant, seems our scrolling speed is off by a magnitude with touchscreens, probably because VTE is not handling certain kinds of events explicitly.

I'm afraid this change could cause scrolling not to work at all on some setups.

I'd really prefer not to think in such workarounds for mainstream. (They're doubtlessly useful for debugging and useful to take a note of them here.)

Just wondering: Do you have another computer or virtual machine or input device or settings or desktop environment or vte-based app etc. where you do _not_ encounter this bug? You could then start diffing the behavior. I guess it would be truly useful to catch the first moment where things happen differently inside GTK+ or X.Org in the two cases.
Comment 24 Nathaniel Smith 2018-01-07 06:12:44 UTC
Yeah, I'm not suggesting that adding that check to VteTerminalPrivate::widget_scroll is a great idea. Maybe it's worth considering as a temporary hack if we can't find a proper solution, but mostly I just mentioned it as further evidence of where the problem is.

Regarding further debugging: I guess there are really two questions. (1) How should this be fixed properly?, and (2) What's happening now that makes it work sometimes and not others?

Regarding a proper fix: if comment 7 is correct about how GTK+ is *supposed* to work, then I think the correct fix is just to change this line:

https://github.com/GNOME/gtk/blob/01c349995cb3a63879aaf8852fb1c3ed3947bd74/gdk/gdkwindow.c#L9614

to 'return TRUE' instead of 'return FALSE', so that the redundant scroll events get discarded the way Carlos suggested they should be. But this needs to be checked by a real GTK+ developer -- the fact that this has never worked this way makes me nervous that there's been some mistake and this is not actually how GTK+ is supposed to work after all.

Regarding what's actually going on now: unfortunately I don't have convenient access to a configuration where VTE works properly. I did spend some time running evince under gdb to track how scroll events work there (using evince as an arbitrarily selected GTK+ app where smooth scrolling works correctly). I got far enough to determine that in evince as well, GDK *is* sending both real and emulated scroll events into gtk_main_do_event. I also looked at what

  g_type_name_from_instance(gtk_get_event_widget(event))

returned for the real and emulated scroll events. In the vte-2.91 test app, this always returned "VteappTerminal", which is unsurprising since we know that both sets of events are being routed to the VTE widget.

For evince, though, the two kinds of scroll events differed: for GDK_SCROLL_SMOOTH events, gtk_get_event_widget returned a "GtkIconView" (I was running evince without any arguments, which pops up its "recent documents" view, which is a GtkIconView), but for emulated GDK_SCROLL_UP/DOWN events the event widget was an "EvWindow".

This suggests to me that the reason VTE apps are affected by this bug has something to do with how their GTK+ widget hierarchy is put together, and how that affects event routing? Maybe there's something going on like, in VTE apps the terminal widget always takes up the whole window so it has some catch-all routing rule that gets all the scroll events, while most apps have some fancier routing rules and that causes the emulate GDK_SCROLL_UP/DOWN events to get accidentally misdirected and lost -- which is what we wanted, so it all works out. (Perhaps because the emulated events don't replaced by a new event whose coordinates have been by convert_toplevel_coords_to_window.)

But that's mostly wild guessing, and really needs someone who understands how GTK+ event routing is supposed to work to take any further.

I guess an interesting question is whether you can reproduce that emulated GDK_SCROLL_UP/DOWN events are being sent to gtk_main_do_event, even in a configuration that works correctly. It's pretty easy to check: in gdb you can do something like

b gtk_main_do_event if event->type == GDK_SCROLL && (event->scroll.direction == GDK_SCROLL_UP || event->scroll.direction == GDK_SCROLL_DOWN)

and then if you hit that see what 'p gdk_event_get_pointer_emulated(event)' says to confirm. That would at least tell us whether whatever weirdness is affecting my configuration is happening at the GDK layer or the GTK+ layer.
Comment 25 Egmont Koblinger 2018-01-07 13:22:47 UTC
(In reply to Nathaniel Smith from comment #24)

> This suggests to me that the reason VTE apps are affected by this bug has
> something to do with how their GTK+ widget hierarchy is put together, and
> how that affects event routing? Maybe there's something going on like, in
> VTE apps the terminal widget always takes up the whole window so it has some
> catch-all routing rule that gets all the scroll events, while [...]

Roxterm vs gnome-terminal behaving differently, as well as input-only window making a difference also pretty much suggest that it'll be roughly something like what you said.

> I guess an interesting question is whether you can reproduce that emulated
> GDK_SCROLL_UP/DOWN events are being sent to gtk_main_do_event, even in a
> configuration that works correctly. It's pretty easy to check: in gdb you
> can do something like

I'll check it. (I'm more of a printf guy than a gdb guy though :))

I'll also try to reproduce the bug digging up old vte+roxterm, and look around.

Yet another thing that occurred to me (and I'm not sure it'll help us in any way, but I'm curious): If you remove GDK_SMOOTH_SCROLL_MASK from VTE, do you receive scroll events one by one, or two at a time?
Comment 26 Egmont Koblinger 2018-01-07 13:49:35 UTC
(In reply to Nathaniel Smith from comment #24)

> b gtk_main_do_event if event->type == GDK_SCROLL && (event->scroll.direction
> == GDK_SCROLL_UP || event->scroll.direction == GDK_SCROLL_DOWN)
> 
> and then if you hit that see what 'p gdk_event_get_pointer_emulated(event)'

I do hit that breakpoint and I get "$(n) = 1" every time (n = 1,2,3...).
Comment 27 Egmont Koblinger 2018-01-07 14:34:36 UTC
I can still reproduce the bug with roxterm + vte just before the 'input-only window' commit.

VTE needs a tiny change to compile: in src/vteseq.cc, at the declaration of vteseq_n_lookup(), it should take a "size_t len" rather than "unsigned int len".

Not sure how to continue from here :-D
Comment 28 Egmont Koblinger 2018-01-07 15:12:16 UTC
(In reply to Egmont Koblinger from comment #25)

> Yet another thing that occurred to me (and I'm not sure it'll help us in any
> way, but I'm curious): If you remove GDK_SMOOTH_SCROLL_MASK from VTE, do you
> receive scroll events one by one, or two at a time?

And what if you keep this but remove GDK_SCROLL_MASK?

https://developer.gnome.org/gtk3/stable/ch32s02.html says:

"""
Changes in GTK+ 3.4

[...] Widgets now need to have either GDK_SCROLL_MASK or GDK_SMOOTH_SCROLL_MASK in their event mask to receive scroll events. [...]
"""

Maybe it's settings both flags at the same time that causes (or triggers) the bug (in some constellations)?
Comment 29 Egmont Koblinger 2018-01-07 15:23:14 UTC
Here's something truly fishy:

I remove enabling GDK_SMOOTH_SCROLL_MASK from VTE. Expected: scroll by a couple of lines (typically 3 to 5 depending on the window's height) at once.

Only prior to the input-only-window commit, and only with Roxterm (that is, only how I could reproduce this bug) I still get to see the exact same "mixed" (smooth + rough) scrolling behavior.

So VTE does not even enable smooth scrolling, but someone enables it for us?!?

Nathaniel, I guess you'll see the same with current VTE too.
Comment 30 Nathaniel Smith 2018-01-08 01:17:36 UTC
> I do hit that breakpoint and I get "$(n) = 1" every time (n = 1,2,3...).

Okay, so that confirms that garnacho's suggestion about how gdk handles scroll events is wrong in all configurations -- gdk always passes on both the emulated and non-emulated events to gtk, and the difference between the working and non-working configurations has something to do with gtk's event routing.

> So VTE does not even enable smooth scrolling, but someone enables it for us?!?

Huh, I don't know why VTE would still be getting GDK_SCROLL_SMOOTH events if it didn't have GDK_SMOOTH_SCROLL_MASK enabled. Sounds like that could be another GTK+ bug. I think that's separate from whatever we're seeing here, though. You obviously want to keep GDK_SMOOTH_SCROLL_MASK enabled because you do want to support smooth scrolling, and if you use an old X server that doesn't have a new enough xinput2 to support smooth scrolling, then you *only* have non-smooth scroll events, so you want GDK_SCROLL_MASK as well. So AFAICT setting both flags is the only reasonable option for modern apps, and that seems to be what the other apps I looked at do (e.g. evince).

I don't think there's much we can do here until garnacho has time to look at this. Hopefully he notices all these comments :-)
Comment 31 Egmont Koblinger 2018-01-08 14:11:49 UTC
(In reply to Nathaniel Smith from comment #24)

> Regarding a proper fix: if comment 7 is correct about how GTK+ is *supposed*
> to work, then I think the correct fix is just to change this line:
> 
> https://github.com/GNOME/gtk/blob/01c349995cb3a63879aaf8852fb1c3ed3947bd74/
> gdk/gdkwindow.c#L9614
> 
> to 'return TRUE' instead of 'return FALSE'

I can confirm that this fixes the issue for me with Roxterm + pre-"input-only window" VTE.
Comment 32 Nathaniel Smith 2018-01-09 02:56:09 UTC
Further evidence that this isn't just a VTE problem: I don't normally use gedit, but I happened to open it just now, and on my system its scrolling behavior is broken in exactly the same way as gnome-terminal's.
Comment 33 Nathaniel Smith 2018-03-25 01:37:49 UTC
Ping?
Comment 34 GNOME Infrastructure Team 2018-05-02 17:46:02 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gtk/issues/704.