New faces 'tab-line-active' and 'tab-line-inactive' (bug#80742)

This is intended to parallel the 'mode-line-active/inactive'
and 'header-line-active/inactive' distinction.

* doc/emacs/display.texi (Standard Faces): Document the new faces.

* lisp/faces.el (tab-line-active, tab-line-inactive): Add new faces.

* lisp/tab-line.el (tab-line-faces): Add new faces
to MEMBERS arg of 'defgroup'.
(tab-line-auto-hscroll): Use one of the faces
depending on 'mode-line-window-selected-p'.

* src/dispextern.h (CURRENT_TAB_LINE_ACTIVE_FACE_ID_3)
(CURRENT_TAB_LINE_ACTIVE_FACE_ID): New macros
based on header-line equivalents.
(CURRENT_TAB_LINE_HEIGHT): Use CURRENT_TAB_LINE_ACTIVE_FACE_ID.
(face_id): Use TAB_LINE_ACTIVE_FACE_ID and
TAB_LINE_INACTIVE_FACE_ID instead of TAB_LINE_FACE_ID.

* src/xdisp.c (window_box_height, pos_visible_p, init_iterator)
(window_text_pixel_size, display_mode_lines, display_mode_line)
(format-mode-line): Replace all uses of TAB_LINE_FACE_ID with
either a new macro or the new face IDs.

* src/xfaces.c (lookup_basic_face, realize_basic_faces):
Map new face IDs to their lisp symbols.
(syms_of_xfaces): New lisp symbols.
This commit is contained in:
Juri Linkov
2026-04-14 20:14:15 +03:00
parent a1899d8cb1
commit 0384600a21
7 changed files with 96 additions and 22 deletions

View File

@@ -811,6 +811,22 @@ Similar to @code{mode-line} for a window's tab line, which appears
at the top of a window with tabs representing window buffers.
@xref{Tab Line}.
The @code{tab-line-active} and @code{tab-line-inactive} faces (which
are the ones actually used on the tab lines) inherit from this face.
@cindex faces for tab lines
@item tab-line-active
Like @code{tab-line}, but used for the tab line of the currently
selected window. This face inherits from @code{tab-line}, so changes
in that face affect tab lines in all windows.
@cindex @code{tab-line-inactive} face
@item tab-line-inactive
Like @code{tab-line}, but used for tab lines of the windows other
than the selected one (if those windows have a tab line). This face
inherits from @code{tab-line}, so changes in that face affect tab
lines in all windows.
@cindex @code{vertical-border} face
@item vertical-border
This face is used for the vertical divider between windows on text

View File

@@ -658,6 +658,12 @@ will change its appearance if the tab buffer has been modified.
This user option controls which buffers should appear in the tab line.
By default, this is set to not filter the buffers.
+++
*** New faces 'tab-line-active' and 'tab-line-inactive'.
These inherit from the 'tab-line' face, but the faces actually used
on the tab lines are now these two: the selected window uses
'tab-line-active', non-selected windows use 'tab-line-inactive'.
** Help
+++

View File

@@ -3005,7 +3005,22 @@ Note: Other faces cannot inherit from the cursor face."
:background "grey")
(t
:inverse-video t))
"Tab line face."
"Basic tab line face.
See `tab-line-active' and `tab-line-inactive' for the faces
used on tab lines."
:version "31.1"
:group 'basic-faces)
(defface tab-line-active
'((t :inherit tab-line))
"Face for the selected tab line.
This inherits from the `tab-line' face."
:version "31.1"
:group 'basic-faces)
(defface tab-line-inactive
'((t :inherit tab-line))
"Basic tab line face for non-selected windows."
:version "31.1"
:group 'basic-faces)

View File

@@ -54,7 +54,11 @@ is selected."
:group 'tab-line
:version "28.1")
(defgroup tab-line-faces '((tab-line custom-face)) ; tab-line is defined in faces.el
(defgroup tab-line-faces
;; These faces are defined in faces.el
'((tab-line custom-face)
(tab-line-active custom-face)
(tab-line-inactive custom-face))
"Faces used in the tab line."
:group 'tab-line
:group 'faces
@@ -860,13 +864,16 @@ the selected tab visible."
(with-current-buffer tab-line-auto-hscroll-buffer
(let ((truncate-partial-width-windows nil)
(inhibit-modification-hooks t)
(face (if (mode-line-window-selected-p)
'tab-line-active
'tab-line-inactive))
show-arrows)
(setq truncate-lines nil
word-wrap nil)
(erase-buffer)
(apply 'insert strings)
(goto-char (point-min))
(add-face-text-property (point-min) (point-max) 'tab-line t)
(add-face-text-property (point-min) (point-max) face t)
;; Continuation means tab-line doesn't fit completely,
;; thus scroll arrows are needed for scrolling.
(setq show-arrows (> (vertical-motion 1) 0))
@@ -888,7 +895,7 @@ the selected tab visible."
(erase-buffer)
(apply 'insert (reverse (seq-subseq strings 0 (1+ selected))))
(goto-char (point-min))
(add-face-text-property (point-min) (point-max) 'tab-line)
(add-face-text-property (point-min) (point-max) face)
(if (> (vertical-motion 1) 0)
(let* ((point (previous-single-property-change (point) 'tab))
(tab-prop (when point
@@ -909,13 +916,13 @@ the selected tab visible."
(erase-buffer)
(apply 'insert (seq-subseq strings (truncate hscroll) (1+ selected)))
(goto-char (point-min))
(add-face-text-property (point-min) (point-max) 'tab-line)
(add-face-text-property (point-min) (point-max) face)
(when (> (vertical-motion 1) 0)
;; Not visible already
(erase-buffer)
(apply 'insert (reverse (seq-subseq strings 0 (1+ selected))))
(goto-char (point-min))
(add-face-text-property (point-min) (point-max) 'tab-line)
(add-face-text-property (point-min) (point-max) face)
(when (> (vertical-motion 1) 0)
(let* ((point (previous-single-property-change (point) 'tab))
(tab-prop (when point

View File

@@ -1610,6 +1610,27 @@ struct glyph_string
: estimate_mode_line_height \
(XFRAME ((W)->frame), CURRENT_HEADER_LINE_ACTIVE_FACE_ID (W)))))
/* Return the desired face id for the tab line of a window, depending
on whether the window is selected or not, or if the window is the
scrolling window for the currently active minibuffer window. */
#define CURRENT_TAB_LINE_ACTIVE_FACE_ID_3(SELW, MBW, SCRW) \
((!mode_line_in_non_selected_windows \
|| (SELW) == XWINDOW (selected_window) \
|| (minibuf_level > 0 \
&& !NILP (minibuf_selected_window) \
&& (MBW) == XWINDOW (minibuf_window) \
&& (SCRW) == XWINDOW (minibuf_selected_window))) \
? TAB_LINE_ACTIVE_FACE_ID \
: TAB_LINE_INACTIVE_FACE_ID)
/* Return the desired face id for the tab line of window W. */
#define CURRENT_TAB_LINE_ACTIVE_FACE_ID(W) \
CURRENT_TAB_LINE_ACTIVE_FACE_ID_3(W, \
XWINDOW (selected_window), \
W)
/* Return the current height of the tab line of window W. If not known
from W->tab_line_height, look at W's current glyph matrix, or return
an estimation based on the height of the font of the face `tab-line'. */
@@ -1621,7 +1642,7 @@ struct glyph_string
= (MATRIX_TAB_LINE_HEIGHT ((W)->current_matrix) \
? MATRIX_TAB_LINE_HEIGHT ((W)->current_matrix) \
: estimate_mode_line_height \
(XFRAME ((W)->frame), TAB_LINE_FACE_ID))))
(XFRAME ((W)->frame), CURRENT_TAB_LINE_ACTIVE_FACE_ID (W)))))
/* Return the height of the desired mode line of window W. */
@@ -1943,7 +1964,8 @@ enum face_id
INTERNAL_BORDER_FACE_ID,
CHILD_FRAME_BORDER_FACE_ID,
TAB_BAR_FACE_ID,
TAB_LINE_FACE_ID,
TAB_LINE_ACTIVE_FACE_ID,
TAB_LINE_INACTIVE_FACE_ID,
BASIC_FACE_ID_SENTINEL
};

