* frame.h (struct frame): New bitfield fonts_changed.
* dispextern.h (fonts_changed_p, adjust_glyphs): Remove declaration.
(adjust_frame_glyphs): Add prototype.
* dispnew.c (fonts_changed_p): Remove.
(adjust_glyphs): Remove becase we do not
adjust matrices on all frames at once any more.
(adjust_frame_glyphs): Block and unblock input here.
(adjust_glyph_matrix): Use fonts_changed.
(change_frame_size_1): Use adjust_frame_glyphs.
* font.c (font_open_entity): Use fonts_changed.
* frame.c (set_menu_bar_lines, Fmake_terminal_frame):
* w32fns.c (x_set_menu_bar_lines, x_set_tool_bar_lines, Fx_show_tip):
* window.c (Fdelete_other_windows_internal, Fwindow_resize_apply)
(Fsplit_window_internal, Fdelete_window_internal, grow_mini_window)
(shrink_mini_window, Fresize_mini_window_internal)
(window_scroll_pixel_based, Fset_window_configuration)
(apply_window_adjustment, Fset_window_vscroll):
* xfns.c (x_set_menu_bar_lines, x_set_tool_bar_lines, Fx_show_tip):
Use adjust_frame_glyphs.
* xdisp.c (redisplay_tool_bar, redisplay_window, try_window)
(try_window_reusing_current_matrix, try_window_id, display_line)
(IT_EXPAND_MATRIX_WIDTH): Use fonts_changed.
(redisplay_internal): Consider fonts_changed and adjust frame
matrices for each frame only if the frame is visible. If font
has been changed on some frame during full redisplay, retry
only visible frames where the font has been actually changed.
+2013-09-06 Dmitry Antipov <dmantipov@yandex.ru>
+
+ Attempt to make redisplay more selective when changing fonts.
+ * frame.h (struct frame): New bitfield fonts_changed.
+ * dispextern.h (fonts_changed_p, adjust_glyphs): Remove declaration.
+ (adjust_frame_glyphs): Add prototype.
+ * dispnew.c (fonts_changed_p): Remove.
+ (adjust_glyphs): Remove becase we do not
+ adjust matrices on all frames at once any more.
+ (adjust_frame_glyphs): Block and unblock input here.
+ (adjust_glyph_matrix): Use fonts_changed.
+ (change_frame_size_1): Use adjust_frame_glyphs.
+ * font.c (font_open_entity): Use fonts_changed.
+ * frame.c (set_menu_bar_lines, Fmake_terminal_frame):
+ * w32fns.c (x_set_menu_bar_lines, x_set_tool_bar_lines, Fx_show_tip):
+ * window.c (Fdelete_other_windows_internal, Fwindow_resize_apply)
+ (Fsplit_window_internal, Fdelete_window_internal, grow_mini_window)
+ (shrink_mini_window, Fresize_mini_window_internal)
+ (window_scroll_pixel_based, Fset_window_configuration)
+ (apply_window_adjustment, Fset_window_vscroll):
+ * xfns.c (x_set_menu_bar_lines, x_set_tool_bar_lines, Fx_show_tip):
+ Use adjust_frame_glyphs.
+ * xdisp.c (redisplay_tool_bar, redisplay_window, try_window)
+ (try_window_reusing_current_matrix, try_window_id, display_line)
+ (IT_EXPAND_MATRIX_WIDTH): Use fonts_changed.
+ (redisplay_internal): Consider fonts_changed and adjust frame
+ matrices for each frame only if the frame is visible. If font
+ has been changed on some frame during full redisplay, retry
+ only visible frames where the font has been actually changed.
+
2013-09-05 Dmitry Antipov <dmantipov@yandex.ru>
Cache current header and mode line height for each window.
((ROW)->phys_height - (ROW)->phys_ascent \
> (ROW)->height - (ROW)->ascent)
-/* True means that fonts have been loaded since the last glyph
- matrix adjustments. The function redisplay_internal adjusts glyph
- matrices when this flag is true. */
-
-extern bool fonts_changed_p;
-
/* A glyph for a space. */
extern struct glyph space_glyph;
extern void init_desired_glyphs (struct frame *);
extern bool update_frame (struct frame *, bool, bool);
extern void bitch_at_user (void);
-void adjust_glyphs (struct frame *);
+extern void adjust_frame_glyphs (struct frame *);
void free_glyphs (struct frame *);
void free_window_matrices (struct window *);
void check_glyph_memory (void);
static void update_frame_line (struct frame *, int);
static int required_matrix_height (struct window *);
static int required_matrix_width (struct window *);
-static void adjust_frame_glyphs (struct frame *);
static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool);
static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
static void fill_up_frame_row_with_spaces (struct glyph_row *, int);
static struct frame *frame_matrix_frame;
-/* True means that fonts have been loaded since the last glyph
- matrix adjustments. Redisplay must stop, and glyph matrices must
- be adjusted when this flag becomes true during display. The
- reason fonts can be loaded so late is that fonts of fontsets are
- loaded on demand. Another reason is that a line contains many
- characters displayed by zero width or very narrow glyphs of
- variable-width fonts. */
-
-bool fonts_changed_p;
-
/* Convert vpos and hpos from frame to window and vice versa.
This may only be used for terminal frames. */
|| right != matrix->right_margin_glyphs);
if (!marginal_areas_changed_p
- && !fonts_changed_p
+ && !XFRAME (w->frame)->fonts_changed
&& !header_line_changed_p
&& matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
&& matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
}
}
-
-/* Re-allocate/ re-compute glyph matrices on frame F. If F is null,
- do it for all frames; otherwise do it just for the given frame.
- This function must be called when a new frame is created, its size
- changes, or its window configuration changes. */
+/* Allocate/reallocate glyph matrices of a single frame F.
+ This function must be called when a new frame is created,
+ its size changes, or its window configuration changes. */
void
-adjust_glyphs (struct frame *f)
+adjust_frame_glyphs (struct frame *f)
{
/* Block input so that expose events and other events that access
glyph matrices are not processed while we are changing them. */
block_input ();
- if (f)
- adjust_frame_glyphs (f);
- else
- {
- Lisp_Object tail, lisp_frame;
-
- FOR_EACH_FRAME (tail, lisp_frame)
- adjust_frame_glyphs (XFRAME (lisp_frame));
- }
-
- unblock_input ();
-}
-
-/* Allocate/reallocate glyph matrices of a single frame F. */
-
-static void
-adjust_frame_glyphs (struct frame *f)
-{
if (FRAME_WINDOW_P (f))
adjust_frame_glyphs_for_window_redisplay (f);
else
adjust_decode_mode_spec_buffer (f);
f->glyphs_initialized_p = 1;
+
+ unblock_input ();
}
/* Return true if any window in the tree has nonzero window margins. See
w->cursor.vpos = w->cursor.y = 0;
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
calculate_costs (f);
SET_FRAME_GARBAGED (f);
f->resized_p = 1;
{
FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
FRAME_SMALLEST_FONT_HEIGHT (f) = height;
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
}
else
{
if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
- FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
+ FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, f->fonts_changed = 1;
if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
- FRAME_SMALLEST_FONT_HEIGHT (f) = height, fonts_changed_p = 1;
+ FRAME_SMALLEST_FONT_HEIGHT (f) = height, f->fonts_changed = 1;
}
#endif
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
FRAME_MENU_BAR_LINES (f) = nlines;
set_menu_bar_lines_1 (f->root_window, nlines - olines);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
}
}
\f
change_frame_size (f, height, width, 0, 0, 0);
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
calculate_costs (f);
XSETFRAME (frame, f);
unsigned external_tool_bar : 1;
#endif
+ /* Nonzero means that fonts have been loaded since the last glyph
+ matrix adjustments. */
+ unsigned fonts_changed : 1;
+
/* Margin at the top of the frame. Used to display the tool-bar. */
int tool_bar_lines;
x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
do_pending_window_change (0);
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
}
FRAME_TOOL_BAR_LINES (f) = nlines;
resize_frame_windows (f, FRAME_LINES (f), 0);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
/* We also have to make sure that the internal border at the top of
the frame, below the menu bar or tool bar, is redrawn when the
}
FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
w->pseudo_window_p = 1;
/* Display the tooltip text in a temporary buffer. */
width /= WINDOW_FRAME_COLUMN_WIDTH (w);
w->total_cols = width;
FRAME_TOTAL_COLS (f) = width;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
w->pseudo_window_p = 1;
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
}
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
run_window_configuration_change_hook (f);
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
run_window_configuration_change_hook (f);
block_input ();
window_resize_apply (p, horflag);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
/* Set buffer of NEW to buffer of reference window. Don't run
any hooks. */
set_window_buffer (new, r->contents, 0, 1);
recombine_windows (sibling);
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
/* We deleted the frame's selected window. */
w->total_lines -= XINT (value);
/* Enforce full redisplay. FIXME: make it more selective. */
windows_or_buffers_changed++;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
}
}
w->total_lines = 1;
/* Enforce full redisplay. FIXME: make it more selective. */
windows_or_buffers_changed++;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
}
/* If the above failed for whatever strange reason we must make a
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
run_window_configuration_change_hook (f);
visible. */
w->vscroll = (it.last_visible_y
- it.current_y + it.max_ascent + it.max_descent);
- adjust_glyphs (it.f);
+ adjust_frame_glyphs (it.f);
}
else
{
++n;
}
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
unblock_input ();
/* Scan dead buffer windows. */
clear_glyph_matrix (w->current_matrix);
w->window_end_valid = 0;
windows_or_buffers_changed++;
- adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
+ adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
}
\f
/* Adjust glyph matrix of the frame if the virtual display
area becomes larger than before. */
if (w->vscroll < 0 && w->vscroll < old_dy)
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
/* Prevent redisplay shortcuts. */
XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
if (WINDOW_TOTAL_LINES (w) != old_height)
{
clear_glyph_matrix (w->desired_matrix);
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
return 1;
}
}
{
clear_glyph_matrix (w->desired_matrix);
f->n_tool_bar_rows = nrows;
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
return 1;
}
}
last_glyphless_glyph_frame = NULL;
last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
- /* If new fonts have been loaded that make a glyph matrix adjustment
- necessary, do it. */
- if (fonts_changed_p)
- {
- adjust_glyphs (NULL);
- ++windows_or_buffers_changed;
- fonts_changed_p = 0;
- }
-
/* If face_change_count is non-zero, init_iterator will free all
realized faces, which includes the faces referenced from current
matrices. So, we can't reuse current matrices in this case. */
struct frame *f = XFRAME (frame);
if (FRAME_VISIBLE_P (f))
- ++number_of_visible_frames;
+ {
+ ++number_of_visible_frames;
+ /* Adjust matrices for visible frames only. */
+ if (f->fonts_changed)
+ {
+ adjust_frame_glyphs (f);
+ f->fonts_changed = 0;
+ }
+ }
clear_desired_matrices (f);
}
if (!display_last_displayed_message_p)
message_cleared_p = 0;
- if (fonts_changed_p)
- goto retry;
- else if (window_height_changed_p)
+ if (window_height_changed_p)
{
consider_all_windows_p = 1;
++update_mode_lines;
&& !EQ (FRAME_TTY (f)->top_frame, frame))
continue;
+ retry_frame:
+
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
/* Mark all the scroll bars to be removed; we'll redeem
if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
- /* If fonts changed, display again. */
- /* ??? rms: I suspect it is a mistake to jump all the way
- back to retry here. It should just retry this frame. */
- if (fonts_changed_p)
- goto retry;
-
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
{
+ /* If fonts changed on visible frame, display again. */
+ if (f->fonts_changed)
+ {
+ adjust_frame_glyphs (f);
+ f->fonts_changed = 0;
+ goto retry_frame;
+ }
+
/* See if we have to hscroll. */
if (!f->already_hscrolled_p)
{
f->already_hscrolled_p = 1;
if (hscroll_windows (f->root_window))
- goto retry;
+ goto retry_frame;
}
/* Prevent various kinds of signals during display
update:
/* If fonts changed, display again. */
- if (fonts_changed_p)
+ if (sf->fonts_changed)
goto retry;
/* Prevent various kinds of signals during display update.
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
selected_window is redisplayed.
- We can return without actually redisplaying the window if
- fonts_changed_p. In that case, redisplay_internal will
- retry. */
+ We can return without actually redisplaying the window if fonts has been
+ changed on window's frame. In that case, redisplay_internal will retry. */
static void
redisplay_window (Lisp_Object window, int just_this_one_p)
debug_method_add (w, "try_window_id %d", tem);
#endif
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
if (tem > 0)
goto done;
IF_DEBUG (debug_method_add (w, "1"));
if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
/* -1 means we need to scroll.
- 0 means we need new matrices, but fonts_changed_p
+ 0 means we need new matrices, but fonts_changed
is set in that case, so we will detect it below. */
goto try_to_scroll;
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
if (w->cursor.vpos >= 0)
/* If new fonts have been loaded (due to fontsets), give up. We
have to start a new redisplay since we need to re-adjust glyph
matrices. */
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
/* If cursor did not appear assume that the middle of the window is
if (WINDOW_WANTS_MODELINE_P (w)
&& CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
{
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
w->mode_line_height = -1;
MATRIX_MODE_LINE_ROW (w->current_matrix)->height
= DESIRED_MODE_LINE_HEIGHT (w);
if (WINDOW_WANTS_HEADER_LINE_P (w)
&& CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
{
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
w->header_line_height = -1;
MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
= DESIRED_HEADER_LINE_HEIGHT (w);
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
}
}
#endif /* HAVE_WINDOW_SYSTEM */
- /* We go to this label, with fonts_changed_p set,
- if it is necessary to try again using larger glyph matrices.
+ /* We go to this label, with fonts_changed set, if it is
+ necessary to try again using larger glyph matrices.
We have to redeem the scroll bar even in this case,
because the loop in redisplay_internal expects that. */
need_larger_matrices:
{
if (display_line (&it))
last_text_row = it.glyph_row - 1;
- if (fonts_changed_p && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
+ if (f->fonts_changed && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
return 0;
}
w->cursor.vpos = -1;
last_text_row = last_reused_text_row = NULL;
- while (it.current_y < it.last_visible_y
- && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
{
/* If we have reached into the characters in the START row,
that means the line boundaries have changed. So we
if (pt_row == NULL)
w->cursor.vpos = -1;
last_text_row = NULL;
- while (it.current_y < it.last_visible_y && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
if (display_line (&it))
last_text_row = it.glyph_row - 1;
last_text_row = NULL;
overlay_arrow_seen = 0;
while (it.current_y < it.last_visible_y
- && !fonts_changed_p
+ && !f->fonts_changed
&& (first_unchanged_at_end_row == NULL
|| IT_CHARPOS (it) < stop_pos))
{
last_text_row = it.glyph_row - 1;
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
return -1;
/* Display the rest of the lines at the window end. */
it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
- while (it.current_y < it.last_visible_y
- && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
{
/* Is it always sure that the display agrees with lines in
the current matrix? I don't think so, so we mark rows
>= it->w->desired_matrix->nrows)
{
it->w->nrows_scale_factor++;
- fonts_changed_p = 1;
+ it->f->fonts_changed = 1;
return 0;
}
#define IT_EXPAND_MATRIX_WIDTH(it, area) \
{ \
- if (!fonts_changed_p \
+ if (!it->f->fonts_changed \
&& (it->glyph_row->glyphs[area] \
< it->glyph_row->glyphs[area + 1])) \
{ \
it->w->ncols_scale_factor++; \
- fonts_changed_p = 1; \
+ it->f->fonts_changed = 1; \
} \
}
clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
}
#endif /* not USE_X_TOOLKIT && not USE_GTK */
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
run_window_configuration_change_hook (f);
}
FRAME_TOOL_BAR_LINES (f) = nlines;
resize_frame_windows (f, FRAME_LINES (f), 0);
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
/* We also have to make sure that the internal border at the top of
the frame, below the menu bar or tool bar, is redrawn when the
}
FRAME_TOTAL_COLS (f) = w->total_cols;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
w->pseudo_window_p = 1;
/* Display the tooltip text in a temporary buffer. */
width /= WINDOW_FRAME_COLUMN_WIDTH (w);
w->total_cols = width;
FRAME_TOTAL_COLS (f) = width;
- adjust_glyphs (f);
+ adjust_frame_glyphs (f);
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
try_window (FRAME_ROOT_WINDOW (f), pos, 0);