tllists are great when dealing with dynamically changing lists. They
are also very easy to use when building lists/arrays where the final
size is unknown.
However, this ease of use comes at a price: code size. tll-macros
expand to a lot of code.
Since things in the config are static, once the config has been
loaded, using tllists for configuration data structures doesn’t make
much sense.
This patch replaces nearly all tllists used by the configuration, with
dynamically allocated arrays.
Since the alt screen have no scrollback, all scrollback-* actions are
effectively no-ops when the alt screen is active.
Make them available to the client application instead.
Closes#573
There were two issues with it:
* Not all applications decode the sequence into a set of modifiers +
key, but use a fixed sequence -> combo mapping, that we broke.
* There were unforeseen issues with e.g. F1-12, where the modifier
were removed from combos like Ctrl+F12, or Alt+F12. The reason is
simple; XKB tells us that Ctrl, or Alt, is a consumed modifier. Now,
_why_ it thinks that is a different story.
This reverts 6cd72bdee6Closes#425
When detecting, and repairing, “broken” key bindings (where the key
binding itself explicitly lists a modifier that is consumed by the
final symbol - e.g “Shift+W”), don’t just look for an intersection
between the set of modifiers needed to produce the final symbol, and
the modifiers listed in the key combo. Instead, check if the key combo
has *all* the required modifiers.
Example: Shift+AltGr+w produces Page_Down. I.e. Page_Down is the
_shifted_ symbol, ‘w’ is the un-shifted symbol, and Shift+AltGr are
the modifiers required to shift ‘w’ to Page_Down.
If we have the key combo Shift+Page_Down, foot would, correctly,
determine that Page_Down is a shifted symbol. It would find the
Shift+AltGr modifier set, and since the intersection of “Shift+AltGr”
and “Shift” (from our key combo) is non-empty, foot
would (incorrectly) determine that we can, and should, replace
Page_Down with its un-shifted symbol ‘w’.
This is completely wrong, since Shift+w does _not_ produce Page_Down.
Closes#407
Shift+Tab is an odd bird in XKB; it produces a shifted variant of tab,
ISO_Left_Tab, with Shift being a consumed modifier.
From a terminal perspective, Tab and ISO_Left_Tab are the same key,
with Shift+Tab generating ‘CSI Z’, and all other combos generating a
‘CSI 27;mods;9~’ escape.
Before, when we didn’t filter out consumed modifiers, we could simply
re-use the keymap for Tab when translating ISO_Left_Tab.
This is no longer possible, since shift has been filtered out. As a
result, Shift+Tab no longer generated ‘CSI Z’, but ‘\t’. I.e as if
shift wasn’t being pressed.
This patch adds a separate keymap table for ISO_Left_Tab. It’s MOD_ANY
entry corresponds to Shift+Tab, and emits ‘CSI Z’. All its other
entries *exclude* shift (since it has been consumed), *but*, the
encoded modifier (in the escape sequences) *include* shift.
If a user-provided key combo contains both an explicit modifier, and
the shifted symbol it produces, replace the symbol with its un-shifted
version.
Example: Control+Shift+U contains both ‘Shift’, and ‘U’, where ‘Shift’
is the modifier that shifts ‘u’ to ‘U’.
Such modifiers are “consumed”, i.e. filtered out, when matching key
combos. As such, Control+Shift+U will never trigger since we’ll never
be able to match the consumed modifier ‘Shift’.
The above combo can be written in two ways:
- Control+U
- Control+Shift+u
To be able to detect that Control+Shift+U is an invalid combination,
we need to check all *shifted* symbols for all key *codes*.
Once we’ve detected a shifted symbol (and where it differs from the
un-shifted symbol), we loop all modifier sets that produce the shift
level where our shifted symbol is. For each such set, check if it
intersects with the user-provided key combo’s modifier set.
If there is an intersection, it means the user provided a key combo
containing a modifier and symbol, such that the modifier is consumed
when the symbol is produced.
In this case, we replace the symbol with its un-shifted version.
Bindings are matched in one out of three ways:
* By translated (by XKB) symbols
* By untranslated symbols
* By raw key codes
A translated symbol is affected by pressed modifiers, some of which
can be “consumed”. Consumed modifiers to not partake in the comparison
with the binding’s modifiers. In this mode, ctrl+shift+2 maps to
ctrl+@ on a US layout.
Untranslated symbols, or un-shifted symbols refer to the “base” symbol
of the pressed key, i.e. it’s unaffected by modifiers. In this mode,
consumed modifiers *do* partake in the comparison with the binding’s
modifiers, and ctrl+shift+2 maps to ctrl+shift+2 on a US layout.
More examples: ctrl+shift+u maps to ctrl+U in the translated lookup,
while ctrl+shift+u maps to ctrl+shift+u in the untranslated lookup.
Finally, we also match raw key codes. This allows our bindings to work
using the same physical keys when the user switches between latin and
non-latin layouts.
This means key bindings in foot.ini *must* not include both +shift+
and a *shifted* key. I.e. ctrl+shift+U is not a valid combo as it
cannot be triggered. Unfortunately, this was how you were supposed to
write bindings up until now... so, we try to detect such bindings, log
a deprecation warning and then “fix” the binding for the user.
When specifying bindings in foot.ini, both ctrl+U and ctrl+shift+u are
valid, and will work. The latter is preferred though, since we cannot
detect the raw key code for the former variant. Personally, I also
prefer the latter one because it is more explicit; it’s more obvious
which keys are involved.
However, in some cases it makes more sense to use the other
variant. Typically for non-letter combos.
Up until now, the various key binding modes (“normal”, “search” and
“url”) have used their own struct definitions for their key bindings.
The only reason for this was to have a properly typed “action” (using
the appropriate “action” enum).
This caused lots of duplicated code. This patch refactors this to use
a single struct definition for the “unparsed” key bindings handled by
the configuration, and another single definition for “parsed” bindings
used while handling input.
This allows us to implement configuration parsing, keymap translation
and so on using one set of functions, regardless of key binding mode.
This is implemented by allocating one of the (few!) remaining bits in
the cells’ attribute struct to indicate the cell should be “URL
highlighted”.
render_cell() looks at this bit and draws an underline using the color
from colors.urls (defaults to regular3 - i.e. yellow).
A new function, url_tag_cells(), iterates the currently detected URLs
and sets the new ‘url’ attribute flag on the affected cells.
Note: this is done in a separate function to keep urls_collect() free
from as many dependencies as possible.
urls_reset() is updated to *clear* the ‘url’ flag (and thus implicitly
also results in a grid refresh, _if_ there were any URLs).
We now exit URL mode on *any* client application input. This needs to
be so since we can’t know if the URLs we previously detected are still
valid.
This works just like show-urls-launch, except that instead of opening
the URL (typically using xdg-open), it is placed in the clipboard when
activated.
When the application is grabbing the mouse, we require ‘shift’ to be
pressed to be able to use foot’s mouse bindings. Otherwise the mouse
event is sent to the application.
This wasn’t being enforced consistently; each and every mouse **only**
action was checking the mouse grab state, but e.g. *primary
paste* (which can be used as both a key binding and a mouse binding)
was not.
The fix is actually quite simple: don’t even try to execute *any*
mouse bindings when the application is grabbing the mouse (unless
shift is pressed).
This fixes an issue where e.g. middle mouse button events (using the
default mouse bindings) were never seen by any mouse grabbing client
applications.
wayland-client-protocol.h:
Negative values for either rate or delay are illegal. A rate of
zero will disable any repeating (regardless of the value of
delay).
This fixes a division-by-zero crash.
This removes the selection_mark_word() and selection_mark_row()
functions. To start a word/row-based selection, use selection_start()
with SELECTION_SEMANTIC_{WORD,ROW}
Store a list of currently pressed buttons, and which surface they
belong to (i.e. which surface that received the press).
Then, in motion events (with a button pressed, aka drag operations),
send the event to the “original” surface (that received the press).
Also send release events to the originating surface.
This means a surface receiving a press will always receive a
corresponding release. And no one will receive a release event without
a corresponding press event.
Motion events with a button pressed will *always* use the *first*
button that was pressed. I.e. if you press a button, start dragging,
and then press another button, we keep generating motion events for
the *first* button.
As long as the mouse button was *pressed* while the pointer was inside
the grid, we want to keep reporting motion events until the button is
released.
Even when the pointer moves outside the grid (but in this case, the
reported coordinates are bounded by the grid size).
This patch also tries to improve multi-button handling (i.e. multiple
buttons pressed at the same time), and the events we report to the
client for these, in the following ways:
* Motion events now report the *initial* button. That is, if you start
a drag operation with the LEFT button, then press RIGHT (before
releasing LEFT), keep reporting LEFT in the motion events.
* Mouse release events are reported for *any* button, as long as the
pointer is *inside* the grid, *or*, the button released was the
button used to start a drag operation.
The last point is important; if we have reported a button press
followed by motion events (i.e. a drag operation), we need to report
the button release, *even* if the pointer is outside the grid.
Note that the client may receive unbalanced button press/release
events in the following ways if the user pressed one, and then a
second button *inside* the grid, then releases the *first*
button (possibly outside the grid), and finally releases the *second*
button *outside* the grid.
In this case, both buttons will report press events. The first button
will report a release event since it is the initial button in the drag
operation.
However, we don’t track the fact that the second button is being
pressed, and thus if it is released outside the grid, it wont generate
a release event.
This is done by allocating cells for the pre-edit text when receiving
the text-input::done() call, and populating them by converting the
utf-8 formatted pre-edit text to wchars.
We also convert the pre-edit cursor position to cell positions (it can
cover multiple cells).
When rendering, we simply render the pre-edit cells on-top off the
regular grid. While doing so, we also mark the underlying, “real”,
cells as dirty, to ensure they are re-rendered when the pre-edit text
is modified or removed.
Don’t require NumLock to be locked. Foot has no idea _which_ modifier
the user has mapped NumLock to, meaning we really cannot require it to
be locked.
This mode can be set by client programs with the DECSET, DECRST,
XTSAVE and XTRESTORE sequences by using 27127 as the parameter.
The sequence "\E[27;1;27~" is encoded in the same way as is done by
xterm's "modifyOtherKeys" mode. Even though xterm itself never emits
such a sequence for the Escape key, many programs already have
support for parsing this style of key sequence.