aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Colascione2025-01-03 23:36:55 -0500
committerDaniel Colascione2025-01-03 23:48:41 -0500
commitb828d36deded145ebbd3419f618cf52f7862c4c8 (patch)
treecb94320aa13d4d98e439d260c27bf5eb874a272c
parent8e9317a1de66314dee96266863827c00cdefde2f (diff)
downloademacs-b828d36deded145ebbd3419f618cf52f7862c4c8.tar.gz
emacs-b828d36deded145ebbd3419f618cf52f7862c4c8.zip
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
-rw-r--r--src/window.c47
-rw-r--r--src/xfaces.c3
2 files changed, 50 insertions, 0 deletions
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. */)
2394{ 2394{
2395 register struct window *w = decode_any_window (window); 2395 register struct window *w = decode_any_window (window);
2396 Lisp_Object old_alist_elt; 2396 Lisp_Object old_alist_elt;
2397 struct frame* f;
2397 2398
2398 old_alist_elt = Fassq (parameter, w->window_parameters); 2399 old_alist_elt = Fassq (parameter, w->window_parameters);
2400
2401 /* If this window parameter has been used in a face remapping filter
2402 expression anywhere at any time and we changed its value, force a
2403 from-scratch redisplay to make sure that everything that depends on
2404 a face filtered on the window parameter value is up-to-date.
2405
2406 We compare with Qt here instead of using !NILP so that users can
2407 set this property to a non-nil, non-t value to inhibit this
2408 mechanism for a specific window parameter.
2409
2410 FIXME: instead of taking a sledgehammer to redisplay, we could be
2411 more precise in tracking which display bits depend on which
2412 remapped faces. In particular, 1) if a window parameter named in a
2413 face filter affects only faces used in drawing fringes, we don't
2414 need to redraw TTY frames, but if the filter is ever used in a
2415 non-fringe context (e.g. the 'face' text property), we need to
2416 redraw TTY frames too. 2) In the fringe case, we should limit the
2417 redraw damage to the fringes of the affected window and not the
2418 whole frame containing the window. Today, we seldom change window
2419 parameters named in face filters. We should implement the
2420 optimizations above when this assumption no longer holds. */
2421 if (SYMBOLP (parameter)
2422 && WINDOW_LIVE_P (window)
2423 && EQ (Fget (parameter, QCfiltered), Qt)
2424 && FRAME_WINDOW_P ((f = WINDOW_XFRAME (w)))
2425 && !EQ (CDR_SAFE (old_alist_elt), value)
2426 && window_auto_redraw_on_parameter_change)
2427 {
2428 f->face_change = 1;
2429 fset_redisplay (f);
2430 }
2431
2399 if (NILP (old_alist_elt)) 2432 if (NILP (old_alist_elt))
2400 wset_window_parameters 2433 wset_window_parameters
2401 (w, Fcons (Fcons (parameter, value), w->window_parameters)); 2434 (w, Fcons (Fcons (parameter, value), w->window_parameters));
@@ -9071,6 +9104,20 @@ Elisp for testing purposes only. */);
9071 window_dead_windows_table 9104 window_dead_windows_table
9072 = CALLN (Fmake_hash_table, QCweakness, Qt); 9105 = CALLN (Fmake_hash_table, QCweakness, Qt);
9073 9106
9107 DEFVAR_BOOL ("window-auto-redraw-on-parameter-change",
9108 window_auto_redraw_on_parameter_change,
9109 doc: /* When non-nil, redraw based on face filters.
9110When this variable is non-nil, force a potentially expensive redraw when
9111a window parameter named in a `:window' expression for ':filtered'
9112changes. This redraw is necessary for correctness; this variable is an
9113escape hatch to recover performance in the case that our assumption that
9114these parameter changes are rare does not hold.
9115
9116You can also inhibit the automatic redraw for a specific window
9117parameter by setting the `:filtered` symbol property of the parameter
9118name to `'ignore'. */);
9119 window_auto_redraw_on_parameter_change = true;
9120
9074 defsubr (&Sselected_window); 9121 defsubr (&Sselected_window);
9075 defsubr (&Sold_selected_window); 9122 defsubr (&Sold_selected_window);
9076 defsubr (&Sminibuffer_window); 9123 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,
2512 if (!NILP (filter)) 2512 if (!NILP (filter))
2513 goto err; 2513 goto err;
2514 2514
2515 if (NILP (Fget (parameter, QCfiltered)))
2516 Fput (parameter, QCfiltered, Qt);
2517
2515 bool match = false; 2518 bool match = false;
2516 if (w) 2519 if (w)
2517 { 2520 {