Merge pull request #66377 from bruvzg/macos_menu_cb_deferred

[macOS] Process menu callback after event processing step to avoid event queue corruption.
This commit is contained in:
Rémi Verschelde 2022-09-25 08:38:10 +02:00 committed by GitHub
commit 67f700d726
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 5 deletions

View file

@ -179,6 +179,12 @@ private:
IOPMAssertionID screen_keep_on_assertion = kIOPMNullAssertionID;
struct MenuCall {
Variant tag;
Callable callback;
};
Vector<MenuCall> deferred_menu_calls;
const NSMenu *_get_menu_root(const String &p_menu_root) const;
NSMenu *_get_menu_root(const String &p_menu_root);

View file

@ -565,11 +565,11 @@ void DisplayServerMacOS::menu_callback(id p_sender) {
}
if (value->callback != Callable()) {
Variant tag = value->meta;
Variant *tagp = &tag;
Variant ret;
Callable::CallError ce;
value->callback.callp((const Variant **)&tagp, 1, ret, ce);
MenuCall mc;
mc.tag = value->meta;
mc.callback = value->callback;
deferred_menu_calls.push_back(mc);
// Do not run callback from here! If it is opening a new window or calling process_events, it will corrupt OS event queue and crash.
}
}
}
@ -3280,6 +3280,16 @@ void DisplayServerMacOS::process_events() {
[NSApp sendEvent:event];
}
// Process "menu_callback"s.
for (MenuCall &E : deferred_menu_calls) {
Variant tag = E.tag;
Variant *tagp = &tag;
Variant ret;
Callable::CallError ce;
E.callback.callp((const Variant **)&tagp, 1, ret, ce);
}
deferred_menu_calls.clear();
if (!drop_events) {
_process_key_events();
Input::get_singleton()->flush_buffered_events();