Subject: bug#39649: 27.0.60; tab-line doesn't scroll

From: Juri Linkov <[email-masked]>
Date: Fri, 21 Feb 2020 01:07:10 +0200

> This seems better to me. However, scrolling is occurring when not
> necessary, which looks kinda weird https://youtu.be/_YG0XH8XJpI

Thanks for the detailed visual bug reports - it's clear now
what should be fixed.  The following patch provides almost
prefect behavior with only one exception: it fails to switch
back from manual scrolling to automatic scrolling when
the tab-line is at its beginning, showing the first tab.
The problem is that in Emacs there is no such thing as
negative zero.

I don't understand why Emacs doesn't support signed zero.
For example in JavaScript: Math.sign(-0) => -0

Signed zero would help in the auto-hscroll implementation where
positive integers encode positions of manual scrolling and
negative integers encode positions of automatic scrolling.
And switching from manual to automatic just changes the sign.

But since positions count from zero, there is no way
to distinguish manual scrolling position from automatic
scrolling position at the beginning of the tab-line.

I have no idea how to overcome this limitation.

diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 8f1221abe4..70ca7e2204 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -464,6 +466,13 @@ tab-line-format
                           (window-buffer)
                           (window-parameter nil 'tab-line-hscroll)))
          (cache (window-parameter nil 'tab-line-cache)))
+    ;; Enable auto-hscroll again after it was disabled on manual scrolling.
+    ;; The moment to enable it is when the window-buffer was updated.
+    (when (and tab-line-auto-hscroll       ; if auto-hscroll was enabled
+               (natnump (nth 2 cache-key)) ; non-negative on manual scroll
+               cache                       ; window-buffer was updated
+               (not (equal (nth 1 (car cache)) (nth 1 cache-key))))
+      (set-window-parameter nil 'tab-line-hscroll (- (nth 2 cache-key))))
     (or (and cache (equal (car cache) cache-key) (cdr cache))
         (cdr (set-window-parameter
               nil 'tab-line-cache