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
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.
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 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}.
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
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
The match logic uses the last start coordinate to determine which end
points in the selection to update. This sometimes fails when the start
coordinate has been changed by e.g. a key binding - the new start
coordinate is incorrectly matched against the old-but-modified start
coordinate, causing foot to e.g. *not* upate the selection start
coordinate.
Example:
$ echo 'test\n\test\ntest'
Then do a scrollback search for 'test. The first match is found
correctly (the last 'test'), but searching for the previous match
(ctrl+r) does not select the middle 'test'.
Fix by passing the search direction to search_find_next(), and have
_it_ calculate the coordinate to start search. There are three possibilities:
* forward
* backward
* "backward", but at the same position
The first two are used when searching for next/prev match with ctrl+s
and ctrl+r. The last one is used when the search criteria is
updated. In this case, we don't want to move to the previous match,
*unless* the current match no longer matches.
When the compositor is asking us to resize ourselves, take
our (visible) CSD borders into account. This is similar to how we
already take the titlebar size into account.
This fixes an issue where the window size “jumps” when the user starts
an interactive resize, when csd.border-width > 0.
This as been observed in GNOME.
When this option is used, the child process in the new terminal
instance will inherit its environment from the footclient process,
instead of the foot server’s.
Implemented by sending (yet another) dynamic string list as part of
the client -> server setup packet. When the new option is *not* used,
the setup packet is now 2 bytes larger than before.
On the server side, the slave process now uses execvpe() instead of
execvp(). There’s plumbing to propagate a new ‘envp’ argument from
term_init() all the way down to slave_exec(). If ‘envp’ is NULL, we
use ‘environ’ instead (thus matching the old behavior of execvp()).
Closes#1004
The underline cursor is positioned just below regular underlines. A
bug in the positioning logic related to this, sometimes resulted in
the cursor being thinner than what it should be, or even invisible.
Fixes#1005
When matching “untranslated” bindings (by matching the base symbol of
the key, e.g. ctrl+shift+2 in US layout), require that no
non-significant modifiers are active.
This fixes an issue where AltGr was “ignored”, and would cause certain
combinations to match a key binding.
Example: ctrl+altgr+0, on many European layouts matched against the
default ctrl+0 (reset the font size), instead of emitting ^]
To make this work, we now need to filter out “locked”
modifiers (e.g. NumLock and CapsLock). Otherwise having e.g. NumLock
active would prevent *all* untranslated matching to fail.
Closes#983
In non-bracketed paste mode, we translate \n to \r, and \r\n to
\r. The latter matches XTerm, urxvt, alacritty and kitty. The former
matches alacritty and kitty (xterm and urxvt just blindly replaces all
\n occurrences with \r, meaning \r\n is translated to \r\r.
For some reason, we then unconditionally translated all \r back to \n,
regardless of whether bracketed paste was enabled or not. Unsure
why/where this comes from, but it doesn't match any of the other
terminal emulators I tested.
One example where this caused issues is in older versions of nano (at
least up to 2.9).
Closes#980