Subject: Re: [External] : Re: bug#51465: 27.2; `face-all-attributes' doc or behavior (?)

From: Eli Zaretskii <[email-masked]>
Date: Fri, 29 Oct 2021 10:24:06 +0300

> From: Drew Adams <[email-masked]>
> CC: "[email-masked]" <[email-masked]>
> Date: Thu, 28 Oct 2021 23:08:42 +0000
> 
> > > (elisp) `Attribute Functions' says "the default attributes of FACE
> > > for newly created frames".  I would expect to see :background as
> > > "LightGoldenrod", not as `unspecified'.
> > 
> > Why? because that's what you actually see in a new frame?  Those
> > aren't the default attributes, those are the attributes specified by
> > defface.
> 
> The Elisp manual says it returns "the default attributes
> of FACE for newly created frames."
> 
> Whenever I create a new frame (from emacs -Q) that face
> on that frame has a :background of "LightGoldenrod" -
> never `unspecified'.  Is the manual wrong?

No, it isn't wrong: the "default attributes for newly created frames"
are those the face has before applying the definitions in defface.

Note that the description of face-attribute in the same section
already hints on what is going on here:

                      If FRAME is ‘t’, this function returns the value
     of the specified attribute for newly-created frames (this is
     normally ‘unspecified’, unless you have specified some value using
     ‘set-face-attribute’; see below).

If you use set-face-attribute with the FRAME argument t to set some
attribute's value, the next call to face-all-attributes will no longer
show 'unspecified' for that attribute.  And the next frame created
after that will use the attribute value you specified, effectively
overriding the corresponding attribute's value defined by defface.

> Unless otherwise specified (which could be by
> `default-frame-alist' or whatever) a newly created
> frame has, according to the manual, the attributes
> for that face that are given by `face-all-attributes'
> when that function is passed a nil FRAME arg: "the
> default attributes of FACE for newly created frames."
> 
> IOW, it calls this "the default attributes" for
> "newly created frames", not the attributes for some
> existing frame (this is the FRAME=nil case).
> 
> And yet, with emacs -Q, every newly created frame
> has :background set to "LightGoldenrod" (AFAICT).
> At the very least, most, if not all, newly created
> frames have that attribute value.  None have that
> attribute with a value of `unspecified'.

That's because defface's definitions are merged with those defaults,
when the frame is created, which in this case yields the
non-unspecified background color.  So you rarely if ever see those
default attributes, except if you call this function.

> I'd think that "default" would just mean what you
> get for a newly created frame unless there is
> something that overrides that somehow.

That is correct, and that is what happens here; see above.

> I'd think that "default" is what the current customized value of the
> face has - that's what you get by default for a newly created frame
> (or if it's not customized then the value given by the original
> defface).

Right.  But the default values are before merging the defface's
definitions.

> I'm hoping you at least see a possibility for
> confusion in the doc.

Thanks, I've now clarified the documentation on the release branch to
be more specific about the meaning of "default" in this context, and
made sure the same explanation appears in both face-attribute and
face-all-attributes.

> And maybe even a problematic behavior

I see no problems in the behavior, no.  It's just a complex issue, and
it isn't easy to explain it clearly to readers that aren't necessarily
privy to the implementation details.  Hopefully, it's more clear now.

> (what's the point of returning `unspecified' everywhere?).

Only if no default values were defined via set-face-attribute.

And with that, I'm closing this bug report.