summaryrefslogtreecommitdiff
path: root/platform/macos
diff options
context:
space:
mode:
authorbruvzg <7645683+bruvzg@users.noreply.github.com>2022-09-24 23:57:00 +0300
committerbruvzg <7645683+bruvzg@users.noreply.github.com>2022-09-24 23:57:24 +0300
commitb66931946b0adb90e5539da8e54dfbeb02b33c4f (patch)
tree22abaf207b19bf0c9f93558e7f2983e1be8424b1 /platform/macos
parentf74491fdee9bc2d68668137fbacd8f3a7e7e8df7 (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.h6
-rw-r--r--platform/macos/display_server_macos.mm20
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();