This allows us to update the jump label positions when the viewport
changes.
This in turn allows us to stay in URL mode while the user is using the
mouse to scroll in the scrollback history.
Scrolling with the keyboard is currently not possible, since input
handling in URL mode does not recognize “regular” key bindings. We
_could_ add scrollback up/down bindings to URL mode too, but lets not,
for the time being.
(Note: an alternative to this patch is to disallow mouse scrolling
too. Then we could have kept the URL start/end as viewport local
coordinates).
When making sure we don't scroll past the scrollback history, and the
current offset was exactly at the wrap around, the new view port was
set to offset+1, which in this particular case meant outside the valid
row numbers.
When we scroll up, we need to ensure that we don't scroll too far,
"past" the scrollback limit. I.e. we need to ensure we don't wrap
around.
The code did this. But, in certain scenarios, the resulting view
points into uninitialized scrollback history.
This happens when we haven't yet filled the entire scrollback, and
scroll up enough lines to wrap around the scrollback. The old code
would adjust the view for the wrap around, but doing so pointed the
view at the not-yet utilized scrollback.
When doing "small" scrolls (typically done via mouse wheel or
similar), we render the scrolling by emitting a "scroll damage".
A recent commit changed how scroll damage is rendered; only when the
view is at the bottom ("following" the screen output) do we render the
damage.
To fix this, add a new type of scroll damage,
SCROLL_DAMAGE_IN_VIEW and SCROLL_DAMAGE_REVERSE_IN_VIEW.
These signal to the renderer that it should always render the damage.
With this assumption, we can replace 'a % b' with 'a & (b - 1)'. In
terms of instructions, this means a fast 'and' instead of a slow
'div'.
Further optimize scrolling by:
* not double-initializing empty rows. Previously, grid_row_alloc()
called calloc(), which was then followed by a memset() when
scrolling. This is of course unnecessary.
* Don't loop the entire set of visible rows (this was done to ensure
all visible rows had been allocated, and to prefetch the cell
contents).
This isn't necessary; only newly pulled in rows can be NULL. For
now, don't prefetch at all.
When scrolling through the scrollback lines, use scroll damage instead
of re-rendering the entire screen whenever it makes sense. I.e. when
the number of lines isn't a whole page or more.
The row array may now contain NULL pointers. This means the
corresponding row hasn't yet been allocated and initialized.
On a resize, we explicitly allocate the visible rows.
Uninitialized rows are then allocated the first time they are
referenced.
Can scroll up and down, and stops when the beginning/end of history is
reached.
However, it probably breaks when the entire scrollback buffer has been
filled - we need to detect when the view has wrapped around to the
current terminal offset.
The detection of when we've reached the bottom of the history is also
flawed, and only works when we overshoot the bottom with at least a
page.
Resizing the windows while in a view most likely doesn't work.
The view will not detect a wrapped around scrollback buffer. I.e. if
the user has scrolled back, and is stationary at a view, but there is
still output being produced. Then eventually the scrollback buffer
will wrap around. In this case, the correct thing to do is make the
view start following the beginning of the history. Right now it
doesn't, meaning once the scrollback buffer wraps around, you'll start
seeing command output...