[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [NonGNU ELPA] New packages: corfu-doc and corfu-doc-terminal

From: Eli Zaretskii
Subject: Re: [NonGNU ELPA] New packages: corfu-doc and corfu-doc-terminal
Date: Sun, 29 May 2022 09:26:14 +0300

> From: Akib Azmain Turja <akib@disroot.org>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org, ibluefocus@outlook.com
> Date: Sun, 29 May 2022 02:40:07 +0600
> >> I think the best solution will be to implement child frames in terminal.
> >> AFAIK, ncurses has a concept of floating window, which we can use to
> >> render the frame.
> >
> > The difficulty in implementing child frames on TTY are not because
> > Emacs cannot draw on TTY at arbitrary coordinates, it's because there
> > are fundamental design principles on which TTY display is based.  I'd
> > actually recommend to implement child frames on TTY as a special kind
> > of window that is free of the "normal" window geometry restrictions.
> I can't understand.  Emacs uses ncurses, and ncurses uses a single type
> for both root window (the ncurses window covering the whole terminal; I
> can't remember the name ncurses uses for this) and other windows.  Does
> Emacs assume while render a frame that its drawing on the root window or
> is it impossible to tell ncurses precisely which window to draw above?

First, Emacs uses ncurses in a very limited manner.  Basically, it
just uses the functions that move the cursor and turn on/off various
attributes, like bold, inverse video, and colors.  I think the only
significant API from ncurses we use is tputs.  Emacs certainly does
NOT use any window-related facilities of ncurses; instead, it manages
the windows by itself.

Next, you need to understand how the Emacs display works on TTY
terminals.  The basis for the Emacs display (on both GUI and TTY
terminals) is a canvas-like model of what should be on the glass,
called "glyph matrix".  A glyph matrix is a 2-dimensional array where
each element corresponds to a character position on the screen (on GUI
terminals, we can also show display elements other than characters:
images, stretches of whitespace, xwidgets, etc.).  When performing
redisplay, Emacs first generates the up-to-date contents of the glyph
matrix, and then redraws the portions of the screen where the actual
screen contents differ from what the glyph matrix says.

Now, on GUI displays, each _window_ (not frame!) has its own glyph
matrix, and redisplay proceeds by walking the window tree and updating
each window which for some reason needs to be redrawn, partially or
fully.  By contrast, on TTY displays, the glyph matrices of the
windows are actually sub-matrices of a larger frame glyph matrix.  So
in TTY redisplay, when Emacs updates the glyph matrices of the
individual windows, it indirectly updates the glyph matrix of the
frame that is the parent of those windows.  Then the entire frame is
updated on the screen by comparing the frame glyph matrix to what is
actually on display.

I hope you now see why I suggested to treat child frames on TTY as
special kinds of windows: if we do that, we "just" need to support
windows whose glyph matrix partially overlaps those of the other
windows, and make sure we update the glyph matrices of the child
frame's windows _after_ we are done with all the windows of the parent
frame.  This way, the frame glyph matrix that is eventually used to
update what's on the glass will correctly reflect what should be on
the screen.

Stefan mentioned the TTY menus as a possible model for implementing
child frames, but I don't think I agree: the implementation of TTY
menus only works well because selecting from a menu is a single user
operation, during which the display is not important, so it is
effectively kept outdated.  We cannot do that for child frames.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]