In this mode, the “shifted” and “base layout” keys are added to the
CSIs, as sub-parameters to the “key” parameter.
Note that this PR only implements the “shifted” key, not the “base
layout key”.
This is done by converting the original XKB symbol to it’s
corresponding UTF-32 codepoint. If this codepoint is different from
the one we use as “key” in the CSI, we add it as a sub-parameter.
Related to #319
The generic input handler now converts the composed character to it’s
UTF-32 equivalent. This means we now provide a valid UTF-32 codepoint
for both composed characters, and non-composed (plain-text)
characters.
Use this in the kitty protocol to simplify the logic around composed
characters, by simply treating them as plain text.
In this mode, key events that generate text now add a third CSI
parameter, indicating the actual codepoint.
Remember that we always use the *unshifted* key in the CSI
escapes. With this mode, those CSI escapes now also included the text
codepoint. I.e. what would have been emitted, had we not generated a
CSI escape.
As far as I can tell, this mode has no effect unless “report all keys
as escape sequences” is enabled (reason being, without that, there
aren’t any text events that generate CSIs - they’re always emitted
as-is).
Note that Kitty itself seems to be somewhat buggy in this mode. At
least on Wayland, with my Swedish layout. For example ‘a’ and ‘A’ does
generate the expected CSIs, but ‘å’ and ‘Å’ appears to be treated as
non-text input.
Furthermore, Kitty optimizes away the modifier parameter, if no
modifiers are pressed (e.g. CSI 97;;97u), while we always emit the
modifier (CSI 97;1;97u).
Related to #319
All plain-text and composed characters are now printed as-is, in a
single place.
Also fix handling of “generic” keys when emitted as escapes; don’t use
the raw XKB symbol as key in the escape, convert it to a unicode code
point first. For many symbols, these are the same. But not
all.
For now, we fallback to using the symbol as is if XKB fails to convert
it to a codepoint. Not sure if we should simply drop the key press
instead.
Composed characters also need special treatment; we can’t use the
symbol as is, since it typically refers to the last key
pressed (i.e. not the composed character). And, that key is
also (usually) a special “dead” key, which cannot be converted to a
unicode codepoint.
So, what we do is convert the generated utf8 string, and (try to)
convert it to a wchar. If it succeeds, use that. If not, fallback to
using the XKB symbol (as above).
Before this, key release events stopped the repeat timer, and then
returned.
Now, we run through the entire function. Most things are still only
done on key press events. But, the goal here is to get to the keyboard
protocol functions (and the kitty protocol in particular), and call
them on release events too.
This is in preparation for the kitty protocol mode 0b10, report event
types.
Now that term_xcursor_update_for_seat() takes the current surface into
account (i.e. doesn’t assume the cursor is over the main grid),
there’s no longer any need to call render_xcursor_set() directly.
Thus, we can simply call term_xcursor_update_for_seat() on **all**
pointer enter and motion events. As long as we take care to update the
internal state to reflect the, possibly new, current surface before
doing so.
Also make sure to **always** reset the seat’s “current” xcursor
pointer on pointer leave events. This is done without actually sending
anything to the compositor, but is necessary to ensure that we *do*
send a request to update the xcursor on the next pointer enter event.
This fixes a regression, where the view (and selection) was only reset
if the keyboard input resulted in plain text. That is, key presses
like enter, arrows etc did not.
Otherwise if you don't receive motion event before e.g. button pressed,
the coordinates will be incorrect. This happens when e.g. you get
alt-tabbed so that the mouse cursor ends up on top of the terminal
window, but the mouse never actually moved.
When term_xcursor_update_for_seat() was called on e.g. keyboard focus
loss, it'd update the curret xcursor to 'text' even if it was e.g. on
top of the window title, or resize areas. This makes the function a bit
more focus aware, and will not be so eager to set the text xcursor.
Not sure why these keys have CSIs in the kitty spec; they don’t emit
anything.
Could it be that they are used if the keys are *not* modifiers in the
current layout?
Not sure if this is the best/correct way to do it. But kitty seems to
ignore at least Num-Lock for printables, while it _does_ affect other
keys. For example, Return, which usually emits ‘\r’, are affected by
Num-Lock and emit ‘CSI 13;129u’.
Note that as soon as some other modifier is in effect, the Num-Lock
modifier *is* encoded in the CSI, also for printables.
Our internal binding handling cares about a different set of
modifiers, compared to the kitty keyboard protocol.
To handle this, get_current_modifiers() has been modified, to no
longer strip the “unsignificant” modifiers. This is now up to the
caller to do.
To help, we keep two masks (for significant modifiers) in the seat
struct; one for our internal binding handling (and the legacy keyboard
protocol), and one for the kitty keyboard protocol. These two masks
are updated when the seat’s keymap is updated/changed.
When emitting an escape sequence for a printable character, with
modifiers (e.g. ctrl+a), use the key’s base symbol instead of
“lowering” it.
This means we now handle e.g. ctrl+2 and ctrl+shift+2, with Swedish
layout.
There’s a twist however. We *only* use the base symbol if the
modifiers that is used to “generate” the symbol are “significant”.
Significant modifiers are, in this context, modifiers we can encode in
the kitty escape sequences.
In the Swedish layout, pressing AltGr+2 results in ‘@’. AltGr cannot
be encoded in the kitty protocol. If we were to use the base symbol,
AltGr+Alt+2 would result in exactly the same escape sequence as Alt+2.
Most things appear to work as in kitty. There’s one known difference:
tri-state keys don’t generate the same unshifted symbol while holding
Shift (but e.g. Ctrl+a and Ctrl+Shift+a *does* generate the same base
symbol).
For example, the Swedish keyboard layout has double quote, ‘2’ and ‘@’
on the same key. ‘2’ is the base (unshifted) symbol. Double quote is
Shift+2. ‘@’ is AltGr+2.
Kitty generates the same base symbol for ‘2’ and double quote (the
base symbol is, as expected, ‘2’).
But, for ‘@’ kitty generates the base symbol ‘@’.
Currently, foot generates the base symbol by calling
xkb_keysym_to_lower().
I _think_ what we need to do is “consume” the shift modifier, and then
re-retrieve the symbol (given the current xkb state and key pressed).
This breaks out all handling of key escapes to-be-sent to the client,
to a separate function, legacy_kbd_protocol().
That is, the key press/release handler first handles key generic
handling, such as starting and stopping the repeat timer.
Then it checks for foot keyboard bindings. If not bindings match, we
need to pass the keyboard event to the client. This code has now been
separated out into a new function.
If a mouse selection was ongoing, and the user switched
workspace (probably using the keyboard...), and then back, the
selection was still treated as ongoing, while all other mouse state
has been reset.
This meant the user had to tap at least once to stop the selection.
Similar to modifyOtherKeys=1 (foot’s default, and only, mode), except
that:
* All modifiers (and not just Ctrl) generate \E[27;m;n~ escapes
* Regular keys (with modifiers) also generate \E[27;m;n~ escapes (for
example, C-h no longer generates ^H, but \E[27;5;104~)
For our keymap based lookups, this is handled by adding
MOD_MODIFY_OTHER_KEYS_STATE<N> variants.
For “generic” keys, we simply adjust the conditions for when to emit a
\E[27;m;n~ escape - the only requirement is that at least one modifier
is active.
* Allow scrolling on the normal (non-alt) screen, when application is
grabbing the mouse (when user presses Shift).
* Use term_mouse_grabbed() instead of explicitly checking for
MOUSE_NONE tracking.
* Remove mouse tracking check from cmd_scrollback_{up,down}. Caller is
expected to have done the check.
* Don’t scroll down on mouse wheel tilt events.
The serial is used when copying/pasting data from the clipboard. Up
until now, we’ve used the serial from the keyboard/mouse enter
events.
This works in most cases, but breaks in the following example:
$ wl-copy WLCOPY
/* Ctrl+Shift+v works fine (pastes "WLCOPY") */
$ printf "\033]52;c;eHl6\a"
/* Ctrl+Shift+v pastes "WLCOPY" instead of "xyz" */
Shifting focus away and then back to the foot window, and re-executing
the printf works, suggesting the “enter” serial is no longer valid
after another process(?) has copied something to the clipboard.
Updating the serial on key press/release (and the corresponding mouse
serial on mouse button events) seems to fix this.
I’ve also tested that “normal” copy/paste operations, within the same
foot instance, and between foot and other applications, are still
working. In at least river (wlroots based), and GNOME/mutter.
Closes#753
Under certain circumstances, GNOME will send multiple pointer button
press events, without any release or leave events in between.
This trips up our button tracking.
Workaround, by replacing the existing state for the pressed button
with the new state.
Previously, debug builds would assert (and thus crash), while release
builds would have multiple states for the same button,
causing (probably) issues like the title bar not being usable (as in,
cannot be dragged, buttons not working etc).
Hopefully closes#709
We now emit button 6/7 events (when the client application grabs the
mouse). This buttons map to mouse wheel horizontal scroll events. Or, left/right
tilting, if you like.
Wayland report these as ‘axis’ events (just like regular scroll wheel events),
and thus we need to translate those scroll events to button events.
libinput does not define any mouse buttons for wheel tilts, so we add our own
defitions. These are added last in the BTN_* range, just before the BTN_JOYSTICK
events.