Synaptics circular scrolling issue

Andy Goth andrew.m.goth at gmail.com
Mon Mar 17 01:35:50 UTC 2025


I'm having a lot of trouble with circular scrolling on my new ThinkPad
21MN005QUS.  Circular scrolling often gets interrupted at some random
time after starting, at which point the mouse starts moving normally
and I have to reinitiate circular scrolling.  This only happens when
initiating from the left, top, or right edges, and only after recently
using the TrackPoint mouse (isometric joystick).  The bottom edge
always works fine, as does using only the touchpad and touchscreen but
never TrackPoint.

I recompiled xf86-input-synaptics 1.10.0 with -DDEBUG and ran Xorg
with -logverbose 7.  This produces output such as the following:

[ 11782.192] (II) SetTapState - 0 -> 1 (millis:11782193)
[ 11782.192] (II) circular scroll detected on edge
[ 11782.372] (II) SetMovingState - 0 -> 1 center at 3520/971 (millis:11782373)
[ 11782.372] (II) SetTapState - 1 -> 2 (millis:11782373)
[ 11782.855] (II) SetMovingState - 1 -> 0 center at 3219/524 (millis:11782856)
[ 11782.855] (II) SetTapState - 2 -> 0 (millis:11782856)
[ 11782.855] (II) cicular scroll off
[ 11782.862] (II) SetTapState - 0 -> 1 (millis:11782863)
[ 11783.042] (II) SetMovingState - 0 -> 1 center at 3107/483 (millis:11783043)
[ 11783.042] (II) SetTapState - 1 -> 2 (millis:11783043)
[ 11783.381] (II) SetMovingState - 1 -> 0 center at 3014/467 (millis:11783382)
[ 11783.381] (II) SetTapState - 2 -> 0 (millis:11783382)

As far as the driver knows, after a half second of scrolling, I lifted
my finger off the touchpad and then touched it again seven
milliseconds later, which is why it turns to ordinary mouse movement.

Adding more arguments to HandleScrolling() and putting them in the
log, I see that at the time of "cicular scroll off" [sic], I'm getting
finger==FS_UNTOUCHED and from_timer==FALSE.

Unless initiating from the bottom edge, this always happens the first
time I attempt circular scrolling after using the TrackPoint, then
usually again the next several times I attempt scrolling.  If I try
enough times, without any intervening use of the TrackPoint, then it
becomes stable and works every time, even when I also do some touchpad
mouse movements (including successfully scrolling from the bottom
edge).  I haven't been able to determine the precise conditions for
failure.  In some respects, it's as if there's some timeout following
my last use of the TrackPoint during which it periodically reasserts
its dominance and interrupts the touchpad.  Except, that doesn't make
sense in light of the fact that it works from the bottom edge.

If I stick to using the touchpad or touchscreen, never bumping the
TrackPoint, or if I always initiate from the bottom edge, scrolling
works every time.  Also, it doesn't make a difference if I do brief or
extended touchpad mouse movements between my last use of the
TrackPoint and starting circular scrolling; the first (and usually
several subsequent) attempts at scrolling are still interrupted.

It doesn't seem like the fault lies in the Xorg Synaptics driver.  The
code looks fine to me, and most especially it shouldn't have any
potential for interaction with the TrackPoint.  Perhaps there's an
issue with the kernel, or even the I2C controller.  Looking at the
output of evtest, I see:

Event: time 1742094311.913760, -------------- SYN_REPORT ------------
Event: time 1742094311.913762, type 3 (EV_ABS), code 57
(ABS_MT_TRACKING_ID), value -1
Event: time 1742094311.913762, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1742094311.913762, type 1 (EV_KEY), code 325
(BTN_TOOL_FINGER), value 0
Event: time 1742094311.913762, -------------- SYN_REPORT ------------
Event: time 1742094311.920697, type 3 (EV_ABS), code 57
(ABS_MT_TRACKING_ID), value 1097
Event: time 1742094311.920697, type 3 (EV_ABS), code 55
(ABS_MT_TOOL_TYPE), value 0
Event: time 1742094311.920697, type 3 (EV_ABS), code 53
(ABS_MT_POSITION_X), value 1832
Event: time 1742094311.920697, type 3 (EV_ABS), code 54
(ABS_MT_POSITION_Y), value 312
Event: time 1742094311.920697, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1742094311.920697, type 1 (EV_KEY), code 325
(BTN_TOOL_FINGER), value 1
Event: time 1742094311.920697, type 3 (EV_ABS), code 0 (ABS_X), value 1832
Event: time 1742094311.920697, type 3 (EV_ABS), code 1 (ABS_Y), value 312
Event: time 1742094311.920697, type 4 (EV_MSC), code 5
(MSC_TIMESTAMP), value 1903900

This shows a finger release and repress within the span of just under
seven milliseconds, which sounds awfully familiar.  But, it's very
hard to think this is a defect in the touchpad, given that it works
perfectly if I never use the TrackPoint or always start from the
bottom edge.

Wondering if it's releasing and repressing more than I realize, I
tried piping the output of evtest to grep 'BTN_TOUCH.*0', but sure
enough, this only prints when (1) I truly lift my finger or (2) once
shortly after I initiate circular scrolling from any edge other than
the bottom, after recently using the TrackPoint.  This makes me think
the kernel driver somehow knows it's in circular scrolling mode, or
else I'd be seeing spurious releases at other times.  Except, the
kernel driver source doesn't mention circular scrolling and doesn't
know about edge zones.

Super confusing to me.  I'd blame the touchpad firmware, except it
wouldn't have a reason to know about the TrackPoint.  I can't very
well blame the I2C controller since it's integrated in the CPU (I
think... it's Meteor Lake-P) and shouldn't care about the meaning of
the data it's passing along.

Where to go from here?  I returned a different laptop and bought this
one at a higher price specifically because the other one's mouse was
terrible, and it took a month and a half to ship, so I'm really not
keen on accepting anything less than perfection from this new mouse.

I've considered putting in some bodge to smooth over very brief
interruptions, but this would be a very crude hack with the side
effect of delaying legitimate releases.  Maybe only ignore brief
release/repress while in the midst of circular scrolling.  I thought
also about whether this change should go into the kernel or Xorg
driver.  The mere fact that I can argue either way about the merits of
the former is itself an argument against the former, plus doing it in
the latter would allow release/repress to be ignored during scrolling
and at no other time.  To be clear: even if such a change would not
tolerable upstream, it would still be beneficial for me to make for my
own use.  That being said, if given the choice, I'd rather do it in a
way that could be accepted upstream than not, so I wouldn't have to
continually repatch and rebuild my X server for as long as I own this
laptop.

Note to search engines indexing this email: circular scrolling is also
known as chiral scrolling.  I've found a lot of material by searching
for that term.

-- 
Andy Goth | <andrew.m.goth/at/gmail/dot/com>


More information about the xorg-devel mailing list