From eeb8e6e4512676e27fc58777dd05e17314d4adc6 Mon Sep 17 00:00:00 2001 From: nanahi <130121847+na-na-hi@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:30:35 -0400 Subject: [PATCH] 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. --- DOCS/interface-changes/keybind-cancel.txt | 2 ++ DOCS/man/lua.rst | 20 ++++++++++++++++++-- player/lua/defaults.lua | 4 +++- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 DOCS/interface-changes/keybind-cancel.txt diff --git a/DOCS/interface-changes/keybind-cancel.txt b/DOCS/interface-changes/keybind-cancel.txt new file mode 100644 index 0000000000..ab137a0cb4 --- /dev/null +++ b/DOCS/interface-changes/keybind-cancel.txt @@ -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 diff --git a/DOCS/man/lua.rst b/DOCS/man/lua.rst index e8065d9a1a..bd5a907d5b 100644 --- a/DOCS/man/lua.rst +++ b/DOCS/man/lua.rst @@ -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 diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua index 5f0ced76a5..0dc6cc8624 100644 --- a/player/lua/defaults.lua +++ b/player/lua/defaults.lua @@ -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