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
Up until now, our Wayland seats have been tracking key bindings. This
makes sense, since the seat’s keymap determines how the key bindings
are resolved.
However, tying bindings to the seat/keymap alone isn’t enough, since
we also depend on the current configuration (i.e. user settings) when
resolving a key binding.
This means configurations that doesn’t match the wayland object’s
configuration, currently don’t resolve key bindings correctly. This
applies to footclients where the user has overridden key bindings on
the command line (e.g. --override key-bindings.foo=bar).
Thus, to correctly resolve key bindings, each set of key bindings must
be tied *both* to a seat/keymap, *and* a configuration.
This patch introduces a key-binding manager, with an API to
add/remove/lookup, and load/unload keymaps from sets of key bindings.
In the API, sets are tied to a seat and terminal instance, since this
makes the most sense (we need to instantiate, or incref a set whenever
a new terminal instance is created). Internally, the set is tied to a
seat and the terminal’s configuration.
Sets are *added* when a new seat is added, and when a new terminal
instance is created. Since there can only be one instance of each
seat, sets are always removed when a seat is removed.
Terminals on the other hand can re-use the same configuration (and
typically do). Thus, sets ref-count the configuration. In other words,
when instantiating a new terminal, we may not have to instantiate a
new set of key bindings, but can often be incref:ed instead.
Whenever the keymap changes on a seat, all key bindings sets
associated with that seat reloads (re-resolves) their key bindings.
Closes#931
The old, complex, way of using a dynamic list to hold each path
component made _some_ sense before, when we needed to support both
~/.config/foot.ini and ~/.config/foot/foot.ini.
But now, it just over complicates things.
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
This fixes a compilation error on FreeBSD:
../../foot/render.c:2055:45: error: no member named 'epoll_shim_close' in 'struct config::(anonymous at ../../foot/config.h:254:9)'
conf_color = &term->conf->csd.color.close;
~~~~~~~~~~~~~~~~~~~~~ ^
/usr/local/include/libepoll-shim/epoll-shim/detail/common.h:8:15:
note: expanded from macro 'close': #define close epoll_shim_close
Fcft no longer uses wchar_t, but plain uint32_t to represent
codepoints.
Since we do a fair amount of string operations in foot, it still makes
sense to use something that actually _is_ a string (or character),
rather than an array of uint32_t.
For this reason, we switch out all wchar_t usage in foot to
char32_t. We also verify, at compile-time, that char32_t used
UTF-32 (which is what fcft expects).
Unfortunately, there are no string functions for char32_t. To avoid
having to re-implement all wcs*() functions, we add a small wrapper
layer of c32*() functions.
These wrapper functions take char32_t arguments, but then simply call
the corresponding wcs*() function.
For this to work, wcs*() must _also_ be UTF-32 compatible. We can
check for the presence of the __STDC_ISO_10646__ macro. If set,
wchar_t is at least 4 bytes and its internal representation is UTF-32.
FreeBSD does *not* define this macro, because its internal wchar_t
representation depends on the current locale. It _does_ use UTF-32
_if_ the current locale is UTF-8.
Since foot enforces UTF-8, we simply need to check if __FreeBSD__ is
defined.
Other fcft API changes:
* fcft_glyph_rasterize() -> fcft_codepoint_rasterize()
* font.space_advance has been removed
* ‘tags’ have been removed from fcft_grapheme_rasterize()
* ‘fcft_log_init()’ removed
* ‘fcft_init()’ and ‘fcft_fini()’ must be explicitly called
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.
With this patch, key- and mouse-bindings structs (the non-layout
specific ones) are unified into a single struct.
The logic that parses, and manages, the key- and mouse binding lists
are almost identical. The *only* difference between a key- and a mouse
binding is that key bindings have an XKB symbol, and mouse bindings a
button and click-count.
The new, unified, struct uses a union around these, and all functions
that need to know which members to use/operate on now takes a ‘type’
parameter.
This allows the user to write, to swap two key bindings:
[key-bindings]
show-urls-launch=Control+Shift+r
search-start=Control+Shift+u
instead of:
[key-bindings]
search-start=none
show-urls-launch=Control+Shift+r
search-start=Control+Shift+u
This should simplify the configuration for people who replace a lot of
the default key bindings.
This also simplifies the parsing somewhat, since we no longer has to
parse a key-binding into a temporary list, ensure it doesn’t have any
collisions, and then copy it into the actual key binding list.
_While_ parsing a key-binding, we still need a temporary array (at
least for the time being), but that temporary array is no longer
visible outside the parsing function that allocates it.
Instead of passing raw char** pointers to argv_compare(), pass
pointers to ‘struct argv’.
This lets argv_compare() handle both argv’s being NULL, or one of them
being NULL. That is, the caller no longer needs to check that both
argv’s are non-NULL before calling argv_compare().
Furthermore, update has_key_binding_collisions() to require the pipe
argv to match, in addition to matching the ‘action’, when allowing a
key collision.
When parsing a key binding with a pipe-argv, we failed to free the
argv vector (or to be precise, the strdup:ed entries in the array)
when failing to parse the remainder of the binding.
The parsing context keeps a pointer to the current section name. This
is used when logging errors.
However, the pointer was into a buffer allocated by getline(). This
buffer are often re-used in the next call to getline(), or free:d.
Regardless, the section name pointer is invalid after the next call to
getline(), which meant all error messages were logging a correct
section name.