unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Eli Zaretskii <eliz@gnu.org>
To: larsi@gnus.org
Cc: 53636@debbugs.gnu.org, tsdh@gnu.org
Subject: bug#53636: 29.0.50; face-remapping broken on master
Date: Sat, 12 Feb 2022 14:20:11 +0200	[thread overview]
Message-ID: <83a6ews2dg.fsf@gnu.org> (raw)
In-Reply-To: <83sfssuoqt.fsf@gnu.org> (message from Eli Zaretskii on Wed, 09 Feb 2022 15:57:14 +0200)

> Date: Wed, 09 Feb 2022 15:57:14 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: 53636@debbugs.gnu.org, tsdh@gnu.org
> 
> > From: Lars Ingebrigtsen <larsi@gnus.org>
> > Cc: 53636@debbugs.gnu.org,  tsdh@gnu.org
> > Date: Wed, 09 Feb 2022 09:01:27 +0100
> > 
> > Eli Zaretskii <eliz@gnu.org> writes:
> > 
> > > So: in the scenario you've shown, do we want *scratch* to have its
> > > mode-line remapped on the new frame, or don't we?  IOW, I agree that
> > > the result ideally shouldn't depend on the buffer where make-frame is
> > > called, but I need to know what is the desired behavior in order to
> > > find code which produces the undesired results.
> > 
> > Yes, I don't think that the results in the new frame should depend on
> > the current buffer when `make-frame' is called.
> 
> OK, I think I know where this happens.  Let me dig a bit.

After digging into this, I'm sorry to say that this is unworkable: if
a basic face inherits from some other face, and that other face is
remapped via a buffer-local value of face-remapping-alist, the result
will be unpredictable.  For a simple demonstration of the
unpredictable nature of the result, try this simple variation of your
recipe, which just adds the last step:

  . emacs -Q
  . M-: (progn (face-remap-add-relative 'mode-line 'link-visited) (make-frame)) RET
  . C-x C-f src/xdisp.c RET

Now all the buffers on the new frame have the mode line rendered with
the default attributes, whereas all the buffers on the old frame
suddenly get the mode line rendered with the link-visited face.  IOW,
just visiting a file on the new frame causes the mode line to be
displayed differently than it was before you visit that file.

This is due to how we handle the basic faces.  There's "face
realization" and "face look up".  The former means we recompute all
the face's attributes and load the necessary GUI resources (colors,
fonts, etc.) from scratch; the latter means we just look up in the
frame's face cache the attributes that were already computed.  Face
realization is obviously much more expensive than look up, so we only
realize the basic faces when the frame's face cache is empty.  A new
frame has its cache empty, but there are other situations when the
face cache could become empty: for example, when attributes of a named
face change.  So fundamentally, whether using a basic face will go
through "face realization" or just "face look up" is unpredictable and
can happen at any moment.

Here is the crucial point: face inheritance is only considered in
"face realization", not in "face look up".  (That is why we empty the
face cache when a named face is modified in the first place.)  So if a
basic face inherits from another face, and that other face is
remapped, the effect of the remapping will make the result of "face
realization" different from "face look up", although no face has
changed the attributes.  And since it is unpredictable when Emacs will
use "face realization" and when it will settle with "face look up",
you get unpredictable results.  Moreover, Emacs expects a remapped
face to have a different face ID internally (the ID is just the index
of the remapped face in the frame's face cache).  But "face
realization" when a parent face is remapped doesn't yield a new face
ID, it just influences the attributes recorded under the original face
ID.  The bottom line is that if "face realization" is called when the
current buffer happens to be one with non-nil face-remapping-alist,
the default face ID will use the attributes of the remapped face, but
Emacs will not know that the face was effectively remapped.  And that
is the root cause of what you see in your recipes.

Contrast this with a perfectly correct and expected behavior with
these slightly modified recipes:

  (progn
    (face-remap-add-relative 'mode-line-active 'link-visited)
    (make-frame))

  (progn
    (face-remap-add-relative 'mode-line-active 'link-visited)
    (switch-to-buffer "*Messages*")
    (make-frame))

Now the only mode line that is affected is the one of the *scratch*
buffer (when it is the current buffer), no matter how many other files
you visit after creating the new frame, and no matter which frame
displays what buffer.

So I can just reiterate what I said up-thread: basic faces cannot
inherit from other faces, if we want to support remapping of those
parent faces.  Our internal infrastructure for handling the basic
faces simply doesn't support this.





  reply	other threads:[~2022-02-12 12:20 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-30 13:52 bug#53636: 29.0.50; face-remapping broken on master Tassilo Horn
2022-01-30 17:41 ` Lars Ingebrigtsen
2022-01-30 18:27   ` Eli Zaretskii
2022-01-30 18:31     ` Lars Ingebrigtsen
2022-01-30 19:19       ` Eli Zaretskii
2022-01-30 20:25         ` Eli Zaretskii
2022-01-30 20:28           ` Lars Ingebrigtsen
2022-01-31 12:20             ` Eli Zaretskii
2022-01-31 19:44               ` Eli Zaretskii
2022-02-01 19:38                 ` Lars Ingebrigtsen
2022-02-01 20:09                   ` Eli Zaretskii
2022-02-02 17:59                     ` Lars Ingebrigtsen
2022-02-02 18:07                       ` Eli Zaretskii
2022-02-02 19:48                         ` Lars Ingebrigtsen
2022-02-02 21:12                           ` bug#53636: [External] : " Drew Adams
2022-02-03  6:53                           ` Eli Zaretskii
2022-02-03 19:24                             ` Lars Ingebrigtsen
2022-02-03 19:53                               ` Eli Zaretskii
2022-02-05  6:20                                 ` Lars Ingebrigtsen
2022-02-05  7:50                                   ` Eli Zaretskii
2022-02-05 16:14                                     ` bug#53636: [External] : " Drew Adams
2022-02-05 22:27                                     ` Lars Ingebrigtsen
2022-02-06  7:12                                       ` Eli Zaretskii
2022-02-06 23:16                                         ` Lars Ingebrigtsen
2022-02-07 15:03                                           ` Eli Zaretskii
2022-02-08  6:08                                             ` Lars Ingebrigtsen
2022-02-08  8:58                                               ` martin rudalics
2022-02-08 12:41                                                 ` Eli Zaretskii
2022-02-08 18:24                                                   ` martin rudalics
2022-02-08 18:57                                                     ` Eli Zaretskii
2022-02-08 12:29                                               ` Eli Zaretskii
2022-02-09  8:01                                                 ` Lars Ingebrigtsen
2022-02-09 13:57                                                   ` Eli Zaretskii
2022-02-12 12:20                                                     ` Eli Zaretskii [this message]
2022-02-13  8:20                                                       ` Lars Ingebrigtsen
2022-02-13  8:31                                                         ` Tassilo Horn
2022-02-15  9:31                                                           ` Tassilo Horn
2022-02-13 11:58                                                         ` Eli Zaretskii
2022-02-14 10:38                                                           ` Lars Ingebrigtsen
2022-02-03 18:30                           ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=83a6ews2dg.fsf@gnu.org \
    --to=eliz@gnu.org \
    --cc=53636@debbugs.gnu.org \
    --cc=larsi@gnus.org \
    --cc=tsdh@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).