Shift is used to enable selection when the client application is
grabbing the mouse.
As such, mouse bindings *never* have Shift as a modifier, but should
still trigger when Shift is being pressed.
We shouldn't start or modify a selection if selection isn't
possible (i.e. client application is grabbing the mouse, and user
isn't holding Shift).
We also shouldn't start or modify a selection if the pointer is
outside the grid (updating an ongoing selection on motion events is an
exception to this).
Check for ongoing selection, and *clear* it before bailing out due to
the selection not having an end-point.
This fixes an issue where a selection was kept as ongoing, even though
the button had been released. Typically triggered by clicking without
moving the mouse; this started a new selection, then (tried to)
finalize it, but failed since the selection didn't have an end-point.
This extends the "normal" bind action enum with mouse specific
actions.
When parsing key bindings, we only check up to the last valid keyboard
binding, while mouse bindings support *both* key actions and mouse
actions.
The new actions are:
* select-begin: starts an interactive selection
* select-extend: interactively extend an existing selection
* select-word: select word under cursor
* select-word-whitespace: select word under cursor, where the only
word separating characters are whitespace characters.
The old hard-coded selection "bindings" have been converted to instead
use these actions, via default bindings added to the configuration.
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.