Camilla Berglund 13 năm trước cách đây
mục cha
commit
830f2b439c

+ 2 - 3
include/GL/glfw3.h

@@ -529,15 +529,14 @@ GLFWAPI const char* glfwErrorString(int error);
 GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun);
 GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun);
 
 
 /* Monitor functions */
 /* Monitor functions */
+GLFWAPI GLFWmonitor* glfwGetMonitors(int* count);
+GLFWAPI GLFWmonitor glfwGetPrimaryMonitor(void);
 GLFWAPI int  glfwGetMonitorParam(GLFWmonitor monitor, int param);
 GLFWAPI int  glfwGetMonitorParam(GLFWmonitor monitor, int param);
 GLFWAPI const char* glfwGetMonitorString(GLFWmonitor monitor, int param);
 GLFWAPI const char* glfwGetMonitorString(GLFWmonitor monitor, int param);
 GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor monitor, void* pointer);
 GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor monitor, void* pointer);
 GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor monitor);
 GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor monitor);
 GLFWAPI void glfwSetMonitorCallback(GLFWmonitorfun cbfun);
 GLFWAPI void glfwSetMonitorCallback(GLFWmonitorfun cbfun);
 
 
-/* Monitor discovery */
-GLFWAPI GLFWmonitor glfwGetNextMonitor(GLFWmonitor iterator);
-
 /* Video mode functions */
 /* Video mode functions */
 GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor monitor, int* count);
 GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor monitor, int* count);
 GLFWAPI void glfwGetVideoMode(GLFWmonitor monitor, GLFWvidmode* mode);
 GLFWAPI void glfwGetVideoMode(GLFWmonitor monitor, GLFWvidmode* mode);

+ 9 - 0
src/init.c

@@ -130,6 +130,13 @@ GLFWAPI int glfwInit(void)
         return GL_FALSE;
         return GL_FALSE;
     }
     }
 
 
+    _glfwLibrary.monitors = _glfwPlatformGetMonitors(&_glfwLibrary.monitorCount);
+    if (!_glfwLibrary.monitors)
+    {
+        _glfwPlatformTerminate();
+        return GL_FALSE;
+    }
+
     atexit(glfwTerminate);
     atexit(glfwTerminate);
 
 
     _glfwInitialized = GL_TRUE;
     _glfwInitialized = GL_TRUE;
@@ -151,6 +158,8 @@ GLFWAPI void glfwTerminate(void)
     while (_glfwLibrary.windowListHead)
     while (_glfwLibrary.windowListHead)
         glfwDestroyWindow(_glfwLibrary.windowListHead);
         glfwDestroyWindow(_glfwLibrary.windowListHead);
 
 
+    _glfwDestroyMonitors();
+
     if (!_glfwPlatformTerminate())
     if (!_glfwPlatformTerminate())
         return;
         return;
 
 

+ 15 - 6
src/internal.h

@@ -206,8 +206,6 @@ struct _GLFWwindow
 //------------------------------------------------------------------------
 //------------------------------------------------------------------------
 struct _GLFWmonitor
 struct _GLFWmonitor
 {
 {
-    struct _GLFWmonitor* next;
-
     void*     userPointer;
     void*     userPointer;
 
 
     char*     name;
     char*     name;
@@ -234,7 +232,9 @@ struct _GLFWlibrary
     _GLFWwindow*  windowListHead;
     _GLFWwindow*  windowListHead;
     _GLFWwindow*  activeWindow;
     _GLFWwindow*  activeWindow;
     _GLFWwindow*  cursorLockWindow;
     _GLFWwindow*  cursorLockWindow;
-    _GLFWmonitor* monitorListHead;
+
+    _GLFWmonitor** monitors;
+    int            monitorCount;
 
 
     GLFWwindowsizefun    windowSizeCallback;
     GLFWwindowsizefun    windowSizeCallback;
     GLFWwindowclosefun   windowCloseCallback;
     GLFWwindowclosefun   windowCloseCallback;
@@ -286,6 +286,10 @@ void _glfwPlatformDisableSystemKeys(_GLFWwindow* window);
 void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y);
 void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y);
 void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
 void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
 
 
+// Monitor support
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count);
+void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor);
+
 // Video mode support
 // Video mode support
 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
