* 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.
Composed characters are stored in a tree structure, using a key as
identifier. The key is calculated from the individual characters that
make up the composed character sequence.
Since the address space for keys is limited, collisions may occur. In
this case, we simply increment the key and try again.
It is theoretically possible to saturate the key space, in which case
we’ll get stuck in an endless loop.
Even if the key space isn’t fully saturated, we fairly easy reach a
point where there are so many collisions for each insertion, that
performance drops significantly.
Since key space is limited (it’s not like a hash table that we can
grow), our only option is to limit the number of collisions. If we
can’t find a slot within a hard code amount of collisions, the
character is simply dropped.
This syncs foot with more recent versions of XTerm, where it’s
“disallowedPasteControls” resource has changed its default value to
BS,DEL,ENQ,EOT,ESC,NULL
Note that we’re already stripping out ENQ,EOT,ESC in all modes.
What does it mean for foot:
* HT, VT and FF are now allowed, regardless of paste mode
* NUL is now stripped in non-bracketed paste mode
Closes#1084
When scrolling the viewport up, we need to ensure we don’t go past the
scrollback wrap around.
This was previously done using “custom” logic that tried to calculate
many rows away from the scrollback start the current viewport is.
But this is *exactly* what grid_row_abs_to_sb() does, except it
doesn’t account for uninitialized scrollback.
So, copy the logic from grid_row_abs_to_sb(), but ensure scrollback
start points to valid scrollback data. The maximum number of rows
we’re allowed to scroll is now the same as the current viewport’s
sb-relative coordinate.
Maybe closes#1074
When a line in the old grid (the one being reflowed) doesn’t have a
hard linebreak, don’t trim trailing empty cells.
Doing so means we’ll “compress” (remove) empty cells between text
if/when we revert to a larger window size.
The output from neofetch suffers from this; it prints a logo to the
left, and system information to the right. The logo and the system
info column is separated by empty cells (i.e. *not* spaces).
If the window is reduced in size such that the system info is pushed
to a new line, each logo line ends with a number of empty cells. The
next time the window is resized, these empty cells were
ignored (i.e. removed).
That meant that once the window was enlarged again, the system info
column was a) no longer aligned, and b) had been pulled closer to the
logo.
This patch doesn’t special case trailing empty cells when the line
being reflowed doesn’t have a hard linebreak. This means e.g. ‘ls’
output is unaffected.
Closes#1055
This allows package maintainers to override the location to which our
systemd service files are installed.
It’s value is an *absolute* path, and *not* relative ${prefix}.
The default is ${systemduserunitdir}.
When XDG activation support was added to URL mode, we introduced a
regression, where it is possible to flood the Wayland socket with XDG
activation token requests.
Start foot with “foot -o bell.urgency=yes”, then run:
while true; do echo -en ‘\a’; done
Finally, switch keyboard focus to another window. Foot crashes.
Throttle the token requests by limiting the number of outstanding
urgency token requests to 1.
Closes#1065
If the viewport is at the top of the scrollback, and a program is
scrolling (e.g. by emitting newlines), the viewport needs to be
moved. Otherwise, the top of the viewport will show the *bottom* of
the scrollback (i.e. the newly emitted lines), and the bottom of the
viewport shows the top of the scrollback.
How do we detect if the viewport needs to be moved?
We convert its absolute row number to a scrollback relative row. This
number is also the maximum number of rows we can scroll without the
viewport being scrolled out.
In other words, if the number of rows to scroll is larger than the
viewports scrollback relative row number, the viewport needs to
moved.
How much do we need to move it? The difference between the number of
rows to scroll, and the viewports scrollback relative row number.
Example:
if the viewport is at the very top of the scrollback, its scrollback
relative row number is 0. In this case, it needs to be moved the same
number of rows as is being scrolled.
First, add a ‘token’ argument to spawn(). When non-NULL, spawn() will
set the ‘XDG_ACTIVATION_TOKEN’ environment variable in the forked
process. If DISPLAY is non-NULL, we also set DESKTOP_STARTUP_ID, for
compatibility with X11 applications. Note that failing to set either
of these environment variables are considered non-fatal - i.e. we
ignore failures.
Next, add a helper function, wayl_get_activation_token(), to generate
an XDG activation token, and call a user-provided callback when it’s
‘done (since token generation is asynchronous). This function takes an
optional ‘seat’ and ‘serial’ arguments - when both are non-NULL/zero,
we set the serial on the token. ‘win’ is a required argument, used to
set the surface on the token.
Re-write wayl_win_set_urgent() to use the new helper function.
Finally, rewrite activate_url() to first try to get an activation
token (and spawn the URL launcher in the token callback). If that
fails, or if we don’t have XDG activation support, spawn the URL
launcher immediately (like before this patch).
Closes#1058
When true, selection_find_word_boundary_right() behaves as before - it
stops as soon as it encounters a character that isn’t of the
same *type* as the “initial” character (the last character in the
selection).
Take this, for example:
The Quick Brown Fox
The selection will first stop at the end of “the”, then just *before*
“quick”, then at the end of “quick”. Then just *before* “brown”, and
then at the end of “brown”, and so on.
This suits mouse selections pretty good. But when
selection_find_word_boundary_right() is used to extend a search match,
it’s better to ignore space-to-word character transitions. That is, we
want
The Quick Brown Fox
to first extend to the end of “the”, then immediately to the end of
“quick”, then to the end of “brown”, and so on.
Setting the ‘stop_to_space_to_word_boundary’ argument to false results
in latter behavior.
This is now done by search, when executing the
“extend-to-word-boundary” and “extend-to-next-whitespace” key
bindings.
We now bind ctrl+v, ctrl+shift+v, ctrl+y and XF86Paste to pasting from
the clipboard into the scrollback search buffer.
Why all these? Because we can, and because all are common shortcuts
for pasting:
* ctrl+v: “normal” apps use this by default
* ctrl+shift+v: used in terminals (including foot)
* ctrl+y: Emacs
* XF86Paste: special keyboard key, for pasting
find_next() did not always terminate correctly, causing
search_matches_next() to never terminate, which finally leads to an
infinite loop when rendering the search overlay surface, while finding
all matches to highlight.
The problem is that find_next(), after having found the initial
matching characters, enters a nested while loop that tries to match
the rest of the search criteria. This inner while loop did not check
if we’ve reached the last cell, and happily continued past
it (eventually wrappping around the scrollback buffer).
Closes#1047
5c4ddebc3c refactored
search_update_selection(), specifically, the logic that moves the
viewport.
It did so by converting the absolute row number (of the match) to
scrollback relative coordinates. This way we could ensure the viewport
wasn’t moved “too much” (e.g. beyond the scrollback start).
However, grid_row_abs_to_sb() and grid_row_sb_to_abs() doesn’t take a
partially filled scrollback into account. This means the row (numbers)
it returns may refer to *uninitialized* rows.
Since:
* The match row itself is valid (we *know* it has text on it)
* We *subtract* from it, when setting the new viewport (to center the
match on the screen).
it’s only the *upper* part of the new viewport that may be
uninitialized. I.e. we may have adjusted it too much.
So, what we need to do is move the viewport forward until its *first*
row is initialized. Then we know the rest will be too.
Unmapping a sub-surface in Sway does not damage the underlying
surface.
As a result, the OSC-555 escape (“flash”) will leave yellow margins on
~every second frame.
Out of sway, river, weston and mutter, only Sway needs this
workaround.
This is a workaround for https://github.com/swaywm/sway/issues/6960Closes#1046
Unmapping a sub-surface in Sway does not damage the underlying
surface.
As a result, "committing" a scrollback search will typically leave
most of the foot window dimmed.
It can be seen when "cancelling" a search as well, but there it's less
obvious - only the margins are left dimmed. This is because cancelling
a search damaged the current viewport (something that shouldn't be
needed).
Out of sway, river, weston and mutter, only Sway needs this
workaround.
This is a workaround for https://github.com/swaywm/sway/issues/6960