From cf2de0728f88ea933a6d9697f96ecab7048cd117 Mon Sep 17 00:00:00 2001 From: rokups Date: Thu, 16 Jun 2022 11:15:26 +0300 Subject: [PATCH] Backends: SDL+GLFW, Examples: SDL+Metal, GLFW+Metal: Fix viewport support with Metal backend. Fixes #5392 + alignment fixes and removed static_cast<> + Amended with fix. --- backends/imgui_impl_glfw.cpp | 12 +++++++++++- backends/imgui_impl_metal.mm | 14 +++++++------- backends/imgui_impl_osx.mm | 28 ++++++++++++++-------------- backends/imgui_impl_sdl.cpp | 14 ++++++++++++-- docs/CHANGELOG.txt | 5 +++-- examples/example_glfw_metal/main.mm | 19 ++++++++++++++++++- examples/example_sdl_metal/main.mm | 17 +++++++++++++++++ 7 files changed, 82 insertions(+), 27 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 92f6c5521df3..e996fa63425d 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -71,11 +71,17 @@ // GLFW #include + #ifdef _WIN32 #undef APIENTRY #define GLFW_EXPOSE_NATIVE_WIN32 -#include // for glfwGetWin32Window +#include // for glfwGetWin32Window() +#endif +#ifdef __APPLE__ +#define GLFW_EXPOSE_NATIVE_COCOA +#include // for glfwGetCocoaWindow() #endif + #define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING #define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED #define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity @@ -538,6 +544,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw main_viewport->PlatformHandle = (void*)bd->Window; #ifdef _WIN32 main_viewport->PlatformHandleRaw = glfwGetWin32Window(bd->Window); +#elif defined(__APPLE__) + main_viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(bd->Window); #endif if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) ImGui_ImplGlfw_InitPlatformInterface(); @@ -877,6 +885,8 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport) viewport->PlatformHandle = (void*)vd->Window; #ifdef _WIN32 viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window); +#elif defined(__APPLE__) + viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(vd->Window); #endif glfwSetWindowPos(vd->Window, (int)viewport->Pos.x, (int)viewport->Pos.y); diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index ae9eff4fb8d3..670a2f17dbe6 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -75,16 +75,16 @@ - (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id(static_cast(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } +static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } #ifdef IMGUI_IMPL_METAL_CPP @@ -462,7 +462,7 @@ static void ImGui_ImplMetal_RenderWindow(ImGuiViewport* viewport, void*) } data->FirstFrame = false; - viewport->DpiScale = static_cast(window.backingScaleFactor); + viewport->DpiScale = (float)window.backingScaleFactor; if (data->MetalLayer.contentsScale != viewport->DpiScale) { data->MetalLayer.contentsScale = viewport->DpiScale; diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 49526d9ff11b..cb8e4103a32a 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -63,23 +63,23 @@ // Data struct ImGui_ImplOSX_Data { - CFTimeInterval Time; - NSCursor* MouseCursors[ImGuiMouseCursor_COUNT]; - bool MouseCursorHidden; - ImGuiObserver* Observer; - KeyEventResponder* KeyEventResponder; - NSTextInputContext* InputContext; - id Monitor; - NSWindow* Window; - - ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); } + CFTimeInterval Time; + NSCursor* MouseCursors[ImGuiMouseCursor_COUNT]; + bool MouseCursorHidden; + ImGuiObserver* Observer; + KeyEventResponder* KeyEventResponder; + NSTextInputContext* InputContext; + id Monitor; + NSWindow* Window; + + 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()); } +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()); } -static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return static_cast(static_cast(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } +static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW)) / 1e9); } // Forward Declarations static void ImGui_ImplOSX_InitPlatformInterface(); diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 0f0fa8bbcbca..45d2a9d17ea1 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -408,12 +408,16 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void // Our mouse update function expect PlatformHandle to be filled for the main viewport ImGuiViewport* main_viewport = ImGui::GetMainViewport(); main_viewport->PlatformHandle = (void*)window; -#ifdef _WIN32 SDL_SysWMinfo info; SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(window, &info)) + { +#ifdef _WIN32 main_viewport->PlatformHandleRaw = (void*)info.info.win.window; +#elif defined(__APPLE__) + main_viewport->PlatformHandleRaw = (void*)info.info.cocoa.window; #endif + } // Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event. // Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered. @@ -639,6 +643,8 @@ static void ImGui_ImplSDL2_UpdateMonitors() monitor.WorkSize = ImVec2((float)r.w, (float)r.h); #endif #if SDL_HAS_PER_MONITOR_DPI + // FIXME-VIEWPORT: On MacOS SDL reports actual monitor DPI scale, ignoring OS configuration. We may want to set + // DpiScale to cocoa_window.backingScaleFactor here. float dpi = 0.0f; if (!SDL_GetDisplayDPI(n, &dpi, NULL, NULL)) monitor.DpiScale = dpi / 96.0f; @@ -748,12 +754,16 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport) SDL_GL_MakeCurrent(vd->Window, backup_context); viewport->PlatformHandle = (void*)vd->Window; -#if defined(_WIN32) SDL_SysWMinfo info; SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(vd->Window, &info)) + { +#if defined(_WIN32) viewport->PlatformHandleRaw = info.info.win.window; +#elif defined(__APPLE__) + viewport->PlatformHandleRaw = (void*)info.info.cocoa.window; #endif + } } static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7dd15120d83b..cb7ddadfab46 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -233,8 +233,9 @@ Docking+Viewports Branch: - Viewports: Fixed main viewport size not matching ImDrawData::DisplaySize for one frame during resize when multi-viewports are disabled. (#4900) - Backends: SDL: Fixed dragging out main viewport broken on some SDL setups. (#5012) [@rokups] -- Backends: OSX: Added suppot for multi-viewports. [@stuartcarnie, @metarutaiga] (#4821, #2778) -- Backends: Metal: Added suppot for multi-viewports. [@stuartcarnie, @metarutaiga] (#4821, #2778) +- Backends: OSX: Added support for multi-viewports. [@stuartcarnie, @metarutaiga] (#4821, #2778) +- Backends: Metal: Added support for multi-viewports. [@stuartcarnie, @metarutaiga] (#4821, #2778) +- Examples: OSX+Metal, SDL+Metal, GLFW+Metal: Added support for multi-viewports. [@rokups] ----------------------------------------------------------------------- diff --git a/examples/example_glfw_metal/main.mm b/examples/example_glfw_metal/main.mm index 6e5966d6f38c..d701abd64d95 100644 --- a/examples/example_glfw_metal/main.mm +++ b/examples/example_glfw_metal/main.mm @@ -29,11 +29,21 @@ int main(int, char**) ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows // Setup style ImGui::StyleColorsDark(); //ImGui::StyleColorsClassic(); + // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones. + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -64,7 +74,7 @@ int main(int, char**) id commandQueue = [device newCommandQueue]; // Setup Platform/Renderer backends - ImGui_ImplGlfw_InitForOpenGL(window, true); + ImGui_ImplGlfw_InitForOther(window, true); ImGui_ImplMetal_Init(device); NSWindow *nswin = glfwGetCocoaWindow(window); @@ -152,6 +162,13 @@ int main(int, char**) ImGui::Render(); ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); + // Update and Render additional Platform Windows + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + [renderEncoder popDebugGroup]; [renderEncoder endEncoding]; diff --git a/examples/example_sdl_metal/main.mm b/examples/example_sdl_metal/main.mm index e836b25b5127..cae754d652c5 100644 --- a/examples/example_sdl_metal/main.mm +++ b/examples/example_sdl_metal/main.mm @@ -20,11 +20,21 @@ int main(int, char**) ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows // Setup style ImGui::StyleColorsDark(); //ImGui::StyleColorsClassic(); + // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones. + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -160,6 +170,13 @@ int main(int, char**) ImGui::Render(); ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); + // Update and Render additional Platform Windows + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + [renderEncoder popDebugGroup]; [renderEncoder endEncoding];