These lists are typically empty when we destroy the terminal. However,
if we had queued up damage, and then manage to destroy the terminal
instance before the last changes were rendered, then they will *not*
be empty.
Found by the address sanitizer.
In reset, we allocated new rows for all the currently visible
lines. We did **not** however, free the 'old' rows.
Fix by not explicitly allocating new rows, but instead allocating
uninitialized rows when needed, and then explicitly erasing the row.
If there already was a row allocated, it is simply erased. If there
wasn't, the a new line is malloc:ed, and then erased.
We now create a copy of the config for each client, and updates it
with the values passed from the client.
Since we're not actually cloning it (and e.g. strdup() all strings
etc) we can't call conf_destroy() to free it, but need to free just
the strings we've replaced.
Before, we applied delayed rendering (that is, we gave the client a
chance to do more writes before we scheduled a render refresh) only
when the renderer were idle.
However, with e.g. a high keyboard repeat rate, it is very much
possible to start the render loop and then never break out of it while
receiving keyboard input.
This causes screen flickering, as we're no longer even trying to
detect the clients transaction boundaries.
So, let's rewrite how this is done.
First, we give the user the ability to disable delayed rendering
altogether, by setting either the lower or upper timeout to 0.
Second, when delayed rendering is enabled, we ignore the frame
callback. That is, when receiving input, we *always* reschedule the
lower timeout timer, regardless of whether the render is idle or not.
The render's frame callback handler will *not* render the grid if the
delayed render timers are armed.
This means for longer client data bursts, we may now skip frames. That
is, we're trading screen flicker for the occasional frame hickup.
For short client data bursts we should behave roughly as before.
This greatly improves the behavior of fullscreen, or near fullscreen,
updates of large grids (example, scrolling in emacs in fullscreen,
with a vertical buffer split).
There's a race/chance that we'll have disarmed the delayed rendering
timers and still get the call.
While it _shouldn't_ be anything to read from the timers, it doesn't
hurt to try. And, if the timers *are* readable, not reading them means
we'll end up in an infinite FDM loop.
This adds an undocumented 'tweak' section to footrc, with two new
options:
* delayed-render-lower
* delayed-render-upper
Both takes an integer value, representing the lower/upper timeout
values (in nano seconds) for delayed rendering.
Track whether app-sync updates were enabled or disabled while handling
the current chunk of PTMX data.
This fixes and issue where we called render_refresh() unnecessarily
under (at least) the following conditions:
* Application sent "BSU <data> ESU" in the *same* chunk. In this case
we never saw that app sync was enabled and triggered delayed
rendering as usual.
* Application sent ESU. While we had noticed app sync updates being
enabled in earlier PTMX reads, when it was disabled *in the current*
PTMX read, we treated it as if it had not been enabled at all.
This caused us to trigger delayed rendering.
Now we call render_refresh() directly from ESU, and detect the "flip
off" case in PTMX read and avoid triggering a delayed rendering.
The end result of all this is that each key press (for e.g. scrolling
in a pager application) went from two frames being rendered, to a
single frame.
This fixes an issue where we failed to restore the cursor correctly
when exiting from the alternate screen, if the client had sent escapes
to save the cursor position while inside the alternate screen.
This was because we used the *same* storage for saving the cursor
position through escapes, as for saving it when entering the alternate
screen.
Fix by using a custom variable dedicated to normal <--> alt screen
switching.
Update the sixels' 'row' attribute when re-flowing a grid, to ensure
it is rendered at the correct place.
This should work in most cases, but will break when the cell size has
changed (e.g. font size increase/decrease, or a DPI change).
This patch also moves the sixel image list from the terminal struct
into the grid struct. The sixels are per-grid after all.
This fixes an issue where the fonts were rendered too small when the
output had fractional scaling.
For integral scaling, using the logical (scaled) DPI multiplied with
the scaling factor results in the same final DPI value as if we had
used the physical DPI.
But for fractional scaling, this works around the fact that the
compositor downscales the surface after we've rendered it.
Closes#5
Handle the CSDs and the search box the same way we handle the main
grid; when we need to redraw them, call
render_refresh_{csd,search}(). This sets a flag that is checked after
each FDM iteration. All actual rendering is done here.
This also ties the commits of the Wayland sub-surfaces to the commit
of the main surface.
Some fonts, even monospaced ones, have a negative line gap (line
height < ascent + descent).
Using the font's line height as cell height will result in some glyphs
overflowing into the cell above or below.
Workaround by using which ever value is the largest: the line height
or ascent + descent.
For now, this behavior is controlled with an ifdef. At least kwin
seems very buggy when the decorations are positioned like this (but
normally you'd use server-side decorations with kwin anyway).
This commit also changes 'use_csd' to be a tri-state variable;
when instantiating a window it is set to 'unknown'.
If there's no decoration manager available (e.g. weston), we
immediately set it to 'yes' (use CSDs).
Otherwise, we wait for the decoration manager callback to indicate
whether we should use CSDs or not.
We draw the CSDs in a darker color when we're inactive.
Weston seems to be buggy with synchronized subsurfaces, so temporarily
reconfigure them to desynchronized surfaces.
This is needed to handle pointer motion and button events correctly,
since mouse actions in e.g. CSD surfaces are very different from mouse
actions in the main window.
In unhook, add the generated image to a list of finished sixel images,
along with positioning and size information.
When rendering, loop this list of images, and render the images (or
parts of) that are visible.
When scrolling, check if any part of the images cover the re-cycled
lines, and if so, remove the *entire* image from the list.
This means we have the following limitations:
* The renderer always renders the whole (visible area of) the
image(s). There are times when this isn't necessary - for example,
when the image is scrolled inside the visible area.
* It would be nice if we could crop the image when parts of it is
scrolled out.
This function reloads the font *if* the DPI has changed. To handle
user run-time adjusted font sizes, we record the number of adjustments
made.
Then, when re-loading the font, we first load the font as specified in
the configuration. Then, we re-apply the size adjustment using
font_size_adjust().
Note that this means we end up loading the fonts twice; first using
the default size (but with adjusted DPI), and then again with the
adjusted size. This can probably be improved upon.
The existing font code has been refactored to avoid code
duplication. For example, term_init() now calls
term_font_dpi_changed() to load the initial fonts, instead of directly
instantiating them.
Finally, the way we calculate the DPI to use has changed: instead of
using the highest DPI of all available outputs, we use the highest DPI
of the output's we're actually mapped on. If we're not mapped at all,
we use the globally highest DPI.
Doing it this way means we usually only have to load the fonts
once. Otherwise, we'd end up using the default DPI of 96 when the
terminal is first instantiated (since it's not mapped at that time).
On a single monitor system, we'll use the globally highest DPI at
first, before being mapped. Then when we get mapped, we re-load the
fonts using the highest mapped DPI. But since they'll be the same,
we can skip actually reloading the fonts.