diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 92f6c5521df37..93416907da91b 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -70,7 +70,10 @@ #endif // GLFW +#define GLFW_EXPOSE_NATIVE_COCOA #include +#include + #ifdef _WIN32 #undef APIENTRY #define GLFW_EXPOSE_NATIVE_WIN32 @@ -538,6 +541,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 +882,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 ae9eff4fb8d3f..98726ffb92e41 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -442,6 +442,16 @@ inline static CGSize MakeScaledSize(CGSize size, CGFloat scale) static void ImGui_ImplMetal_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) { ImGuiViewportDataMetal* data = (ImGuiViewportDataMetal*)viewport->RendererUserData; +#if TARGET_OS_OSX + // FIXME-VIEWPORT: On MacOS we expect to scale windows by using backingScaleFactor, however SDL backend sets actual + // monitor scaling factor to monitor.DpiScale, which in turn gets set to viewport->DpiScale by core library. When + // a common (non-Apple-made) monitor is attached to MacOS host, SDL will report actual monitor scale factor, which + // may not match backingScaleFactor. In such cases resizing a viewport window would produce inaccurate metal + // drawable size not covering entire Cocoa window precisely. + void* handle = viewport->PlatformHandleRaw ? viewport->PlatformHandleRaw : viewport->PlatformHandle; + NSWindow* window = (__bridge NSWindow*)handle; + viewport->DpiScale = static_cast(window.backingScaleFactor); +#endif data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), viewport->DpiScale); } diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 0f0fa8bbcbca2..1396db7c0307b 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -408,12 +408,18 @@ 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; +#else + (void); #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 +645,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 +756,18 @@ 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; +#else + (void); #endif + } } static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport) diff --git a/examples/example_glfw_metal/main.mm b/examples/example_glfw_metal/main.mm index 6e5966d6f38c2..d701abd64d956 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 e836b25b51270..cae754d652c5d 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];