summaryrefslogtreecommitdiffstats
path: root/deps/imgui/src/imgui_impl_glfw.cpp
diff options
context:
space:
mode:
authoruntodesu <kirill@untode.su>2025-09-11 15:10:18 +0500
committeruntodesu <kirill@untode.su>2025-09-11 15:10:18 +0500
commita6ea7b7bbc66327cc2a957496f65dcfab5361cee (patch)
treea4fda8a1a490bf1d88afe4e8d2f8814afdcc0de1 /deps/imgui/src/imgui_impl_glfw.cpp
parent8784cbfebcb8a0220fb947a6070032e20b80fc2f (diff)
downloadvoxelius-a6ea7b7bbc66327cc2a957496f65dcfab5361cee.tar.bz2
voxelius-a6ea7b7bbc66327cc2a957496f65dcfab5361cee.zip
Update ImGui to a newer version with font scaling
Diffstat (limited to 'deps/imgui/src/imgui_impl_glfw.cpp')
-rw-r--r--deps/imgui/src/imgui_impl_glfw.cpp161
1 files changed, 114 insertions, 47 deletions
diff --git a/deps/imgui/src/imgui_impl_glfw.cpp b/deps/imgui/src/imgui_impl_glfw.cpp
index baa8541..d0a75ac 100644
--- a/deps/imgui/src/imgui_impl_glfw.cpp
+++ b/deps/imgui/src/imgui_impl_glfw.cpp
@@ -9,6 +9,7 @@
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// [X] Multiple Dear ImGui contexts support.
// Missing features or Issues:
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
@@ -28,6 +29,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
+// 2025-06-18: Added support for multiple Dear ImGui contexts. (#8676, #8239, #8069)
+// 2025-06-11: Added ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window) and ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor) helper to facilitate making DPI-aware apps.
// 2025-03-10: Map GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 into ImGuiKey_Oem102.
// 2025-03-03: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled.
// 2024-08-22: Moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
@@ -117,6 +120,7 @@
#ifndef _WIN32
#include <unistd.h> // for usleep()
#endif
+#include <stdio.h> // for snprintf()
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
@@ -130,6 +134,7 @@
// We gather version tests as define in order to easily see which features are version-dependent.
#define GLFW_VERSION_COMBINED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION)
+#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale
#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
#define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
#else
@@ -139,6 +144,16 @@
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
+// Map GLFWWindow* to ImGuiContext*.
+// - Would be simpler if we could use glfwSetWindowUserPointer()/glfwGetWindowUserPointer(), but this is a single and shared resource.
+// - Would be simpler if we could use e.g. std::map<> as well. But we don't.
+// - This is not particularly optimized as we expect size to be small and queries to be rare.
+struct ImGui_ImplGlfw_WindowToContext { GLFWwindow* Window; ImGuiContext* Context; };
+static ImVector<ImGui_ImplGlfw_WindowToContext> g_ContextMap;
+static void ImGui_ImplGlfw_ContextMap_Add(GLFWwindow* window, ImGuiContext* ctx) { g_ContextMap.push_back(ImGui_ImplGlfw_WindowToContext{ window, ctx }); }
+static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); return; } }
+static ImGuiContext* ImGui_ImplGlfw_ContextMap_Get(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) return entry.Context; return nullptr; }
+
// GLFW data
enum GlfwClientApi
{
@@ -149,6 +164,7 @@ enum GlfwClientApi
struct ImGui_ImplGlfw_Data
{
+ ImGuiContext* Context;
GLFWwindow* Window;
GlfwClientApi ClientApi;
double Time;
@@ -157,6 +173,7 @@ struct ImGui_ImplGlfw_Data
ImVec2 LastValidMousePos;
bool InstalledCallbacks;
bool CallbacksChainForAllWindows;
+ char BackendPlatformName[32];
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
const char* CanvasSelector;
#endif
@@ -184,10 +201,18 @@ struct ImGui_ImplGlfw_Data
// (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.
// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
+namespace ImGui { extern ImGuiIO& GetIO(ImGuiContext*); }
static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
{
+ // Get data for current context
return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
}
+static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData(GLFWwindow* window)
+{
+ // Get data for a given GLFW window, regardless of current context (since GLFW events are sent together)
+ ImGuiContext* ctx = ImGui_ImplGlfw_ContextMap_Get(window);
+ return (ImGui_ImplGlfw_Data*)ImGui::GetIO(ctx).BackendPlatformUserData;
+}
// Functions
@@ -323,38 +348,36 @@ ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
// X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
// See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
-static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window)
+static void ImGui_ImplGlfw_UpdateKeyModifiers(ImGuiIO& io, GLFWwindow* window)
{
- ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(ImGuiMod_Ctrl, (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS));
io.AddKeyEvent(ImGuiMod_Shift, (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS));
io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
}
-static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window)
+static bool ImGui_ImplGlfw_ShouldChainCallback(ImGui_ImplGlfw_Data* bd, GLFWwindow* window)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
return bd->CallbacksChainForAllWindows ? true : (window == bd->Window);
}
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
- if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
- bd->PrevUserCallbackMousebutton(window, button, action, mods);
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
- ImGui_ImplGlfw_UpdateKeyModifiers(window);
+ if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
+ bd->PrevUserCallbackMousebutton(window, button, action, mods);
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
+ ImGui_ImplGlfw_UpdateKeyModifiers(io, window);
if (button >= 0 && button < ImGuiMouseButton_COUNT)
io.AddMouseButtonEvent(button, action == GLFW_PRESS);
}
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
- if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
+ if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
@@ -362,7 +385,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
return;
#endif
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
}
@@ -402,18 +425,18 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
- if (bd->PrevUserCallbackKey != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
+ if (bd->PrevUserCallbackKey != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackKey(window, keycode, scancode, action, mods);
if (action != GLFW_PRESS && action != GLFW_RELEASE)
return;
- ImGui_ImplGlfw_UpdateKeyModifiers(window);
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
+ ImGui_ImplGlfw_UpdateKeyModifiers(io, window);
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
- ImGuiIO& io = ImGui::GetIO();
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode);
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
@@ -421,21 +444,21 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
- if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
+ if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackWindowFocus(window, focused);
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
io.AddFocusEvent(focused != 0);
}
void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
- if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
+ if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackCursorPos(window, x, y);
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
io.AddMousePosEvent((float)x, (float)y);
bd->LastValidMousePos = ImVec2((float)x, (float)y);
}
@@ -444,11 +467,11 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
// so we back it up and restore on Leave/Enter (see https://github.com/ocornut/imgui/issues/4984)
void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
- if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
+ if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackCursorEnter(window, entered);
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
if (entered)
{
bd->MouseWindow = window;
@@ -464,11 +487,11 @@ void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
- if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
+ if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackChar(window, c);
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
io.AddInputCharacter(c);
}
@@ -478,17 +501,18 @@ void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
}
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
-static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
+static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void* user_data)
{
// Mimic Emscripten_HandleWheel() in SDL.
// Corresponding equivalent in GLFW JS emulation layer has incorrect quantizing preventing small values. See #6096
+ ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
float multiplier = 0.0f;
if (ev->deltaMode == DOM_DELTA_PIXEL) { multiplier = 1.0f / 100.0f; } // 100 pixels make up a step.
else if (ev->deltaMode == DOM_DELTA_LINE) { multiplier = 1.0f / 3.0f; } // 3 lines make up a step.
else if (ev->deltaMode == DOM_DELTA_PAGE) { multiplier = 80.0f; } // A page makes up 80 steps.
float wheel_x = ev->deltaX * -multiplier;
float wheel_y = ev->deltaY * -multiplier;
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
io.AddMouseWheelEvent(wheel_x, wheel_y);
//IMGUI_DEBUG_LOG("[Emsc] mode %d dx: %.2f, dy: %.2f, dz: %.2f --> feed %.2f %.2f\n", (int)ev->deltaMode, ev->deltaX, ev->deltaY, ev->deltaZ, wheel_x, wheel_y);
return EM_TRUE;
@@ -509,7 +533,9 @@ static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
}
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)::GetPropA(hWnd, "IMGUI_BACKEND_DATA");
+ ImGuiIO& io = ImGui::GetIO(bd->Context);
+
switch (msg)
{
case WM_MOUSEMOVE: case WM_NCMOUSEMOVE:
@@ -517,8 +543,9 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
- ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
+ io.AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
break;
+ default: break;
}
return ::CallWindowProcW(bd->PrevWndProc, hWnd, msg, wParam, lParam);
}
@@ -526,7 +553,7 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
IM_ASSERT(bd->InstalledCallbacks == false && "Callbacks already installed!");
IM_ASSERT(bd->Window == window);
@@ -543,7 +570,7 @@ void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window)
{
- ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
IM_ASSERT(bd->InstalledCallbacks == true && "Callbacks not installed!");
IM_ASSERT(bd->Window == window);
@@ -593,13 +620,16 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Setup backend capabilities flags
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
+ snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
io.BackendPlatformUserData = (void*)bd;
- io.BackendPlatformName = "imgui_impl_glfw";
+ io.BackendPlatformName = bd->BackendPlatformName;
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+ bd->Context = ImGui::GetCurrentContext();
bd->Window = window;
bd->Time = 0.0;
+ ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
#if GLFW_VERSION_COMBINED < 3300
@@ -657,7 +687,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32
- bd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
+ HWND hwnd = (HWND)main_viewport->PlatformHandleRaw;
+ ::SetPropA(hwnd, "IMGUI_BACKEND_DATA", bd);
+ bd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
IM_ASSERT(bd->PrevWndProc != nullptr);
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif
@@ -668,7 +700,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
if (emscripten::glfw3::IsRuntimePlatformApple())
{
- ImGui::GetIO().ConfigMacOSXBehaviors = true;
+ io.ConfigMacOSXBehaviors = true;
// Due to how the browser (poorly) handles the Meta Key, this line essentially disables repeats when used.
// This means that Meta + V only registers a single key-press, even if the keys are held.
@@ -717,6 +749,7 @@ void ImGui_ImplGlfw_Shutdown()
// Windows: restore our WndProc hook
#ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
+ ::SetPropA((HWND)main_viewport->PlatformHandleRaw, "IMGUI_BACKEND_DATA", nullptr);
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->PrevWndProc);
bd->PrevWndProc = nullptr;
#endif
@@ -724,6 +757,7 @@ void ImGui_ImplGlfw_Shutdown()
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
+ ImGui_ImplGlfw_ContextMap_Remove(bd->Window);
IM_DELETE(bd);
}
@@ -789,7 +823,7 @@ static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0
static void ImGui_ImplGlfw_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
- if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
+ if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs, but see #8075
return;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
@@ -837,20 +871,53 @@ static void ImGui_ImplGlfw_UpdateGamepads()
#undef MAP_ANALOG
}
+// - On Windows the process needs to be marked DPI-aware!! SDL2 doesn't do it by default. You can call ::SetProcessDPIAware() or call ImGui_ImplWin32_EnableDpiAwareness() from Win32 backend.
+// - Apple platforms use FramebufferScale so we always return 1.0f.
+// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
+float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
+{
+#if GLFW_HAS_PER_MONITOR_DPI && !defined(__APPLE__)
+ float x_scale, y_scale;
+ glfwGetWindowContentScale(window, &x_scale, &y_scale);
+ return x_scale;
+#else
+ IM_UNUSED(window);
+ return 1.0f;
+#endif
+}
+
+float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor)
+{
+#if GLFW_HAS_PER_MONITOR_DPI && !defined(__APPLE__)
+ float x_scale, y_scale;
+ glfwGetMonitorContentScale(monitor, &x_scale, &y_scale);
+ return x_scale;
+#else
+ IM_UNUSED(monitor);
+ return 1.0f;
+#endif
+}
+
+static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window, ImVec2* out_size, ImVec2* out_framebuffer_scale)
+{
+ int w, h;
+ int display_w, display_h;
+ glfwGetWindowSize(window, &w, &h);
+ glfwGetFramebufferSize(window, &display_w, &display_h);
+ if (out_size != nullptr)
+ *out_size = ImVec2((float)w, (float)h);
+ if (out_framebuffer_scale != nullptr)
+ *out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f);
+}
+
void ImGui_ImplGlfw_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
- // Setup display size (every frame to accommodate for window resizing)
- int w, h;
- int display_w, display_h;
- glfwGetWindowSize(bd->Window, &w, &h);
- glfwGetFramebufferSize(bd->Window, &display_w, &display_h);
- io.DisplaySize = ImVec2((float)w, (float)h);
- if (w > 0 && h > 0)
- io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);
+ // Setup main viewport size (every frame to accommodate for window resizing)
+ ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale);
// Setup time step
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
@@ -914,7 +981,7 @@ void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow*, const char* canvas_s
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
// FIXME: May break chaining in case user registered their own Emscripten callback?
- emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
+ emscripten_set_wheel_callback(bd->CanvasSelector, bd, false, ImGui_ImplEmscripten_WheelCallback);
}
#elif defined(EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3)
// When using --use-port=contrib.glfw3 for the GLFW implementation, you can override the behavior of this call