Commit graph

5584 commits

Author SHA1 Message Date
Daniel Eklöf
688bf1bd59
changelog: crash when resizing window, or scrolling 2022-08-31 19:16:06 +02:00
Daniel Eklöf
23871d4db5
grid: reflow: assert there aren’t any open URIs on the last row 2022-08-31 19:16:05 +02:00
Daniel Eklöf
22989ef9b3
grid: reflow: don’t line-wrap the last row
Before this patch, we would line-wrap the last row, just like any
other row, and then afterwards try to reverse this, by adjusting the
offset and free:ing and NULL:ing the "last row".

The problem with this is if the scrollback is full. In this case, the
row we’re freeing is the first row in the scrollback history. This
means we’ll crash as soon as the viewport is moved to the top of the
scrollback.

The fix is fairly, simple. Skip the post-processing logic, and instead
detect when we’re line-wrapping the last row, and skip the call to
line_wrap().

This way, the last row in the new grid corresponds to the last row in
the old grid.
2022-08-31 19:16:04 +02:00
Daniel Eklöf
649d56a4e5
grid: when setting the new viewport, ensure it’s correctly bounded
Do this by using scrollback relative coordinates, and ensure the new
viewport is not larger than (grid_rows - screen_rows), as that would
mean the viewport crosses the scrollback wrap-around.
2022-08-31 19:16:02 +02:00
Daniel Eklöf
d810e4fc8e
selection: mark_selected_region(): use an enum to encode how the cells are to be updated 2022-08-31 19:15:54 +02:00
Daniel Eklöf
2354298eca
selection: restore <= 1.12 behavior in block selection wrt empty cells
That is, highlight empty cells, regardless of whether they’re trailing
or not.
2022-08-31 19:15:51 +02:00
Daniel Eklöf
03d3887e6b
ci (sr.ht): pull directly from git.sr.ht 2022-08-31 19:15:48 +02:00
Daniel Eklöf
6f1cf6fc56
selection: once again highlight non-trailing empty cells
Foot 1.13.0 introduced a regression where non-trailing empty cells
were highlighted inconsistently (cells that shouldn’t be highlighted,
were, seemingly at random).

86663522d5 “fixed” this by never
highlighting *any* empty cells.

This meant the behavior, compared to foot 1.12 and earlier,
changed. In foot 1.12 and older versions, non-trailing empty cells
were highlighted, as long as the selection covered at least one of the
trailing non-empty cells.

This patch restores that behavior.

To understand how this works, lets first take a look at how selection
works:

When a selection is made, and updated (i.e. the mouse is dragged, or
the selection is extended through RMB etc), we need to (un)tag and dirty
the cells that are a) newly selected, or b) newly deselected. That is,
we look at the diff between the “old” and the “new” selection, and
only update those cells.

This is for performance reasons: iterating the entire selection is not
feasible with large selections. However, it also means we cannot
reason about empty cells; we simply don’t know if an empty cells is a
trailing empty cell, or a non-trailing one.

Then, when we render a frame, we iterate all the *visible*
and *selected* cells, once again tagging them as selected (this is
needed since a selected cell might have lost its selected tag if the
cell was written to, by the client application, after the selection
was made).

At this point, we *can* reason about empty cells.

So, to restore the highlighting behavior to that of foot 1.12, we do
this:

When working with the selection diffs when a selection is updated, we
don’t special case empty cells at all. Thus, all empty cells covered
by the selection is highlighted, and dirtied.

But, when rendering the frame, we _do_ special case them. The only
difference (compared to foot 1.12) is that we *must*
explicitly *clear* the selection tag, and dirty the empty cells. This
is to ensure the empty cells that were incorrectly highlighted by the
selection update algorithm, isn’t rendered as that.

This does have a slight performance impact, as empty cells are now
always re-rendered. The impact should however be small.
2022-08-31 19:15:44 +02:00
Daniel Eklöf
736babcdbc
selection: never highlight selected, empty cells
This fixes a regression, where empty cells "between" non-empty
cells (i.e. non-trailing empty cells) sometimes were incorrectly
highlighted.

