xdg_output_handle_logical_size() reports _logical_ output size. That
is, it is scaled by the output's scale factor.
We want the _actual_ DPI. The _real_ output size is reported by
output_mode(), so use that instead.
Apparently, a frame callback for the cursor surface is *never*
triggered if we get a pointer-leave event *before* the callback is
triggered. At least on Sway 1.4.
This caused the cursor being stuck, and never updating once this state
was reached.
Fix by destroying the cursor frame callback on pointer-leave.
The 'last-row' variable points to the last row the cursor is *on*,
thus it's not a counter, and we need to add one when calculating the
new grid offsets, or we get an off-by-one error.
With this, there's no longer any need to scroll the reflowed text.
To do text reflow, we only need to know if a line has been explicitly
linebreaked or not. If not, that means it wrapped, and that we
should *not* insert a linebreak when reflowing text.
When reflowing text, when reaching the end of a row in the old grid,
only insert a linebreak in the new grid if the old row had been
explicitly linebreaked.
Furthermore, when reflowing text and wrapping a row in the new grid,
mark the previous row as linebreaked if either the last cell was
(the last column in the last row) empty, or the current cell (the
first column in the new row) is empty. If both are non-empty, then we
assume a linewrap.
A window resize doesn't necessarily mean the grid layout changes. When
it doesn't, don't reflow text.
This fixes a slowness issue on Sway, when swapping positions of two
~equally sized windows.
This was intended to prevent a new prompt from being printed on a
newline. However, it breaks normal output under certain conditions,
that have yet to be determined exactly what they are.
When cursor.lcf is set, that means the cursor column was *not*
incremented when we printed the last character. Thus, we should *not*
decrement the column before setting the linefeed bit.
When current view is at a grid wrap around (last emitted row index is
< grid offset), the cursor row ended up being negative which we then
mapped to the top line.
This is wrong. When we're at a wrap around, re-adjust cursor by adding
the grid's row count.
To handle text reflow correctly when a line has a printable character
in the last column, but was still line breaked, we need to track the
fact that the slave inserted a line break here.
Otherwise, when the window width is increased, we'll end up pulling up
the next line, when we really should have inserted a line break.
The algorithm is as follows:
Start at the beginning of the scrollback. That is, at the oldest
emitted lines. This is done by taking the current offset, and adding
the number of (old) screen rows, and then iterating until we find the
first allocated line.
Next, we iterate the entire old grid. At the beginning, we allocate a
line for the new grid, and setup a global pointer for that line, and
the current cell index.
For each line in the old grid, iterate its cells. Copy the the cells
over to the new line. Whenever the new line reaches its maximum number
of columns, we line break it by increasing the current row index and
allocating a new row (if necessary - we may be overwriting old
scrollback if the new grid is smaller than the old grid).
Whenever we reach the end of a line of the old grid, we insert a line
break in the new grid's line too **if** the last cell in the old line
was empty. If it was **not** empty, we **don't** line break the new
line.
Furthermore, empty cells in general need special consideration. A line
ending with a string of empty cells doesn't have to be copied the new
line. And more importantly, should **not** increase the new line's
cell index (which may cause line breaks, which is incorrect).
However, if a string of empty cells is followed by non empty cells, we
need to copy all the preceding empty cells to the line too.
When the entire scrollback history has been reflowed, we need to
figure out the new grid's offset.
This is done by trying to put the **last** emitted line at the bottom
of the screen. I.e. the new offset is typically "last_line_idx -
term->rows". However, we need to handle empty lines. So, after
subtracting the number of screen rows, we _increase_ the offset until
we see a non-empty line. This ensures we handle grid's that doesn't
fill an entire screen.
Finally, we need to re-position the cursor. This is done by trying to
place the cursor **at** (_not_ after) the last emitted line. We keep
the current cursor column as is (but possibly truncated, if the grid's
width decreased).