-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
Hi,
I’m currently experiencing problems with monitor handling after hotplug events or when resuming from Windows sleep/power saving.
I couldn’t find an existing issue describing this, so here is a detailed report:
On Windows 10/11, after disconnecting/reconnecting external monitors (or resuming from sleep), GLFW monitor enumeration becomes inconsistent:
- glfwGetMonitors() sometimes drops to only 1 monitor, even though Windows still reports all displays.
- glfwGetMonitorContentScale() occasionally returns (0,0) for some monitors.
- Error callback reports:
code=65544, desc=Win32: Failed to query monitor DPI code=65544, desc=Win32: Failed to query display settings
- Meanwhile, direct Win32 API calls (EnumDisplayDevices, EnumDisplaySettings, GetDpiForMonitor) continue to return valid information for all monitors.
Restarting the application always resolves the issue, which indicates GLFW state is inconsistent after monitor changes.
To Reproduce
- Start GLFW-based app with multiple monitors attached.
- Disconnect and reconnect one or more monitors (or put system into sleep and wake up).
- Observe GLFW monitor count and DPI values.
Expected behavior
GLFW should keep reporting correct monitor info (glfwGetVideoMode != NULL, glfwGetMonitorContentScale > 0) as soon as Windows APIs do. At least it should not return (0,0) DPI or drop monitors while Win32 still reports them active.
Environment:
- GLFW version: [GLFW 3.4]
- OS: Windows 10/11
- GPU/driver: [Tested on Intel Iris(R) Xe Graphics, but also happens on others]
Additional context / logs
Log excerpt showing the issue:
[ERROR] GLFW: code=65544, desc=Win32: Failed to query monitor DPI
[INFO] MonitorsOncePerSec(): [Wide viewing angle & High density FlexView Display 1920x1080] pos=(-1920,0) scale=(0,0) mode=1920x1080@60
At the same time, Win32 diagnostics report:
[Win32] Device: \\.\DISPLAY1 1920x1080@60 pos=(-1920,0)
[Win32] DPI for DISPLAY1 = 96x96
So Windows APIs are consistent, while GLFW reports invalid DPI and sometimes invalid video modes.
Workaround
In our app we patched ImGui_ImplGlfw_UpdateMonitors() to:
- Skip monitors with mode==NULL or scale==0 instead of clearing the entire list.
- Never replace the monitor list with zero entries.
- Fall back to previous valid monitors until GLFW recovers.
This prevents crashes in ImGui but does not solve the root issue.
Summary
It looks like the Win32 backend in GLFW fails to refresh monitor state correctly after hotplug/sleep events. A fix would be valuable since restarting the app is currently the only way to get consistent data again.
Minimal test snippet (C++11 + GLFW + Win32 diagnostics)
#include "glfw3.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
static void GlfwErrorCallback(int error, const char* description)
{
printf("GLFW error %d: %s\n", error, description);
}
static void DumpMonitors()
{
int count = 0;
GLFWmonitor** mons = glfwGetMonitors(&count);
printf("GLFW monitors_count = %d\n", count);
for (int i = 0; i < count; i++) {
const GLFWvidmode* mode = glfwGetVideoMode(mons[i]);
float xs=0, ys=0;
glfwGetMonitorContentScale(mons[i], &xs, &ys);
printf(" monitor[%d]: mode=%s scale=%f,%f\n", i, mode ? "ok":"NULL", xs, ys);
}
}
// Win32 diagnostics
static void DumpWin32Displays()
{
DWORD devNum = 0;
DISPLAY_DEVICE dd;
dd.cb = sizeof(dd);
while (EnumDisplayDevices(NULL, devNum, &dd, 0)) {
if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) {
DEVMODE dm;
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
if (EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) {
printf(" Win32 device %S %dx%d@%d pos=(%d,%d)\n",
dd.DeviceName, dm.dmPelsWidth, dm.dmPelsHeight, dm.dmDisplayFrequency,
dm.dmPosition.x, dm.dmPosition.y);
}
}
devNum++;
}
}
int main()
{
glfwSetErrorCallback(GlfwErrorCallback);
if (!glfwInit()) return -1;
GLFWwindow* win = glfwCreateWindow(800,600,"test",NULL,NULL);
while (!glfwWindowShouldClose(win)) {
glfwPollEvents();
DumpMonitors();
DumpWin32Displays();
Sleep(1000);
}
glfwTerminate();
return 0;
}