Subject: bug#74876: 31.0.50; Force fringe refresh / force-window-update not affecting fringes

From: Eli Zaretskii <[email-masked]>
Date: Sat, 14 Dec 2024 22:28:07 +0200

> From: Michal Nazarewicz <[email-masked]>
> Date: Sat, 14 Dec 2024 20:31:00 +0100
> 
> I’m implementing fringe dimming in non-selected windows as an extension
> of the NonGNU ELPA auto-dim-other-buffers package (see
> <https://github.com/mina86/auto-dim-other-buffers.el/issues/27>).
> 
> <https://github.com/mina86/auto-dim-other-buffers.el/tree/fringes> is
> a test code which tries to achieve it.  The expected behaviour is that
> after enabling auto-dim-other-buffers-mode defined there, as you switch
> between windows, the fringes of non-selected windows will be red.
> 
> Alas, it appears that fringes are redrawn lazily such that changing
> window does not refresh the fringes.

Yes, because redrawing the fringes is expensive, especially in large
frames.  So I'm not surprised that you see what you see, since no one
expected the fringe face to be changed frequently during the session.

> For a bit more context, the package uses face-remap-add-relative and
> :filtered faces, i.e. something like:
> 
>     (face-remap-add-relative
>      'fringe
>      '(:filtered (:window adob--dim t) auto-dim-other-buffers-fringe-face))
> 
> I’ve tried toggling fringe-mode when forcing window update with the
> below code, but it did not do the trick.
> 
>     (defun adob--force-window-update (object)
>       (force-window-update object)
>       ;; Force fringes to be updated
>       (when fringe-mode
>         (dolist (wnd (if (windowp object)
>                          (list object)
>                        (get-buffer-window-list object nil t)))
>           (let* ((frame  (window-frame wnd))
>                  (params (frame-parameters frame))
>                  (left   (alist-get 'left-fringe  params))
>                  (right  (alist-get 'right-fringe params)))
>             (when (and left right)
>               (modify-frame-parameters
>                frame '((left-fringe nil) (right-fringe nil)))
>               (modify-frame-parameters
>                frame `((left-fringe . ,left) (right-fringe . ,right))))))))
> 
> I think what I’d like is for force-window-update to force full fringe
> redraw?  Honestly, I haven’t yet dug through all of the window and
> fringe code so I’m not entirely sure where the main issue lays.

Can you show a simple Lisp which could be used to investigate the
behavior and perhaps see how what you want could be enabled?  It is
not easy to do that by having the code of the whole package.
Presumably, what the package does to dynamically change the face of
the fringe can be done by a short Lisp function, which could then be
used from "emacs -Q" to see what prevents the fringe face from being
updated immediately.