The idea has always been to highlight exactly those cells that will
get extracted when they’re copied. This means we’ve not highlighted
trailing empty cells, but we _have_ highlighted other empty cells,
since they are converted to spaces when copied (whereas trailing empty
cells are skipped).

fa2d9f8699 changed how a selection is
updated. That is, which cells gets marked as selected, and which ones
gets unmarked.

Since we no longer walk all the cells, but instead work with pixman
regions representing selection diffs, we can no longer determine (with
certainty) which empty cells should be selected and which shouldn’t.

Before this patch (but after
fa2d9f8699), we sometimes incorrectly
highlighted empty cells that should not have been highlighted. This
happened when we’ve first (correctly) highlighted a region of empty
cells, but then shrink the selection such that all those empty cells
should be de-selected.

This patch changes the selection behavior to *never* highlight empty
cells. This fixes the regression, but also means slightly different
behavior, compared to pre-fa2d9f86996467ba33cc381f810ea966a4323381.

The other alternative is to always highlight all empty cells. But,
since I personally like the fact that we’re skipping trailing empty
cells, I prefer the approach taken by this patch.
2022-08-31 19:14:18 +02:00
Daniel Eklöf
ccef435736
ci: codespell: ignore ‘zar’ (user who contributed) 2022-08-31 19:14:03 +02:00
Daniel Eklöf
20b8ca1601
input: ignore pointer motion events on unknown surfaces
In some cases, the compositor sends a pointer enter event with a NULL
surface. It’s unclear if this is a compositor bug, or a race (where
the compositor sends an enter event on a CSD surface at the same time
foot unmaps the CSDs). Regardless, this causes seat->mouse_focus to be
unset, which triggers a crash in foot on the next pointer motion
event.

This patch does two things:

a) log a warning when we receive a pointer event with a NULL surface
b) ignore motion events where seat->mouse_focus is NULL
2022-08-12 16:15:55 +02:00
Daniel Eklöf
5697348b46
wayland: #ifdef on XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
This enables us to compile against wayland-protocols < 1.25
2022-08-12 16:15:53 +02:00
Daniel Eklöf
1cf22846a0
render: apply a dimmed overlay while in Unicode input mode 2022-08-12 16:15:50 +02:00
Daniel Eklöf
157b64098a
changelog: add new ‘unreleased’ section 2022-08-12 16:15:47 +02:00
Daniel Eklöf
e0465d3a7a
meson: bump version to 1.13.0 2022-08-07 09:32:02 +02:00
Daniel Eklöf
e3eefdacde
changelog: prepare for 1.13.0 2022-08-07 09:31:56 +02:00
Daniel Eklöf
aaf5894ad9
grid: get rid of empty row at the bottom after reflowing
When the window is resized and we reflow the text, we ended up
inserting an empty row at the bottom.

This happens whenever the actual last row has a hard linebreak (which
almost always is the case); we then end the reflow with a line break,
causing an extra, empty, row to be allocated and inserted.

This patch fixes this by detecting when:

1) the last row is empty
2) the next to last row has a hard line break

In this case, we roll back the last line break, by adjusting the new
offset we just calculated, and free:ing the empty row.

TODO: it would be nice if we could detect this in the reflow loop
instead, and avoid doing the last line break all together. I haven’t
yet been able to find a way to do this correctly.

Closes #1108
2022-08-05 18:26:37 +02:00
Simon Ser
129e1a9b8e Add support for xdg_toplevel.wm_capabilities
See https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/122
2022-08-04 14:23:03 +02:00
Simon Ser
2f68b421bf Add no-op xdg_toplevel.configure_bounds handler
Next commit uses v5.
2022-08-03 13:50:13 +02:00
Max Gautier
ffdac61e2a
server: Use "normal" socket activation, not inetd
Systemd, when doing socket activation, pass file descriptors in a
non-stable order when there is multiples ones.

