diff options
| author | Daniel Colascione | 2025-01-03 23:36:55 -0500 |
|---|---|---|
| committer | Daniel Colascione | 2025-01-03 23:48:41 -0500 |
| commit | b828d36deded145ebbd3419f618cf52f7862c4c8 (patch) | |
| tree | cb94320aa13d4d98e439d260c27bf5eb874a272c | |
| parent | 8e9317a1de66314dee96266863827c00cdefde2f (diff) | |
| download | emacs-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.c | 47 | ||||
| -rw-r--r-- | src/xfaces.c | 3 |
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. | ||
| 9110 | When this variable is non-nil, force a potentially expensive redraw when | ||
| 9111 | a window parameter named in a `:window' expression for ':filtered' | ||
| 9112 | changes. This redraw is necessary for correctness; this variable is an | ||
| 9113 | escape hatch to recover performance in the case that our assumption that | ||
| 9114 | these parameter changes are rare does not hold. | ||
| 9115 | |||
| 9116 | You can also inhibit the automatic redraw for a specific window | ||
| 9117 | parameter by setting the `:filtered` symbol property of the parameter | ||
| 9118 | name 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 | { |