emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master b828d36dede: Automatically redraw frames for filtered faces


From: Daniel Colascione
Subject: master b828d36dede: Automatically redraw frames for filtered faces
Date: Fri, 3 Jan 2025 23:49:19 -0500 (EST)

branch: master
commit b828d36deded145ebbd3419f618cf52f7862c4c8
Author: Daniel Colascione <dancol@dancol.org>
Commit: Daniel Colascione <dancol@dancol.org>

    Automatically redraw frames for filtered faces
    
    Automatically redraw frames when we detect that a window
    parameter used in a face filter is changed.  (Bug#75291)
    
    * src/window.c (Fset_window_parameter): redraw window, actually
    whole frame in this implementation, on face-relevant parameter
    change
    (syms_of_window): add window_auto_redraw_on_parameter_change
    * src/xfaces.c (evaluate_face_filter): record properties
---
 src/window.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 src/xfaces.c |  3 +++
 2 files changed, 50 insertions(+)

diff --git a/src/window.c b/src/window.c
index 5a10c381eaf..17bbe213e05 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2394,8 +2394,41 @@ Return VALUE.  */)
 {
   register struct window *w = decode_any_window (window);
   Lisp_Object old_alist_elt;
+  struct frame* f;
 
   old_alist_elt = Fassq (parameter, w->window_parameters);
+
+  /* If this window parameter has been used in a face remapping filter
+     expression anywhere at any time and we changed its value, force a
+     from-scratch redisplay to make sure that everything that depends on
+     a face filtered on the window parameter value is up-to-date.
+
+     We compare with Qt here instead of using !NILP so that users can
+     set this property to a non-nil, non-t value to inhibit this
+     mechanism for a specific window parameter.
+
+     FIXME: instead of taking a sledgehammer to redisplay, we could be
+     more precise in tracking which display bits depend on which
+     remapped faces.  In particular, 1) if a window parameter named in a
+     face filter affects only faces used in drawing fringes, we don't
+     need to redraw TTY frames, but if the filter is ever used in a
+     non-fringe context (e.g. the 'face' text property), we need to
+     redraw TTY frames too.  2) In the fringe case, we should limit the
+     redraw damage to the fringes of the affected window and not the
+     whole frame containing the window.  Today, we seldom change window
+     parameters named in face filters.  We should implement the
+     optimizations above when this assumption no longer holds.  */
+  if (SYMBOLP (parameter)
+      && WINDOW_LIVE_P (window)
+      && EQ (Fget (parameter, QCfiltered), Qt)
+      && FRAME_WINDOW_P ((f = WINDOW_XFRAME (w)))
+      && !EQ (CDR_SAFE (old_alist_elt), value)
+      && window_auto_redraw_on_parameter_change)
+    {
+      f->face_change = 1;
+      fset_redisplay (f);
+    }
+
   if (NILP (old_alist_elt))
     wset_window_parameters
       (w, Fcons (Fcons (parameter, value), w->window_parameters));
@@ -9071,6 +9104,20 @@ Elisp for testing purposes only.  */);
   window_dead_windows_table
     = CALLN (Fmake_hash_table, QCweakness, Qt);
 
+  DEFVAR_BOOL ("window-auto-redraw-on-parameter-change",
+              window_auto_redraw_on_parameter_change,
+              doc: /* When non-nil, redraw based on face filters.
+When this variable is non-nil, force a potentially expensive redraw when
+a window parameter named in a `:window' expression for ':filtered'
+changes.  This redraw is necessary for correctness; this variable is an
+escape hatch to recover performance in the case that our assumption that
+these parameter changes are rare does not hold.
+
+You can also inhibit the automatic redraw for a specific window
+parameter by setting the `:filtered` symbol property of the parameter
+name to `'ignore'.  */);
+  window_auto_redraw_on_parameter_change = true;
+
   defsubr (&Sselected_window);
   defsubr (&Sold_selected_window);
   defsubr (&Sminibuffer_window);
diff --git a/src/xfaces.c b/src/xfaces.c
index d1ca2e0d5d4..75fe73154ca 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2512,6 +2512,9 @@ evaluate_face_filter (Lisp_Object filter, struct window 
*w,
     if (!NILP (filter))
       goto err;
 
+    if (NILP (Fget (parameter, QCfiltered)))
+      Fput (parameter, QCfiltered, Qt);
+
     bool match = false;
     if (w)
       {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]