; * src/xdisp.c: Improve commentary. (Bug#64596)

This commit is contained in:
Eli Zaretskii 2023-07-19 17:54:53 +03:00
parent ac075176bf
commit 86f2d6d62f

View file

@ -21,17 +21,17 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
Redisplay. Redisplay.
Emacs separates the task of updating the display from code Emacs separates the task of updating the display -- which we call
modifying global state, e.g. buffer text. This way functions "redisplay" -- from the code modifying global state, e.g. buffer
operating on buffers don't also have to be concerned with updating text. This way functions operating on buffers don't also have to
the display. be concerned with updating the display as result of their
operations.
Updating the display is triggered by the Lisp interpreter when it Redisplay is triggered by the Lisp interpreter when it decides it's
decides it's time to do it. This is done either automatically for time to do it. This is done either automatically for you as part
you as part of the interpreter's command loop or as the result of of the interpreter's command loop, or as the result of calling Lisp
calling Lisp functions like `sit-for'. The C function functions like `sit-for'. The C function `redisplay_internal' in
`redisplay_internal' in xdisp.c is the only entry into the inner xdisp.c is the only entry into the inner redisplay code.
redisplay code.
The following diagram shows how redisplay code is invoked. As you The following diagram shows how redisplay code is invoked. As you
can see, Lisp calls redisplay and vice versa. can see, Lisp calls redisplay and vice versa.
@ -75,35 +75,68 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
and to make these changes visible. Preferably it would do that in and to make these changes visible. Preferably it would do that in
a moderately intelligent way, i.e. fast. a moderately intelligent way, i.e. fast.
Changes in buffer text can be deduced from window and buffer At its highest level, redisplay can be divided into 3 distinct
structures, and from some global variables like `beg_unchanged' and steps, all of which are visible in `redisplay_internal':
`end_unchanged'. The contents of the display are additionally
recorded in a `glyph matrix', a two-dimensional matrix of glyph
structures. Each row in such a matrix corresponds to a line on the
display, and each glyph in a row corresponds to a column displaying
a character, an image, or what else. This matrix is called the
`current glyph matrix' or `current matrix' in redisplay
terminology.
For buffer parts that have been changed since the last update, a . decide which windows on which frames need their windows
second glyph matrix is constructed, the so called `desired glyph considered for redisplay
matrix' or short `desired matrix'. Current and desired matrix are . for each window whose display might need to be updated, compute
then compared to find a cheap way to update the display, e.g. by a structure, called "glyph matrix", which describes how it
reusing part of the display by scrolling lines. The actual update should look on display
of the display of each window by comparing the desired and the . actually update the display of windows on the glass where the
current matrix is done by `update_window', which calls functions newly obtained glyph matrix differs from the one produced by the
which draw to the glass (those functions are specific to the type previous redisplay cycle
of the window's frame: X, w32, NS, etc.).
The first of these steps is done by `redisplay_internal' itself, by
looping through all the frames and testing their various flags,
such as their visibility. The result of this could be that only
the selected window on the selected frame must be redisplayed, or
it could conclude that other windows need to be considered as well.
The second step considers each window that might need to be
redisplayed. This could be only the selected window, or the window
trees of one or more frames. The function which considers a window
and decides whether it actually needs redisplay is
`redisplay_window'. It does so by looking at the changes in
position of point, in buffer text, in text properties, overlays,
etc. These changes can be deduced from window and buffer
structures, and from some global variables like `beg_unchanged' and
`end_unchanged'. The current contents of the display are recorded
in a `glyph matrix', a two-dimensional matrix of glyph structures.
Each row in such a matrix corresponds to a line on the display, and
each glyph in a row corresponds to a column displaying a character,
an image, or what else. This matrix is called the `current glyph
matrix', or `current matrix', in redisplay terminology.
For buffer parts that have been changed since the last redisplay,
`redisplay_window' constructs a second glyph matrix is constructed,
the so called `desired glyph matrix' or short `desired matrix'. It
does so in the most optimal way possible, avoiding the examination
of text that didn't change, reusing portions of the current matrix
if possible, etc. It could, in particular, decide that a window
doesn't need to be redisplayed at all.
This second step of redisplay also updates the parts of the desired
matrix that correspond to the mode lines, header lines, and
tab-lines of the windows which need that; see `display_mode_lines'.
In the third and last step, the current and desired matrix are then
compared to find a cheap way to update the display, e.g. by reusing
part of the display by scrolling lines. The actual update of the
display of each window by comparing the desired and the current
matrix is done by `update_window', which calls functions which draw
to the glass (those functions are specific to the type of the
window's frame: X, w32, NS, etc.).
Once the display of a window on the glass has been updated, its Once the display of a window on the glass has been updated, its
desired matrix is used to update the corresponding rows of the desired matrix is used to update the corresponding rows of the
current matrix, and then the desired matrix is discarded. current matrix, and then the desired matrix is discarded.
You will find a lot of redisplay optimizations when you start You will find a lot of redisplay optimizations when you start
looking at the innards of redisplay. The overall goal of all these looking at the innards of `redisplay_window'. The overall goal of
optimizations is to make redisplay fast because it is done all these optimizations is to make redisplay fast because it is
frequently. Some of these optimizations are implemented by the done frequently. Some of these optimizations are implemented by
following functions: the following functions:
. try_cursor_movement . try_cursor_movement
@ -142,16 +175,17 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
Note that there's one more important optimization up Emacs's Note that there's one more important optimization up Emacs's
sleeve, but it is related to actually redrawing the potentially sleeve, but it is related to actually redrawing the potentially
changed portions of the window/frame, not to reproducing the changed portions of the window/frame as part of the third step, not
desired matrices of those potentially changed portions. Namely, to generating the desired matrices of those potentially changed
the function update_frame and its subroutines, which you will find portions. Namely, the function `update_frame' and its subroutines,
in dispnew.c, compare the desired matrices with the current which you will find in dispnew.c, compare the desired matrices with
matrices, and only redraw the portions that changed. So it could the current matrices, and only redraw the portions that changed.
happen that the functions in this file for some reason decide that So it could happen that the functions in this file for some reason
the entire desired matrix needs to be regenerated from scratch, and decide that the entire desired matrix needs to be regenerated from
still only parts of the Emacs display, or even nothing at all, will scratch, and still only parts of the Emacs display, or even nothing
be actually delivered to the glass, because update_frame has found at all, will be actually delivered to the glass, because
that the new and the old screen contents are similar or identical. `update_frame' has found that the new and the old screen contents
are similar or identical.
Desired matrices. Desired matrices.
@ -161,7 +195,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
redisplay tries to optimize its work, and thus only generates redisplay tries to optimize its work, and thus only generates
glyphs for rows that need to be updated on the screen. Rows that glyphs for rows that need to be updated on the screen. Rows that
don't need to be updated are left "disabled", and their contents don't need to be updated are left "disabled", and their contents
should be ignored. in the desired matrix should be ignored.
The function `display_line' is the central function to look at if The function `display_line' is the central function to look at if
you are interested in how the rows of the desired matrix are you are interested in how the rows of the desired matrix are