Commit graph

99 commits

Author SHA1 Message Date
Daniel Eklöf
c470825067
wip: multi-seat support
Compiles and runs, but mouse, clipboard and other things have been
disabled.
2020-07-08 16:45:26 +02:00
Daniel Eklöf
159bfddb87
selection: fix typo when extending selection to cover double-width character 2020-06-03 17:31:41 +02:00
Daniel Eklöf
056fd4ffe0
selection: don't allow only half of double-width characters to be selected 2020-06-02 18:21:39 +02:00
Daniel Eklöf
8ad3b9c172
selection: performance: check for < 0 or >= 0 instead of == -1 2020-05-19 18:51:30 +02:00
Daniel Eklöf
08588cd0fc
selection: handle viewport wrap around correctly
When the viewport wraps around, the selection points may be
"incorrect".
2020-05-19 18:49:42 +02:00
Daniel Eklöf
96a4f1b993
term: scrolling: hopefully fix all selection/scrolling related crashes
When scrolling, there are a couple of cases where an existing
selection must be canceled because we cannot meaningfully represent it
after scrolling.

These are when the selection is (partly) inside:

* The top scrolling region
* The bottom scrolling region
* The new lines scrolled in. I.e. re-used lines

For the scrolling regions, the real problem is when the selection
crosses the scrolling region boundary; a selection that is completely
inside a scrolling regions _might_ be possible to keep, but we would
need to translate the selection coordinates to the new scrolling
region lines.

For simplicity, we cancel the selection if it touches the scrolling
region. Period.

The last item, newly scrolled in lines is when the selection covers
very old lines and we're now wrapping around the scrollback history.

Then there's a fourth problem case: when the user has started a
selection, but hasn't yet moved the cursor. In this case, we have no
end point.

What's more problematic is that when the user (after scrolling) moves
the cursor, we try to create a huge selection that covers mostly
empty (NULL) rows, causing us to crash.

This can happen e.g. when reverse scrolling in such a way that we wrap
around the scrollback history.

The actual viewport in this case is something like `-n - m`. But the
selection we'll end up trying to create will be `m - (rows - n)`. This
range may very well contain NULL rows.

To deal with this, we simply cancel the selection.
2020-05-17 15:34:49 +02:00
Daniel Eklöf
5d643e63fe
selection: on_rows_in_view: fix range check 2020-05-17 12:04:08 +02:00
Daniel Eklöf
6902c22a77
selection: copy: insert line break if either cell is empty 2020-05-16 22:29:53 +02:00
Daniel Eklöf
1a8ccb0ffa
selection/render: sync cells' 'selected' bit before rendering
For performance reasons, we track whether a cell is selected or not
using a bit in a cell's attributes.

This makes it easy for the renderer to determine if the cells should
be rendered as selected or not - it just have to look at the
'selected' bit instead of doing a complex range check against the
current selection.

This works nicely in most cases. But, if the cell is updated, the
'selected' bit is cleared. This results in the renderer rendering the
cell normally, i.e. _not_ selected.

Checking for this, and re-setting the 'selected' bit when the cell is
updated (printed to) is way too expensive as it is in the hot path.

Instead, sync the 'selected' bits just before rendering. This isn't so
bad as it may sound; if there is no selection this is a no-op. Even if
there is a selection, only those cells whose 'selected' bit have been
cleared are dirtied (and thus re-rendered) - these cells would have
been re-rendered anyway.
2020-05-16 21:36:08 +02:00
Daniel Eklöf
e3992b8379
selection: update: don't assert on 'start' being set 2020-05-16 21:16:35 +02:00
Daniel Eklöf
e4a2d41f51
selection: don't automatically no-op operations if selection isn't enabled
When the client is capturing the mouse, selection can only be done by
holding done shift.

This is why a lot of selection functions are no-ops if selection isn't
currently enabled.

However, there are many cases where we actually need to modify the
selection. In particular, selection_cancel().

Thus, only check for enabled selection when we're dealing with user
input.

