The version bump was done since we now use XKB_VMOD_NAME_*; macros
added in libxkbcommon 1.8.0.
Not all distros have updated libxkbcommon yet (read: Debian). Since
it's fairly easy to work around, let's do that.
Closes#2103
* Recognize 'CSI ? 996 n', and respond with
- 'CSI ? 997 ; 1 n' if the primary theme is active
- 'CSI ? 997 ; 2 n' if the alternative theme is actice
* Implement private mode 2031, where changing the color
theme (currently only possible via key bindings) causes the terminal
to send the same CSI sequences as above.
In this context, foot's primary theme is considered dark, and the
alternative theme light (since the default theme is dark).
Closes#2025
* color-theme-switch-1: select the primary color theme
* color-theme-switch-2: select the alternative color theme
* color-theme-toggle: toggle between the primary and alternative color themes
Edge constraints are new (not yet available in a wayland-protocols
release) toplevel states, acting as a complement to the existing tiled
states.
Tiled tells us we shouldn't draw shadows etc *outside our window
geometry*.
Constrained tells us the window cannot be resized in the constrained
direction.
This patch does a couple of things:
* Recognize the new states when debug logging
* Change is_top_left() etc to look at the new constrained state
instead of the tiled state. These functions are used when both
choosing cursor shape, and when determining if/how to resize a
window on a CSD edge click-and-drag.
* Update cursor shape selection to use the default (left_ptr) shape
when on a constrained edge (or corner).
* Update CSD resize triggering, to not trigger a resize when attempted
on a constrained edge (or corner).
See
86750c99ed:
An edge constraint is an complementery state to the tiled state,
meaning that it's not only tiled, but constrained in a way that it
can't resize in that direction.
This typically means that the constrained edge is tiled against a
monitor edge. An example configuration is two windows tiled next
to each other on a single monitor. Together they cover the whole
work area.
The left window would have the following tiled and edge constraint
state:
[ tiled_top, tiled_right, tiled_bottom, tiled_left,
constrained_top, constrained_bottom, constrained_left ]
while the right window would have the following:
[ tiled_top, tiled_right, tiled_bottom, tiled_left,
constrained_top, constrained_bottom, constrained_right ]
This aims to replace and deprecate the
`gtk_surface1.configure_edges` event and the
`gtk_surface1.edge_constraint` enum.
Some compositors (mutter/GNOME is one) adds _virtual_ modifiers to the
set of active modifiers when e.g. Alt, Meta, Super or Hyper is
pressed. For example, pressing Alt+b would result in *both* the Alt
*and* the Mod1 modifier being set.
Since foot makes close to zero assumptions on how the modifiers should
be interpreted, this causes various breakages.
For example, a foot shortcut defined as Mod1+b will not match, since
the Alt modifiers is also set. This has forced users to
redefine/override some of the default key bindings to include the
additional modifiers.
It also causes issues with the kitty keyboard protocol, for some key
combinations. Mainly whether or not to use unshifted key or not,
resulting in incorrect escape sequences.
Since all the "real" modifiers are always set as well, we can safely
ignore the virtual modifiers.
Closes#2009
Users can now define their own regex patterns, and use them via key
bindings:
[regex:foo]
regex=foo(bar)?
launch=path-to-script-or-application {match}
[key-bindings]
regex-launch=[foo] Control+Shift+q
regex-copy=[foo] Control+Mod1+Shift+q
That is, add a section called 'regex:', followed by an
identifier. Define a regex and a launcher command line.
Add a key-binding, regex-launch and/or regex-copy (similar to
show-urls-launch and show-urls-copy), and connect them to the regex
with the "[regex-name]" syntax (similar to how the pipe-* bindings
work).
That is, try to match e.g. Control+shift+a, before trying to match
Control+A.
In most cases, order doesn't matter. There are however a couple of
symbols where the layout consumes the shift-modifier, and the
generated symbol is the same in both the shifted and unshifted
form. One such example is backspace.
Before this patch, key-bindings with shift-backspace would be ignored,
if there were another key-binding with backspace.
So, for example, if we had one key-binding with Control+Backspace, and
another with Control+Shift+Backspace, the latter would never trigger,
as we would always match the first one.
By checking for unshifted matches first, we ensure
Control+Shift+Backspace does match.
When matching the unshifted symbol, or the raw key code, ignore all
key bindings that don't have any modifiers.
This fixes an issue where it was impossible to enter (some of the)
numbers on the keypad, **if** there was a key-binding for
e.g. KP_Page_Up, or KP_Page_Down.
When trying to match key bindings, we do three types of matching:
* Match the _translated_ symbol (e.g. Control+C)
* Match the _untranslated_ symbol (e.g. Control+Shift+c)
* Match raw keyboard codes
This was done for *each* key binding. This meant we sometimes matched
a keybinding in raw mode, even though there was a
translated/untranslated binding that would match it too. All depending
on the internal order of the key binding list.
This patch changes it, so that we first try all bindings in translated
mode, then all bindings in untranslated mode, and finally all bindings
in raw mode.
Closes#1929
Use better named variables while juggling the shifted vs. unshifted
key codes.
Switch to variable names appropriate for the kitty keyboard protocol
once we have all the unshifted, shifted and base key codes done. It's
not until then we can decide which key code to use as the main key,
and whether or not to report the alternate key code.
Test a couple of key combos from the se and de(neo) layouts.
This unit test isn't intended to test _all_ key combinations, for all
kitty flag combinations, but to be more of a regression test -
whenever we discover a buggy, weird combo, add it here.
* Always do a base key lookup. Before this, we didn't do that if we
matched the XKB sym to a lookup table entry (i.e. keypads, cursor keys
etc.)
* Try to retrieve the unshifted symbol also when we matched the symbol
to a lookup table entry. When successful, we now report an alternate
key for keypad and cursor keys; before this patch, we only did that
for keys that didn't have an entry in the lookup table (i.e. ASCII
chars etc).
This improves compatibility with kitty (and the kitty keyboard
protocol) in more corner cases. One particular example is the neo
keyboard layout, where part of the regular keys act as keypad keys
when num-lock is active.
When alternate key reporting is enabled (i.e. when we're supposed to
report the shifted key along with the unshifted key), we try to figure
out whether the key really is shifted or not (and thus which xkb
keysym to use for the unshifted and shifted keys in the escape).
This was done by getting the layout's *all* modifier combinations that
produce the shifted keysym, and if any of of them contained a modifier
that isn't supported by the kitty protocol, the shifted and unshifted
keys are derived from the same keysym. This is to ensure we handle
things like AltGr-combos correctly.
The issue is, since there may be more than one modifier combination
generating the shifted keysym, we may end up using the wrong keysym
just because _another_ combination set contains modifiers not
supported by the kitty protocol. What we're interrested in is whether
the *pressed* set of modifiers contains such modifiers.
Closes#1918
From the specification:
The Enter, Tab and Backspace keys will not have release events
unless Report all keys as escape codes is also set, so that the
user can still type reset at a shell prompt when a program that
sets this mode ends without resetting it.
Closes#1892
* Render button as highlighted only when pointer is above them
* Releasing the mouse button while *not* on the button does *not*
activate the button
When pressing, and holding, a mouse button, the compositor keeps
sending motion events for the surface where the button was pressed,
even if the mouse has moved outside it.
We also don't get any surface leave/enter events.
This meant that the button was rendered as highlighted, and a click
registered, if the user pressed the mouse button while on the button,
and then moved the cursor away from the button before releasing the
button.
This patch fixes it, by checking if the current cursor coordinates
fall within the button surface.
This is how most UIs work.
Note that we (at least on River) don't get any surface enter/leave
events while a button is held. This means we can't detect if the user
pressed the mouse button while on a CSD button, but then moves the
mouse outside. Releasing the mouse button will still activate the CSD
button.
Closes#1787
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
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 the compositor sends a new keymap, don't reset the XKB compose
state.
This is done by initializing the XKB context, along with the compose
state, when binding the seat, instead of in keymap().
Then, in keymap(), simply stop destroying the old xkb state. Only
destroy, and re-create the keymap state.
Closes#1744
This implements high resolution mouse wheel scroll events. A "normal"
scroll step corresponds to the value 120. Anything less than that is a
partial scroll step.
This event replaces axis_discrete(), when we bind wl_seat v8 (which we
now do, when available).
We calculate the number of degrees that is required to scroll a single
line, based off of the scrollback.multiplier value.
Each high-res event accumulates, until we have at least the number of
degress required to scroll one, or more lines.
The remaining degrees are kept, and added to in the next scroll event.
Closes#1738
This fixes an issue where entering unicode-mode in one foot client,
also enabled unicode-mode on other foot clients. Both
visually (although glitchy), and in effect.
The reason the state was originally in the seat objects, was to fully
support multi-seat. That is, one seat/keyboard entering unicode-mode
should not affect other seats/keyboards.
The issue with this is that seat objects are Wayland global. Thus, in
server mode, all seat objects are shared between the foot clients.
There is a similarity with IME, which also keeps state in the
seat. There's one big difference, however, and that is IME has Wayland
native enter/leave events, that the compositor emits when windows are
focused/unfocused. These events allow us to reset IME state. For our
own Unicode mode, there is nothing similar.
This patch moves the Unicode state from seats, to the terminal
struct. This does mean that if one seat/keyboard enters Unicode mode,
then *all* seats/keyboards will affect the unicode state. This
potential downside is outweighed by the fact that different foot
clients no longer affect each other.
Closes#1717
The kitty keyboard specification has been updated/clarified yet
again. Locked modifiers are to be ignored if the key event would
result in plain text without the locked modifier being enabled.
In short, locked modifiers are included in the set of modifiers
reported in a key event. But having a locked modifier enabled doesn't
turn all key events into CSIu sequences.
For example, with only the disambiguate mode enabled, pressing 'a', or
'shift+a' results in a/A regardless of the state of Caps- or NumLock.
But 'ctrl+a', which always results in a CSIu, will have a different
modifier list, depending on whether Caps- or NumLock are enabled.
This fixes an issue where some key combinations resulted in different
output (e.g. escape code vs. plain text) depending on the state of
e.g. the NumLock key. One such example is Shift+space. Another example
is Shift+BackSpace.
This patch also removes the hardcoded CapsLock filter, when
determining whether a key combo produces text or not, and instead uses
the locked modifiers as reported by XKB.
When kitty keyboard is enabled, pressing a modifier key will clear the
text selection. This makes it difficult to copy text because the
selection clears as soon as the user presses "ctrl".
Tested-by: Robin Jarry <robin@jarry.cc>
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
For the purpose of matching key bindings, "significant" modifiers are
no more.
We're really only interested in filtering out "locked"
modifiers. We're already doing this, so there's no need to *also*
match against a set of "significant" modifiers.
Furthermore, we *never* want to consider locked keys (e.g. when
emitting escapes to the client application), thus we can filter those
out already when retrieving the set of active modifiers.
The exception is the kitty keyboard protocol, which has support for
CapsLock and NumLock. Since we're already re-retrieving the "consumed"
modifiers (using the GTK style, rather than normal "XKB" style, to
better match the kitty terminal), we might as well re-retrieve the
effective modifiers as well.
That is, allow custom modifiers (i.e. other than ctrl/shift/alt etc)
in key bindings.
This is done by no longer validating/translating modifier names to
booleans for a pre-configured set of modifiers (ctrl, shift, alt,
super).
Instead, we keep the modifier *names* in a list, in the key binding
struct.
When a keymap is loaded, and we "convert" the key binding, _then_ we
do modifier translation. For invalid modifier names, we print an
error, and then ignore it. I.e. we no longer fail to load a config due
to invalid modifier names.
We also need to update how we determine the set of significant
modifiers. Any modifier not in this list will be ignored when matching
key bindings.
Before this patch, we hardcoded this to shift/alt/ctrl/super. Now, to
handle custom modifiers as well, we simply treat *all* modifiers
defined by the current layout as significant.
Typically, the only unwanted modifiers are "locked" modifiers. We are
already filtering these out.
Starting with kitty 0.32.0, the modifier bits during modifier key
events behave differently, compared to before. Or, rather, they have
now been spec:ed; before, behavior was different on e.g. MacOS, and
Linux.
The new behavior is this:
On key press, the modifier bits in the kitty key event *includes* the
pressed modifier key.
On key release, the modifier bits in the kitty key event does *not*
include the released modifier key.
In other words, The modifier bits reflects the state *after* the key
event.
This is the exact opposite of what foot did before this patch.
The patch is really pretty small: in order to include the key in the
modifier set, we simulate a key press to update the XKB state, using
xkb_state_uppate_key(). For key pressed, we simulate an XKB_KEY_DOWN
event, and for key releases we simulate an XKB_KEY_UP event.
Then we re-retrieve the modifers, both the full set, and the consumed
set.
Closes#1561
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
No longer inhibits touch event handling when terminal window
has pointer focus. Instead, inhibit touch event when at least
one pointer button is held down.
This change improves user experience when using foot with both
a mouse and a touchscreen.
Closes#1428.
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