Subject: bug#73862: [PATCH] Add `header-line-active` and `header-line-inactive` faces.

From: Eli Zaretskii <[email-masked]>
Date: Fri, 06 Dec 2024 10:55:22 +0200

> From: Aaron Jensen <[email-masked]>
> Date: Thu, 5 Dec 2024 13:14:32 -0800
> Cc: [email-masked], [email-masked], [email-masked]
> 
> > Why are you changing the attributes of the default face in step 3 and step
> > 5 when what you want is to change the header-line face? And do you
> > understand why step 2 didn't change the way header line is displayed, but
> > step 3 did?
> 
> Only to force a redisplay in a way that actually causes the inheritance to
> be considered. Note that when you reproduce this same thing with the
> mode-line, force-mode-line-update doesn't work to cause the inheritance to
> be considered. There's something "special" about changing the font or the
> geometry of the frame or something that's causing the consideration of
> inheritance.

That's because changing the default face causes recomputation of all
the faces, starting from the basic faces.  It is not directly related
to redisplay (which is why force-mode-line-update doesn't have that
effect), although, of course, the recomputation is triggered by the
next redisplay cycle.

> > If you then switch back to the original buffer and change the font size
> > again, the highlight will display again.
> >
> > How come the font of the default face affects the colors of the
> > header-line faces? Doesn't that already look strange?
> 
> The strange thing is that when and how the inheritance is taken into
> account is not the same as for other faces. So yes, it already looks
> strange — I shouldn't need to force a redisplay. Affecting the font of the
> default face is just one means by which I can trigger the redisplay in a
> way that causes the issue. The specifics of it are a red herring. When I
> first noticed the issue it was as a result of a vterm popup window being
> shown. No default font modifications were made. I don't know what the
> specific trigger was, however.

See above: I hope the situation is more clear now.

> > So I tend to close this bug as wontfix, and just mention in the
> > documentation (NEWS at least) that people who remap header-line or
> > mode-line need now to remap the new -active and -inactive faces.
> 
> Ok, I get what you're saying here, but I don't know that I agree with this:
> "...people somehow expect that remapping the header-line face will affect
> header-line-active and header-line-inactive." I'm not sure why it wouldn't
> be expected.

It shouldn't be expected for basic faces.

> It's reasonable to expect that inherit and face remapping
> would work the same way always.

It doesn't, and never was.  The current implementation of faces has a
built-in assumption that basic faces don't inherit from any other
faces, except the (implicit) inheritance from the default face.  So
face-remapping of basic faces doesn't take inheritance into account,
and never did.

> I didn't even know there was a notion of "basic faces" and what that
> meant.

As a Lisp programmer, you aren't supposed to know that, or care.  The
problem here is that, by making some basic faces inherit from other
faces, we caused this abstraction to leak.

> If basic faces do not fully support inheritance, we probably shouldn't
> allow them to have inheritance.

Yes.  But that train has left the station, unfortunately, and quite a
long time ago.  I don't think there's a way back.  Note that
mode-line-inactive was originally introduced _in_addition_ to
mode-line (which was then used only for the "active" mode-line), so
people were expected to customize/remap that new face _in_addition_ to
mode-line.  It's when we introduced mode-line-active, which _always_
inherits from mode-line, that this problem was first introduced.  And
now the two header-line faces, which basically repeat the same
paradigm, added yet another group of problems.

> That would mean that header-line-inactive
> would be defined explicitly, without inheritance, and if someone attempted
> to add an inherit property, it would fail.

Or we could do what the mode-line case did originally: leave the
active face to be header-line and define header-line-inactive without
inheritance.  This will at least let existing remapping of header-line
work as it did before.

For the same reasons, I would prefer to go back on the
mode-line-active change, but I'm not sure this is practical at this
point.

> This would mean that the base faces, header-line and mode-line would be
> eliminated.

No need to go that far.  These faces are still useful, because they
allow to define the inheriting faces more compactly, and allow to
change the definitions easier.  Inheritance still works on the defface
level, even for basic faces.

> Is it too much to ask for someone to explicitly configure the
> four faces (mode-line-active, mode-line-inactive, header-line-active, and
> header-line-inactive) any time they want to apply a theme to them? It
> sounds like that's the expectation for remapping, so why not extend that to
> customizing them?

Remapping and customizing are two different customizations, though.
They don't have to work the same.

> If there were no header-line or mode-line face then I would not have run
> into this.

Yes, but removing a face from Emacs is a much more significant
backward incompatibility than the problems discussed in this bug.

I added Stefan to this discussion, in the hope that he could have some
suggestions or comments.