From b5b704d376ae9ba2fa2e42f8728ef489d4499efd Mon Sep 17 00:00:00 2001 From: Dima Koltun Date: Fri, 22 Apr 2022 20:20:40 +0200 Subject: [PATCH 1/9] Windows: Fixed first-time windows appearing in negative coordinates. (#5215, #3414) Regression added in 6af92b05b --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 70dc498d6..e3d262d33 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,9 @@ Other Changes: Not that even thought you shouldn't need to disable io.ConfigInputTrickleEventQueue, you can technically dynamically change its setting based on the context (e.g. disable only when hovering or interacting with a game/3D view). +- Windows: Fixed first-time windows appearing in negative coordinates from being initialized + with a wrong size. This would most often be noticeable in multi-viewport mode (docking branch) + when spawning a window in a monitor with negative coordinates. (#5215, #3414) [@DimaKoltun] - Clipper: Fixed a regression in 1.86 when not calling clipper.End() and late destructing the clipper instance. High-level languages (Lua,Rust etc.) would typically be affected. (#4822) - Layout: Fixed mixing up SameLine() and SetCursorPos() together from creating situations where line diff --git a/imgui.cpp b/imgui.cpp index 3f76dc169..82e72d0cb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5339,7 +5339,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags) SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); ApplyWindowSettings(window, settings); } - window->DC.CursorStartPos = window->DC.CursorMaxPos = window->Pos; // So first call to CalcContentSize() doesn't return crazy values + window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos; // So first call to CalcWindowContentSizes() doesn't return crazy values if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) { From 04689979b49a1b519c9f5bed4d4f143eeae87782 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 22 Apr 2022 20:38:59 +0200 Subject: [PATCH 2/9] Examples: Emscripten+WebGPU: Fix for latest spec rename of WGPURenderPassColorAttachment::clearColor to ::clearValue (#3632) --- docs/CHANGELOG.txt | 2 +- examples/example_emscripten_wgpu/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e3d262d33..f0c4db902 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -99,7 +99,7 @@ Other Changes: - Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu] - Backends: SDL, OpenGL3: Fixes to facilitate building on AmigaOS4. (#5190) [@afxgroup] - Backends: OSX: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) [@thedmd] -- Examples: Emscripten: Fix building for latest Emscripten specs. (#3632) +- Examples: Emscripten+WebGPU: Fix building for latest WebGPU specs. (#3632) ----------------------------------------------------------------------- diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index 6a63db26d..00ed79222 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -205,7 +205,7 @@ static void main_loop(void* window) WGPURenderPassColorAttachment color_attachments = {}; color_attachments.loadOp = WGPULoadOp_Clear; color_attachments.storeOp = WGPUStoreOp_Store; - color_attachments.clearColor = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; + color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain); WGPURenderPassDescriptor render_pass_desc = {}; render_pass_desc.colorAttachmentCount = 1; From e54db4ee708b99e24348f31847e8032921913989 Mon Sep 17 00:00:00 2001 From: noisewuwei <1215058854@qq.com> Date: Wed, 20 Apr 2022 21:31:44 +0800 Subject: [PATCH 3/9] Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with multiple contexts. (#5203, #5221, #4141) # Conflicts: # docs/CHANGELOG.txt --- backends/imgui_impl_metal.mm | 55 +++++++++++------- backends/imgui_impl_osx.mm | 107 +++++++++++++++++++++-------------- docs/CHANGELOG.txt | 2 + 3 files changed, 102 insertions(+), 62 deletions(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 3d5772e5f..744f59011 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts. // 2022-01-03: Metal: Ignore ImDrawCmd where ElemCount == 0 (very rare but can technically be manufactured by user code). // 2021-12-30: Metal: Added Metal C++ support. Enable with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file. // 2021-08-24: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted. (#4464) @@ -54,6 +55,7 @@ // renderer backend. Stores the render pipeline state cache and the default // font texture, and manages the reusable buffer cache. @interface MetalContext : NSObject +@property (nonatomic, strong) id device; @property (nonatomic, strong) id depthStencilState; @property (nonatomic, strong) FramebufferDescriptor *framebufferDescriptor; // framebuffer descriptor for current frame; transient @property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors @@ -77,7 +79,16 @@ commandEncoder:(id)commandEncoder; @end -static MetalContext *g_sharedMetalContext = nil; +struct ImGui_ImplMetal_Data +{ + MetalContext* SharedMetalContext; + + ImGui_ImplMetal_Data() { memset(this, 0, sizeof(*this)); } +}; + +static ImGui_ImplMetal_Data* ImGui_ImplMetal_CreateBackendData() { return IM_NEW(ImGui_ImplMetal_Data)(); } +static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : NULL; } +static void ImGui_ImplMetal_DestroyBackendData() { IM_DELETE(ImGui_ImplMetal_GetBackendData()); } #ifdef IMGUI_IMPL_METAL_CPP @@ -119,16 +130,14 @@ bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device) bool ImGui_ImplMetal_Init(id device) { + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_CreateBackendData(); ImGuiIO& io = ImGui::GetIO(); + io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_metal"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - g_sharedMetalContext = [[MetalContext alloc] init]; - }); - - ImGui_ImplMetal_CreateDeviceObjects(device); + bd->SharedMetalContext = [[MetalContext alloc] init]; + bd->SharedMetalContext.device = device; return true; } @@ -136,42 +145,48 @@ bool ImGui_ImplMetal_Init(id device) void ImGui_ImplMetal_Shutdown() { ImGui_ImplMetal_DestroyDeviceObjects(); + ImGui_ImplMetal_DestroyBackendData(); } void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor) { - IM_ASSERT(g_sharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?"); + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); + IM_ASSERT(bd->SharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?"); + bd->SharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]; - g_sharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]; + if (bd->SharedMetalContext.depthStencilState == nil) + ImGui_ImplMetal_CreateDeviceObjects(bd->SharedMetalContext.device); } // Metal Render function. void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id commandBuffer, id commandEncoder) { - [g_sharedMetalContext renderDrawData:draw_data commandBuffer:commandBuffer commandEncoder:commandEncoder]; + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); + [bd->SharedMetalContext renderDrawData:draw_data commandBuffer:commandBuffer commandEncoder:commandEncoder]; } bool ImGui_ImplMetal_CreateFontsTexture(id device) { - [g_sharedMetalContext makeFontTextureWithDevice:device]; - + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - io.Fonts->SetTexID((__bridge void *)g_sharedMetalContext.fontTexture); // ImTextureID == void* + [bd->SharedMetalContext makeFontTextureWithDevice:device]; + io.Fonts->SetTexID((__bridge void *)bd->SharedMetalContext.fontTexture); // ImTextureID == void* - return (g_sharedMetalContext.fontTexture != nil); + return (bd->SharedMetalContext.fontTexture != nil); } void ImGui_ImplMetal_DestroyFontsTexture() { + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); - g_sharedMetalContext.fontTexture = nil; + bd->SharedMetalContext.fontTexture = nil; io.Fonts->SetTexID(nullptr); } bool ImGui_ImplMetal_CreateDeviceObjects(id device) { - [g_sharedMetalContext makeDeviceObjectsWithDevice:device]; - + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); + [bd->SharedMetalContext makeDeviceObjectsWithDevice:device]; ImGui_ImplMetal_CreateFontsTexture(device); return true; @@ -179,8 +194,9 @@ bool ImGui_ImplMetal_CreateDeviceObjects(id device) void ImGui_ImplMetal_DestroyDeviceObjects() { + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); ImGui_ImplMetal_DestroyFontsTexture(); - [g_sharedMetalContext emptyRenderPipelineStateCache]; + [bd->SharedMetalContext emptyRenderPipelineStateCache]; } #pragma mark - MetalBuffer implementation @@ -458,8 +474,9 @@ void ImGui_ImplMetal_DestroyDeviceObjects() vertexBuffer:(MetalBuffer *)vertexBuffer vertexBufferOffset:(size_t)vertexBufferOffset { + ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [commandEncoder setCullMode:MTLCullModeNone]; - [commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState]; + [commandEncoder setDepthStencilState:bd->SharedMetalContext.depthStencilState]; // Setup viewport, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 3c6635c1a..e733541fd 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts. // 2022-03-22: Inputs: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key // 2022-02-07: Inputs: Forward keyDown/keyUp events to OS when unused by dear imgui. // 2022-01-31: Fix building with old Xcode versions that are missing gamepad features. @@ -57,13 +58,22 @@ @class KeyEventResponder; // Data -static double g_HostClockPeriod = 0.0; -static double g_Time = 0.0; -static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; -static bool g_MouseCursorHidden = false; -static ImFocusObserver* g_FocusObserver = nil; -static KeyEventResponder* g_KeyEventResponder = nil; -static NSTextInputContext* g_InputContext = nil; +struct ImGui_ImplOSX_Data +{ + double HostClockPeriod; + double Time; + NSCursor* MouseCursors[ImGuiMouseCursor_COUNT]; + bool MouseCursorHidden; + ImFocusObserver* FocusObserver; + KeyEventResponder* KeyEventResponder; + NSTextInputContext* InputContext; + + ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); } +}; + +static ImGui_ImplOSX_Data* ImGui_ImplOSX_CreateBackendData() { return IM_NEW(ImGui_ImplOSX_Data)(); } +static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; } +static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); } // Undocumented methods for creating cursors. @interface NSCursor() @@ -75,14 +85,16 @@ static NSTextInputContext* g_InputContext = nil; static void InitHostClockPeriod() { + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); struct mach_timebase_info info; mach_timebase_info(&info); - g_HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Period is the reciprocal of frequency. + bd->HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Period is the reciprocal of frequency. } static double GetMachAbsoluteTimeInSeconds() { - return (double)mach_absolute_time() * g_HostClockPeriod; + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); + return (double)mach_absolute_time() * bd->HostClockPeriod; } /** @@ -363,6 +375,8 @@ static ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code) bool ImGui_ImplOSX_Init(NSView* view) { ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_CreateBackendData(); + io.BackendPlatformUserData = (void*)bd; // Setup backend capabilities flags io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) @@ -372,16 +386,16 @@ bool ImGui_ImplOSX_Init(NSView* view) io.BackendPlatformName = "imgui_impl_osx"; // Load cursors. Some of them are undocumented. - g_MouseCursorHidden = false; - g_MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor]; - g_MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor]; - g_MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor]; - g_MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor]; - g_MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor]; - g_MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor]; - g_MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor]; - g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor]; - g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor]; + bd->MouseCursorHidden = false; + bd->MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor]; + bd->MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor]; + bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor]; + bd->MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor]; + bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor]; + bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor]; + bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor]; + bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor]; + bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor]; // Note that imgui.cpp also include default OSX clipboard handlers which can be enabled // by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line. @@ -412,44 +426,45 @@ bool ImGui_ImplOSX_Init(NSView* view) return s_clipboard.Data; }; - g_FocusObserver = [[ImFocusObserver alloc] init]; - [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver + bd->FocusObserver = [[ImFocusObserver alloc] init]; + [[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver selector:@selector(onApplicationBecomeActive:) name:NSApplicationDidBecomeActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver + [[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver selector:@selector(onApplicationBecomeInactive:) name:NSApplicationDidResignActiveNotification object:nil]; // Add the NSTextInputClient to the view hierarchy, // to receive keyboard events and translate them to input text. - g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect]; - g_InputContext = [[NSTextInputContext alloc] initWithClient:g_KeyEventResponder]; - [view addSubview:g_KeyEventResponder]; + bd->KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect]; + bd->InputContext = [[NSTextInputContext alloc] initWithClient:bd->KeyEventResponder]; + [view addSubview:bd->KeyEventResponder]; // Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down). // This monitor taps into global event stream and captures these events. NSEventMask eventMask = NSEventMaskFromType(NSKeyUp) | NSEventMaskFlagsChanged; [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event) { - ImGui_ImplOSX_HandleEvent(event, g_KeyEventResponder); + ImGui_ImplOSX_HandleEvent(event, bd->KeyEventResponder); return event; }]; io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void { + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); if (data->WantVisible) { - [g_InputContext activate]; + [bd->InputContext activate]; } else { - [g_InputContext discardMarkedText]; - [g_InputContext invalidateCharacterCoordinates]; - [g_InputContext deactivate]; + [bd->InputContext discardMarkedText]; + [bd->InputContext invalidateCharacterCoordinates]; + [bd->InputContext deactivate]; } - [g_KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight]; + [bd->KeyEventResponder setImePosX:data->InputPos.x imePosY:data->InputPos.y + data->InputLineHeight]; }; return true; @@ -457,11 +472,14 @@ bool ImGui_ImplOSX_Init(NSView* view) void ImGui_ImplOSX_Shutdown() { - g_FocusObserver = NULL; + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); + bd->FocusObserver = NULL; + ImGui_ImplOSX_DestroyBackendData(); } static void ImGui_ImplOSX_UpdateMouseCursor() { + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return; @@ -470,23 +488,23 @@ static void ImGui_ImplOSX_UpdateMouseCursor() if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) { // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor - if (!g_MouseCursorHidden) + if (!bd->MouseCursorHidden) { - g_MouseCursorHidden = true; + bd->MouseCursorHidden = true; [NSCursor hide]; } } else { - NSCursor* desired = g_MouseCursors[imgui_cursor] ?: g_MouseCursors[ImGuiMouseCursor_Arrow]; + NSCursor* desired = bd->MouseCursors[imgui_cursor] ?: bd->MouseCursors[ImGuiMouseCursor_Arrow]; // -[NSCursor set] generates measureable overhead if called unconditionally. if (desired != NSCursor.currentCursor) { [desired set]; } - if (g_MouseCursorHidden) + if (bd->MouseCursorHidden) { - g_MouseCursorHidden = false; + bd->MouseCursorHidden = false; [NSCursor unhide]; } } @@ -553,15 +571,18 @@ static void ImGui_ImplOSX_UpdateGamepads() static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view) { + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); if (io.WantTextInput) - [g_KeyEventResponder updateImePosWithView:view]; + [bd->KeyEventResponder updateImePosWithView:view]; } void ImGui_ImplOSX_NewFrame(NSView* view) { - // Setup display size + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); + + // Setup display size if (view) { const float dpi = (float)[view.window backingScaleFactor]; @@ -570,14 +591,14 @@ void ImGui_ImplOSX_NewFrame(NSView* view) } // Setup time step - if (g_Time == 0.0) + if (bd->Time == 0.0) { InitHostClockPeriod(); - g_Time = GetMachAbsoluteTimeInSeconds(); + bd->Time = GetMachAbsoluteTimeInSeconds(); } double current_time = GetMachAbsoluteTimeInSeconds(); - io.DeltaTime = (float)(current_time - g_Time); - g_Time = current_time; + io.DeltaTime = (float)(current_time - bd->Time); + bd->Time = current_time; ImGui_ImplOSX_UpdateMouseCursor(); ImGui_ImplOSX_UpdateGamepads(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f0c4db902..5ebec7da1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -99,6 +99,8 @@ Other Changes: - Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu] - Backends: SDL, OpenGL3: Fixes to facilitate building on AmigaOS4. (#5190) [@afxgroup] - Backends: OSX: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) [@thedmd] +- Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with + multiple contexts. (#5203, #5221, #4141) [@noisewuwei] - Examples: Emscripten+WebGPU: Fix building for latest WebGPU specs. (#3632) From 314c7bd12fb8f1137f3771c446755ca55fdbcae7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 12 Apr 2022 15:46:27 +0200 Subject: [PATCH 4/9] Internals: renamed ImGuiInputReadMode to ImGuiNavReadMode (internals) to avoid ambiguity with upcoming flags. + minor tweak --- imgui.cpp | 44 ++++++++++++++++++++++---------------------- imgui_internal.h | 20 ++++++++++---------- imgui_widgets.cpp | 10 +++++----- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 82e72d0cb..8bcd9ab6f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3975,9 +3975,9 @@ static void ImGui::UpdateKeyboardInputs() // Update keys for (int i = 0; i < IM_ARRAYSIZE(io.KeysData); i++) { - ImGuiKeyData& key_data = io.KeysData[i]; - key_data.DownDurationPrev = key_data.DownDuration; - key_data.DownDuration = key_data.Down ? (key_data.DownDuration < 0.0f ? 0.0f : key_data.DownDuration + io.DeltaTime) : -1.0f; + ImGuiKeyData* key_data = &io.KeysData[i]; + key_data->DownDurationPrev = key_data->DownDuration; + key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f; } } @@ -5656,9 +5656,9 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s { ImVec2 nav_resize_delta; if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift) - nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiInputReadMode_Down); + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiNavReadMode_Down); if (g.NavInputSource == ImGuiInputSource_Gamepad) - nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down); + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiNavReadMode_Down); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { const float NAV_RESIZE_SPEED = 600.0f; @@ -10024,29 +10024,29 @@ const char* ImGui::GetNavInputName(ImGuiNavInput n) return names[n]; } -float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) +float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) { ImGuiContext& g = *GImGui; - if (mode == ImGuiInputReadMode_Down) + if (mode == ImGuiNavReadMode_Down) return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) const float t = g.IO.NavInputsDownDuration[n]; - if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input. + if (t < 0.0f && mode == ImGuiNavReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input. return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f); if (t < 0.0f) return 0.0f; - if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. + if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. return (t == 0.0f) ? 1.0f : 0.0f; - if (mode == ImGuiInputReadMode_Repeat) + if (mode == ImGuiNavReadMode_Repeat) return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.80f); - if (mode == ImGuiInputReadMode_RepeatSlow) + if (mode == ImGuiNavReadMode_RepeatSlow) return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f); - if (mode == ImGuiInputReadMode_RepeatFast) + if (mode == ImGuiNavReadMode_RepeatFast) return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f); return 0.0f; } -ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor) +ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiNavReadMode mode, float slow_factor, float fast_factor) { ImVec2 delta(0.0f, 0.0f); if (dir_sources & ImGuiNavDirSourceFlags_RawKeyboard) @@ -10166,8 +10166,8 @@ static void ImGui::NavUpdate() { bool activate_down = IsNavInputDown(ImGuiNavInput_Activate); bool input_down = IsNavInputDown(ImGuiNavInput_Input); - bool activate_pressed = activate_down && IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed); - bool input_pressed = input_down && IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed); + bool activate_pressed = activate_down && IsNavInputTest(ImGuiNavInput_Activate, ImGuiNavReadMode_Pressed); + bool input_pressed = input_down && IsNavInputTest(ImGuiNavInput_Input, ImGuiNavReadMode_Pressed); if (g.ActiveId == 0 && activate_pressed) { g.NavActivateId = g.NavId; @@ -10224,7 +10224,7 @@ static void ImGui::NavUpdate() // *Normal* Manual scroll with NavScrollXXX keys // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. - ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f / 10.0f, 10.0f); + ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiNavReadMode_Down, 1.0f / 10.0f, 10.0f); if (scroll_dir.x != 0.0f && window->ScrollbarX) SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); if (scroll_dir.y != 0.0f) @@ -10297,7 +10297,7 @@ void ImGui::NavUpdateCreateMoveRequest() g.NavMoveScrollFlags = ImGuiScrollFlags_None; if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs)) { - const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat; + const ImGuiNavReadMode read_mode = ImGuiNavReadMode_Repeat; if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && (IsNavInputTest(ImGuiNavInput_DpadLeft, read_mode) || IsNavInputTest(ImGuiNavInput_KeyLeft_, read_mode))) { g.NavMoveDir = ImGuiDir_Left; } if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && (IsNavInputTest(ImGuiNavInput_DpadRight, read_mode) || IsNavInputTest(ImGuiNavInput_KeyRight_, read_mode))) { g.NavMoveDir = ImGuiDir_Right; } if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && (IsNavInputTest(ImGuiNavInput_DpadUp, read_mode) || IsNavInputTest(ImGuiNavInput_KeyUp_, read_mode))) { g.NavMoveDir = ImGuiDir_Up; } @@ -10504,7 +10504,7 @@ void ImGui::NavMoveRequestApplyResult() static void ImGui::NavUpdateCancelRequest() { ImGuiContext& g = *GImGui; - if (!IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed)) + if (!IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed)) return; IMGUI_DEBUG_LOG_NAV("[nav] ImGuiNavInput_Cancel\n"); @@ -10754,7 +10754,7 @@ static void ImGui::NavUpdateWindowing() } // Start CTRL+Tab or Square+L/R window selection - const bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); + const bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiNavReadMode_Pressed); const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && io.KeyCtrl && IsKeyPressed(ImGuiKey_Tab); if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) @@ -10773,7 +10773,7 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // Select window to focus - const int focus_change_dir = (int)IsNavInputTest(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputTest(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow); + const int focus_change_dir = (int)IsNavInputTest(ImGuiNavInput_FocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputTest(ImGuiNavInput_FocusNext, ImGuiNavReadMode_RepeatSlow); if (focus_change_dir != 0) { NavUpdateWindowingHighlightWindow(focus_change_dir); @@ -10834,9 +10834,9 @@ static void ImGui::NavUpdateWindowing() { ImVec2 move_delta; if (g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift) - move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiInputReadMode_Down); + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiNavReadMode_Down); if (g.NavInputSource == ImGuiInputSource_Gamepad) - move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiNavReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float NAV_MOVE_SPEED = 800.0f; diff --git a/imgui_internal.h b/imgui_internal.h index 08df5271d..52631973f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1218,14 +1218,14 @@ struct ImGuiInputEvent }; // FIXME-NAV: Clarify/expose various repeat delay/rate -enum ImGuiInputReadMode +enum ImGuiNavReadMode { - ImGuiInputReadMode_Down, - ImGuiInputReadMode_Pressed, - ImGuiInputReadMode_Released, - ImGuiInputReadMode_Repeat, - ImGuiInputReadMode_RepeatSlow, - ImGuiInputReadMode_RepeatFast + ImGuiNavReadMode_Down, + ImGuiNavReadMode_Pressed, + ImGuiNavReadMode_Released, + ImGuiNavReadMode_Repeat, + ImGuiNavReadMode_RepeatSlow, + ImGuiNavReadMode_RepeatFast }; //----------------------------------------------------------------------------- @@ -2651,8 +2651,8 @@ namespace ImGui IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API const char* GetNavInputName(ImGuiNavInput n); - IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); - IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); + IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode); + IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiNavReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); @@ -2679,7 +2679,7 @@ namespace ImGui inline void SetActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; g.ActiveIdUsingKeyInputMask.SetBit(key); } IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; } - inline bool IsNavInputTest(ImGuiNavInput n, ImGuiInputReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); } + inline bool IsNavInputTest(ImGuiNavInput n, ImGuiNavReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); } IMGUI_API ImGuiModFlags GetMergedModFlags(); #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // [removed in 1.87] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c35e093ba..78fed5e66 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -609,7 +609,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if (g.NavActivateDownId == id) { bool nav_activated_by_code = (g.NavActivateId == id); - bool nav_activated_by_inputs = IsNavInputTest(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed); + bool nav_activated_by_inputs = IsNavInputTest(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); if (nav_activated_by_code || nav_activated_by_inputs) { // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. @@ -2176,7 +2176,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const else if (g.ActiveIdSource == ImGuiInputSource_Nav) { const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0; - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis]; + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiNavReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis]; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; @@ -2780,7 +2780,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ g.SliderCurrentAccumDirty = false; } - const ImVec2 input_delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); + const ImVec2 input_delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); float input_delta = (axis == ImGuiAxis_X) ? input_delta2.x : -input_delta2.y; if (input_delta != 0.0f) { @@ -4290,8 +4290,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. const bool is_validate_enter = IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_KeypadEnter); - const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed) && !IsKeyPressed(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed); - const bool is_cancel = IsKeyPressed(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed); + const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiNavReadMode_Pressed) && !IsKeyPressed(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiNavReadMode_Pressed); + const bool is_cancel = IsKeyPressed(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed); if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } From 709bc03d6f07467fe10f892f9198913f0298b58e Mon Sep 17 00:00:00 2001 From: cpichard Date: Sat, 30 Apr 2022 08:21:04 +0100 Subject: [PATCH 5/9] Backends: GLFW: fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX (#5260, #5261) --- backends/imgui_impl_glfw.cpp | 2 ++ docs/CHANGELOG.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 5670f106e..6fde3a6a1 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX. // 2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11. // 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend. // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. @@ -308,6 +309,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys)); if (key_name[0] >= '0' && key_name[0] <= '9') { key = GLFW_KEY_0 + (key_name[0] - '0'); } else if (key_name[0] >= 'A' && key_name[0] <= 'Z') { key = GLFW_KEY_A + (key_name[0] - 'A'); } + else if (key_name[0] >= 'a' && key_name[0] <= 'z') { key = GLFW_KEY_A + (key_name[0] - 'a'); } else if (const char* p = strchr(char_names, key_name[0])) { key = char_keys[p - char_names]; } } // if (action == GLFW_PRESS) printf("key %d scancode %d name '%s'\n", key, scancode, key_name); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5ebec7da1..b4d843c83 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -95,6 +95,7 @@ Other Changes: - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] - Backends: GLFW: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11, due to a bug in GLFW. [@rokups] +- Backends: GLFW: Fixed untranslated keys when pressing lower case letters on OSX (#5260, #5261) [@cpichard] - Backends: SDL: Fixed dragging out viewport broken on some SDL setups. (#5012) [@rokups] - Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu] - Backends: SDL, OpenGL3: Fixes to facilitate building on AmigaOS4. (#5190) [@afxgroup] From 3e5dde9a2606addd702726b4769c7f93314bf7ac Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 2 May 2022 16:32:17 +0200 Subject: [PATCH 6/9] Tables: Fixed incorrect auto-fit of parent windows when using non-resizable weighted columns. (#5276) --- docs/CHANGELOG.txt | 1 + imgui.h | 2 +- imgui_internal.h | 1 + imgui_tables.cpp | 17 ++++++++++++----- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b4d843c83..6ca8b8e74 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -74,6 +74,7 @@ Other Changes: trickled with the new input queue (happened on some backends only). (#2467, #1336) - Tables: Fixed incorrect border height used for logic when resizing one of several synchronized instance of a same table ID, when instances have a different height. (#3955). +- Tables: Fixed incorrect auto-fit of parent windows when using non-resizable weighted columns. (#5276) - Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate. - ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. - Menus: Adjusted BeginMenu() closing logic so hovering void or non-MenuItem() in parent window diff --git a/imgui.h b/imgui.h index 71efa1038..612d30177 100644 --- a/imgui.h +++ b/imgui.h @@ -65,7 +65,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.88 WIP" -#define IMGUI_VERSION_NUM 18718 +#define IMGUI_VERSION_NUM 18719 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE diff --git a/imgui_internal.h b/imgui_internal.h index 52631973f..ed9d68df4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2346,6 +2346,7 @@ struct IMGUI_API ImGuiTable float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. float ColumnsGivenWidth; // Sum of current column width float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window + float ColumnsStretchSumWeights; // Sum of weight of all enabled stretching columns float ResizedColumnNextWidth; float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table. float RefScale; // Reference scale to be able to rescale columns on font/dpi changes. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 9a01c6929..bf04f44b5 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -888,6 +888,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) sum_width_requests += table->CellPaddingX * 2.0f; } table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed; + table->ColumnsStretchSumWeights = stretch_sum_weights; // [Part 4] Apply final widths based on requested widths const ImRect work_rect = table->WorkRect; @@ -1284,17 +1285,23 @@ void ImGui::EndTable() splitter->Merge(inner_window->DrawList); // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() - const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); - table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; + float auto_fit_width_for_fixed = 0.0f; + float auto_fit_width_for_stretched = 0.0f; + float auto_fit_width_for_stretched_min = 0.0f; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if (table->EnabledMaskByIndex & ((ImU64)1 << column_n)) { ImGuiTableColumn* column = &table->Columns[column_n]; - if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) - table->ColumnsAutoFitWidth += column->WidthRequest; + float column_width_request = ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) ? column->WidthRequest : TableGetColumnWidthAuto(table, column); + if (column->Flags & ImGuiTableColumnFlags_WidthFixed) + auto_fit_width_for_fixed += column_width_request; else - table->ColumnsAutoFitWidth += TableGetColumnWidthAuto(table, column); + auto_fit_width_for_stretched += column_width_request; + if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) && (column->Flags & ImGuiTableColumnFlags_NoResize) != 0) + auto_fit_width_for_stretched_min = ImMax(auto_fit_width_for_stretched_min, column_width_request / (column->StretchWeight / table->ColumnsStretchSumWeights)); } + const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); + table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount + auto_fit_width_for_fixed + ImMax(auto_fit_width_for_stretched, auto_fit_width_for_stretched_min); // Update scroll if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window) From d58b8414b90025d5803aa15edbd1a3cdb0e9c79c Mon Sep 17 00:00:00 2001 From: stuartcarnie Date: Wed, 27 Apr 2022 16:33:14 +0300 Subject: [PATCH 7/9] Backends: OSX, Metal: Tweaks. Use preferred method of obtaining a timestamp. (#4821) + Rename ImGuiFocusObserver. Docking branch will use it for more than focus. --- backends/imgui_impl_metal.mm | 16 +++++------ backends/imgui_impl_osx.mm | 42 ++++++++++------------------ examples/example_apple_metal/main.mm | 2 -- 3 files changed, 22 insertions(+), 38 deletions(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 744f59011..6d369bfdc 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -27,17 +27,15 @@ #include "imgui.h" #include "imgui_impl_metal.h" - +#import #import -// #import // Not supported in XCode 9.2. Maybe a macro to detect the SDK version can be used (something like #if MACOS_SDK >= 10.13 ...) -#import #pragma mark - Support classes // A wrapper around a MTLBuffer object that knows the last time it was reused @interface MetalBuffer : NSObject @property (nonatomic, strong) id buffer; -@property (nonatomic, assign) NSTimeInterval lastReuseTime; +@property (nonatomic, assign) double lastReuseTime; - (instancetype)initWithBuffer:(id)buffer; @end @@ -61,7 +59,7 @@ @property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors @property (nonatomic, strong, nullable) id fontTexture; @property (nonatomic, strong) NSMutableArray *bufferCache; -@property (nonatomic, assign) NSTimeInterval lastBufferCachePurge; +@property (nonatomic, assign) double lastBufferCachePurge; - (void)makeDeviceObjectsWithDevice:(id)device; - (void)makeFontTextureWithDevice:(id)device; - (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id)device; @@ -90,6 +88,8 @@ static ImGui_ImplMetal_Data* ImGui_ImplMetal_CreateBackendData() { return I static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : NULL; } static void ImGui_ImplMetal_DestroyBackendData() { IM_DELETE(ImGui_ImplMetal_GetBackendData()); } +static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return static_cast(static_cast(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } + #ifdef IMGUI_IMPL_METAL_CPP #pragma mark - Dear ImGui Metal C++ Backend API @@ -207,7 +207,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects() if ((self = [super init])) { _buffer = buffer; - _lastReuseTime = [NSDate date].timeIntervalSince1970; + _lastReuseTime = GetMachAbsoluteTimeInSeconds(); } return self; } @@ -269,7 +269,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects() { _renderPipelineStateCache = [NSMutableDictionary dictionary]; _bufferCache = [NSMutableArray array]; - _lastBufferCachePurge = [NSDate date].timeIntervalSince1970; + _lastBufferCachePurge = GetMachAbsoluteTimeInSeconds(); } return self; } @@ -309,7 +309,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects() - (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id)device { - NSTimeInterval now = [NSDate date].timeIntervalSince1970; + uint64_t now = GetMachAbsoluteTimeInSeconds(); // Purge old buffers that haven't been useful for a while if (now - self.lastBufferCachePurge > 1.0) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index e733541fd..59c34a1b7 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -17,9 +17,9 @@ #import "imgui.h" #import "imgui_impl_osx.h" #import -#import #import #import +#import // CHANGELOG // (minor and older changes stripped away, please see git history for details) @@ -54,17 +54,16 @@ #define APPLE_HAS_CONTROLLER (__IPHONE_OS_VERSION_MIN_REQUIRED >= 140000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 || __TV_OS_VERSION_MIN_REQUIRED >= 140000) #define APPLE_HAS_THUMBSTICKS (__IPHONE_OS_VERSION_MIN_REQUIRED >= 120100 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101401 || __TV_OS_VERSION_MIN_REQUIRED >= 120100) -@class ImFocusObserver; +@class ImGuiObserver; @class KeyEventResponder; // Data struct ImGui_ImplOSX_Data { - double HostClockPeriod; - double Time; + CFTimeInterval Time; NSCursor* MouseCursors[ImGuiMouseCursor_COUNT]; bool MouseCursorHidden; - ImFocusObserver* FocusObserver; + ImGuiObserver* Observer; KeyEventResponder* KeyEventResponder; NSTextInputContext* InputContext; @@ -75,6 +74,8 @@ static ImGui_ImplOSX_Data* ImGui_ImplOSX_CreateBackendData() { return IM_NEW(I static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; } static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); } +static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return static_cast(static_cast(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } + // Undocumented methods for creating cursors. @interface NSCursor() + (id)_windowResizeNorthWestSouthEastCursor; @@ -83,20 +84,6 @@ static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui + (id)_windowResizeEastWestCursor; @end -static void InitHostClockPeriod() -{ - ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); - struct mach_timebase_info info; - mach_timebase_info(&info); - bd->HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Period is the reciprocal of frequency. -} - -static double GetMachAbsoluteTimeInSeconds() -{ - ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); - return (double)mach_absolute_time() * bd->HostClockPeriod; -} - /** KeyEventResponder implements the NSTextInputClient protocol as is required by the macOS text input manager. @@ -225,14 +212,14 @@ static double GetMachAbsoluteTimeInSeconds() @end -@interface ImFocusObserver : NSObject +@interface ImGuiObserver : NSObject - (void)onApplicationBecomeActive:(NSNotification*)aNotification; - (void)onApplicationBecomeInactive:(NSNotification*)aNotification; @end -@implementation ImFocusObserver +@implementation ImGuiObserver - (void)onApplicationBecomeActive:(NSNotification*)aNotification { @@ -385,6 +372,8 @@ bool ImGui_ImplOSX_Init(NSView* view) //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy) io.BackendPlatformName = "imgui_impl_osx"; + bd->Observer = [ImGuiObserver new]; + // Load cursors. Some of them are undocumented. bd->MouseCursorHidden = false; bd->MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor]; @@ -426,12 +415,11 @@ bool ImGui_ImplOSX_Init(NSView* view) return s_clipboard.Data; }; - bd->FocusObserver = [[ImFocusObserver alloc] init]; - [[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver + [[NSNotificationCenter defaultCenter] addObserver:bd->Observer selector:@selector(onApplicationBecomeActive:) name:NSApplicationDidBecomeActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:bd->FocusObserver + [[NSNotificationCenter defaultCenter] addObserver:bd->Observer selector:@selector(onApplicationBecomeInactive:) name:NSApplicationDidResignActiveNotification object:nil]; @@ -473,7 +461,7 @@ bool ImGui_ImplOSX_Init(NSView* view) void ImGui_ImplOSX_Shutdown() { ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); - bd->FocusObserver = NULL; + bd->Observer = NULL; ImGui_ImplOSX_DestroyBackendData(); } @@ -592,10 +580,8 @@ void ImGui_ImplOSX_NewFrame(NSView* view) // Setup time step if (bd->Time == 0.0) - { - InitHostClockPeriod(); bd->Time = GetMachAbsoluteTimeInSeconds(); - } + double current_time = GetMachAbsoluteTimeInSeconds(); io.DeltaTime = (float)(current_time - bd->Time); bd->Time = current_time; diff --git a/examples/example_apple_metal/main.mm b/examples/example_apple_metal/main.mm index d92fc6b3c..db1ef3ac8 100644 --- a/examples/example_apple_metal/main.mm +++ b/examples/example_apple_metal/main.mm @@ -125,8 +125,6 @@ #endif io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale); - io.DeltaTime = 1 / float(view.preferredFramesPerSecond ?: 60); - id commandBuffer = [self.commandQueue commandBuffer]; MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor; From 26f817807cb9edfa2057a2b07a700f8e53b923fb Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 May 2022 12:51:51 +0200 Subject: [PATCH 8/9] Backends: Vulkan: Don't use VK_PRESENT_MODE_MAX_ENUM_KHR as specs state it isn't part of the API. (#5254) --- backends/imgui_impl_vulkan.h | 2 +- docs/CHANGELOG.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index f2f3e345f..52d9ffe74 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -148,7 +148,7 @@ struct ImGui_ImplVulkanH_Window ImGui_ImplVulkanH_Window() { memset((void*)this, 0, sizeof(*this)); - PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; + PresentMode = (VkPresentModeKHR)~0; // Ensure we get an error if user doesn't set this. ClearEnable = true; } }; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6ca8b8e74..f23fe48ae 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -94,6 +94,7 @@ Other Changes: - Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] +- Backends: Vulkan: Don't use VK_PRESENT_MODE_MAX_ENUM_KHR as specs state it isn't part of the API. (#5254) - Backends: GLFW: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11, due to a bug in GLFW. [@rokups] - Backends: GLFW: Fixed untranslated keys when pressing lower case letters on OSX (#5260, #5261) [@cpichard] From e66fc2205744a3b84422ed208933b29c31093f18 Mon Sep 17 00:00:00 2001 From: stuartcarnie Date: Wed, 27 Apr 2022 16:51:01 +0300 Subject: [PATCH 9/9] Backends: OSX: Removed ImGui_ImplOSX_HandleEvent() from backend API. Move event tracking (desktop only) to OSX backend. (#4821) Fix using NSKeyUp (#5268). --- backends/imgui_impl_osx.h | 1 - backends/imgui_impl_osx.mm | 47 ++++++++++++++++++++------ docs/CHANGELOG.txt | 5 +++ examples/example_apple_metal/main.mm | 40 ++++++++-------------- examples/example_apple_opengl2/main.mm | 20 ----------- imgui.cpp | 1 + 6 files changed, 58 insertions(+), 56 deletions(-) diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index 859061920..d483dcf21 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -22,4 +22,3 @@ IMGUI_IMPL_API bool ImGui_ImplOSX_Init(NSView* _Nonnull view); IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view); -IMGUI_IMPL_API bool ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view); diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 59c34a1b7..fa4807f55 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-05-03: Inputs: Removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend automatically handling event capture. // 2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts. // 2022-03-22: Inputs: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key // 2022-02-07: Inputs: Forward keyDown/keyUp events to OS when unused by dear imgui. @@ -66,6 +67,7 @@ struct ImGui_ImplOSX_Data ImGuiObserver* Observer; KeyEventResponder* KeyEventResponder; NSTextInputContext* InputContext; + id Monitor; ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); } }; @@ -76,6 +78,10 @@ static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return static_cast(static_cast(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } +// Forward Declarations +static void ImGui_ImplOSX_AddTrackingArea(NSView* _Nonnull view); +static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view); + // Undocumented methods for creating cursors. @interface NSCursor() + (id)_windowResizeNorthWestSouthEastCursor; @@ -429,15 +435,7 @@ bool ImGui_ImplOSX_Init(NSView* view) bd->KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect]; bd->InputContext = [[NSTextInputContext alloc] initWithClient:bd->KeyEventResponder]; [view addSubview:bd->KeyEventResponder]; - - // Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down). - // This monitor taps into global event stream and captures these events. - NSEventMask eventMask = NSEventMaskFromType(NSKeyUp) | NSEventMaskFlagsChanged; - [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event) - { - ImGui_ImplOSX_HandleEvent(event, bd->KeyEventResponder); - return event; - }]; + ImGui_ImplOSX_AddTrackingArea(view); io.SetPlatformImeDataFn = [](ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void { @@ -462,6 +460,11 @@ void ImGui_ImplOSX_Shutdown() { ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); bd->Observer = NULL; + if (bd->Monitor != NULL) + { + [NSEvent removeMonitor:bd->Monitor]; + bd->Monitor = NULL; + } ImGui_ImplOSX_DestroyBackendData(); } @@ -591,7 +594,7 @@ void ImGui_ImplOSX_NewFrame(NSView* view) ImGui_ImplOSX_UpdateImePosWithView(view); } -bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) +static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) { ImGuiIO& io = ImGui::GetIO(); @@ -716,3 +719,27 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) return false; } + +static void ImGui_ImplOSX_AddTrackingArea(NSView* _Nonnull view) +{ + // If we want to receive key events, we either need to be in the responder chain of the key view, + // or else we can install a local monitor. The consequence of this heavy-handed approach is that + // we receive events for all controls, not just Dear ImGui widgets. If we had native controls in our + // window, we'd want to be much more careful than just ingesting the complete event stream. + // To match the behavior of other backends, we pass every event down to the OS. + ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); + if (bd->Monitor) + return; + NSEventMask eventMask = 0; + eventMask |= NSEventMaskMouseMoved | NSEventMaskScrollWheel; + eventMask |= NSEventMaskLeftMouseDown | NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged; + eventMask |= NSEventMaskRightMouseDown | NSEventMaskRightMouseUp | NSEventMaskRightMouseDragged; + eventMask |= NSEventMaskOtherMouseDown | NSEventMaskOtherMouseUp | NSEventMaskOtherMouseDragged; + eventMask |= NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged; + bd->Monitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask + handler:^NSEvent* _Nullable(NSEvent* event) + { + ImGui_ImplOSX_HandleEvent(event, view); + return event; + }]; +} diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f23fe48ae..1a8181327 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,10 @@ Breaking changes: - Renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete). (This was never used in public API functions but technically present in imgui.h and ImGuiIO). +- Backends: OSX: Removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend + automatically handling event capture. Examples that are using the OSX backend have removed + all the now-unnecessary calls to ImGui_ImplOSX_HandleEvent(), applications can do as well. + [@stuartcarnie] (#4821) Other Changes: @@ -105,6 +109,7 @@ Other Changes: - Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with multiple contexts. (#5203, #5221, #4141) [@noisewuwei] - Examples: Emscripten+WebGPU: Fix building for latest WebGPU specs. (#3632) +- Examples: OSX+Metal, OSX+OpenGL: Removed now-unnecessary calls to ImGui_ImplOSX_HandleEvent(). (#4821) ----------------------------------------------------------------------- diff --git a/examples/example_apple_metal/main.mm b/examples/example_apple_metal/main.mm index db1ef3ac8..d29f8d967 100644 --- a/examples/example_apple_metal/main.mm +++ b/examples/example_apple_metal/main.mm @@ -17,7 +17,7 @@ #include "imgui_impl_metal.h" #if TARGET_OS_OSX #include "imgui_impl_osx.h" -@interface AppViewController : NSViewController +@interface AppViewController : NSViewController @end #else @interface AppViewController : UIViewController @@ -100,15 +100,8 @@ self.mtkView.delegate = self; #if TARGET_OS_OSX - // Add a tracking area in order to receive mouse events whenever the mouse is within the bounds of our view - NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect - options:NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways - owner:self - userInfo:nil]; - [self.view addTrackingArea:trackingArea]; - ImGui_ImplOSX_Init(self.view); - + [NSApp activateIgnoringOtherApps:YES]; #endif } @@ -209,20 +202,18 @@ #if TARGET_OS_OSX -// Forward Mouse events to Dear ImGui OSX backend. --(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)rightMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)otherMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)rightMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)otherMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)mouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)mouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)rightMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)rightMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)otherMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)otherMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } --(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); } +- (void)viewWillAppear +{ + [super viewWillAppear]; + self.view.window.delegate = self; +} + +- (void)windowWillClose:(NSNotification *)notification +{ + ImGui_ImplMetal_Shutdown(); + ImGui_ImplOSX_Shutdown(); + ImGui::DestroyContext(); +} #else @@ -286,9 +277,8 @@ backing:NSBackingStoreBuffered defer:NO]; self.window.contentViewController = rootViewController; - [self.window orderFront:self]; [self.window center]; - [self.window becomeKeyWindow]; + [self.window makeKeyAndOrderFront:self]; } return self; } diff --git a/examples/example_apple_opengl2/main.mm b/examples/example_apple_opengl2/main.mm index 482a94f50..92754b85f 100644 --- a/examples/example_apple_opengl2/main.mm +++ b/examples/example_apple_opengl2/main.mm @@ -142,26 +142,6 @@ -(void)animationTimerFired:(NSTimer*)timer { [self setNeedsDisplay:YES]; } -(void)dealloc { animationTimer = nil; } -//----------------------------------------------------------------------------------- -// Input processing -//----------------------------------------------------------------------------------- - -// Forward Mouse/Keyboard events to Dear ImGui OSX backend. -// Other events are registered via addLocalMonitorForEventsMatchingMask() --(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)rightMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)otherMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)rightMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)otherMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)mouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)mouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)rightMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)rightMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)otherMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)otherMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } --(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); } - @end //----------------------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 8bcd9ab6f..bc801bbdf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -386,6 +386,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2022/05/03 (1.88) - backends: osx: removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend automatically handling event capture. All ImGui_ImplOSX_HandleEvent() calls should be removed as they are now unnecessary. - 2022/04/05 (1.88) - inputs: renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete). This was never used in public API functions but technically present in imgui.h and ImGuiIO. - 2022/01/20 (1.87) - inputs: reworded gamepad IO. - Backend writing to io.NavInputs[] -> backend should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX values.