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.
Add a new config option, desktop-notifications.close, defining what to
execute to close a notification. It has a single template parameter,
${id}, that is expanded to the external notification ID foot may have
picked up from the notification helper.
notify-send does not support closing notifications, and it appears
impossible to pass an *unsigned* integer as argument to gdbus. Hence
no default value for the new 'close' option.
Example:
printf '\e]99;i=123;this is a notification\e\\'
printf '\e]99;i=123:p=close;\e\\'
Split it up into two, ${action-name} and ${action-label}.
Dunstify, for example, has a different syntax compared to notify-send:
notify-send: default=foobar
dunstify: default,foobar
Only do it when the notification was activated.
Here, activated means the 'click to activate' notification action was
triggered.
How do we tie everything together?
First, we add a new template parameter, ${action}. It's intended to be
used with e.g. notify-send's --action option.
When the action is triggered, notify-send prints its name on stdout,
on a separate line. Look for this in stdout. Only if we've seen it do
we focus/report the notification.
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/
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
This patch changes the default of triple clicking, from selecting the
current logical row, to first trying to select the contents of the
quote under the cursor, and if failing to find a quote, selecting the
current row (like before).
This is implemented by adding a new key binding, 'select-quote'.
It will search for surrounding quote characters, and if one is found
on each side of the cursor, the quote is selected. If not, the entire
row is selected instead.
Subsequent selection operations will behave as if the selection is
either a word selection (a quote was found), or a row selection (no
quote found).
Escaped quote characters are not supported: "foo \" bar" will match
'foo \', and not 'foo " bar'.
Mismatched quotes are not custom handled. They will simply not match.
Nested quotes ("123 'abc def' 456") are supported.
Closes#1364
Un-grabbed wheel events are now passed through the mouse binding
matching logic, instead of being hardcoded to scrolling the terminal
contents.
They are mappable through the BTN_BACK and BTN_FORWARD buttons.
Since they're not actually button *presses*, they never generate a
click count other than 1. This limitation is documented, but not
checked in the config. This means it's possible to create bindings
like "BTN_BACK+3" (i.e. triple "click"). They will however never
trigger.
The old, hardcoded logic is now accessible through the new
scrollback-up-mouse and scrollback-down-mouse mouse
bindings. They (obiously) default to BTN_BACK and BTN_FORWARD,
respectively.
Example usage: keep the default of scrolling terminal contents with
the wheel, when used without modifiers, but map Control+wheel to font
zoom in/out:
[mouse-bindings]
font-increase=Control+BTN_FORWARD
font-decrease=Control+BTN_BACK
(this also keeps the default key bindings to zoom in/out; ctrl-+ and
ctrl+-)
Closes#1077
When enabled, double-clicking the CSD titlebar will (un)maximize the
window.
Defaults to ‘yes’ (since this is the old hard-coded behavior).
Closes#1293
Having a keybinding to invoke arbitrary unicode characters is very
useful. It's often used as a method of last resort to communicate with
people outside of your main language. For example, if you want to type
the last letter of my real name, you can invoke the latin-1 character
0xe9 or unicode 0x00e9.
You can also use this to type special characters, for example, unicode
U+1F4A9 is of course, the infamous PILE OF POO, which is sure to
produce million laughs everywhere you go.
In foot, there's no keybinding by default to invoke the very useful
unicode-input command. There is no "standard" (as in "ISO") keybinding
this either. But there *is* a de-facto standard currently deployed
by *both* GTK and Qt (a rare feat) *and* Chrome OS (an even rarer
feat) and it's control-shift-u.
Alternatives include Control-x 8 (emacs), Control V u (vim),
Alt (Windows, LibreOffice), or Option (Mac). I doubt we want to adopt
any of those.
So let's use control-shift-u for this. Unfortunately, it's currently
assigned to show-urls-launch, which is unfortunate, but
insurmountable. We can reassign this keybinding elsewhere. I have
picked control-shift-o in my configuration, because "o" is a good
mnemonic for "open URLs". Others have suggested "m" instead.
Closes: #1183
We now default to scaling fonts using the scaling factor, not monitor
DPI.
The ‘auto’ value for dpi-aware has been removed.
Documentation (man pages and README) have been updated to reflect the
new default.
For this to work, the default app-id of footclient has been changed
from ‘foot’ to ‘footclient’.
By using distinct StartupWMClasses, the compositor can connect a
running foot/footclient instance to the correct .desktop-file. This
ensures the correct icon is being used in e.g. docks, and that actions
like “open another window” works correctly.
Note that the user can override the app-id, either by setting app-id
in foot.ini, or with the -a,--app-id command line option.
Closes#1355
This patch generalizes the utmp support, to not only support
libutempter, but also ulog (and in the future, even more interfaces).
* Rename config option main.utempter to main.utmp-helper
* Add meson option -Dutmp-backend=none|libutempter|ulog|auto
* Rename meson option -Ddefault-utempter-path to -Dutmp-default-helper-path
* utmp is no longer detected at compile time, but at runtime instead.
Meson will configure the following pre-processor macros, based on the
selected utmp backend:
* UTMP_ADD - argument to pass to utmp helper when adding a record (starting foot)
* UTMP_DEL - argument to pass to utmp helper when removing a record (exiting foot)
* UTMP_DEL_HAVE_ARGUMENT - if defined, UTMP_DEL expects an extra argument ($WAYLAND_DISPLAY)
* UTMP_DEFAULT_HELPER_PATH - path to the default utmp helper binary
The documentation has been updated to mention which arguments are
passed to the helper binary.
Closes#1314
This patch adds support for creating utmp records using the ‘utempter’
helper binary from the ‘libutempter’ package.
* New config option ‘main.utempter’
* New meson command line option, -Ddefault-utempter-path. Defaults to
auto-detecting the path.
The default value of the new ‘main.utempter’ config option depends on
the meson command line option ‘-Ddefault-utempter-path’.
If ‘main.utempter’ is *not* set to ‘none’, foot will try to execute
the utempter helper binary to create utmp records when a new terminal
is instantiated. The record is removed when the terminal instance is
destroyed.
This is my variant of the solarized theme, were only the first eight
colors (i.e. the "normal") colors are from the solarized theme. The
remaining eight (the "bright" colors) are brightened versions of the
"normal" colors. This results in a theme that is usually in all
applications, not just those that are "aware" that the terminal color
theme is "solarized".
This adds an "underline-thickness" setting to the "main" section,
similar to the existing "underline-offset" setting. This setting is used
to specify a custom height for regular (= non-cursor) underlines.
Fixes#1136
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
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
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
This makes the example config `foot.ini` and its man page slightly more
coherent regarding the specification of default values.
Note that the cursor color is not hardcoded like e.g. foreground or
background, thus in the example config, `<inverse foreground/background>`
makes more sense.
With this, it is now possible to map key combos to custom escapes. The
new bindings are defined in a new section, “text-bindings”, on the
form “string=key combo”.
The string can consist of printable characters, or \xNN style hex
digits:
[text-bindings]
abcd = Control+a
\x1b[A = Control+b Control+c Control+d # map ctrl+b/c/d to UP
Editors like Vim and Kakoune ship filetypes dosini and ini
respectively. Both use ";" as comment character, which is used for
example by Vim's "gq" command which wraps lines while preserving
comment prefixes.
foot only accepts # comments. I think it's desirable to stick to
a single commenting style (easier to diff configs).
Make Vim accept that by adding modeline to use the "conf"
filetype, which is for "generic Unix config files". We already
have an Emacs modeline at the top, but Vim seems to ignore it.
Kakoune doesn't have that filetype, but a patch has been
proposed to use # whenever it already occurs in the file, see
https://github.com/mawww/kakoune/pull/4537
These work as expected and don't interfere with anything else.
They are useful on the increasing number of keyboards with custom
firmware. The keycodes enable using the same key combination
for terminals as other apps.
For example: by holding down a layer-switching key with a thumb, the
Copy and Paste key codes can be assigned to the C and V keys on a secondary
layer, making for a natural universal copy/paste key combination.