Skip to content
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

Rapidly pressing enter to confirm AcceptDialog freezes game (possible Popup issue?) #45258

Open
JustYourAverageJosh opened this issue Jan 17, 2021 · 1 comment

Comments

@JustYourAverageJosh
Copy link

JustYourAverageJosh commented Jan 17, 2021

Godot version:
v3.2.4.beta5.official

OS/device including version:
Windows 10

Issue description:
-Button is pressed which causes AcceptDialog.popup()
-then if you immediately press enter on keyboard: AcceptDialog Confirmed() (since focus goes directly to the OK button)
-then immediately press the Button to popup the AcceptDialog again
-immediately press enter again to confirm AcceptDialog
-rinse and repeat until...
game freezes (doesn't take long)

Steps to reproduce:
Add a button
Add an AcceptDialog
On button press, AcceptDialog.popup()
Load scene
-Rapidly click the button and press enter, the game will freeze (it does on my computer and godot version).

Minimal reproduction project:
AcceptDialogBug.zip
*note, I have it set to popup_centered() but tested it with popup() and it still happens so that doesn't change anything

@arrowinaknee
Copy link
Contributor

arrowinaknee commented Jan 20, 2021

Can reproduce this on 3.2 (40b3546), also tried on master (eba982b) and it seems to work fine there.

The bug appears when button that shows the popup gets pressed with both ui_accept and a mouse click in the same frame. So show_modal gets called for the second time before _modal_stack_remove gets called. This discards one of the data.MI assigned with _gui_show_modal thus gui.modal_stack never gets empty when the engine tries to hide all modals and we are stuck in an infinite loop.

And this is where the most interesting part begins. It may seem like show_modal should have failed because data.MI is already set. And this would happen if calls of show_modal happened in turn, but what actually happens is that _gui_show_modal calls _drop_mouse_focus, whitch in turn calls another _gui_input and the button gets it's second press and calls show_modal again while it's first call is still in process. In this second call data.MI is set, then the first call continues and also sets it's value to data.MI thus discarding the previous one. And now the dialog is added to modal_stack twice but can remove itself from the stack only once

So in summary show_modal can trigger another button press that calls show_modal and we get this sort of weird recursion
image

Fix? There is already a check that hides the modal if it is currently being displayed. Replacing hide() with return there (if the modal is already displayed just leave it as it is) seems to fix the bug but the hide() is likely there for a reason so it definetly at least needs to be tested more or probably there is a better solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants