diff --git a/src/win32_monitor.c b/src/win32_monitor.c index c8fd5fe2..7b03b9fb 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -83,6 +83,9 @@ _GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor) return result; } +// todo: This is ugly. The platform should only allocate a list of the current devices. +// The platform independent code should be in charge of the handling for the initial +// setup, refreshing and freeing the list. void _glfwInitMonitors(void) { _GLFWmonitor** curMonitor; @@ -106,7 +109,7 @@ void _glfwInitMonitors(void) while (EnumDisplayDevices(NULL, adapterNum++, &adapter, 0)) { - if (adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) + if (adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER || !(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) continue; EnumDisplaySettingsEx(adapter.DeviceName, @@ -120,6 +123,106 @@ void _glfwInitMonitors(void) } } +void _glfwRefreshMonitors(void) +{ + DISPLAY_DEVICE adapter; + DWORD adapterNum = 0; + + DISPLAY_DEVICE monitor; + + DEVMODE setting; + + _GLFWmonitor* newMonitorList = NULL; + _GLFWmonitor** curMonitor = &newMonitorList; + + _GLFWmonitor* curNewMonitor; + _GLFWmonitor* curOldMonitor; + + while (EnumDisplayDevices(NULL, adapterNum++, &adapter, 0)) + { + if (adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER || !(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) + continue; + + EnumDisplaySettingsEx(adapter.DeviceName, ENUM_CURRENT_SETTINGS, &setting, EDS_ROTATEDMODE); + + EnumDisplayDevices(adapter.DeviceName, 0, &monitor, 0); + + curMonitor = _glfwCreateMonitor(curMonitor, &adapter, &monitor, &setting); + } + + curNewMonitor = newMonitorList; + curOldMonitor = _glfwLibrary.monitorListHead; + + while (_glfwLibrary.monitorCallback && (curNewMonitor || curOldMonitor)) + { + _GLFWmonitor* lookAheadOldMonitor; + _GLFWmonitor* lookAheadNewMonitor; + + if (curOldMonitor && curNewMonitor && !strcmp(curOldMonitor->name, curOldMonitor->name)) + { + curNewMonitor = curNewMonitor->next; + curOldMonitor = curOldMonitor->next; + continue; + } + + if (curNewMonitor && !curOldMonitor) + { + _glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED); + curNewMonitor = curNewMonitor->next; + continue; + } + + if (!curNewMonitor && curOldMonitor) + { + _glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED); + curOldMonitor = curOldMonitor->next; + continue; + } + + lookAheadOldMonitor = curOldMonitor->next; + lookAheadNewMonitor = curNewMonitor->next; + + while (lookAheadOldMonitor && !strcmp(curNewMonitor->name, lookAheadOldMonitor->name)) + lookAheadOldMonitor = lookAheadOldMonitor->next; + + while (lookAheadNewMonitor && !strcmp(curOldMonitor->name, lookAheadNewMonitor->name)) + lookAheadNewMonitor = lookAheadNewMonitor->next; + + if (!lookAheadOldMonitor) + { + // nothing found in the old monitor list, that matches the current new monitor. + _glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED); + curNewMonitor = curNewMonitor->next; + } + else + { + while (strcmp(curOldMonitor->name, lookAheadOldMonitor->name)) + { + _glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED); + curOldMonitor = curOldMonitor->next; + } + } + + if (!lookAheadNewMonitor) + { + // nothing found in the new monitor list, that matches the current old monitor. + _glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED); + curOldMonitor = curOldMonitor->next; + } + else + { + while (strcmp(curNewMonitor->name, lookAheadNewMonitor->name)) + { + _glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED); + curNewMonitor = curNewMonitor->next; + } + } + } + + _glfwTerminateMonitors(); + _glfwLibrary.monitorListHead = newMonitorList; +} + void _glfwTerminateMonitors(void) { while (_glfwLibrary.monitorListHead) diff --git a/src/win32_platform.h b/src/win32_platform.h index c09b6235..91c71fbe 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -42,6 +42,7 @@ #include #include +#include // This path may need to be changed if you build GLFW using your own setup // We ship and use our own copy of wglext.h since GLFW uses fairly new @@ -332,6 +333,7 @@ void _glfwInitTimer(void); // Monitor support void _glfwInitMonitors(void); +void _glfwRefreshMonitors(void); void _glfwTerminateMonitors(void); // Fullscreen support diff --git a/src/win32_window.c b/src/win32_window.c index fcc9e891..f362368a 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -30,7 +30,6 @@ #include "internal.h" -#include #include @@ -1104,6 +1103,16 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, break; } + + case WM_DEVICECHANGE: + { + if (DBT_DEVNODES_CHANGED == wParam) + { + _glfwRefreshMonitors(); + return TRUE; + } + break; + } } // Pass all unhandled messages to DefWindowProc