Add data structure to term->vt. This structure tracks the free-form
data that is passed-through, and the handler to call at the end.
Intermediates and parameters are collected by the normal VT
parser. Then, when we enter the passthrough state, we call dcs_hook().
This function checks the intermediate(s) and parameters, and selects
the appropriate unhook handler (and optionally does some execution
already).
In passthrough mode, we simply append strings to an internal
buffer. This might have to be changed in the future, if we need to
support a DCS that needs to execute as we go.
In unhook (i.e. when the DCS is terminated), we execute the unhook
handler.
As a proof-of-concept, handlers for BSU/ESU (Begin/End Synchronized
Update) has been added (but are left unimplemented).
Previously when updating a selection, we would unmark *all* cells in
the old selection, and then mark all cells in the new selection.
This caused *all* cells to be dirtied and thus re-rendered.
Avoid this, by adding a temporary state to the cells' selected state.
Before unmarking the old selection, pre-mark the new selection using a
temporary state.
When unmarking the old selection, ignore cells in this temporary state.
When marking the new selection, ignore cells in this temporary
state (except clearing the temporary state).
Maintain a view 'offset' (which glyph from the search string to start
rendering at).
This defines the start of the viewable area. The end is the offset +
the search box size (which is limited to the window size).
Adjust this offset whenever the cursor moves outside the viewable
area. For now, this is always done in the same way: set the offset to
the cursor position.
This means that when we're entering text at the end of the search
criteria (i.e. the normal case; we're simply typing), and the search
box reaches the window size, the cursor will jump to the start of the
search box, which will be empty. This could be confusing, but let's go
with for now.
In some cases, we end up calling render_refresh() multiple times in
the same FDM iteration. This means will render the first update
immediately, and then set the 'pending' flag, causing the updated
content to be rendered in the next frame.
This can cause flicker, or flashes, since we're presenting one or more
intermediate frames until the final content is shown.
Not to mention that it is inefficient to render multiple frames like
this.
Fix by:
* render_refresh() only sets a flag in the terminal
* install an FDM hook; this hook loops all terminals and executes what
render_refresh() _used_ to do (that is, render immediately if we're
not waiting for a frame callback, otherwise set 'pending' flag). for
all terminals that have the 'refresh_needed' flag set.
Instead of having the renderer calculate, for each cell, whether that
cell is currently selected or not, make selection_update() mark/unmark
the selected cells.
The renderer now only has to look at the cells' 'selected'
attribute. This makes the renderer both smaller and faster.
This adds a flag, -p,--presentation-timings, that enables input lag
measuring using the presentation time Wayland protocol.
When enabled, we store a timestamp when we *send* a key to the
slave. Then, when we commit a frame for rendering to the compositor,
we request presentation feedback. We also store a timestamp for when
the frame was committed.
The 'presented' callback then looks at the input and commit
timestamps, and compares it with the presented timestamp.
The delay is logged at INFO when the delay was less than one frame
interval, at WARN when it was one frame interval, and at ERR when it
was two or more frame intervals.
We also update statistic counters that we log when foot is shut down.
This is used when spawning the slave, to set its current working
directory just before we exec() the client.
In a regular foot instance, we set the cwd from getcwd().
In a foot server instance, each connecting client sends its cwd to the
server, and we use that.
Instead of trying to figure out if we had to render
something (i.e. something in the grid was dirty), and using that to
determine whether to post a callback or not, we now let
render_refresh() set a flag indication we need to render another
frame.
This simplifies render_grid(), which now _always_ renders, and pushes
it to the compositor.
The callback handler checks the pending flag and simply doesn't call
render_grid() when there's no more pending state to render.
This ends up reducing the number of wakeups when e.g. having a
blinking cursor.
Normally we don't dirty the cell on cursor movement. But, since a
blinking cursor isn't a cursor that has moved, our normal cursor
rendering wont work.
Dirty the cursor cell to force a redraw of it.
Blinking can be enabled either by setting the cursor style with
CSI Ps SP q
and selecting a blinking style.
Or, with 'CSI ? 12 h'
Note that both affect the same internal state. I.e. you can disable
blinking with CSI ? 12l after having selected a blinking cursor
style. This is consistent with XTerm behavior.
The mouse reporting functions are called from input when we receive
Wayland mouse events.
We used to pass the current keyboard modifier (shift, alt, ctrl, etc)
to the terminal functions.
This however is wrong, since we may receive Wayland mouse events
without having keyboard focus. When we don't have keyboard focus, the
modifier state doesn't apply to us.
Remove the modifier arguments from the terminal mouse reporting
functions. These functions now read this state directly instead, but
only when the terminal instance in question has keyboard focus.
When this returns true, it means we have keyboard focus and are
grabbing the mouse (for e.g. selections), regardless of whether the
client has enabled mouse tracking or not.
When support was added for DECOM (absolute/relative row addressing), a
small but noticeable (~3.5%) performance regression was introduced.
Try to improve the situation by simplifying the relative-to-absolute
conversion; only the row needs to be transformed.
The default is absolute mode, where 0,0 is the upper left corner of
the screen.
In relative mode, the origin is relative the top scroll margin.
Internally, we always track the current cursor position in absolute
mode. Every time we the client *sets* or *queries* the cursor position
in relative mode, we translate it to absolute.
Make ptmx non-blocking. Then, when writing data to the slave would
have blocked, use the FDM to asynchronously write the remaining data.
This is done by enabling EPOLLOUT on ptmx, and enqueueing all outgoing
data. The FDM handler will go through the enqueued data, and once all
of it has been written, we turn off EPOLLOUT again (thus switching
back to synchronous writes)
This function unmaps the terminal window, removes itself from the
wayland list of terminals and then finally destroys itself.
We ensure we don't get any callbacks/events referring to a free:d
terminal struct, we close all terminal related FDs and unmap the
wayland window.
Then, to be really really sure there aren't any (by the FDM) queued up
events, we delay the self-destruction to the next FDM poll iteration,
by opening an event FD and adding it to the FDM.
The callback for the event FD removes the FD from the FDM again, and
closes it. And then proceeds to destroy the terminal.