From e573d08ef15f0431ad8289b4242c49826f20efb6 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 26 Sep 2015 09:50:58 +0300 Subject: [PATCH] Make face realization be more frame-specific * src/frame.h (struct f): New flag face_change. * src/xfaces.c (Finternal_make_lisp_face) (Finternal_copy_lisp_face, Finternal_set_lisp_face_attribute) (update_face_from_frame_parameter): Set the face_change flag only for the frame whose faces are affected. * src/xdisp.c (init_iterator): If a frame's face_change flag is set, free faces only on that frame. (redisplay_internal): Disable "display optimization 1" if the frame's face_change flag is set. (redisplay_window): Don't allow skipping a window's redisplay if its frame's face_change flag is set. * src/frame.c (x_set_screen_gamma): Instead of calling Fclear_face_cache, call clear_face_cache and set windows_or_buffers_changed to a non-zero value. This avoids setting the global face_change flag that triggers face realization on all frames and thorough redisplay of all of them. * lisp/term/tty-colors.el (tty-register-default-colors): Don't clear face cache if the selected frame is a GUI frame. --- lisp/term/tty-colors.el | 8 +++++--- src/frame.c | 3 ++- src/frame.h | 3 +++ src/xdisp.c | 16 +++++++++++++--- src/xfaces.c | 40 ++++++++++++++++++++++++++-------------- 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/lisp/term/tty-colors.el b/lisp/term/tty-colors.el index 98108ce6356..3bc1aa0ee48 100644 --- a/lisp/term/tty-colors.el +++ b/lisp/term/tty-colors.el @@ -810,9 +810,11 @@ Value is the modified color alist for FRAME." (while colors (tty-color-define (car color) (cadr color) (cddr color)) (setq colors (cdr colors) color (car colors))) - ;; Modifying color mappings means realized faces don't - ;; use the right colors, so clear them. - (clear-face-cache))) + ;; Modifying color mappings means realized faces don't use the + ;; right colors, so clear them, if we modified colors on a TTY + ;; frame. + (or (display-graphic-p) + (clear-face-cache)))) (defun tty-color-canonicalize (color) "Return COLOR in canonical form. diff --git a/src/frame.c b/src/frame.c index 0e95749a055..121c55fdb20 100644 --- a/src/frame.c +++ b/src/frame.c @@ -3539,7 +3539,8 @@ x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu (f, bgcolor, Qnil); } - Fclear_face_cache (Qnil); + clear_face_cache (true); + windows_or_buffers_changed = 70; } diff --git a/src/frame.h b/src/frame.h index 546bede213d..af0dadb3d99 100644 --- a/src/frame.h +++ b/src/frame.h @@ -335,6 +335,9 @@ struct frame /* Set to true after this frame was made by `make-frame'. */ bool_bf after_make_frame : 1; + /* Non-zero if this frame's faces need to be recomputed. */ + bool_bf face_change : 1; + /* Bitfield area ends here. */ /* Number of lines (rounded up) of tool bar. REMOVE THIS */ diff --git a/src/xdisp.c b/src/xdisp.c index bac74e2a34f..2c38aa9ccff 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2661,10 +2661,18 @@ init_iterator (struct it *it, struct window *w, free realized faces now because they depend on face definitions that might have changed. Don't free faces while there might be desired matrices pending which reference these faces. */ - if (face_change && !inhibit_free_realized_faces) + if (!inhibit_free_realized_faces) { - face_change = false; - free_all_realized_faces (Qnil); + if (face_change) + { + face_change = false; + free_all_realized_faces (Qnil); + } + else if (XFRAME (w->frame)->face_change) + { + XFRAME (w->frame)->face_change = 0; + free_all_realized_faces (w->frame); + } } /* Perhaps remap BASE_FACE_ID to a user-specified alternative. */ @@ -13541,6 +13549,7 @@ redisplay_internal (void) && FRAME_VISIBLE_P (XFRAME (w->frame)) && !FRAME_OBSCURED_P (XFRAME (w->frame)) && !XFRAME (w->frame)->cursor_type_changed + && !XFRAME (w->frame)->face_change /* Make sure recorded data applies to current buffer, etc. */ && this_line_buffer == current_buffer && match_p @@ -15887,6 +15896,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) && REDISPLAY_SOME_P () && !w->redisplay && !w->update_mode_line + && !f->face_change && !f->redisplay && !buffer->text->redisplay && BUF_PT (buffer) == w->last_point) diff --git a/src/xfaces.c b/src/xfaces.c index 94f3c4d67c2..40713f167ff 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -687,7 +687,6 @@ clear_face_cache (bool clear_fonts_p) #endif /* HAVE_WINDOW_SYSTEM */ } - DEFUN ("clear-face-cache", Fclear_face_cache, Sclear_face_cache, 0, 1, 0, doc: /* Clear face caches on all frames. Optional THOROUGHLY non-nil means try to free unused fonts, too. */) @@ -2528,7 +2527,10 @@ Value is a vector of face attributes. */) free realized faces. */ if (NILP (Fget (face, Qface_no_inherit))) { - face_change = true; + if (f) + f->face_change = 1; + else + face_change = true; windows_or_buffers_changed = 54; } @@ -2576,6 +2578,7 @@ The value is TO. */) (Lisp_Object from, Lisp_Object to, Lisp_Object frame, Lisp_Object new_frame) { Lisp_Object lface, copy; + struct frame *f; CHECK_SYMBOL (from); CHECK_SYMBOL (to); @@ -2586,6 +2589,7 @@ The value is TO. */) strings etc. because 20.2 didn't do it either. */ lface = lface_from_face_name (NULL, from, true); copy = Finternal_make_lisp_face (to, Qnil); + f = NULL; } else { @@ -2596,6 +2600,7 @@ The value is TO. */) CHECK_LIVE_FRAME (new_frame); lface = lface_from_face_name (XFRAME (frame), from, true); copy = Finternal_make_lisp_face (to, new_frame); + f = XFRAME (new_frame); } vcopy (copy, 0, XVECTOR (lface)->contents, LFACE_VECTOR_SIZE); @@ -2607,7 +2612,10 @@ The value is TO. */) free realized faces. */ if (NILP (Fget (to, Qface_no_inherit))) { - face_change = true; + if (f) + f->face_change = 1; + else + face_change = true; windows_or_buffers_changed = 55; } @@ -2630,6 +2638,7 @@ FRAME 0 means change the face on all frames, and change the default /* Set one of enum font_property_index (> 0) if ATTR is one of font-related attributes other than QCfont and QCfontset. */ enum font_property_index prop_index = 0; + struct frame *f; CHECK_SYMBOL (face); CHECK_SYMBOL (attr); @@ -2650,6 +2659,7 @@ FRAME 0 means change the face on all frames, and change the default /* Set lface to the Lisp attribute vector of FACE. */ if (EQ (frame, Qt)) { + f = NULL; lface = lface_from_face_name (NULL, face, true); /* When updating face-new-frame-defaults, we put :ignore-defface @@ -2665,9 +2675,10 @@ FRAME 0 means change the face on all frames, and change the default { if (NILP (frame)) frame = selected_frame; + f = XFRAME (frame); CHECK_LIVE_FRAME (frame); - lface = lface_from_face_name (XFRAME (frame), face, false); + lface = lface_from_face_name (f, face, false); /* If a frame-local face doesn't exist yet, create one. */ if (NILP (lface)) @@ -2989,11 +3000,11 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCfont)) { #ifdef HAVE_WINDOW_SYSTEM - if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame))) + if (EQ (frame, Qt) || FRAME_WINDOW_P (f)) { if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) { - struct frame *f; + struct frame *f1; old_value = LFACE_FONT (lface); if (! FONTP (value)) @@ -3013,28 +3024,29 @@ FRAME 0 means change the face on all frames, and change the default signal_error ("Invalid font or font-spec", value); } if (EQ (frame, Qt)) - f = XFRAME (selected_frame); + f1 = XFRAME (selected_frame); else - f = XFRAME (frame); + f1 = XFRAME (frame); /* FIXME: If frame is t, and selected frame is a tty frame, the font can't be realized. An improvement would be to loop over frames for a non-tty frame and use that. See discussion in Bug#18573. For a daemon, frame may be an initial frame (Bug#18869). */ - if (FRAME_WINDOW_P (f)) + if (FRAME_WINDOW_P (f1)) { if (! FONT_OBJECT_P (value)) { Lisp_Object *attrs = XVECTOR (lface)->contents; Lisp_Object font_object; - font_object = font_load_for_lface (f, attrs, value); + font_object = font_load_for_lface (f1, attrs, value); if (NILP (font_object)) signal_error ("Font not available", value); value = font_object; } - set_lface_from_font (f, lface, value, true); + set_lface_from_font (f1, lface, value, true); + f1->face_change = 1; } } else @@ -3045,7 +3057,7 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCfontset)) { #ifdef HAVE_WINDOW_SYSTEM - if (EQ (frame, Qt) || FRAME_WINDOW_P (XFRAME (frame))) + if (EQ (frame, Qt) || FRAME_WINDOW_P (f)) { Lisp_Object tmp; @@ -3107,7 +3119,7 @@ FRAME 0 means change the face on all frames, and change the default && NILP (Fget (face, Qface_no_inherit)) && NILP (Fequal (old_value, value))) { - face_change = true; + f->face_change = true; windows_or_buffers_changed = 56; } @@ -3280,7 +3292,7 @@ update_face_from_frame_parameter (struct frame *f, Lisp_Object param, if (!NILP (face) && NILP (Fget (face, Qface_no_inherit))) { - face_change = true; + f->face_change = true; windows_or_buffers_changed = 57; } } -- 2.39.2