@@ -357,6 +361,9 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action);
 void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y);
 void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y);
 void _glfwInputCursorEnter(_GLFWwindow* window, int entered);
 void _glfwInputCursorEnter(_GLFWwindow* window, int entered);
 
 
+// Monitor event notification (monitor.c)
+void _glfwInputMonitorChange(void);
+
 
 
 //========================================================================
 //========================================================================
 // Prototypes for internal utility functions
 // Prototypes for internal utility functions
@@ -385,8 +392,10 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig);
 GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig);
 GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig);
 
 
 // Monitor management (monitor.c)
 // Monitor management (monitor.c)
-void _glfwInitMonitors(void);
-void _glfwRefreshMonitors(void);
-void _glfwTerminateMonitors(void);
+_GLFWmonitor* _glfwCreateMonitor(const char* name,
+                                 int physicalWidth, int physicalHeight,
+                                 int screenX, int screenY);
+void _glfwDestroyMonitor(_GLFWmonitor* monitor);
+void _glfwDestroyMonitors(void);
 
 
 #endif // _internal_h_
 #endif // _internal_h_

+ 102 - 79
src/monitor.c

@@ -31,6 +31,7 @@
 #include "internal.h"
 #include "internal.h"
 
 
 #include <string.h>
 #include <string.h>
+#include <stdlib.h>
 
 
 
 
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
@@ -38,108 +39,115 @@
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
 //========================================================================
 //========================================================================
-// Initialize the monitor list
+// Create a monitor struct from the specified information
 //========================================================================
 //========================================================================
 
 
-void _glfwInitMonitors(void)
+_GLFWmonitor* _glfwCreateMonitor(const char* name,
+                                 int physicalWidth, int physicalHeight,
+                                 int screenX, int screenY)
 {
 {
-    _glfwLibrary.monitorListHead = _glfwCreateMonitors();
+    _GLFWmonitor* monitor = (_GLFWmonitor*) calloc(1, sizeof(_GLFWmonitor));
+    if (!monitor)
+    {
+        _glfwSetError(GLFW_OUT_OF_MEMORY, NULL);
+        return NULL;
+    }
+
+    monitor->name = strdup(name);
+    monitor->physicalWidth = physicalWidth;
+    monitor->physicalHeight = physicalHeight;
+    monitor->screenX = screenX;
+    monitor->screenY = screenY;
+
+    return monitor;
 }
 }
 
 
 
 
 //========================================================================
 //========================================================================
-// Refresh monitor list and notify callback
+// Destroy the specified monitor
 //========================================================================
 //========================================================================
 
 
