From d1edf66a13b52125c0fb4cf50f983121d820b852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Wed, 26 Mar 2025 12:18:55 +0200 Subject: [PATCH] [macOS] Release keys and regenerate mouse events after native popup menu tracking. --- platform/macos/display_server_macos.h | 1 + platform/macos/display_server_macos.mm | 32 ++++++++++++++++++++++++++ platform/macos/native_menu_macos.mm | 3 +++ 3 files changed, 36 insertions(+) diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index abce3bac06d..8ff42c8bb1a 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -253,6 +253,7 @@ public: void send_event(NSEvent *p_event); void send_window_event(const WindowData &p_wd, WindowEvent p_event); void release_pressed_events(); + void sync_mouse_state(); void get_key_modifier_state(unsigned int p_macos_state, Ref r_state) const; void update_mouse_pos(WindowData &p_wd, NSPoint p_location_in_window); void push_to_key_event_buffer(const KeyEvent &p_event); diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index e3f474cd64c..60d6d672249 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -681,6 +681,38 @@ void DisplayServerMacOS::release_pressed_events() { } } +void DisplayServerMacOS::sync_mouse_state() { + _THREAD_SAFE_METHOD_ + if (Input::get_singleton()) { + Vector2i pos = Input::get_singleton()->get_mouse_position(); + BitField in_mask = Input::get_singleton()->get_mouse_button_mask(); + BitField ds_mask = mouse_get_button_state(); + for (int btn = (int)MouseButton::LEFT; btn <= (int)MouseButton::MB_XBUTTON2; btn++) { + MouseButtonMask mbm = mouse_button_to_mask(MouseButton(btn)); + if (in_mask.has_flag(mbm) && !ds_mask.has_flag(mbm)) { + Ref mb; + mb.instantiate(); + mb->set_button_index(MouseButton(btn)); + mb->set_pressed(false); + mb->set_position(pos); + mb->set_global_position(pos); + mb->set_button_mask(ds_mask); + Input::get_singleton()->parse_input_event(mb); + } + if (!in_mask.has_flag(mbm) && ds_mask.has_flag(mbm)) { + Ref mb; + mb.instantiate(); + mb->set_button_index(MouseButton(btn)); + mb->set_pressed(true); + mb->set_position(pos); + mb->set_global_position(pos); + mb->set_button_mask(ds_mask); + Input::get_singleton()->parse_input_event(mb); + } + } + } +} + void DisplayServerMacOS::get_key_modifier_state(unsigned int p_macos_state, Ref r_state) const { r_state->set_shift_pressed((p_macos_state & NSEventModifierFlagShift)); r_state->set_ctrl_pressed((p_macos_state & NSEventModifierFlagControl)); diff --git a/platform/macos/native_menu_macos.mm b/platform/macos/native_menu_macos.mm index 843e28280d5..bd3ccf25f5c 100644 --- a/platform/macos/native_menu_macos.mm +++ b/platform/macos/native_menu_macos.mm @@ -294,6 +294,9 @@ void NativeMenuMacOS::popup(const RID &p_rid, const Vector2i &p_position) { position /= ds->screen_get_max_scale(); [md->menu popUpMenuPositioningItem:nil atLocation:NSMakePoint(position.x, position.y - 5) inView:nil]; // Menu vertical position doesn't include rounded corners, add `5` display pixels to better align it with Godot buttons. + + ds->release_pressed_events(); // Note: context menu block main loop and consume events, pressed keys and mouse buttons should be released manually. + ds->sync_mouse_state(); } }