Bonus: this also fixes a bug where an ongoing selection were finalized
as soon as the user released shift, even if he was still holding down
the mouse button.
2020-05-16 21:16:11 +02:00
Daniel Eklöf
38c050746d
selection: on_row_in_view() -> on_rows_in_view(), and now takes a range
This allows us to check the selection once when scrolling, instead of
once for each scrolled in line.
2020-05-16 21:16:11 +02:00
Daniel Eklöf
62e0774319
unicode-combining: store seen combining chains "globally" in the term struct
Instead of storing combining data per cell, realize that most
combinations are re-occurring and that there's lots of available space
left in the unicode range, and store seen base+combining combinations
chains in a per-terminal array.

When we encounter a combining character, we first try to pre-compose,
like before. If that fails, we then search for the current
base+combining combo in the list of previously seen combinations. If
not found there either, we allocate a new combo and add it to the
list. Regardless, the result is an index into this array. We store
this index, offsetted by COMB_CHARS_LO=0x40000000ul in the cell.

When rendering, we need to check if the cell character is a plain
character, or if it's a composed character (identified by checking if
the cell character is >= COMB_CHARS_LO).

Then we render the grapheme pretty much like before.
2020-05-03 11:03:22 +02:00
Daniel Eklöf
d945b68b73
unicode-combine: remove utf8proc dependency
We only used utf8proc to try to pre-compose a glyph from a base and
combining character.

We can do this ourselves by using a pre-compiled table of valid
pre-compositions. This table isn't _that_ big, and binary searching it
is fast.

That is, for a very small amount of code, and not too much extra RO
data, we can get rid of the utf8proc dependency.
2020-05-02 17:29:00 +02:00
Daniel Eklöf
3474624c2c
unicode-combining: completely remove unicode combining characters when feature is disabled 2020-05-01 12:05:38 +02:00
Daniel Eklöf
623329cf23
selection: extract text: also copy combining characters 2020-05-01 11:59:09 +02:00
Daniel Eklöf
69c3e74498
util.h: new header file defining commonly used macros 2020-05-01 11:46:24 +02:00
Daniel Eklöf
035eccbb13
selection: extend: new row must be offsetted with the current view offset 2020-04-04 12:05:40 +02:00
Daniel Eklöf
aa01521ff6
selection: add selection_extend()
This function extends an existing selection in the following way:

If the extension point is *before* the upper boundary of the current
selection, extend the selection upwards.

If the extension point is *after* the bottom boundary of the current
selection, extend the selection downwards.

If the extension point is *inside* the current selection, shrink the
selection such that the new size is maximized. This means we move the
*closest* start/end point from in the current selection.
2020-04-04 11:59:15 +02:00
Daniel Eklöf
ce8005545d
term: convert cell 'linefeed' attribute to a row 'linebreak' property
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.
2020-02-14 22:39:26 +01:00
Daniel Eklöf
b28a742a00
selection: handle line break at last column correctly
Insert a newline into the selection even if the last column contained
a printable character, *if* that column also has linefeed=1.
2020-02-11 19:36:31 +01:00
Daniel Eklöf
3957d50a8a
Revert "selection: use edge-triggered FDM handlers"
This reverts commit 5bac3cfa2c.
2020-01-10 19:49:48 +01:00
Daniel Eklöf
5bac3cfa2c
selection: use edge-triggered FDM handlers 2020-01-10 19:24:04 +01:00
Daniel Eklöf
40bb63e206
selection: finalize: ignore whether selections are 'enabled' or not
This fixes an issue where a "forced" selection (shift being pressed
while slave is tracking mouse events) would not finalize if the user
released shift *before* releasing the mouse button.
2020-01-06 11:59:26 +01:00
Daniel Eklöf
457eb573c4
selection: update: don't dirty cells that don't change state
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).
2020-01-06 11:56:18 +01:00
Daniel Eklöf
6833abf33c
selection: foreach_selection_*: must wrap row number
Fixes occasional crashes when we're at the end of the grid and
selection wraps around.
2020-01-05 15:38:45 +01:00
Daniel Eklöf
a83c9e2813
selection: min_bufsize_for_extraction: add one extra column for *all* rows 2020-01-04 14:06:39 +01:00
Daniel Eklöf
4c78b0203e
selection: rename selection_cell_count -> min_bufsize_for_extraction 2020-01-04 13:56:52 +01:00
Daniel Eklöf
e6f0483294
selection: cell count now adds one extra column per row, for \n
When we extract text, we may insert '\n' at the end of each line (or
last column of selection, for block selections).

