From 6054b1a2a12194cfe9810060bb77ef0fb9e6ba3e Mon Sep 17 00:00:00 2001 From: Tim Kane Date: Thu, 14 Mar 2024 22:40:21 +1100 Subject: [PATCH] Needed a little more work to resolve a number of outstanding thread sanitiser concerns This is a little nasty.. I'm trying to keep all changes localised to imgui_impl_osx.mm Ideally the ImGui_IO_lock would live within ImGuiIO but I didn't want to muddy the waters Perhaps better if this lock primitive is delivered through BackendPlatformUserData, and only used where provided This change requires the client platform to explicitly lock the primitive from outside of ImGui around ImGui::NewFrame specifically, and additionally from anywhere on the client side (external to ImGui) that concurrently hooks into ImGuiIO That requires the client to define an extern lock (and use it appropriately) extern NSlock *ImGui_IO_lock If this lock were native to ImGui we could have ImGui::NewFrame() handle the lock on our behalf, negating the need for client side locking --- backends/imgui_impl_osx.mm | 42 ++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 0afbf4028..94b83be6d 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -402,8 +402,12 @@ IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view) { #endif +NSLock *ImGui_IO_lock; + bool ImGui_ImplOSX_Init(NSView* view) { + ImGui_IO_lock = [[NSLock alloc] init]; + ImGuiIO& io = ImGui::GetIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); IMGUI_CHECKVERSION(); @@ -673,6 +677,7 @@ static ImGuiMouseSource GetMouseSource(NSEvent* event) } } + static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) { // Only process events from the window containing ImGui view @@ -680,6 +685,10 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) return false; ImGuiIO& io = ImGui::GetIO(); + [ImGui_IO_lock lock]; + + bool WantCaptureMouse = io.WantCaptureMouse; + if (event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRightMouseDown || event.type == NSEventTypeOtherMouseDown) { int button = (int)[event buttonNumber]; @@ -688,7 +697,8 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) io.AddMouseSourceEvent(GetMouseSource(event)); io.AddMouseButtonEvent(button, true); } - return io.WantCaptureMouse; + [ImGui_IO_lock unlock]; + return WantCaptureMouse; } if (event.type == NSEventTypeLeftMouseUp || event.type == NSEventTypeRightMouseUp || event.type == NSEventTypeOtherMouseUp) @@ -699,7 +709,8 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) io.AddMouseSourceEvent(GetMouseSource(event)); io.AddMouseButtonEvent(button, false); } - return io.WantCaptureMouse; + [ImGui_IO_lock unlock]; + return WantCaptureMouse; } if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMouseDragged || event.type == NSEventTypeRightMouseDragged || event.type == NSEventTypeOtherMouseDragged) @@ -714,7 +725,9 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePoint.y); io.AddMouseSourceEvent(GetMouseSource(event)); io.AddMousePosEvent((float)mousePoint.x, (float)mousePoint.y); - return io.WantCaptureMouse; + + [ImGui_IO_lock unlock]; + return WantCaptureMouse; } if (event.type == NSEventTypeScrollWheel) @@ -732,7 +745,10 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) // scrollingDeltaY. When these are added to the current x and y positions of the scrolling view, // it appears to jump up or down. It can be observed in Preview, various JetBrains IDEs and here. if (event.phase == NSEventPhaseCancelled) + { + [ImGui_IO_lock unlock]; return false; + } double wheel_dx = 0.0; double wheel_dy = 0.0; @@ -757,20 +773,25 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) if (wheel_dx != 0.0 || wheel_dy != 0.0) io.AddMouseWheelEvent((float)wheel_dx, (float)wheel_dy); - return io.WantCaptureMouse; + [ImGui_IO_lock unlock]; + return WantCaptureMouse; } if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp) { if ([event isARepeat]) - return io.WantCaptureKeyboard; + { + [ImGui_IO_lock unlock]; + return WantCaptureMouse; + } int key_code = (int)[event keyCode]; ImGuiKey key = ImGui_ImplOSX_KeyCodeToImGuiKey(key_code); io.AddKeyEvent(key, event.type == NSEventTypeKeyDown); io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexing (<1.87 user code) - return io.WantCaptureKeyboard; + [ImGui_IO_lock unlock]; + return WantCaptureMouse; } if (event.type == NSEventTypeFlagsChanged) @@ -801,15 +822,20 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) case ImGuiKey_LeftAlt: mask = 0x0020; break; case ImGuiKey_RightAlt: mask = 0x0040; break; default: - return io.WantCaptureKeyboard; + { + [ImGui_IO_lock unlock]; + return WantCaptureMouse; + } } io.AddKeyEvent(key, (modifier_flags & mask) != 0); io.SetKeyEventNativeData(key, key_code, -1); // To support legacy indexing (<1.87 user code) } - return io.WantCaptureKeyboard; + [ImGui_IO_lock unlock]; + return WantCaptureMouse; } + [ImGui_IO_lock unlock]; return false; }