Skip to content

Commit

Permalink
Backends: Metal: Add a workaround for resizing windows on monitors wi…
Browse files Browse the repository at this point in the history
…th DPI scale not matching OS configuration.

Backends: SDL+GLFW: Fix viewport support with metal backend.
Examples: SDL+Metal, GLFW+Metal: Add viewports support.

Fixes ocornut#5392.
  • Loading branch information
rokups committed Jun 16, 2022
1 parent 24dfebf commit c962d5b
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 3 deletions.
7 changes: 7 additions & 0 deletions backends/imgui_impl_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@
#endif

// GLFW
#define GLFW_EXPOSE_NATIVE_COCOA
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>

#ifdef _WIN32
#undef APIENTRY
#define GLFW_EXPOSE_NATIVE_WIN32
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);

Expand Down
10 changes: 10 additions & 0 deletions backends/imgui_impl_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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<float>(window.backingScaleFactor);
#endif
data->MetalLayer.drawableSize = MakeScaledSize(CGSizeMake(size.x, size.y), viewport->DpiScale);
}

Expand Down
18 changes: 16 additions & 2 deletions backends/imgui_impl_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
19 changes: 18 additions & 1 deletion examples/example_glfw_metal/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -64,7 +74,7 @@ int main(int, char**)
id <MTLCommandQueue> 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);
Expand Down Expand Up @@ -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];

Expand Down
17 changes: 17 additions & 0 deletions examples/example_sdl_metal/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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];

Expand Down

0 comments on commit c962d5b

Please sign in to comment.