From: Daniel Colascione <dancol@dancol.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 75291@debbugs.gnu.org, mina86@mina86.com
Subject: bug#75291: Redisplay not updating fringe when face filter changes
Date: Thu, 02 Jan 2025 14:50:54 -0500 [thread overview]
Message-ID: <87ikqx2dwh.fsf@dancol.org> (raw)
In-Reply-To: <86v7uxhv9c.fsf@gnu.org> (Eli Zaretskii's message of "Thu, 02 Jan 2025 21:26:55 +0200")
Eli Zaretskii <eliz@gnu.org> writes:
> merge 75291 74876
> thanks
>
>> From: Daniel Colascione <dancol@dancol.org>
>> Cc: 75291@debbugs.gnu.org, Michal Nazarewicz <mina86@mina86.com>
>> Date: Thu, 02 Jan 2025 13:36:34 -0500
>>
>> Eli Zaretskii <eliz@gnu.org> writes:
>>
>> > I think this is bug#74876 again. I tried to explain there why the way
>> > the fringe drawing is implemented doesn't work well with
>> > face-remapping (or with changes in the fringe face in general).
>> >
>> > Maybe I'm missing something, but supporting what this and that bug
>> > want would need a rewrite of update_window_fringes (and possibly also
>> > the way we record fringes' attributes in the glyph row).
>>
>> That's amazing. Seven years ago, I implemented
>> https://github.com/dcolascione/emacs-window-highlight/blob/master/window-highlight.el.
>> I worked around the bug we're discussing using redraw-display. I see
>> that Michal (++) implemented the same feature independently and reported
>> the same bug just a few weeks before I got around to reporting the same
>> bug from seven years ago! Pure serendipity.
>
> Yes, redrawing everything will work, but will also cause flicker, and
> is generally expensive, thus undesirable.
FWIW, it doesn't seem to cause flicker in practice. I see flicker only
when walking through messages in mu4e --- we do redisplay and draw only
the background, and I haven't figured out why yet. But in general, on a
modern window system, turning a given redisplay into a full redisplay
shouldn't cause flicker, even if it's inefficient.
>> Anyway, given that the feature has been implemented twice now, maybe we
>> can find some way to make it work efficiently? I haven't looked into
>> how exactly we do fringe invalidation, but isn't there a way we can
>> limit the blast radius of the redraw by providing a lisp-level function
>> to invalidate extra GUI parts of specific windows rather than forcing a
>> redraw-frame? It's not clear to me why we couldn't skip redrawing every
>> row's content but redraw every row's fringe anyway.
>>
>> Ideally, a change to a face in which the change couldn't possibly affect
>> layout (e.g. changing a background color) would be pretty efficient from
>> a redisplay POV, since we wouldn't have to even try to reflow any text.
>
> AFAIR, the current implementation is the other way around: when some
> glyph row changes, we consider redrawing its fringes. E.g.,
> draw_window_fringes only considers glyph rows that are enabled in the
> glyph matrix, which means redisplay found that glyph row has changed.
> Clearly, someone didn't think the fringe face will change during a
> session!
I came across overlay_arrows_changed_p --- isn't this function trying to
deal with exactly the case of something in the fringe changing outside
the changed text region?
> Regarding your idea about Lisp function that would invalidate GUI
> parts: it is not very easy, since a Lisp program cannot easily know
> where on the screen a given region of buffer positions will be.
> There is posn-at-point, of course, but (a) it is quite expensive, and
> (b) when Lisp runs, display could be outdated, so what posn-at-point
> returns could be inaccurate.
I was imagining a lisp function that would make the next redisplay of a
window do what you suggest in the next paragraph.
I'm not sure we'd even need an explicit Lisp function though.
Face filters with :window are defined to compare window parameter values
with eq, so couldn't we keep track of all the :filtered face
specifications we encounter during face resolution and have
set-window-parameter check whether the parameter it's setting is on the
list of possible face filters and, if so, force next redisplay to
evaluate faces? set-window-parameter wouldn't even have to do a deep
comparison, because it's just eq.
> In any case, I don't think this will be needed in the case in point,
> because when the fringe face changes, we'd want to redraw the fringes
> of the entire window, right? So redisplay_window would need to notice
> the change in the face, and invoke update_window_fringes in a special
> way, such that update_window_fringes marks fringes to be redrawn not
> only when the glyph row is enabled. Maybe that would work.
> The way to "notice the change in the face" is not a simple problem to
> solve, btw. We currently don't know which faces change when some face
> is modified. So we have a frame-global flag that is set when any face
> changes its attributes. If we use that flag for detecting potential
> changes in the fringe face, we'd start redrawing fringes
> unnecessarily.
How many unnecessary face recalculations would we do? ISTM we could make
the invalidation pretty precise as long as we're just looking at
window parameters.
> We could add a special flag for the fringe face, but
> then we'd need to add a special mechanism in xfaces.c which would
> analyze each change in some face's attribute and determine whether it
> could possibly affect the fringe face. Or maybe I'm missing some more
> elegant/easier solution.
next prev parent reply other threads:[~2025-01-02 19:50 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-02 17:30 bug#75291: Redisplay not updating fringe when face filter changes Daniel Colascione
2025-01-02 17:50 ` Eli Zaretskii
2025-01-02 18:36 ` Daniel Colascione
2025-01-02 19:24 ` Michal Nazarewicz
2025-01-02 19:26 ` Eli Zaretskii
2025-01-02 19:50 ` Daniel Colascione [this message]
2025-01-02 20:56 ` Eli Zaretskii
2025-01-03 17:25 ` Daniel Colascione
2025-01-03 19:31 ` Eli Zaretskii
2025-01-03 19:46 ` Daniel Colascione
2025-01-03 20:10 ` Eli Zaretskii
2025-01-03 20:27 ` Eli Zaretskii
2025-01-03 20:57 ` Daniel Colascione
2025-01-04 7:12 ` Eli Zaretskii
[not found] ` <C3F80FE6-077F-4A74-9C48-DD9EAE4E3266@dancol.org>
2025-01-18 9:29 ` 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=87ikqx2dwh.fsf@dancol.org \
--to=dancol@dancol.org \
--cc=75291@debbugs.gnu.org \
--cc=eliz@gnu.org \
--cc=mina86@mina86.com \
/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).