This lessens the burden on (primarily) the compositor, since we no
longer tear down and re-create the SHM pool when scrolling.
The SHM pool is setup once, and its size is fixed at the maximum
allowed (512MB for now, 2GB would be possible).
This also allows us to mmap() the memfd once. The exposed raw pointer
is simply an offset from the memfd mmapping.
Note that this means e.g. rouge rendering code will be able to write
outside the buffer.
Finally, only do this if the caller explicitly wants to enable
scrolling. The memfd of other buffers are sized to the requested size.
Implemented by truncating the file size and moving the offset
backwards. This means we can only reverse scroll when we've previously
scrolled forward.
TODO: figure out if we can somehow do fast reverse scrolling even
though offset is 0 (or well, less than required for scrolling).
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).
shm_scroll() is fast when memmove() is slow. That is, when scrolling
a *small* amount of lines, shm_scroll() is fast.
Conversely, when scrolling a *large* number of lines, memmove() is
fast.
For now, assume the two methods perform _roughly_ the same given a
certain number of bytes they have to touch.
This means we should use shm_scroll() when number of scroll lines is
less than half the screen. Otherwise we use memmove.
Since we need to repair the bottom scroll region after a shm_scroll,
those lines are added to the count when determining which method to
use.
TODO:
* Check if it's worth to do shm scrolling when we have a top scroll
region.
* Do more performance testing with a) various amount of scrolling
lines, and b) larger bottom scroll regions.
When resizing in alt mode, we never updated the saved 'normal'
cursor. This meant that when we exited alt mode, the cursor would be
positioned where it was in the old pre-resize/reflow grid.
Now, we update the saved cursor in the same way we update visible
cursor. The result is that when we exit the alt screen, the cursor
is restored to the same coordinates it would have been updated to had
the resize been done in the 'normal' screen.
This fixes an issue where we sometimes (depends on compositor?) tried
to signal a TIOCSWINSZ and failed. This caused us to log a misleading
error message.
This fixes an issue where an 'underline' cursor wasn't visible on
underlined text - the cursor was rendered first, and then shadowed by
the text underline.
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.
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.
* minimize: a downward triangle
* maximize (window): an upward triangle
* maximize (already maximized): a hollow square
* close: a filled square
The glyphs are now rendered using the default background color instead
of hardcoded to black.
Applications may temporarily change the foreground color. Don't use
this when rendering the CSD title bar - use the default
foreground (i.e the default default one, or the one configured by the
user in footrc).
But it *does* include the title bar. This simplifies the 'adjustment'
needed to be done to the configured window size.
It also fixes a number of issues:
* the compositor will now properly snap the window to screen
edges (before, there was an empty space between the edge and the
window - the CSD border).
* This also removes the need for the mutter 'commit' workaround. We
must be doing something right now.
The user can now configure the following:
* Whether to prefer CSDs or SSDs. But note that this is only a hint to
the compositor - it may deny our request. Furthermore, not all
compositors implement the decoration manager protocol, meaning CSDs
will be used regardless of the user configuration (GNOME/mutter
being the most prominent one).
* Title bar size and color, including transparency
* Border size and color, including transparency
Also drop support for rendering the CSDs inside the main surface.