-void _glfwRefreshMonitors(void)
+void _glfwDestroyMonitor(_GLFWmonitor* monitor)
 {
 {
-    _GLFWmonitor* newMonitorList;
-    _GLFWmonitor* curNewMonitor;
-    _GLFWmonitor* curOldMonitor;
-
-    newMonitorList = _glfwCreateMonitors();
-    curNewMonitor = newMonitorList;
-    curOldMonitor = _glfwLibrary.monitorListHead;
-
-    while (_glfwLibrary.monitorCallback && (curNewMonitor || curOldMonitor))
-    {
-        _GLFWmonitor* lookAheadOldMonitor;
-        _GLFWmonitor* lookAheadNewMonitor;
+    if (monitor == NULL)
+        return;
 
 
-        if (curOldMonitor && curNewMonitor && !strcmp(curOldMonitor->name, curOldMonitor->name))
-        {
-            curNewMonitor = curNewMonitor->next;
-            curOldMonitor = curOldMonitor->next;
-            continue;
-        }
+    _glfwPlatformDestroyMonitor(monitor);
 
 
-        if (curNewMonitor && !curOldMonitor)
-        {
-            _glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED);
-            curNewMonitor = curNewMonitor->next;
-            continue;
-        }
+    free(monitor->modes);
+    free(monitor->name);
+    free(monitor);
+}
 
 
-        if (!curNewMonitor && curOldMonitor)
-        {
-            _glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED);
-            curOldMonitor = curOldMonitor->next;
-            continue;
-        }
 
 
-        lookAheadOldMonitor = curOldMonitor->next;
-        lookAheadNewMonitor = curNewMonitor->next;
+//========================================================================
+// Enumerate monitors and notify user of changes
+//========================================================================
 
 
-        while (lookAheadOldMonitor && !strcmp(curNewMonitor->name, lookAheadOldMonitor->name))
-            lookAheadOldMonitor = lookAheadOldMonitor->next;
+void _glfwInputMonitorChange(void)
+{
+    int i, j, monitorCount;
+    _GLFWmonitor** monitors;
 
 
-        while (lookAheadNewMonitor && !strcmp(curOldMonitor->name, lookAheadNewMonitor->name))
-            lookAheadNewMonitor = lookAheadNewMonitor->next;
+    monitors = _glfwPlatformGetMonitors(&monitorCount);
 
 
-        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
+    for (i = 0;  i < monitorCount;  i++)
+    {
+        for (j = 0;  j < _glfwLibrary.monitorCount;  j++)
         {
         {
-            while (strcmp(curOldMonitor->name, lookAheadOldMonitor->name))
+            if (_glfwLibrary.monitors[j] == NULL)
+                continue;
+
+            if (strcmp(monitors[i]->name, _glfwLibrary.monitors[j]->name) == 0)
             {
             {
-                _glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED);
-                curOldMonitor = curOldMonitor->next;
+                // This monitor was connected before, so re-use the existing
+                // monitor object to preserve its address and user pointer
+
+                _glfwDestroyMonitor(monitors[i]);
+                monitors[i] = _glfwLibrary.monitors[j];
+                _glfwLibrary.monitors[j] = NULL;
+                break;
             }
             }
         }
         }
 
 
-        if (!lookAheadNewMonitor)
+        if (j == _glfwLibrary.monitorCount)
         {
         {
-            // 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;
-            }
+            // This monitor was not connected before
+            _glfwLibrary.monitorCallback(monitors[i], GLFW_MONITOR_CONNECTED);
         }
         }
     }
     }
 
 
-    _glfwTerminateMonitors();
-    _glfwLibrary.monitorListHead = newMonitorList;
+    for (i = 0;  i < _glfwLibrary.monitorCount;  i++)
+    {
+        if (_glfwLibrary.monitors[i] == NULL)
+            continue;
+
+        // This monitor is no longer connected
+        _glfwLibrary.monitorCallback(_glfwLibrary.monitors[i],
+                                     GLFW_MONITOR_DISCONNECTED);
+    }
+
+    _glfwDestroyMonitors();
+
+    _glfwLibrary.monitors = monitors;
+    _glfwLibrary.monitorCount = monitorCount;
 }
 }
 
 
 
 
 //========================================================================
 //========================================================================
-// Delete the monitor list
+// Destroy all monitors
 //========================================================================
 //========================================================================
 
 
-void _glfwTerminateMonitors(void)
+void _glfwDestroyMonitors(void)
 {
 {
-    while (_glfwLibrary.monitorListHead)
-        _glfwLibrary.monitorListHead = _glfwDestroyMonitor(_glfwLibrary.monitorListHead);
+    int i;
+
+    for (i = 0;  i < _glfwLibrary.monitorCount;  i++)
+        _glfwDestroyMonitor(_glfwLibrary.monitors[i]);
+
+    free(_glfwLibrary.monitors);
+    _glfwLibrary.monitors = NULL;
+    _glfwLibrary.monitorCount = 0;
 }
 }
 
 
 
 
@@ -148,26 +156,41 @@ void _glfwTerminateMonitors(void)
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
 //========================================================================
 //========================================================================
-// Iterate through connected monitors
+// Return the currently connected monitors
 //========================================================================
 //========================================================================
 
 
-GLFWAPI GLFWmonitor glfwGetNextMonitor(GLFWmonitor handle)
+GLFWAPI GLFWmonitor* glfwGetMonitors(int* count)
 {
 {
-    _GLFWmonitor* iterator = (_GLFWmonitor*) handle;
-    _GLFWmonitor* result;
-
     if (!_glfwInitialized)
     if (!_glfwInitialized)
     {
     {
         _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
         _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
         return NULL;
         return NULL;
     }
     }
 
 
-    if (iterator == NULL)
-        result = _glfwLibrary.monitorListHead;
-    else
-        result = iterator->next;
+    if (count == NULL)
+    {
+        _glfwSetError(GLFW_INVALID_VALUE, NULL);
+        return NULL;
+    }
+
+    *count = _glfwLibrary.monitorCount;
+    return (GLFWmonitor*) _glfwLibrary.monitors;
+}
+
+
+//========================================================================
+// Get the primary monitor
+//========================================================================
+
+GLFWAPI GLFWmonitor glfwGetPrimaryMonitor(void)
+{
+    if (!_glfwInitialized)
+    {
+        _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
+        return NULL;
+    }
 
 
-    return result;
+    return _glfwLibrary.monitors[0];
 }
 }
 
 
 
 

+ 4 - 21
src/win32_fullscreen.c

@@ -185,16 +185,8 @@ void _glfwRestoreVideoMode(void)
 
 
 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
 {
 {
-    int deviceModeIndex = 0, count = 0;
+    int modeIndex = 0, count = 0;
     GLFWvidmode* result = NULL;
     GLFWvidmode* result = NULL;
-    WCHAR* deviceName;
-
-    deviceName = _glfwCreateWideStringFromUTF8(monitor->Win32.name);
-    if (!deviceName)
-    {
-        _glfwSetError(GLFW_PLATFORM_ERROR, "Win32: Failed to convert device name");
-        return NULL;
-    }
 
 
     *found = 0;
     *found = 0;
 
 
@@ -207,10 +199,10 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
         ZeroMemory(&dm, sizeof(DEVMODE));
         ZeroMemory(&dm, sizeof(DEVMODE));
         dm.dmSize = sizeof(DEVMODE);
         dm.dmSize = sizeof(DEVMODE);
 
 
-        if (!EnumDisplaySettings(deviceName, deviceModeIndex, &dm))
+        if (!EnumDisplaySettings(monitor->Win32.name, modeIndex, &dm))
             break;
             break;
 
 
-        deviceModeIndex++;
+        modeIndex++;
 
 
         if (dm.dmBitsPerPel < 15)
         if (dm.dmBitsPerPel < 15)
         {
         {
@@ -262,7 +254,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
         (*found)++;
         (*found)++;
     }
     }
 
 
-    free(deviceName);
     return result;
     return result;
 }
 }
 
 
@@ -274,19 +265,11 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
 {
 {
     DEVMODE dm;
     DEVMODE dm;
-    WCHAR* deviceName;
-
-    deviceName = _glfwCreateWideStringFromUTF8(monitor->Win32.name);
-    if (!deviceName)
-    {
-        _glfwSetError(GLFW_PLATFORM_ERROR, "Win32: Failed to convert device name");
-        return;
-    }
 
 
     ZeroMemory(&dm, sizeof(DEVMODE));
     ZeroMemory(&dm, sizeof(DEVMODE));
     dm.dmSize = sizeof(DEVMODE);
     dm.dmSize = sizeof(DEVMODE);
 
 
-    EnumDisplaySettings(deviceName, ENUM_REGISTRY_SETTINGS, &dm);
+    EnumDisplaySettings(monitor->Win32.name, ENUM_REGISTRY_SETTINGS, &dm);
 
 
     mode->width  = dm.dmPelsWidth;
     mode->width  = dm.dmPelsWidth;
     mode->height = dm.dmPelsHeight;
     mode->height = dm.dmPelsHeight;

+ 0 - 4
src/win32_init.c

@@ -178,8 +178,6 @@ int _glfwPlatformInit(void)
     _glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp);
     _glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp);
     _glfwLibrary.currentRamp = _glfwLibrary.originalRamp;
     _glfwLibrary.currentRamp = _glfwLibrary.originalRamp;
 
 
-    _glfwInitMonitors();
-
     _glfwInitTimer();
     _glfwInitTimer();
 
 
     return GL_TRUE;
     return GL_TRUE;
@@ -196,8 +194,6 @@ int _glfwPlatformTerminate(void)
     if (_glfwLibrary.rampChanged)
     if (_glfwLibrary.rampChanged)
         _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp);
         _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp);
 
 
