mp.input: use unique event handlers for input.get requests

This makes changes to mp.input and console.lua so that every input.get
request uses a unique script-message to handle input events.

Previously, making new input.get requests shortly after the termination
of a previous request made by the same script could cause a race
condition where the input handler was closed but the new request
was still being drawn in the UI. This was caused by the `closed` event
for the previous request being received only after the new request was
registered, hence closing the event handler for the new request instead.

In addition, this commit makes the behaviour of calling input.get while
another request is active more consistent. When a new request is
received it overwrites the in-progress request, sending a `closed`
event. However, previously, the `closed` event could not be sent if both
requests came from the same script, as the new request would have
overwritten the event handler. Now, the `closed` event is called
regardless of where the new request comes from.
This commit is contained in:
CogentRedTester
2026-01-22 00:04:35 +01:00
committed by Kacper Michajłow
parent 49b6d80e87
commit 17551b2d43
3 changed files with 41 additions and 23 deletions
+12 -7
View File
@@ -653,8 +653,12 @@ mp.options = { read_options: read_options };
/**********************************************************************
* input
*********************************************************************/
var input_handle_counter = 0;
function register_event_handler(t) {
mp.register_script_message("input-event", function (type, args) {
var handler_id = "input-event/" + input_handle_counter++;
mp.register_script_message(handler_id, function (type, args) {
if (t[type]) {
args = args ? JSON.parse(args) : [];
var result = t[type].apply(null, args);
@@ -666,18 +670,19 @@ function register_event_handler(t) {
}
if (type == "closed")
mp.unregister_script_message("input-event");
mp.unregister_script_message(handler_id);
})
return handler_id;
}
mp.input = {
get: function(t) {
t.has_completions = t.complete !== undefined
t.has_completions = t.complete !== undefined;
t.client_name = mp.script_name;
t.handler_id = register_event_handler(t);
mp.commandv("script-message-to", "console", "get-input", mp.script_name,
JSON.stringify(t));
register_event_handler(t)
mp.commandv("script-message-to", "console", "get-input", JSON.stringify(t));
},
terminate: function () {
mp.commandv("script-message-to", "console", "disable");
+17 -11
View File
@@ -96,6 +96,7 @@ local key_bindings = {}
local dont_bind_up_down = false
local global_margins = { t = 0, b = 0 }
local input_caller
local input_caller_handler
local keep_open = false
local completion_buffer = {}
@@ -949,7 +950,7 @@ end
local function handle_edit()
if not selectable_items then
handle_cursor_move()
mp.commandv("script-message-to", input_caller, "input-event", "edited",
mp.commandv("script-message-to", input_caller, input_caller_handler, "edited",
utils.format_json({line}))
return
end
@@ -1070,7 +1071,7 @@ local function submit()
if selectable_items then
if #matches > 0 then
mp.commandv("script-message-to", input_caller, "input-event", "submit",
mp.commandv("script-message-to", input_caller, input_caller_handler, "submit",
utils.format_json({matches[focused_match].index}))
end
else
@@ -1079,7 +1080,7 @@ local function submit()
cycle_through_completions()
end
mp.commandv("script-message-to", input_caller, "input-event", "submit",
mp.commandv("script-message-to", input_caller, input_caller_handler, "submit",
utils.format_json({line}))
history_add(line)
@@ -1481,7 +1482,7 @@ end
complete = function ()
completion_old_line = line
completion_old_cursor = cursor
mp.commandv("script-message-to", input_caller, "input-event",
mp.commandv("script-message-to", input_caller, input_caller_handler,
"complete", utils.format_json({line:sub(1, cursor - 1)}))
render()
end
@@ -1651,7 +1652,7 @@ set_active = function (active)
unbind_mouse()
mp.set_property_bool("user-data/mpv/console/open", false)
mp.set_property_bool("input-ime", ime_active)
mp.commandv("script-message-to", input_caller, "input-event",
mp.commandv("script-message-to", input_caller, input_caller_handler,
"closed", utils.format_json({line, cursor}))
collectgarbage()
end
@@ -1662,14 +1663,15 @@ mp.register_script_message("disable", function()
set_active(false)
end)
mp.register_script_message("get-input", function (script_name, args)
if open and script_name ~= input_caller then
mp.commandv("script-message-to", input_caller, "input-event",
mp.register_script_message("get-input", function (args)
if open then
mp.commandv("script-message-to", input_caller, input_caller_handler,
"closed", utils.format_json({line, cursor}))
end
input_caller = script_name
args = utils.parse_json(args)
input_caller = args.client_name
input_caller_handler = args.handler_id
prompt = args.prompt or ""
line = args.default_text or ""
cursor = tonumber(args.cursor_position) or line:len() + 1
@@ -1704,7 +1706,7 @@ mp.register_script_message("get-input", function (script_name, args)
else
selectable_items = nil
unbind_mouse()
id = args.id or script_name .. prompt
id = args.id or args.client_name .. prompt
log_offset = 0
completion_buffer = {}
autoselect_completion = args.autoselect_completion
@@ -1721,11 +1723,15 @@ mp.register_script_message("get-input", function (script_name, args)
if line ~= "" then
complete()
elseif open then
-- This is needed to update the prompt if a new request is
-- received while another is still active.
render()
end
end
set_active(true)
mp.commandv("script-message-to", input_caller, "input-event", "opened")
mp.commandv("script-message-to", input_caller, input_caller_handler, "opened")
end)
-- Add a line to the log buffer
+12 -5
View File
@@ -18,6 +18,8 @@ License along with mpv. If not, see <http://www.gnu.org/licenses/>.
local utils = require "mp.utils"
local input = {}
local handle_counter = 0
local function get_non_callbacks(t)
local non_callbacks = {}
@@ -31,7 +33,10 @@ local function get_non_callbacks(t)
end
local function register_event_handler(t)
mp.register_script_message("input-event", function (type, args)
local handler_id = "input-event/"..handle_counter
handle_counter = handle_counter + 1
mp.register_script_message(handler_id, function (type, args)
if t[type] then
local completions, completion_pos, completion_append =
t[type](unpack(utils.parse_json(args or "") or {}))
@@ -44,18 +49,20 @@ local function register_event_handler(t)
end
if type == "closed" then
mp.unregister_script_message("input-event")
mp.unregister_script_message(handler_id)
end
end)
return handler_id
end
function input.get(t)
t.has_completions = t.complete ~= nil
t.client_name = mp.get_script_name()
t.handler_id = register_event_handler(t)
mp.commandv("script-message-to", "console", "get-input",
mp.get_script_name(), utils.format_json(get_non_callbacks(t)))
register_event_handler(t)
utils.format_json(get_non_callbacks(t)))
end
input.select = input.get