-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
popup deferred hide suppressed if reopened on Windows platform #61001
popup deferred hide suppressed if reopened on Windows platform #61001
Conversation
popup no longer tries to close itself a second time popup no longer closes after having been reopened fixed bug in RenameDialog not calling base (by inspection) fixes godotengine#59181 fixes godotengine#60921 reverts godotengine#59287
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes seem good to me, I'll fully test it tomorrow.
if (win_id != p_window) { | ||
// Only request close on related windows, not this window. We are already processing it. | ||
_send_window_event(windows[win_id], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is likely relevant for X11 and macOS as well (need testing, code is almost same).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just put that in the notes above, since I am not set up to test Linux (yet) unfortunately. Is there something else I could have done to make sure this PR gets to the right "other platforms" people? Obviously you caught it this time, just wondering about future.
@bruvzg do we need someone from X11 and MacOS before this can advance? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be working fine on Windows, since neither of the mentioned bugs is reproducible on Linux/macOS there's no need to add anything else to the same PR.
call_deferred(SNAME("hide")); | ||
// Hide after returning to process events, but only if we don't | ||
// get popped up in the interim. | ||
call_deferred(SNAME("_popup_conditional_hide")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could remove the need for binding this method in _bind_methods
(which makes it accessible from scripting, even if hidden by default due to the leading _
) by using Callables instead of StringNames:
call_deferred(SNAME("_popup_conditional_hide")); | |
callable_mp(this, &Popup::_popup_conditional_hide).call_deferred({}, 0); |
CC @KoBeWi to confirm, currently we seem to only use Callable::call_deferred
on a callable_mp
once:
scene/3d/collision_object_3d.cpp
322: callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferred({}, 0);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks! That's exactly what I wanted. I will wait for confirmation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to admit though, if it is only used in one place right now, that seems a bit high on the risk/reward scale? We already tested as written, including bruvzg's time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well Callable
s and callable_mp
are new in 4.0 and while a big part of the codebase has been ported where it was trivial, I don't think we've really looked at deferred calls yet. But it should work fine, and that should be the "good" approach going forwards. The less we need to rely on strings, the better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we don't agree on this, I'll do it myself in a follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No argument there. I just wouldn't put that on this PR at this point in time. I await your decision after discussion off-line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After further discussion, it was made clear that converting remaining uses of call_deferred(StringName, VarArgs...)
is not that trivial and requires further discussion to define how we want to do this exactly (if at all). So it was indeed well outside the scope of this PR.
Here's an example conversion in a case where there's actually an argument to pass to call_deferred
and how it requires getting a const Variant **
to pass:
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index 6e9a2e1b61..3d40e4853b 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -183,7 +183,8 @@ void OpenXRActionMapEditor::_on_add_action_set() {
// Make sure our action set is the current tab
tabs->set_current_tab(0);
- call_deferred("_set_focus_on_action_set", new_action_set_editor);
+ const Variant *argp = &new_action_set_editor;
+ callable_mp(this, &OpenXRActionMapEditor::_set_focus_on_action_set).call_deferred(&argp, 1);
}
void OpenXRActionMapEditor::_set_focus_on_action_set(OpenXRActionSetEditor *p_action_set_editor) {
Which is arguably more bothersome than the original code, even if it makes it possible to unbind the method.
Thanks! |
Summary
These changes address two problems with the way deferred close of popups is implemented on the Windows platform.
Problem 1: call_deferred("hide") on popups causes a duplicate call_deferred("hide")
This is addressed by having the relevant notification code in DisplayServerWindows not notify the same window that is the source of the close request.
This problem most likely affects other platforms, but there don't seem to be any issues reported on other platforms, so maybe it does no harm there. At least the X11 display manager appears to operate the same way.
Problem 2: popup requests deferred hide of itself, but is reopened before that hide operation is executed
This happens due to the sequence of operations in the main loop. Deferred calls and buffered input are on separate queues and therefore get out of order. To work around this, popup will now be aware of its popped_up state even when single window mode is not used. If a request to hide is processed after the same popup window is reopened, it won't hide.
Note that several other places in the code base also use deferred hide to close the current window, in order to pop out of the stack and process messages correctly. The resulting reordering probably cannot be corrected centrally in the Window code, because it would change how Window works in a basic way, breaking many things. I tried some different ways to fix it centrally, but will just create a discussion instead. This fix just for the Popup() class addressed the existing issues.
Problem sequence of calls
This shows the sequence of calls that happens during a right mouse click that closes a popup in one location and opens it in the other. This figure is showing the slow case, where even with delayed input the (second) hide is processed after the reopen. There are also timings where the input and the (first) hide happen in the same main loop iteration, but the same problems occur.
After the changes in this PR, the sequences are intended to be as follows:
Fixed case 1: reopened before hide executes -> don't hide at all
Fixed case2: not reopened before hide executes -> execute hide, but only once
Limitations
This fix does not change the behavior of --single-window mode. In this mode, popups already don't automatically close when you click else where. This is unchanged from the current 4.0 master, and I do not know what the intended behavior is in this mode.