-    _glfwTerminateMonitors();
-
     if (_glfwLibrary.Win32.classAtom)
     if (_glfwLibrary.Win32.classAtom)
     {
     {
         UnregisterClass(_GLFW_WNDCLASSNAME, _glfwLibrary.Win32.instance);
         UnregisterClass(_GLFW_WNDCLASSNAME, _glfwLibrary.Win32.instance);

+ 89 - 67
src/win32_monitor.c

@@ -32,6 +32,7 @@
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <wchar.h>
 
 
 // The MinGW package for Debian lacks this
 // The MinGW package for Debian lacks this
 #ifndef EDS_ROTATEDMODE
 #ifndef EDS_ROTATEDMODE
@@ -49,34 +50,102 @@
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
 //========================================================================
 //========================================================================
-// Create a monitor struct from the specified information
+// Return a list of available monitors
 //========================================================================
 //========================================================================
 
 
-_GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current,
-                                  DISPLAY_DEVICE* adapter,
-                                  DISPLAY_DEVICE* monitor,
-                                  DEVMODE* setting)
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
 {
 {
-    HDC dc = NULL;
-
-    *current = malloc(sizeof(_GLFWmonitor));
-    memset(*current, 0, sizeof(_GLFWmonitor));
-
-    dc = CreateDC(L"DISPLAY", monitor->DeviceString, NULL, NULL);
+    int size = 0, found = 0;
+    _GLFWmonitor** monitors = NULL;
+    DWORD adapterIndex = 0;
 
 
-    (*current)->physicalWidth  = GetDeviceCaps(dc, HORZSIZE);
-    (*current)->physicalHeight = GetDeviceCaps(dc, VERTSIZE);
+    for (;;)
+    {
+        DISPLAY_DEVICE adapter;
+        DWORD monitorIndex = 0;
 
 
-    DeleteDC(dc);
+        ZeroMemory(&adapter, sizeof(DISPLAY_DEVICE));
+        adapter.cb = sizeof(DISPLAY_DEVICE);
 
 
-    (*current)->name = _glfwCreateUTF8FromWideString(monitor->DeviceName);
+        if (!EnumDisplayDevices(NULL, adapterIndex, &adapter, 0))
+            break;
 
 
-    (*current)->screenX = setting->dmPosition.x;
-    (*current)->screenY = setting->dmPosition.y;
+        adapterIndex++;
 
 
-    (*current)->Win32.name = _glfwCreateUTF8FromWideString(adapter->DeviceName);
+        if ((adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) ||
+            !(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
+        {
+            continue;
+        }
+
+        for (;;)
+        {
+            DISPLAY_DEVICE monitor;
+            DEVMODE settings;
+            const char* name;
+            HDC dc;
+
+            ZeroMemory(&monitor, sizeof(DISPLAY_DEVICE));
+            monitor.cb = sizeof(DISPLAY_DEVICE);
+
+            if (!EnumDisplayDevices(adapter.DeviceName, monitorIndex, &monitor, 0))
+                break;
+
+            ZeroMemory(&settings, sizeof(DEVMODE));
+            settings.dmSize = sizeof(DEVMODE);
+
+            EnumDisplaySettingsEx(adapter.DeviceName,
+                                  ENUM_CURRENT_SETTINGS,
+                                  &settings,
+                                  EDS_ROTATEDMODE);
+
+            name = _glfwCreateUTF8FromWideString(monitor.DeviceName);
+            if (!name)
+            {
+                // TODO: wat
+                return NULL;
+            }
+
+            dc = CreateDC(L"DISPLAY", monitor.DeviceString, NULL, NULL);
+            if (!dc)
+            {
+                // TODO: wat
+                return NULL;
+            }
+
+            if (found == size)
+            {
+                if (size)
+                    size *= 2;
+                else
+                    size = 4;
+
+                monitors = (_GLFWmonitor**) realloc(monitors, sizeof(_GLFWmonitor*) * size);
+            }
+
+            monitors[found] = _glfwCreateMonitor(name,
+                                                 GetDeviceCaps(dc, HORZSIZE),
+                                                 GetDeviceCaps(dc, VERTSIZE),
+                                                 settings.dmPosition.x,
+                                                 settings.dmPosition.y);
+
+            DeleteDC(dc);
+
+            if (!monitors[found])
+            {
+                // TODO: wat
+                return NULL;
+            }
+
+            monitors[found]->Win32.name = wcsdup(monitor.DeviceName);
+
+            found++;
+            monitorIndex++;
+        }
+    }
 
 
-    return &((*current)->next);
+    *count = found;
+    return monitors;
 }
 }
 
 
 
 
@@ -84,55 +153,8 @@ _GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current,
 // Destroy a monitor struct
 // Destroy a monitor struct
 //========================================================================
 //========================================================================
 
 
-_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor)
+void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
 {
 {
-    _GLFWmonitor* result;
-
-    result = monitor->next;
-
     free(monitor->Win32.name);
     free(monitor->Win32.name);
-    free(monitor->name);
-    free(monitor);
-
-    return result;
-}
-
-
-//========================================================================
-// Return a list of available monitors
-//========================================================================
-
-_GLFWmonitor* _glfwCreateMonitors(void)
-{
-    DISPLAY_DEVICE adapter;
-    DWORD adapterNum;
-    DISPLAY_DEVICE monitor;
-    DEVMODE setting;
-    _GLFWmonitor* monitorList;
-    _GLFWmonitor** curMonitor;
-
-    adapter.cb = sizeof(DISPLAY_DEVICE);
-    adapterNum = 0;
-    monitor.cb = sizeof(DISPLAY_DEVICE);
-    setting.dmSize = sizeof(DEVMODE);
-    monitorList = NULL;
-    curMonitor = &monitorList;
-
-    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);
-    }
-
-    return monitorList;
 }
 }
 
 

