From the release notes:
system bell - allowing e.g. terminal emulators to hand off system
bell alerts to the compositor for among other things accessibility
purposes
The new protocol is used when the new config option
bell.system=yes (and the compositor implements the protocol,
obviously).
The system bell is rung independent of whether the foot window has
keyboard focus or not (thus relying on compositor configuration to
determine whether anything should be done or not in response to the
bell).
The new option is enabled by default.
If the compositor sends a keyboard enter event before our window has
been mapped, foot crashes; the enter event triggers a cursor
refresh (hollow -> non-hollow block cursor), which crashes since we
haven't yet allocated a grid.
Fix by no-op:ing the refresh if the window hasn't been configured yet.
Closes#1910
If we call render_refresh, that will wait for a callback to the main
surface. In the case of a flash, the main surface might not get callbacks
if the compositor implements fancy culling optimizations like wlroots
wlr_scene compositors such as sway version >=1.10.
Unsure if the protocol imposes a limit (haven't found any
documentation), or if the issue is in the libwayland implementation,
or wlroots (triggers in at least sway+river).
The issue is that setting a too long app-id causes the
compositor (river at least) to peg the CPU at 100%, and stop sending
e.g. frame callbacks to foot.
Closes#1897
In fact, there appears there *is* no escape sequence to set the icon.
Keep most of the logic in place, but in practice, we'll always set the
icon to the app-id. That is, at startup, we set it to the configured
app-id (either from config, or the command line).
OSC-176, which sets the app-id, also updates the icon (to the app-id).
* The toplevel icon is now set to the app-id, unless "overridden" by
OSC-1 or OSC-0.
* Implemented OSC-1
* OSC-0 extended to also set the icon
* Implemented CSI 20 t - report window icon
* Implemented CSI 21 t - report window title
* Implemented CSI 22 ; 1 t - push window icon
* Implemented CS 23 ; 1 t - pop window icon
* Extended CSI 22/23 ; 0 t to also push/pop the icon
* Verify app-id set by OSC-176 is valid UTF-8
* Verify icon set by OSC-0/1 is valid UTF-8
Summary of changes:
* Make xvsnprintf() static
* restrict-qualify pointer arguments (as done by the libc equivalents)
* Make comments and spec references more thorough
* Remove pointless `n <= INT_MAX` assertion (see comment)
* Use FATAL_ERROR() instead of xassert() (since the assertion is inside
a shared util function but the caller is responsible for ensuring the
condition holds true)
* Change some callers to use size_t instead of int for the return value
(negative returns are impossible and all subsequent uses are size_t)
The updated comments and code were taken (and adapted) from:
49260bb154/src/util/xsnprintf.c (L6-50)
This work was entirely authored by me and I hereby license this
contribution under the MIT license (stated explicitly, so that
there's no ambiguity w.r.t. the original license).
Or put more propertly; if the notification daemon, and the
notification helper used by foot has been configured
properly (i.e. they both support XDG activation tokens), notifications
generated by BEL and OSC-777 will now raise/focus the window when the
default action of the notification is activated - typically by
clicking the notification.
Closes#1822
This avoids the need for an unused third argument for most xstrjoin()
calls and replaces the cases where it's needed with a more flexible
function. Code generation is the same in both cases, when there are 2
string params and a compile-time known delimiter.
This commit also converts 4 uses of xasprintf() to use xstrjoin*().
See also: https://godbolt.org/z/xsjrhv9b6
* Don't store a list of unfinished notifications. Use a single one. If
the notification ID of the 'current' notification doesn't match the
previous, unfinished one, the 'current' notification replaces the
previous one, instead of updating it.
* Update xstrjoin() to take an optional delimiter (for example ','),
and use that when joining categories and 'alive IDs'.
* Rename ${action-arg} to ${action-argument}
* Update handling of the 'n' parameter (symbolic icon name); the spec
allows it to be used multiple times, and the terminal is supposed to
pick the first one it can resolve. Foot can't resolve icons at all,
neither can 'notify-send' or 'fyi' (which is what foot typically
executes to display a notification); it's the notification daemon that
resolves icons.
The spec _could_ be interpreted to mean the terminal should lookup
.desktop files, and use the value of the 'Icon' key from the first
matching .desktop files. But foot doesn't read .desktop files, and I
don't intend to implement XDG directory scanning and parsing of
.desktop files just to figure out which icon to use.
Instead, use a simple heuristics; use the *shortest* symbolic
names. The idea is pretty simple: plain icon names are typically
shorter than .desktop file IDs.
First, icons have been finalized in the specification. There were only
three things we needed to adjust:
* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
to use p=icon without having to cache the icon first).
Second, add support for the following new additions to the protocol:
* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
the terminal defined "default" action) actions. The 'activated' event
has been updated to report which button/action was used to activate
the notification.
To support button/actions, desktop-notifications.command had to be
reworked a bit.
There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.
command-action-arg gets expanded for *each* action.
${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
This fixes a regression where closing a terminal instance, or hard- or
soft-resetting a terminal caused FD 0 to be closed.
This meant it became re-usable. Usually, by memfd_create() when
allocating a new surface buffer. So far nothing _really_ bad has
happened.
But what if FD 0 is now used by a memfd, and we close _another_
terminal instance?
This causes our memfd to be closed. And then, when e.g. trying to
scroll the terminal content: fallocate() fails with bad FD.
This fixes an issue where it wasn't possible to trigger multiple
notifications with the same kitty notification ID. This is something
that works in kitty, and there's no reason why it shouldn't work.
The issue was that we track stdout, and the notification helper's PID
in the notification struct. Thus, when a notification is being
displayed, we can't re-use the same notification struct instance for
another notification.
This patch fixes this by adding a new notification list,
'active_notifications'. Whenever we detect that we need to track the
helper (notification want's to either focus the window on activation,
or send an event to the application), we add a copy of the
notification to the 'active' list.
The notification can then be removed from the 'kitty' list, allowing
kitty notifications to re-use the same ID over and over again, even if
old notifications are still being displayed.
This implements the suggested protocol discussed in
https://github.com/kovidgoyal/kitty/issues/7657.
Icons are handled by loading a cache. Both in-band PNG data, and
symbolic names are allowed.
Applications use a graphical ID to reference the icon both when
loading the cache, and when showing a notification.
* 'g' is the graphical ID
* 'n' is optional, and assigns a symbolic name to the icon
* 'p=icon' - the payload is icon PNG data. It needs to be base64
encoded, but this is *not* implied. I.e. the application *must* use
e=1 explicitly.
To load an icon (in-band PNG data):
printf '\e]99;g=123:p=icon;<base64-encoded-png-data>\e\\'
or (symbolic name)
printf '\e]99;g=123:n=firefox:p=icon;\e\\'
Of course, we can combine the two, assigning *both* a symbolic
name, *and* PNG data:
printf '\e]99;g=123:n=firefox:p=icon;<base64-encoded-png>\e\\'
Then, to use the icon in a notification:
printf '\e]99;g=123;this is a notification\e\\'
Foot also allows a *symbolic* icon to be defined and used at the same
time:
printf '\e]99;g=123:n=firefox;this is a notification\e\\'
This obviously won't work with PNG data, since it uses the payload
portion of the escape sequence.
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.
* Refactor notification related configuration options:
- add desktop-notifications sub-section
- deprecate 'notify' in favor of 'desktop-notifications.command'
- deprecate 'notify-focus-inhibit' in favor of
'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
notification'
* Pass a 'struct notification' to notify_notify(), instead of many
arguments.
* notify_notify() now registers a reaper callback. When the notifier
process has terminated, the notification is considered closed, and we
either try to focus (activate) the window, or send an event to the
client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
spec. Foot's implementation:
- uses the 'I' parameter
- the value is expected to be a symbolic icon name
- a quick check for absolute paths is done, and such icon requests
are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
the icon specified in the notification, or ${app-id} if not set.
This adds limited support for OSC-99, kitty desktop notifications[^1]. We
support everything defined by the "protocol", except:
* 'a': action to perform on notification activation. Since we don't
trigger the notification ourselves (over D-Bus), we don't know a)
which ID the notification got, or b) when it is clicked.
* ... and that's it. Everything else is supported
To be explicit, we *do* support:
* Chunked notifications (d=0|1), allowing the application to append
data to a notification in chunks, before it's finally displayed.
* Plain UTF-8, or base64-encoded UTF-8 payload (e=0|1).
* Notification identifier (i=xyz).
* Payload type (p=title|body).
* When to honor the notification (o=always|unfocused|invisible), with
the following quirks:
- we don't know when the window is invisible, thus it's treated as
'unfocused'.
- the foot option 'notify-focus-inhibit' overrides 'always'
* Urgency (u=0|1|2)
[^1]: https://sw.kovidgoyal.net/kitty/desktop-notifications/
Before this, margins were special cased:
* The mouse cursor was always a pointer, and never an I-beam (thus
signaling selections cannot be made).
* The internal mouse coords where set to -1 when the cursor was inside
the margins, causing:
- text selections from being made
- mouse events being passed to mouse grabbing applications
In particular, even with a one-pixel margin, making selections was
unnecessarily hard in e.g. fullscreen mode, where you'd expect to be
able to throw the cursor into the corner of the screen and then start
a selection.
With this patch, the cursor is treated as if it was in the first/last
column/row, when inside the margin(s).
An unintended side-effect of this, initially, was that auto-scrolling
selections where way too easy to trigger, since part of its logic is
checking if the cursor is inside the margins.
That problem has been reduced by two things:
* auto-scrolling does not occur unless a selection has been
started. That is, just holding down the mouse in the margins and
moving up/down doesn't cause scrolling. You have to first select at
least one cell in the visible viewport.
* A selection isn't fully started (i.e. a cell is actually selected)
unless the cursor is inside the actual grid, and *not* in the
margins.
What does the last point mean? We now allow a selection to be
_started_ when clicking in the margin. What this means internally is
we set a start coordinate for a selection, but *not* and end
coordinate. At this point, we don't have an actual selection. Nothing
is selected, and no cells are highlighted, graphically.
This happens when we set an end coordinate. Without the last bullet
point, that would happen as soon as the cursor was _moved_, even if
still inside the margins. Now, we require the cursor to leave the
margins and touch an actual cell before we set an end coordinate.
Closes#1702
This implements
https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83,
in-band window resize notifications.
When user enables private mode 2048 (in-band resize
notifications), *always* send current size, even if the mode is
already active.
This ensures applications can rely on getting a reply from the
terminal.
BTN_BACK and BTN_FORWARD are separate buttons. The scroll wheel don't
have any button mappings in libinput/wayland, so make up our own
defines.
This allows us to map them in mouse bindings.
Also expose BTN_WHEEL_{LEFT,RIGHT}. These were already defined, and
used, internally, to handle wheel tilt events. With this, they can
also be used in mouse bindings.
Finally, fix encoding used for BTN_{BACK,FORWARD} when sending mouse
button events to the client application. Before this, they were mapped
to buttons 4/5. But, button 4/5 are for the scroll wheel, and as
mentioned above, BTN_{BACK,FORWARD} are not the same as scroll wheel
"buttons".
Closes#1763
When changing part of the color palette, through either OSC-4, or
OSC-10 and OSC-11 (and the corresponding reset OSCs: 104, 110 and
111), only dirty affected cells.
We've always done this, but only for OSC-4.
This patch breaks out that logic, and extends it to handle default
fg/bg too.
It also fixes a bug where cells with colored underlines were not
dirtied if the underline was the only part of the cell that was
affected by a OSC-4 change.
The documentation of these sequences are vague and lacking, as is
often the case with XTerm invented control sequences.
I've tried to replicate what XTerm does (as of xterm-392).
The stack represents *stashed/stored* palettes. The currently active
palette is *not* stored on the stack.
The stack is dynamically allocated, and starts out with zero elements.
Now, XTerm has a somewhat weird definition of "pushing" and "popping"
in this context, and the documentation is somewhat misleading.
What a push does is this: it stores the current palette to the stack
at the specified slot. If the specified slot number (Pm) is 0, the
slot used is the current slot index incremented by 1.
The "current" slot index is then set to the specified slot (which is
current slot + 1 if Pm == 0).
Thus, "push" (i.e. when Pm == 0 is used) means store to the "next"
slot. This is true even if the current slot index points into the
middle of stack.
Pop works in a similar way. The palette is restored from the specified
slot index. If the specified slot number is 0, we use the current slot
index.
The "current" slot index is then set to the specified slot -
1 (current slot - 1 if Pm == 0).
XTREPORTCOLORS return the current slot index, and the number of
palettes stored on the stack, on the format
CSI ? <slot index> ; <palette count> # Q
When XTPUSHCOLORS grows the stack with more than one element (i.e. via
a 'CSI N # P' sequence), make sure *all* new slots are initialized (to
the current color palette). This avoids uninitialized slots, that
could then be popped with XTPOPCOLORS.
Closes#856
10/11/17/19 were already merged, so this patch just stops special
casing 12 (cursor color).
In preparation for XTPUSHCOLORS/XTPOPCOLORS, the cursor colors are
moved from their own struct, into the 'colors' struct.
Also fix a bug where OSC 17/19 queries returned OSC-11 data.
The things affecting which ASCII printer we use have grown...
Instead of checking everything inside term_update_ascii_printer(), use
a bitfield.
Anything affecting the printer used, must now set a bit in this
bitfield. This makes term_update_ascii_printer() much faster, since
all it needs to do is check if the bitfield is zero or not.
Only clear OSC-8 hyperlinks at the target columns if we don't have an
active OSC-8 URI. This corresponds to normal VT attributes; the
currently active attributes are set, and all others are cleared.
Handle styled underlines in the same way
This is work in progress, and fairly untested.
This adds initial tracking of styled underlines. Setting attributes
seems to work (both color and underline style). Grid reflow has *not*
been tested.
When rendering, style is currently ignored (all styles are rendered as
a plain, legacy underline).
Color however, *is* applied.
The unicode-mode, and flash overlays are single color buffers. This
means we can use the single-pixel buffer protocol.
It's undefined whether the compositor will release the buffer or not;
to make things easier, simply destroy the buffer as soon as we've
committed it.
Note that since compositors don't necessarily release single-pixel
buffers, we can't plug them into our own buffer interface. This means
we can't use buffer pointers to check if we can re-use the previous
buffer (i.e. we can skip comitting a new buffer), or if we have to
create a new one.
It's _almost_ enough to just check if the last overlay style is the
same as the current one. Except that that doesn't take window resizes
into account...
A compositor may unmap, and then remap the window, for example when
the window is minimized, or if the user switches workspace.
With DPI aware rendering, we *need* to know on which output we're
mapped, in order to use the correct DPI. This means the first frame we
render, before being mapped, always guesses the DPI.
In an unmap/map sequence, guessing the wrong DPI means the window will
flicker.
Fix by stashing the last used DPI value, and use that instead of
guessing.
This means the *only* time we _actually_ guess the DPI, is the very
first frame, when starting up foot.
When auto-wrap is disabled, a multi-column character may be printed on
a line that doesn't fit the entire character. That is, the "spacers"
we print, as place holders in the columns after the first one, may
reach outside the grid.
We did (try to) check for this, but the check was off by one. Meaning,
we could, in some cases, print outside the grid.
We deviate slightly from the specification, in that we don't assume a
preferred buffer scale of 1. Instead, we "guess" the scale *until we
receive a surface_preferred_buffer_scale event.
Because of this, we don't need the has_wl_compositor_v6 member, as
it's enough to check if we have a non-zero 'preferred buffer scale'.
If we're the ones initiating shutdown, start by sending SIGHUP. Only
if the client application does not terminate, send SIGTERM (and if it
still refuses to terminate, send SIGKILL).
Also reduce the timeout between the signals from 60s to 30s.
Unless --pty has been used, we do *not* want to shutdown the terminal
when the PTY is closed by the client application; we want to wait for
the client application to actually terminate.
This was the behavior before the --pty patch.
This was changed in the --pty patch, since then, we don't *have* a
client application. That is, foot has not forked+exec:ed anything. The
only way to trigger a shutdown (from the client side) is to close the
PTY.
This patch restores the old behavior, when --pty is *not* used.
Closes#1666
Before this patch, we would, in some cases, fallback to the surface
preferred (not fractional) scaling, even though the compositor hadn't
actually published a preferred buffer scale; the presence of a v6
compositor interface doesn't mean we've actually received a preferred
scale yet.
Virtual machine monitor programs (e.g. QEMU, Cloud Hypervisor) expose
guest consoles as PTYs. With this patch, foot can access these guest
consoles.
Usually, the program used for accessing these PTYs is screen, but
screen is barely developed, doesn't support resizing, and has a bunch
of other unrelated stuff going on. It would be nice to have a
terminal emulator that properly supported opening an existing PTY.
The VMM controls the master end of the PTY, so to the other end (in
this case foot), it just behaves like any application running in a
directly-opened PTY, and all that's needed is to change foot's code to
support opening an existing PTY rather than creating one.
Co-authored-by: tanto <tanto@ccc.ac>