-
Notifications
You must be signed in to change notification settings - Fork 3.2k
mp.input: use unique event handlers for input.get requests #17251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mp.input: use unique event handlers for input.get requests #17251
Conversation
|
I'm not sure if there's any documentation I should be modifying for this as the current docs don't really explain anything regarding the behaviour of multiple input.get requests. |
|
Is there anything wrong with passing |
|
The scenario that lead to this PR was actually caused by me wanting to trigger input.select from input.get, which you can see in this youtube-search script that I modified earlier today: CogentRedTester/mpv-scripts#40 The fact that an input UI can be visible, but just silently fail to do anything can be very confounding. It took me quite a while to figure out what was going on and necessitated looking through the input.lua and console.lua source code. I don't see any advantage to leaving things as they are, whereas this PR would help prevent developers from encountering this unexpected behaviour in the future. |
|
You don't need timeouts to call input.select from input.get. You just pass I think the advantage of leaving it like this is that it encourages to use it in the intended way with |
c332245 to
d21717c
Compare
|
Now that you've pointed it out, I do realise how Also, this PR allows the |
|
Dunno, this already doesn't update Not sending Also a simpler way to make nested calls work without |
d21717c to
3a4293c
Compare
Woops, I forgot about JavaScript, I've added it now.
This really is very minor extra complexity; it's literally just adding an incrementing counter and building a string with it. I don't think it's a valid reason to avoid this change.
But I don't think that is how the input requests are really presented, the documentation implies (to me) that each
I would argue that this is might be worse as then the closed callback would be run on the new request. If a script is relying on this to be called after the submit/edited/etc callbacks are run then this could cause a whole new class of bugs. |
Fair, these are a good points which convinced me. It is fortunate that I did not document the JSON API yet or you could not change it. On the other hand it is unfortunate that nesting calls without diff --git a/player/lua/input.lua b/player/lua/input.lua
index 3dded33dd7..31daf87c1c 100644
--- a/player/lua/input.lua
+++ b/player/lua/input.lua
@@ -42,10 +42,6 @@ local function register_event_handler(t)
completion_append or "")
end
end
-
- if type == "closed" then
- mp.unregister_script_message("input-event")
- end
end)
end
diff --git a/player/lua/select.lua b/player/lua/select.lua
index 0ecbff4ea5..9b50ce1610 100644
--- a/player/lua/select.lua
+++ b/player/lua/select.lua
@@ -742,13 +742,8 @@ mp.add_key_binding(nil, "menu", function ()
input.select({
prompt = "",
items = labels,
- keep_open = true,
submit = function (i)
mp.command(commands[i])
-
- if not commands[i]:find("^script%-binding select/select") then
- input.terminate()
- end
end,
})
end)press Ctrl+p and open submenus, the flicker is quite noticeable. So the manual should still recommend using it for nesting. I will update the other PR accordingly. |
Before mpv-player#17251 keep_open was needed to make nested mp.input calls. Even after that change it is still better to pass it to not show console quickly closing and reopening to the user, so recommend it.
No argument there, I have a couple of suggested tweaks to the documentation myself, so maybe hold off on merging that PR until I get a chance to look at it tomorrow? |
|
Yeah that depends on this PR anyway and it's not like I have merge rights. I am also planning to deprecate |
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.
3a4293c to
103df92
Compare
I disagree actually, I think that opened is maybe more useful after this PR given the improved reliability of local file
input.get({
prompt = 'Append text to file:\n> ',
opened = function()
file = io.open('/path/to/file', 'w+')
end,
submit = function(line)
file:write(line)
end,
closed = function()
file:close()
end,
})Technically, the current code essentially guarantees that any input request will almost immediately be opened, at least briefly. However, the reality is that mp.input is an asynchronous API, and I don't think we should be encouraging people to treat the console like it has been opened the moment they call Currently, the documentation makes no explicit guarantees that a request will actually be made to the user when calling |
|
|
|
Superseded by #17256. |
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
closedeventfor 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
closedevent. However, previously, the
closedevent could not be sent if bothrequests came from the same script, as the new request would have
overwritten the event handler. Now, the
closedevent is calledregardless of where the new request comes from.
Edit: this PR has largely been superseded by #17256, but since that PR
requires changes to the
mp.inputinterface and this one doesn't, I'llkeep this open until I find out if that PR has interest in being merged.
Examples
If you use the first keybind specified above you can see that after every
keypress the contents of the input are printed to the console.
After pressing enter, the
submitcallback is run, creating a new prompt.However, while the new prompt is being drawn on the screen, no callbacks
are being triggered. This is because console.lua not only sent a
submitcallback, it also sent a
closedcallback which will only be processedby the event loop once the
submitcallback is done.Since the
submitcallback creates a new input.get request, overridingthe event handler with the handler for the new request,
closeends upclosing the new request instead. The second keybind above delays the new
input.getrequest by 0.1 seconds to give theclosedcallback a chance to run first,and so should work in the current version of mpv.
The changes in this PR mean that this race condition cannot occur, and so
both keybinds behave the same (other than perhaps a small flash caused by the
timeout).
This race condition can also occur when explicitly closing a request with
input.terminate.In the first of the above keybinds, the first select prompt is overridden by the second,
which is drawn to the screen. However, the
input.terminatecall triggers aclosedevent that removes the second select request's event handler. As such, selecting an
item does not print anything to the screen. The second example again uses a timeout
to fix the behaviour on the current version of mpv.
Overriding an existing request without first terminating the input does work currently,
as shown by the above keybind. However, the single event handler means that
console.luacannot send a
closedevent to the first select request like it does when a request is overriddenby a request from a different script. The changes in this PR mean that the closed event is sent
for the overridden request regardless of the source.