defaults.lua: handle canceled key bindings

There is a subtle behavior difference for built-in/input.conf key bindings
and key bindings registered by scripts: when a key binding is canceled
(e.g. a mouse button is bound to a command, is pressed down, and then
another key is pressed which is bound to another command), the command is
not invoked if the binding is built-in/input.conf, but is invoked if it's
registered by scripts, because it's handled with a different mechanism,
which gives no way for scripts to detect this.

Fix this by using the newly available canceled flag to detect this.
If a key binding is canceled, the callback is now not invoked unless
the key binding is registered with the complex option. In this situation,
the callback is invoked with the canceled state available so that scripts
can detect and handle this situation.
This commit is contained in:
nanahi 2024-06-06 01:30:35 -04:00 committed by avih
parent 5fcbe1c417
commit eeb8e6e451
3 changed files with 23 additions and 3 deletions

View File

@ -0,0 +1,2 @@
change `mp.add_key_binding` so that by default, the callback is not invoked if the event is canceled; clients should now use the `complex` option to detect this situation
add `canceled` entry to `mp.add_key_binding` callback argument

View File

@ -292,6 +292,18 @@ The ``mp`` module is preloaded, although it can be loaded manually with
After calling this function, key presses will cause the function ``fn`` to
be called (unless the user remapped the key with another binding).
However, if the key binding is canceled , the function will not be called,
unless ``complex`` flag is set to ``true``, where the function will be
called with the ``canceled`` entry set to ``true``.
For example, a canceled key binding can happen in the following situations:
- If key A is pressed while key B is being held down, key B is logically
released ("canceled" by key A), which stops the current autorepeat
action key B has.
- If key A is pressed while a mouse button is being held down, the mouse
button is logically released, but the mouse button's action will not be
called, unless ``complex`` flag is set to ``true``.
The ``name`` argument should be a short symbolic string. It allows the user
to remap the key binding via input.conf using the ``script-message``
@ -318,10 +330,14 @@ The ``mp`` module is preloaded, although it can be loaded manually with
``event``
Set to one of the strings ``down``, ``repeat``, ``up`` or
``press`` (the latter if key up/down/repeat can't be
tracked).
tracked), which indicates the key's logical state.
``is_mouse``
Boolean Whether the event was caused by a mouse button.
Boolean: Whether the event was caused by a mouse button.
``canceled``
Boolean: Whether the event was canceled.
Not all types of cancellations set this flag.
``key_name``
The name of they key that triggered this, or ``nil`` if

View File

@ -207,6 +207,7 @@ local function add_binding(attrs, key, name, fn, rp)
fn({
event = key_states[state:sub(1, 1)] or "unknown",
is_mouse = state:sub(2, 2) == "m",
canceled = state:sub(3, 3) == "c",
key_name = key_name,
key_text = key_text,
})
@ -222,7 +223,8 @@ local function add_binding(attrs, key, name, fn, rp)
-- Also, key repeat triggers the binding again.
local event = state:sub(1, 1)
local is_mouse = state:sub(2, 2) == "m"
if event == "r" and not repeatable then
local canceled = state:sub(3, 3) == "c"
if canceled or event == "r" and not repeatable then
return
end
if is_mouse and (event == "u" or event == "p") then