But we only use one, so we don't need to identify it, and the file
descriptors always start at 3.
So use 3 for the systemd service.

Source : sd_listen_fds (systemd man pages)

We also need to unset variables systemd pass to socket activated
process, since we don't need them and sub-process (footclient and
theirs forks) could be confused by those.

Closes #1107
2022-07-30 15:13:56 +02:00
Daniel Eklöf
c0a7c7bf0d
config: reset errno before calling getline() again
Related to #1107
2022-07-29 21:27:27 +02:00
Daniel Eklöf
0cbd99710b
unicode-mode: ‘q’ aborts Unicode input mode 2022-07-29 11:56:41 +02:00
Daniel Eklöf
001f96c4e3
unicode-input: move input (key press) handling to unicode_mode_input() 2022-07-29 09:26:42 +02:00
Daniel Eklöf
8967dd9cfe
input: add new Unicode input mode
This mode is activated through the new key-bindings.unicode-input and
search-bindings.unicode-input key bindings.

When active, the user can “build” a Unicode codepoint by typing its
hexadecimal value.

Note that there’s no visual feedback in this mode. This is
intentional. This mode is intended to be a fallback for users that
don’t use an IME.

Closes #1116
2022-07-29 09:26:31 +02:00
Daniel Eklöf
fa2d9f8699
selection: rework how we update a selection
Before this patch, each selection update would result in grid covered
by the selection being walked *three* times. First to “premark” the
area that *will* be selected after the update, then again to unmark
the previous selection (excluding the cells that were premarked - but
the cells are still iterated), and then one more time to finalize the
selection state in the grid.

Furthermore, each time a frame is rendered, the entire selection were
iterated again, to ensure all the cells have their ‘selected’ bit
set.

This quickly gets *very* slow.

This patch takes a completely different approach. Instead of looking
at the selection as a range of cells to iterate, we view it as an
area, or region. Thus, on each update, we have to regions: the region
representing the previous selection, and the region representing the
to-be selection.

By diffing these two regions, we get two new regions: one that
represents the cells that were selected, but aren’t any more, and one
that represents the cells that previously were not selected, but now
will be.

We implement the regions using pixman regions. By subtracting the
current selection from the previous selection, we get the region
representing the cells that are no longer selected, and that should be
unmarked.

By subtracting the previous selection from the current, we get the
region representing the cells that was added to the selection in this
update, and that should be marked.

selection_dirty_cells() is rewritten in a similar manner. We create
pixman regions for the selection, and the current scrollback view. The
intersection represents the (selected) cells that are visible. These
need to iterated and marked as being selected.

Closes #1114
2022-07-28 21:06:58 +02:00
Daniel Eklöf
b8506bbea0
selection: extend: use scrollback relative coordinates
When extending a selection, we determine *how* to extend it (which
endpoint to move, and whether to grow or shrink the selection) by
comparing the extension point with the old start and end coordinates.

For this to work correctly, we need to use scrollback relative
coordinates.

This fixes an issue where extending a very large selection (covering
many pages) sometimes shrunk the selection instead of growing it, or
just misbehaving in general.
2022-07-28 21:06:58 +02:00
Daniel Eklöf
6ebf55572e
selection: foreach_selected_*(): refactor: use grid_row_abs_to_sb() 2022-07-28 21:06:58 +02:00
Daniel Eklöf
a05eaf28bd
selection: selection_on_rows(): use scrollback relative coords
When checking if the current selection intersects with the
region (passed as parameter to the function), use scrollback relative
coordinates.

This fixes an issue where selections crossing the scrollback
wrap-around being misdetected, resulting in either the selection being
canceled while scrolling, even though it wasn’t scrolled out, or the
selection _not_ being canceled, when it _was_ scrolled out.
2022-07-28 21:06:57 +02:00
Daniel Eklöf
632c4839cd
search: find_next(): handle trailing SPACER cells
Make sure to increment match_end_col to account for trailing SPACER
cells after a match.