+ 1 - 5
src/win32_platform.h

@@ -219,7 +219,7 @@ typedef struct _GLFWlibraryWin32
 //------------------------------------------------------------------------
 //------------------------------------------------------------------------
 typedef struct _GLFWmonitorWin32
 typedef struct _GLFWmonitorWin32
 {
 {
-    char* name;
+    WCHAR* name;
 
 
 } _GLFWmonitorWin32;
 } _GLFWmonitorWin32;
 
 
@@ -244,10 +244,6 @@ char* _glfwCreateUTF8FromWideString(const WCHAR* source);
 // Time
 // Time
 void _glfwInitTimer(void);
 void _glfwInitTimer(void);
 
 
-// Monitor support
-_GLFWmonitor* _glfwCreateMonitors(void);
-_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor);
-
 // OpenGL support
 // OpenGL support
 int _glfwCreateContext(_GLFWwindow* window,
 int _glfwCreateContext(_GLFWwindow* window,
                        const _GLFWwndconfig* wndconfig,
                        const _GLFWwndconfig* wndconfig,

+ 1 - 1
src/win32_window.c

@@ -670,7 +670,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
         {
         {
             if (DBT_DEVNODES_CHANGED == wParam)
             if (DBT_DEVNODES_CHANGED == wParam)
             {
             {
-                _glfwRefreshMonitors();
+                _glfwInputMonitorChange();
                 return TRUE;
                 return TRUE;
             }
             }
             break;
             break;

+ 0 - 4
src/x11_init.c

@@ -651,8 +651,6 @@ int _glfwPlatformInit(void)
     if (!_glfwInitJoysticks())
     if (!_glfwInitJoysticks())
         return GL_FALSE;
         return GL_FALSE;
 
 
-    _glfwInitMonitors();
-
     // Start the timer
     // Start the timer
     _glfwInitTimer();
     _glfwInitTimer();
 
 
@@ -676,8 +674,6 @@ int _glfwPlatformTerminate(void)
 
 
     terminateDisplay();
     terminateDisplay();
 
 
-    _glfwTerminateMonitors();
-
     _glfwTerminateJoysticks();
     _glfwTerminateJoysticks();
 
 
     _glfwTerminateOpenGL();
     _glfwTerminateOpenGL();

+ 53 - 81
src/x11_monitor.c

@@ -34,111 +34,83 @@
 #include <string.h>
 #include <string.h>
 
 
 
 
-//========================================================================
-// Create a monitor struct from the specified information
-//========================================================================
-
-#if defined (_GLFW_HAS_XRANDR)
-static _GLFWmonitor** createMonitor(_GLFWmonitor** current,
-                                    XRROutputInfo* outputInfo,
-                                    XRRCrtcInfo* crtcInfo)
-{
-    *current = malloc(sizeof(_GLFWmonitor));
-    memset(*current, 0, sizeof(_GLFWmonitor));
-
-    (*current)->physicalWidth  = outputInfo->mm_width;
-    (*current)->physicalHeight = outputInfo->mm_height;
-
-    (*current)->name = strdup(outputInfo->name);
-
-    (*current)->screenX = crtcInfo->x;
-    (*current)->screenY = crtcInfo->y;
-
-    (*current)->X11.output = outputInfo;
-    return &((*current)->next);
-}
-#endif /*_GLFW_HAS_XRANDR*/
-
-
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////                       GLFW platform API                      //////
 //////                       GLFW platform API                      //////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
-//========================================================================
-// Destroy a monitor struct
-//========================================================================
-
-_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor)
-{
-    _GLFWmonitor* result;
-
-    result = monitor->next;
-
-#if defined (_GLFW_HAS_XRANDR)
-    XRRFreeOutputInfo(monitor->X11.output);
-#endif /*_GLFW_HAS_XRANDR*/
-
-    free(monitor->modes);
-    free(monitor->name);
-    free(monitor);
-
-    return result;
-}
-
 
 
 //========================================================================
 //========================================================================
 // Return a list of available monitors
 // Return a list of available monitors
 //========================================================================
 //========================================================================
 
 
-_GLFWmonitor* _glfwCreateMonitors(void)
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
 {
 {
-    _GLFWmonitor* monitorList = NULL;
+    int found = 0;
+    _GLFWmonitor** monitors = NULL;
 
 
     if (_glfwLibrary.X11.RandR.available)
     if (_glfwLibrary.X11.RandR.available)
     {
     {
 #if defined (_GLFW_HAS_XRANDR)
 #if defined (_GLFW_HAS_XRANDR)
-        int oi;
-        XRRScreenResources* resources;
-        _GLFWmonitor** monitor = &monitorList;
+        int i;
+        XRRScreenResources* sr;
 
 
-        resources = XRRGetScreenResources(_glfwLibrary.X11.display,
-                                          _glfwLibrary.X11.root);
+        sr = XRRGetScreenResources(_glfwLibrary.X11.display,
+                                   _glfwLibrary.X11.root);
+
+        monitors = (_GLFWmonitor**) calloc(sr->noutput, sizeof(_GLFWmonitor*));
+        if (!monitors)
+        {
+            _glfwSetError(GLFW_OUT_OF_MEMORY, NULL);
+            return NULL;
+        }
 
 
-        for (oi = 0;  oi < resources->noutput;  oi++)
+        for (i = 0;  i < sr->noutput;  i++)
         {
         {
-            // physical device
-            XRROutputInfo* outputInfo = NULL;
-            // logical surface
-            XRRCrtcInfo* crtcInfo = NULL;
+            XRROutputInfo* oi;
+            XRRCrtcInfo* ci;
 
 
-            outputInfo = XRRGetOutputInfo(_glfwLibrary.X11.display,
-                                          resources,
-                                          resources->outputs[oi]);
+            oi = XRRGetOutputInfo(_glfwLibrary.X11.display, sr, sr->outputs[i]);
+            if (oi->connection != RR_Connected)
+            {
+                XRRFreeOutputInfo(oi);
+                continue;
+            }
+
+            ci = XRRGetCrtcInfo(_glfwLibrary.X11.display, sr, oi->crtc);
 
 
-            if (outputInfo->connection == RR_Connected)
+            monitors[found] = _glfwCreateMonitor(oi->name,
+                                                 oi->mm_width, oi->mm_height,
+                                                 ci->x, ci->y);
+
+            XRRFreeCrtcInfo(ci);
+
+            if (!monitors[found])
             {
             {
-                int ci;
-
-                for (ci = 0;  ci < outputInfo->ncrtc;  ci++)
-                {
-                    if (outputInfo->crtc == outputInfo->crtcs[ci])
-                    {
-                        crtcInfo = XRRGetCrtcInfo(_glfwLibrary.X11.display,
-                                                  resources,
-                                                  outputInfo->crtcs[ci]);
-                        break;
-                    }
-                }
-
-                monitor = createMonitor(monitor, outputInfo, crtcInfo);
-
-                // Freeing of the outputInfo is done in _glfwDestroyMonitor
-                XRRFreeCrtcInfo(crtcInfo);
+                // TODO: wat
+                return NULL;
             }
             }
+
+            // This is retained until the monitor object is destroyed
+            monitors[found]->X11.output = oi;
+
+            found++;
         }
         }
 #endif /*_GLFW_HAS_XRANDR*/
 #endif /*_GLFW_HAS_XRANDR*/
     }
     }
 
 
-    return monitorList;
+    *count = found;
+    return monitors;
+}
+
+
+//========================================================================
+// Destroy a monitor struct
+//========================================================================
+
+void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
+{
+#if defined (_GLFW_HAS_XRANDR)
+    XRRFreeOutputInfo(monitor->X11.output);
+#endif /*_GLFW_HAS_XRANDR*/
 }
 }
 
 

+ 0 - 4
src/x11_platform.h

@@ -325,10 +325,6 @@ void _glfwRestoreVideoMode(void);
 int  _glfwInitJoysticks(void);
 int  _glfwInitJoysticks(void);
 void _glfwTerminateJoysticks(void);
 void _glfwTerminateJoysticks(void);
 
 
-// Monitors
-_GLFWmonitor* _glfwCreateMonitors(void);
-_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor);
-
 // Unicode support
 // Unicode support
 long _glfwKeySym2Unicode(KeySym keysym);
 long _glfwKeySym2Unicode(KeySym keysym);
 
 

+ 1 - 1
src/x11_window.c

@@ -810,7 +810,7 @@ static void processEvent(XEvent *event)
                 case RRScreenChangeNotify:
                 case RRScreenChangeNotify:
                 {
                 {
                     XRRUpdateConfiguration(event);
                     XRRUpdateConfiguration(event);
-                    _glfwRefreshMonitors();
+                    _glfwInputMonitorChange();
                     break;
                     break;
                 }
                 }
             }
             }

