mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-12 03:49:05 +08:00
Backends: GLFW, SDL: Platform monitors declared properly even if multi-viewport is not enabled.
This commit is contained in:
parent
3bde375078
commit
7e2d172ae5
@ -83,11 +83,12 @@ static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL;
|
||||
static GLFWscrollfun g_PrevUserCallbackScroll = NULL;
|
||||
static GLFWkeyfun g_PrevUserCallbackKey = NULL;
|
||||
static GLFWcharfun g_PrevUserCallbackChar = NULL;
|
||||
static GLFWmonitorfun g_PrevUserCallbackMonitor = NULL;
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplGlfw_UpdateMonitors();
|
||||
static void ImGui_ImplGlfw_InitPlatformInterface();
|
||||
static void ImGui_ImplGlfw_ShutdownPlatformInterface();
|
||||
static void ImGui_ImplGlfw_UpdateMonitors();
|
||||
|
||||
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||
{
|
||||
@ -149,6 +150,11 @@ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
|
||||
io.AddInputCharacter(c);
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
||||
{
|
||||
g_WantUpdateMonitors = true;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
|
||||
{
|
||||
g_Window = window;
|
||||
@ -220,6 +226,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
g_PrevUserCallbackScroll = NULL;
|
||||
g_PrevUserCallbackKey = NULL;
|
||||
g_PrevUserCallbackChar = NULL;
|
||||
g_PrevUserCallbackMonitor = NULL;
|
||||
if (install_callbacks)
|
||||
{
|
||||
g_InstalledCallbacks = true;
|
||||
@ -227,8 +234,13 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
|
||||
g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
|
||||
g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
|
||||
g_PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
||||
}
|
||||
|
||||
// Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
|
||||
ImGui_ImplGlfw_UpdateMonitors();
|
||||
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
||||
|
||||
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
main_viewport->PlatformHandle = (void*)g_Window;
|
||||
@ -405,6 +417,40 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfw_UpdateMonitors()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
int monitors_count = 0;
|
||||
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
|
||||
platform_io.Monitors.resize(0);
|
||||
for (int n = 0; n < monitors_count; n++)
|
||||
{
|
||||
ImGuiPlatformMonitor monitor;
|
||||
int x, y;
|
||||
glfwGetMonitorPos(glfw_monitors[n], &x, &y);
|
||||
const GLFWvidmode* vid_mode = glfwGetVideoMode(glfw_monitors[n]);
|
||||
#if GLFW_HAS_MONITOR_WORK_AREA
|
||||
monitor.MainPos = ImVec2((float)x, (float)y);
|
||||
monitor.MainSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
|
||||
int w, h;
|
||||
glfwGetMonitorWorkarea(glfw_monitors[n], &x, &y, &w, &h);
|
||||
monitor.WorkPos = ImVec2((float)x, (float)y);;
|
||||
monitor.WorkSize = ImVec2((float)w, (float)h);
|
||||
#else
|
||||
monitor.MainPos = monitor.WorkPos = ImVec2((float)x, (float)y);
|
||||
monitor.MainSize = monitor.WorkSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
|
||||
#endif
|
||||
#if GLFW_HAS_PER_MONITOR_DPI
|
||||
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
||||
float x_scale, y_scale;
|
||||
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
|
||||
monitor.DpiScale = x_scale;
|
||||
#endif
|
||||
platform_io.Monitors.push_back(monitor);
|
||||
}
|
||||
g_WantUpdateMonitors = false;
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@ -746,45 +792,6 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
|
||||
}
|
||||
#endif // GLFW_HAS_VULKAN
|
||||
|
||||
static void ImGui_ImplGlfw_UpdateMonitors()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
int monitors_count = 0;
|
||||
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
|
||||
platform_io.Monitors.resize(0);
|
||||
for (int n = 0; n < monitors_count; n++)
|
||||
{
|
||||
ImGuiPlatformMonitor monitor;
|
||||
int x, y;
|
||||
glfwGetMonitorPos(glfw_monitors[n], &x, &y);
|
||||
const GLFWvidmode* vid_mode = glfwGetVideoMode(glfw_monitors[n]);
|
||||
#if GLFW_HAS_MONITOR_WORK_AREA
|
||||
monitor.MainPos = ImVec2((float)x, (float)y);
|
||||
monitor.MainSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
|
||||
int w, h;
|
||||
glfwGetMonitorWorkarea(glfw_monitors[n], &x, &y, &w, &h);
|
||||
monitor.WorkPos = ImVec2((float)x, (float)y);;
|
||||
monitor.WorkSize = ImVec2((float)w, (float)h);
|
||||
#else
|
||||
monitor.MainPos = monitor.WorkPos = ImVec2((float)x, (float)y);
|
||||
monitor.MainSize = monitor.WorkSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
|
||||
#endif
|
||||
#if GLFW_HAS_PER_MONITOR_DPI
|
||||
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
||||
float x_scale, y_scale;
|
||||
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
|
||||
monitor.DpiScale = x_scale;
|
||||
#endif
|
||||
platform_io.Monitors.push_back(monitor);
|
||||
}
|
||||
g_WantUpdateMonitors = false;
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
||||
{
|
||||
g_WantUpdateMonitors = true;
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfw_InitPlatformInterface()
|
||||
{
|
||||
// Register platform interface (will be coupled with a renderer interface)
|
||||
@ -812,10 +819,6 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
|
||||
platform_io.Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos;
|
||||
#endif
|
||||
|
||||
// Note: monitor callback are broken GLFW 3.2 and earlier (see github.com/glfw/glfw/issues/784)
|
||||
ImGui_ImplGlfw_UpdateMonitors();
|
||||
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
||||
|
||||
// Register main window handle (which is owned by the main application, not by us)
|
||||
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
|
@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
struct GLFWwindow;
|
||||
struct GLFWmonitor;
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
||||
@ -32,3 +33,4 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, i
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
||||
|
@ -77,6 +77,7 @@ static bool g_MouseCanUseGlobalState = true;
|
||||
static bool g_UseVulkan = false;
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplSDL2_UpdateMonitors();
|
||||
static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_gl_context);
|
||||
static void ImGui_ImplSDL2_ShutdownPlatformInterface();
|
||||
|
||||
@ -222,6 +223,9 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
|
||||
main_viewport->PlatformHandleRaw = info.info.win.window;
|
||||
#endif
|
||||
|
||||
// Update monitors
|
||||
ImGui_ImplSDL2_UpdateMonitors();
|
||||
|
||||
// We need SDL_CaptureMouse(), SDL_GetGlobalMouseState() from SDL 2.0.4+ to support multiple viewports.
|
||||
// We left the call to ImGui_ImplSDL2_InitPlatformInterface() outside of #ifdef to avoid unused-function warnings.
|
||||
if ((io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (io.BackendFlags & ImGuiBackendFlags_PlatformHasViewports))
|
||||
@ -405,6 +409,34 @@ static void ImGui_ImplSDL2_UpdateGamepads()
|
||||
#undef MAP_ANALOG
|
||||
}
|
||||
|
||||
// FIXME-PLATFORM: SDL doesn't have an event to notify the application of display/monitor changes
|
||||
static void ImGui_ImplSDL2_UpdateMonitors()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Monitors.resize(0);
|
||||
int display_count = SDL_GetNumVideoDisplays();
|
||||
for (int n = 0; n < display_count; n++)
|
||||
{
|
||||
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
||||
ImGuiPlatformMonitor monitor;
|
||||
SDL_Rect r;
|
||||
SDL_GetDisplayBounds(n, &r);
|
||||
monitor.MainPos = monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
|
||||
monitor.MainSize = monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
|
||||
#if SDL_HAS_USABLE_DISPLAY_BOUNDS
|
||||
SDL_GetDisplayUsableBounds(n, &r);
|
||||
monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
|
||||
monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
|
||||
#endif
|
||||
#if SDL_HAS_PER_MONITOR_DPI
|
||||
float dpi = 0.0f;
|
||||
if (!SDL_GetDisplayDPI(n, &dpi, NULL, NULL))
|
||||
monitor.DpiScale = dpi / 96.0f;
|
||||
#endif
|
||||
platform_io.Monitors.push_back(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@ -632,34 +664,6 @@ static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
|
||||
}
|
||||
#endif // SDL_HAS_VULKAN
|
||||
|
||||
// FIXME-PLATFORM: SDL doesn't have an event to notify the application of display/monitor changes
|
||||
static void ImGui_ImplSDL2_UpdateMonitors()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Monitors.resize(0);
|
||||
int display_count = SDL_GetNumVideoDisplays();
|
||||
for (int n = 0; n < display_count; n++)
|
||||
{
|
||||
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
||||
ImGuiPlatformMonitor monitor;
|
||||
SDL_Rect r;
|
||||
SDL_GetDisplayBounds(n, &r);
|
||||
monitor.MainPos = monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
|
||||
monitor.MainSize = monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
|
||||
#if SDL_HAS_USABLE_DISPLAY_BOUNDS
|
||||
SDL_GetDisplayUsableBounds(n, &r);
|
||||
monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
|
||||
monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
|
||||
#endif
|
||||
#if SDL_HAS_PER_MONITOR_DPI
|
||||
float dpi = 0.0f;
|
||||
if (!SDL_GetDisplayDPI(n, &dpi, NULL, NULL))
|
||||
monitor.DpiScale = dpi / 96.0f;
|
||||
#endif
|
||||
platform_io.Monitors.push_back(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_gl_context)
|
||||
{
|
||||
// Register platform interface (will be coupled with a renderer interface)
|
||||
@ -689,8 +693,6 @@ static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_g
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
#endif
|
||||
|
||||
ImGui_ImplSDL2_UpdateMonitors();
|
||||
|
||||
// Register main window handle (which is owned by the main application, not by us)
|
||||
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
|
@ -263,6 +263,33 @@ static void ImGui_ImplWin32_UpdateGamepads()
|
||||
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, HDC, LPRECT, LPARAM)
|
||||
{
|
||||
MONITORINFO info = { 0 };
|
||||
info.cbSize = sizeof(MONITORINFO);
|
||||
if (!::GetMonitorInfo(monitor, &info))
|
||||
return TRUE;
|
||||
ImGuiPlatformMonitor imgui_monitor;
|
||||
imgui_monitor.MainPos = ImVec2((float)info.rcMonitor.left, (float)info.rcMonitor.top);
|
||||
imgui_monitor.MainSize = ImVec2((float)(info.rcMonitor.right - info.rcMonitor.left), (float)(info.rcMonitor.bottom - info.rcMonitor.top));
|
||||
imgui_monitor.WorkPos = ImVec2((float)info.rcWork.left, (float)info.rcWork.top);
|
||||
imgui_monitor.WorkSize = ImVec2((float)(info.rcWork.right - info.rcWork.left), (float)(info.rcWork.bottom - info.rcWork.top));
|
||||
imgui_monitor.DpiScale = ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
|
||||
ImGuiPlatformIO& io = ImGui::GetPlatformIO();
|
||||
if (info.dwFlags & MONITORINFOF_PRIMARY)
|
||||
io.Monitors.push_front(imgui_monitor);
|
||||
else
|
||||
io.Monitors.push_back(imgui_monitor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_UpdateMonitors()
|
||||
{
|
||||
ImGui::GetPlatformIO().Monitors.resize(0);
|
||||
::EnumDisplayMonitors(NULL, NULL, ImGui_ImplWin32_UpdateMonitors_EnumFunc, NULL);
|
||||
g_WantUpdateMonitors = false;
|
||||
}
|
||||
|
||||
void ImGui_ImplWin32_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@ -764,33 +791,6 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd,
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, HDC, LPRECT, LPARAM)
|
||||
{
|
||||
MONITORINFO info = { 0 };
|
||||
info.cbSize = sizeof(MONITORINFO);
|
||||
if (!::GetMonitorInfo(monitor, &info))
|
||||
return TRUE;
|
||||
ImGuiPlatformMonitor imgui_monitor;
|
||||
imgui_monitor.MainPos = ImVec2((float)info.rcMonitor.left, (float)info.rcMonitor.top);
|
||||
imgui_monitor.MainSize = ImVec2((float)(info.rcMonitor.right - info.rcMonitor.left), (float)(info.rcMonitor.bottom - info.rcMonitor.top));
|
||||
imgui_monitor.WorkPos = ImVec2((float)info.rcWork.left, (float)info.rcWork.top);
|
||||
imgui_monitor.WorkSize = ImVec2((float)(info.rcWork.right - info.rcWork.left), (float)(info.rcWork.bottom - info.rcWork.top));
|
||||
imgui_monitor.DpiScale = ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
|
||||
ImGuiPlatformIO& io = ImGui::GetPlatformIO();
|
||||
if (info.dwFlags & MONITORINFOF_PRIMARY)
|
||||
io.Monitors.push_front(imgui_monitor);
|
||||
else
|
||||
io.Monitors.push_back(imgui_monitor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_UpdateMonitors()
|
||||
{
|
||||
ImGui::GetPlatformIO().Monitors.resize(0);
|
||||
::EnumDisplayMonitors(NULL, NULL, ImGui_ImplWin32_UpdateMonitors_EnumFunc, NULL);
|
||||
g_WantUpdateMonitors = false;
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_InitPlatformInterface()
|
||||
{
|
||||
WNDCLASSEX wcex;
|
||||
|
@ -15329,9 +15329,11 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
|
||||
ImGui::ShowViewportThumbnails();
|
||||
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
|
||||
if (g.PlatformIO.Monitors.Size > 0 && ImGui::TreeNode("Monitors", "Monitors (%d)", g.PlatformIO.Monitors.Size))
|
||||
bool open = ImGui::TreeNode("Monitors", "Monitors (%d)", g.PlatformIO.Monitors.Size);
|
||||
ImGui::SameLine();
|
||||
MetricsHelpMarker("Dear ImGui uses monitor data:\n- to query DPI settings on a per monitor basis\n- to position popup/tooltips so they don't straddle monitors.");
|
||||
if (open)
|
||||
{
|
||||
ImGui::TextWrapped("(When viewports are enabled, imgui needs uses monitor data to position popup/tooltips so they don't straddle monitors.)");
|
||||
for (int i = 0; i < g.PlatformIO.Monitors.Size; i++)
|
||||
{
|
||||
const ImGuiPlatformMonitor& mon = g.PlatformIO.Monitors[i];
|
||||
|
Loading…
Reference in New Issue
Block a user