This fixes an issue where search matches weren’t highlighted correctly
when the match *ends* with a double-width character.
2022-07-28 21:05:06 +02:00
Daniel Eklöf
d79a3b9350
config: add colors.search-box-{no-,}match
Closes #1112
2022-07-28 19:02:56 +02:00
Daniel Eklöf
4873004c37
test: config: test colors.{jump-labels,scrollback-indicator} 2022-07-28 19:02:55 +02:00
Daniel Eklöf
801970aa33
input: kitty: always treat composed characters as ‘printable’
Certain dead key combinations results different escape sequences in
foot, compared to kitty, when the kitty keyboard protocol is used.

        if (composed && is_text)
            key = utf32;
        else {
            key = xkb_keysym_to_utf32(sym_to_use);
            if (key == 0)
                return false;

            /* The *shifted* key. May be the same as the unshifted
             * key - if so, this is filtered out below, when
             * emitting the CSI */
            alternate = xkb_keysym_to_utf32(sym);
        }

If is_text=false, we’ll fall through to the non-composed
logic. is_text is set to true if the character is printable *and*
there aren’t any non-consumed modifiers enabled.

shift+space is one example where shift is *not* consumed (typically -
may be layouts where it is).

As a result, pressing ", followed by shift+space with the
international english keyboard layout (where " is a dead key) results
in different sequences in foot and kitty.

This patch fixes this by always treating composed characters as
printable.

Closes #1120
2022-07-28 19:02:25 +02:00
Daniel Eklöf
4abf46955f
keymap: change alt+escape to emit \E\E instead of a CSI 27 sequence
Closes #1105
2022-07-28 19:02:05 +02:00
Daniel Eklöf
24c2d56804
render: it’s unlikely() the current cell is where the cursor is 2022-07-28 18:55:34 +02:00
Daniel Eklöf
87e4004960
csi: clamp color index for ‘CSI 38/48 ; 5 ; idx m’ sequences
Indexed color values are stored in the cell attributes as color
indices (into the 256-color table). However, the index from the CSI
was not validated in any way, meaning you can do something like this:

  echo -e ‘\e[38:5:1024m CRASH \e[m’

and foot will crash on an out-of-bounds access.

Fix by clamping the color index.

Closes #1111
2022-07-22 10:44:33 +02:00
Daniel Eklöf
0c60bb3f29
grid: reflow: require col count > 0 when skipping line truncation
When reflowing the grid, we truncate lines with a hard linebreak after
the last non-empty cell. This way we don’t reflow trailing empty cells
to a new line when resizing the window to a smaller size.

However, “logical” lines (i.e. those without a hard linebreak)
are *not* truncated. This is to ensure we don’t trim empty cells in
the middle of a logical line spanning multiple physical lines.

Since newly allocated rows are initialized with linebreak=false, we
need to ensure _those_ are still truncated - otherwise all that empty
space under the current prompt will be reflowed.

Note that this is a temporary workaround. The correct solution, I
think, is to track whether a line has been printed to or not, and
simply ignore (not reflow) lines that haven’t yet been touched.
2022-06-30 19:47:18 +02:00
Daniel Eklöf
37f094280b
Revert "grid: invert the default value of ‘linebreak’, from false to true"
This reverts commit cdd46cdf85.
2022-06-30 19:37:01 +02:00
Daniel Eklöf
d58290ea12
input: don’t ignore keyboard enter/leave events when there’s no keymap
The compositor _usually_ sends the keymap event *before* the enter
event. But not always.

Not (yet) having a keymap is not a reason to ignore the enter
event (now, on the other hand, getting a key press/release event
without a keymap is a compositor bug).

Closes #1097
2022-06-28 20:57:48 +02:00
Daniel Eklöf
206e9a1050
selection: wl_data_offer_set_action: use enum values instead of magic integers 2022-06-21 19:46:31 +02:00
Daniel Eklöf
6d4d4502e9
selection: reject dnd offers with unsupported mime-types
We were already doing this, implicitly, *if* the offer was for the
main grid.

This patch makes it more clear that we do not accept the offer.
2022-06-20 20:57:26 +02:00
Daniel Eklöf
0d22e9fa01
selection: explicitly reject *all* dnd offers not targeting the grid 2022-06-20 20:57:23 +02:00
Daniel Eklöf
2e4da6fbf6
selection: ignore drag-and-drops with unsupported mime-types
Specifically, make sure we do *not* call wl_data_offer_receive() with
a NULL mime-type, as this causes libwayland to error out, which in
turn causes foot to exit.

Closes #1092
2022-06-20 20:56:11 +02:00
Daniel Eklöf
bfc53d1e71
shm-formats: #ifdef on formats added in 1.20 2022-06-20 19:20:28 +02:00
Daniel Eklöf
fabffd626b
wayland: log human readable SHM format names in debug builds 2022-06-20 18:58:40 +02:00
Daniel Eklöf
8689389523
key-binding: set BIND_ACTION_KEY_COUNT correctly
When the new promp-prev/next bindings were added, we forgot to update
BIND_ACTION_KEY_COUNT to reflect this.
2022-06-17 18:42:42 +02:00
Daniel Eklöf
bdb79e8b9f
osc: add support for OSC 133;A (prompt markers)
This patch adds support for the OSC-133;A sequence, introduced by
FinalTerm and implemented by iTerm2, Kitty and more. See
https://iterm2.com/documentation-one-page.html#documentation-escape-codes.html.

The shell emits the OSC just before printing the prompt. This lets the
terminal know where, in the scrollback, there are prompts.

We implement this using a simple boolean in the row struct ("this row
has a prompt"). The prompt marker must be reflowed along with the text
on window resizes.

In an ideal world, erasing, or overwriting the cell where the OSC was
emitted, would remove the prompt mark. Since we don't store this
information in the cell struct, we can't do that. The best we can do
is reset it in erase_line(). This works well enough in the "normal"
screen, when used with a "normal" shell. It doesn't really work in
fullscreen apps, on the alt screen. But that doesn't matter since we
don't support jumping between prompts on the alt screen anyway.

To be able to jump between prompts, two new key bindings have been
added: prompt-prev and prompt-next, bound to ctrl+shift+z and
ctrl+shift+x respectively.

prompt-prev will jump to the previous, not currently visible, prompt,
by moving the viewport, ensuring the prompt is at the top of the
screen.

prompt-next jumps to the next prompt, visible or not. Again, by moving
the viewport to ensure the prompt is at the top of the screen. If
we're at the bottom of the scrollback, the viewport is instead moved
as far down as possible.

Closes #30
2022-06-16 19:02:10 +02:00
Daniel Eklöf
96f23b4c64
ime: track IME focus independently from keyboard focus
Replace the seat->ime.focused boolean with a terminal instace pointer,
seat->ime_focus.

Set and reset this on ime::enter() and ime::leave() events, and use
this instead of seat->kbd_focus on all other IME events.

This fixes two issues:

a) buggy compositors that sometimes sends an IME enter event without
  first having sent a keyboard enter event.

b) seats may be IME capable while still lacking the keyboard
  capability. Such seats will *always* see IME enter events without a
  corresponding keyboard enter event.
2022-06-15 19:25:33 +02:00
Daniel Eklöf
d852178540
ime: ime_reset_pending_{preedit,commit} is not used outside ime.c 2022-06-15 19:25:32 +02:00
Daniel Eklöf
9dc4f48e7a
vt: tag collision-count check with ‘unlikely’ 2022-06-15 19:25:00 +02:00
Daniel Eklöf
fbcb30bf98
vt: improve key calculation for compose sequences
* Don’t assume 32 bits when rotating the old key. Use the number of
  actual bits available, as determined by CELL_COMB_CHARS_{HI,LO}
* Multiply with magic hash constant

This greatly reduces the number of collisions seen. For example, the
Emoji test file (from the Unicode specification), now has zero
collisions.
2022-06-15 19:25:00 +02:00