+ 1 - 1
tests/gamma.c

@@ -120,7 +120,7 @@ int main(int argc, char** argv)
     if (mode == GLFW_FULLSCREEN)
     if (mode == GLFW_FULLSCREEN)
     {
     {
         GLFWvidmode mode;
         GLFWvidmode mode;
-        glfwGetVideoMode(glfwGetNextMonitor(NULL), &mode);
+        glfwGetVideoMode(glfwGetPrimaryMonitor(), &mode);
         width = mode.width;
         width = mode.width;
         height = mode.height;
         height = mode.height;
     }
     }

+ 1 - 1
tests/iconify.c

@@ -101,7 +101,7 @@ int main(int argc, char** argv)
     if (mode == GLFW_FULLSCREEN)
     if (mode == GLFW_FULLSCREEN)
     {
     {
         GLFWvidmode current_mode;
         GLFWvidmode current_mode;
-        glfwGetVideoMode(glfwGetNextMonitor(NULL), &current_mode);
+        glfwGetVideoMode(glfwGetPrimaryMonitor(), &current_mode);
         width = current_mode.width;
         width = current_mode.width;
         height = current_mode.height;
         height = current_mode.height;
     }
     }

+ 7 - 5
tests/modes.c

@@ -199,8 +199,8 @@ static void test_modes(GLFWmonitor monitor)
 
 
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {
 {
-    int ch, mode = LIST_MODE;
-    GLFWmonitor monitor = NULL;
+    int ch, i, count, mode = LIST_MODE;
+    GLFWmonitor* monitors;
 
 
     while ((ch = getopt(argc, argv, "th")) != -1)
     while ((ch = getopt(argc, argv, "th")) != -1)
     {
     {
@@ -226,12 +226,14 @@ int main(int argc, char** argv)
     if (!glfwInit())
     if (!glfwInit())
         exit(EXIT_FAILURE);
         exit(EXIT_FAILURE);
 
 
-    while ((monitor = glfwGetNextMonitor(monitor)))
+    monitors = glfwGetMonitors(&count);
+
+    for (i = 0;  i < count;  i++)
     {
     {
         if (mode == LIST_MODE)
         if (mode == LIST_MODE)
-            list_modes(monitor);
+            list_modes(monitors[i]);
         else if (mode == TEST_MODE)
         else if (mode == TEST_MODE)
-            test_modes(monitor);
+            test_modes(monitors[i]);
     }
     }
 
 
     exit(EXIT_SUCCESS);
     exit(EXIT_SUCCESS);