Several terminal emulators can report horizontal mouse or touchpad scrolling events, using values 66 and 67 (where vertical scrolling uses 64 and 65 -- this is prior to adding 32 if the "1006" mouse extension isn't used).
See https://gitlab.gnome.org/GNOME/vte/-/issues/2765, including the 2nd comment for an important caveat, and the 3rd comment for an overview of current support status in terminals and apps.
Let's see what happens in joe -mouse with one of these terminal emulators.
First lets choose a terminal that only sends a single (click) event.
joe converts horizontal scrolling events into vertical ones. Scrolling to the left is equivalent to scrolling up, and right is the same as down.
This is quite an annoying behavior (surprisingly frequently found on the web and at other places too). You can't move your fingers on the touchpad exactly vertically. If you happen to move your fingers slightly along a /-diagonal, i.e., either up and a bit right, or down and a bit left, then scrolling becomes annoyingly jaggered, with lots of tiny back and forth movements.
Now let's pick a terminal that delivers two events, a click and a release.
For some reason, joe interprets all those "scrolling release" events as a downwards (or right) scroll. So, moving my fingers to the right scrolls downward in the file with double speed (both the press and the release events cause a bit of scrolling), and moving my fingers to the left is a no-op (the press and release events cancel out each other).
(Note that I do not use "natural scrolling", if you do then the directions are swapped.)
joe should recognize the horizontal scrolling escape sequences, including their "release" counterparts. It should do nothing on "release". On "press", i.e. the actual scroll event, it should either do nothing, or scroll horizontally (but not vertically).
Diff:
Cbcontains the button number, as encoded in decimal ASCII as the first parameter if the 1006 extension is supported by the terminal, or the first rawy byte minus 32 with the legacy byte-based protocol if 1006 is not supported by the terminal.Cb's value consists of the following bits:- bit 7 (128): button value bit 3 (8)
- bit 6 (64): button value bit 2 (4)
- bit 5 (32): drag
- bit 4 (16): ctrl
- bit 3 (8): alt
- bit 2 (4): shift
- bit 1 (2): button value bit 1 (2)
- bit 0 (1): button value bit 0 (1)
Whereas button value, if stiched together from the above bits, is:
- 0: left button (X mouse button 1)
- 1: middle button (X mouse button 2)
- 2: right button (X mouse button 3)
- 3: release
- 4: scroll up (X mouse button 4)
- 5: scroll down (X mouse button 5)
- 6: scroll left (X mouse button 6)
- 7: scroll right (X mouse button 7)
- 8: X mouse button 8
- ...
- 15: X mouse button 15
(Notice the discontinuity in the mapping at value 3.)
With these in mind, looking at
mouse_event():For scrolling, the check of
Cb & 0x41obviously maps left-right to up-down as it ignores the bit that separates them. My gut instinct for the quick fix (to ignore horizontal scrolling) would beCb & 0x43but that's still not correct because that would ignore the high bit of the mouse button, and buttons 12-13 would still be misinterpreted as vertical scrolling. The mask should include all the bits that contribute to the button number, i.e.Cb & 0xC3.Similarly, 3 times below in the same method, checking the value
Cb & 3is incorrect since buttons 4, 8, 12 could also be mistaken as left clicks; 5, 9, 13 as middle clicks; 6, 10, 14 as right clicks; and 7, 11, 15 as release events. You get the idea. They should beCb & 0xC3.Yet again similarly, at the bottom of
uextmouse(), the codeCb |= 3is again incorrect, it needs to set the button value to 3, but instead e.g. if it was button 8 then sets it to 11, etc. Gotta clear those two high bits, something likeCb &= ~0xC0first.... (nitpicking) or maybe clear all the bits using
Cb &= ~0xC3and then set the two low ones withCb |= 3. This is more consistent in the sense that the same bitmask0xC3is used throughout the method.Also, I didn't mention it explicitly, but this last paragraph of my previous post explains why "release" events of left scrolling become right scrolling instead, resulting in back-n-forth pairs in some terminals.