These newlines doesn't occupy any physical cells, and thus we
must **make** room for them in the extraction buffer.
2020-01-04 13:53:30 +01:00
Daniel Eklöf
6ee86be1bf
selection: fix bug where first column on all rows but the first was lost
When extracting text from the selection, we lost the first column on
all rows but the first.

This is because the algorithm changed slightly when we moved to
foreach_selection(); the end-of-line detection is now done on the
first column of the new line, instead of the last column on the
previous line.
2020-01-04 13:19:30 +01:00
Daniel Eklöf
e28cb989d8
selection: simplify extraction by converting to UTF-8 at the end
Instead of converting a cell at a time to UTF-8, copy the wide
characters as is, and then convert everything at once at the end.
2020-01-04 13:09:06 +01:00
Daniel Eklöf
975a35ae16
selection: extract_selection now uses foreach_selected()
This "automagically" adds support for block selections, since
foreach_selected already handles block selections.
2020-01-04 13:01:00 +01:00
Daniel Eklöf
2a531327dd
selection: selection_cancel() now sets 'kind' to SELECTION_NONE 2020-01-04 12:09:09 +01:00
Daniel Eklöf
f12b1473fd
selection: store cell 'selected' state in the cells' attributes
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.
2020-01-04 12:03:04 +01:00
Daniel Eklöf
d706e68280
selection: track selection type; normal or block selection 2020-01-03 23:29:45 +01:00
Daniel Eklöf
c6e46bbfac
selection: remove unneeded wayland display roundtrips 2020-01-03 21:01:07 +01:00
Daniel Eklöf
2f475d7b44
selection: optimize \r\n -> \n when receiving clipboard data
Instead of first memmoving, possibly lots of data lots of times, the
received buffer, and _then_ calling the callback, simply call the
callback multiple times, and just skip the \r character(s).
2019-12-15 12:11:12 +01:00
Daniel Eklöf
198529525c
selection: break out isword() to a new file 2019-12-03 19:16:58 +01:00
Daniel Eklöf
2208f4304b
term: add term_mouse_grabbed()
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.
2019-11-30 17:06:15 +01:00
Daniel Eklöf
edb78575c7
selection: forced selection requires keyboard focus
Up the requirements for enabling "forced" selection (that is, allowing
selections even though mouse tracking has been disabled).

* Require keyboard focus (if we don't have it, then the shift-key
  isn't is for us)
* Don't just require shift being pressed, but that all other modifiers
  are *not* pressed.
2019-11-30 11:59:47 +01:00
Daniel Eklöf
903581b7eb
async: first synchronous write may succeed partially
When trying to write (to e.g. the slave, or to a clipboard receiver),
we first try to send the data synchronously, and only if that fails do
we switch to asynchronous mode.

However, the first synchronous may (in fact, is likely to) succeed
partially.
2019-11-28 19:20:25 +01:00
Daniel Eklöf
fc7069e1a6
selection: text_to_clipboard: assert the clipboard serial is not 0 2019-11-22 21:55:47 +01:00
Daniel Eklöf
f9e7ae8a89
selection: selection_to_clipboard: exit early on no-selection
When there's no selection, exit early to avoid trying to get grid data
from row -1.
2019-11-22 21:55:47 +01:00
Daniel Eklöf
da92abef31
selection: we already have a direct pointer to the clipboard struct 2019-11-22 21:55:46 +01:00
Daniel Eklöf
b31c18c741
selection: buffer may be empty if only empty cells where selected 2019-11-16 10:56:10 +01:00
Daniel Eklöf
15b12f45c6
scan-build: fix a couple of minor warnings from a scan-build run 2019-11-05 10:39:36 +01:00
Daniel Eklöf
b17358bd0a
selection: make text_from_{clipboard,primary} async 2019-11-05 09:09:51 +01:00
Daniel Eklöf
dd57418494
selection: initialize 'ctx' before jumping into its scope 2019-11-05 08:51:10 +01:00
Daniel Eklöf
b15032d223
selection: text_from_{clipboard,primary}: add 'done' callback
This callback is *always* called, including when there has been an
error.

This is in preparation for making text_from_{clipboard,primary}
asynchronous.
2019-11-05 08:49:32 +01:00
Daniel Eklöf
9cd22dc398
selection: async send: handle POLLHUP 2019-11-05 08:40:39 +01:00