View File

@@ -1343,7 +1343,7 @@ window_box_height (struct window *w)
if (tl_row && tl_row->mode_line_p)
height -= tl_row->height;
else
height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
height -= estimate_mode_line_height (f, CURRENT_TAB_LINE_ACTIVE_FACE_ID (w));
}
}
@@ -1743,7 +1743,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
= window_parameter (w, Qtab_line_format);
w->tab_line_height
= display_mode_line (w, TAB_LINE_FACE_ID,
= display_mode_line (w, CURRENT_TAB_LINE_ACTIVE_FACE_ID (w),
NILP (window_tab_line_format)
? BVAR (current_buffer, tab_line_format)
: window_tab_line_format);
@@ -3285,7 +3285,8 @@ init_iterator (struct it *it, struct window *w,
if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
|| base_face_id == MODE_LINE_INACTIVE_FACE_ID)
row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
else if (base_face_id == TAB_LINE_FACE_ID)
else if (base_face_id == TAB_LINE_ACTIVE_FACE_ID
|| base_face_id == TAB_LINE_INACTIVE_FACE_ID)
row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
else if (base_face_id == HEADER_LINE_ACTIVE_FACE_ID
|| base_face_id == HEADER_LINE_INACTIVE_FACE_ID)
@@ -11975,7 +11976,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
Lisp_Object window_tab_line_format
= window_parameter (w, Qtab_line_format);
y = y + display_mode_line (w, TAB_LINE_FACE_ID,
y = y + display_mode_line (w, CURRENT_TAB_LINE_ACTIVE_FACE_ID (w),
NILP (window_tab_line_format)
? BVAR (current_buffer, tab_line_format)
: window_tab_line_format);
@@ -27946,7 +27947,7 @@ display_mode_lines (struct window *w)
Lisp_Object window_tab_line_format
= window_parameter (w, Qtab_line_format);
display_mode_line (w, TAB_LINE_FACE_ID,
display_mode_line (w, CURRENT_TAB_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
NILP (window_tab_line_format)
? BVAR (current_buffer, tab_line_format)
: window_tab_line_format);
@@ -27975,10 +27976,10 @@ display_mode_lines (struct window *w)
/* Display mode or header/tab line of window W. FACE_ID specifies which
line to display; it is either MODE_LINE_ACTIVE_FACE_ID,
HEADER_LINE_ACTIVE_FACE_ID, HEADER_LINE_INACTIVE_FACE_ID, or
TAB_LINE_FACE_ID. FORMAT is the mode/header/tab line format to
display. Value is the pixel height of the mode/header/tab line
displayed. */
HEADER_LINE_ACTIVE_FACE_ID, HEADER_LINE_INACTIVE_FACE_ID,
TAB_LINE_ACTIVE_FACE_ID or TAB_LINE_INACTIVE_FACE_ID.
FORMAT is the mode/header/tab line format to display.
Value is the pixel height of the mode/header/tab line displayed. */
static int
display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
@@ -27994,7 +27995,8 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
prepare_desired_row (w, it.glyph_row, true);
it.glyph_row->mode_line_p = true;
if (face_id == TAB_LINE_FACE_ID)
if (face_id == TAB_LINE_ACTIVE_FACE_ID
|| face_id == TAB_LINE_INACTIVE_FACE_ID)
{
it.glyph_row->tab_line_p = true;
w->desired_matrix->tab_line_p = true;
@@ -28021,7 +28023,8 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
if (NILP (Vmode_line_compact)
|| face_id == HEADER_LINE_ACTIVE_FACE_ID
|| face_id == HEADER_LINE_INACTIVE_FACE_ID
|| face_id == TAB_LINE_FACE_ID)
|| face_id == TAB_LINE_ACTIVE_FACE_ID
|| face_id == TAB_LINE_INACTIVE_FACE_ID)
{
mode_line_target = MODE_LINE_DISPLAY;
display_mode_element (&it, 0, 0, 0, format, Qnil, false);
@@ -28879,7 +28882,8 @@ are the selected window and the WINDOW's buffer). */)
: EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
: EQ (face, Qheader_line_active) ? HEADER_LINE_ACTIVE_FACE_ID
: EQ (face, Qheader_line_inactive) ? HEADER_LINE_INACTIVE_FACE_ID
: EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
: EQ (face, Qtab_line_active) ? TAB_LINE_ACTIVE_FACE_ID
: EQ (face, Qtab_line_inactive) ? TAB_LINE_INACTIVE_FACE_ID
: EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
: EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
: DEFAULT_FACE_ID;

View File

@@ -5195,7 +5195,8 @@ lookup_basic_face (struct window *w, struct frame *f, int face_id)
case MODE_LINE_INACTIVE_FACE_ID: name = Qmode_line_inactive; break;
case HEADER_LINE_ACTIVE_FACE_ID: name = Qheader_line_active; break;
case HEADER_LINE_INACTIVE_FACE_ID: name = Qheader_line_inactive; break;
case TAB_LINE_FACE_ID: name = Qtab_line; break;
case TAB_LINE_ACTIVE_FACE_ID: name = Qtab_line_active; break;
case TAB_LINE_INACTIVE_FACE_ID: name = Qtab_line_inactive; break;
case TAB_BAR_FACE_ID: name = Qtab_bar; break;
case TOOL_BAR_FACE_ID: name = Qtool_bar; break;
case FRINGE_FACE_ID: name = Qfringe; break;
@@ -5975,7 +5976,8 @@ realize_basic_faces (struct frame *f)
realize_named_face (f, Qinternal_border, INTERNAL_BORDER_FACE_ID);
realize_named_face (f, Qchild_frame_border, CHILD_FRAME_BORDER_FACE_ID);
realize_named_face (f, Qtab_bar, TAB_BAR_FACE_ID);
realize_named_face (f, Qtab_line, TAB_LINE_FACE_ID);
realize_named_face (f, Qtab_line_active, TAB_LINE_ACTIVE_FACE_ID);
realize_named_face (f, Qtab_line_inactive, TAB_LINE_INACTIVE_FACE_ID);
unbind_to (count, Qnil);
/* Reflect changes in the `menu' face in menu bars. */
@@ -7534,6 +7536,8 @@ syms_of_xfaces (void)
DEFSYM (Qtab_bar, "tab-bar");
DEFSYM (Qfringe, "fringe");
DEFSYM (Qtab_line, "tab-line");
DEFSYM (Qtab_line_inactive, "tab-line-inactive");
DEFSYM (Qtab_line_active, "tab-line-active");
DEFSYM (Qheader_line, "header-line");
DEFSYM (Qheader_line_inactive, "header-line-inactive");
DEFSYM (Qheader_line_active, "header-line-active");