Subject: Re: bug#45556: 27.1; Unexpected behavior of `tab-bar-show' variable

From: Juri Linkov <[email-masked]>
Date: Wed, 06 Jan 2021 20:04:25 +0200

> This was not a bug after all. But would it be useful to mention in the
> doc string that the variable's behavior will be different if modified
> by setq? Or is this already common knowledge? 

Thank you for the suggestion to mention this in the doc string.
While updating the doc string, I noticed the problem that currently
it doesn't update each frame individually according to the new
customized value, so this problem will be fixed with this patch:

diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 5a95e5975d..69746d5f84 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -236,18 +236,27 @@ tab-bar-show
 and show it again once more tabs are created.
 If nil, always keep the tab bar hidden.  In this case it's still
 possible to use persistent named window configurations by relying on
-keyboard commands `tab-new', `tab-close', `tab-next', `tab-switcher', etc."
+keyboard commands `tab-new', `tab-close', `tab-next', `tab-switcher', etc.
+
+Please customize this variable using the Customization UI, then
+it will automatically update the existing tab bars on each frame."
   :type '(choice (const :tag "Always" t)
                  (const :tag "When more than one tab" 1)
                  (const :tag "Never" nil))
   :initialize 'custom-initialize-default
   :set (lambda (sym val)
          (set-default sym val)
-         (tab-bar-mode
-          (if (or (eq val t)
-                  (and (natnump val)
-                       (> (length (funcall tab-bar-tabs-function)) val)))
-              1 -1)))
+         ;; Preload button images
+         (tab-bar-mode 1)
+         ;; Then handle each frame individually
+         (dolist (frame (frame-list))
+           (set-frame-parameter
+            frame 'tab-bar-lines
+            (if (or (eq val t)
+                    (and (natnump val)
+                         (> (length (funcall tab-bar-tabs-function frame))
+                            val)))
+                1 0))))
   :group 'tab-bar
   :version "27.1")

> Somehow reading a function name "toggle-tab-bar-mode..." my
> understanding is that such a function would enable and disable tab-bar
> functionality itself, rather than only show and hide the bar. I see
> now that toggling the 'tab-bar-mode' minor mode also does not
> enable/disable the tab-bar functionality, but rather seems to just
> toggle the actual bar. Is this correct?

This is almost correct.  Additionally, 'tab-bar-mode' also
loads button images and assigns C-TAB keys.

> If so, what is the difference between 'toggle-tab-bar-mode-from-frame'
> and 'tab-bar-mode'. Both of them seem to toggle the tab bar in
> _all_ frames.

Indeed, 'tab-bar-mode' toggles the tab bar in all frames, but
'toggle-tab-bar-mode-from-frame' is a very specialized command.
It's used only in the Show/Hide menu, to have the toggle reflect
the current frame, as the comment before its definition says.
Maybe this comment should be moved to its doc string like this:

diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 5a95e5975d..e239a02a64 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -187,9 +187,9 @@ tab-bar-handle-mouse
         ;; Clicking anywhere outside existing tabs will add a new tab
         (tab-bar-new-tab)))))
 
-;; Used in the Show/Hide menu, to have the toggle reflect the current frame.
 (defun toggle-tab-bar-mode-from-frame (&optional arg)
   "Toggle tab bar on or off, based on the status of the current frame.
+Used in the Show/Hide menu, to have the toggle reflect the current frame.
 See `tab-bar-mode' for more information."
   (interactive (list (or current-prefix-arg 'toggle)))
   (if (eq arg 'toggle)