diff options
author | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-09-24 23:57:00 +0300 |
---|---|---|
committer | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-09-24 23:57:24 +0300 |
commit | b66931946b0adb90e5539da8e54dfbeb02b33c4f (patch) | |
tree | 22abaf207b19bf0c9f93558e7f2983e1be8424b1 /platform/macos | |
parent | f74491fdee9bc2d68668137fbacd8f3a7e7e8df7 (diff) |
[macOS] Process menu callback after event processing step to avoid event queue corruption.
Diffstat (limited to 'platform/macos')
-rw-r--r-- | platform/macos/display_server_macos.h | 6 | ||||
-rw-r--r-- | platform/macos/display_server_macos.mm | 20 |
2 files changed, 21 insertions, 5 deletions
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index a27e0d5efa..e72273a681 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -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); diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 34723c7d4b..1914c5f35d 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -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(); |