diff --git a/src/internal.h b/src/internal.h index e323ee96..16485b0e 100644 --- a/src/internal.h +++ b/src/internal.h @@ -65,6 +65,13 @@ // extensions and not all operating systems come with an up-to-date version #include "../support/GL/glext.h" +typedef struct _GLFWhints _GLFWhints; +typedef struct _GLFWwndconfig _GLFWwndconfig; +typedef struct _GLFWfbconfig _GLFWfbconfig; +typedef struct _GLFWwindow _GLFWwindow; +typedef struct _GLFWlibrary _GLFWlibrary; +typedef struct _GLFWmonitor _GLFWmonitor; + #if defined(_GLFW_COCOA_NSGL) #include "cocoa_platform.h" #elif defined(_GLFW_WIN32_WGL) @@ -75,14 +82,6 @@ #error "No supported platform selected" #endif -typedef struct _GLFWhints _GLFWhints; -typedef struct _GLFWwndconfig _GLFWwndconfig; -typedef struct _GLFWfbconfig _GLFWfbconfig; -typedef struct _GLFWwindow _GLFWwindow; -typedef struct _GLFWlibrary _GLFWlibrary; -typedef struct _GLFWmonitor _GLFWmonitor; - - //------------------------------------------------------------------------ // Window hints, set by glfwOpenWindowHint and consumed by glfwOpenWindow // A bucket of semi-random stuff lumped together for historical reasons @@ -386,5 +385,9 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig); GLboolean _glfwIsValidContext(_GLFWwindow* window, _GLFWwndconfig* wndconfig); +// Monitor management (monitor.c) +void _glfwInitMonitors(void); +void _glfwRefreshMonitors(void); +void _glfwTerminateMonitors(void); #endif // _internal_h_ diff --git a/src/monitor.c b/src/monitor.c index 3263eb9f..0cc8f511 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -145,3 +145,106 @@ GLFWAPI void glfwSetMonitorDeviceCallback(GLFWmonitordevicefun cbfun) _glfwLibrary.monitorCallback= cbfun; } +//======================================================================== +// Initialize the monitor list. +//======================================================================== + +void _glfwInitMonitors(void) +{ + _glfwLibrary.monitorListHead = _glfwCreateMonitors(); +} + +//======================================================================== +// Refresh monitor list and notify callback. +//======================================================================== + +void _glfwRefreshMonitors(void) +{ + _GLFWmonitor* newMonitorList; + _GLFWmonitor* curNewMonitor; + _GLFWmonitor* curOldMonitor; + + newMonitorList = _glfwCreateMonitors(); + 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; +} + +//======================================================================== +// Delete the monitor list. +//======================================================================== + +void _glfwTerminateMonitors(void) +{ + while (_glfwLibrary.monitorListHead) + _glfwLibrary.monitorListHead = _glfwDestroyMonitor(_glfwLibrary.monitorListHead); +} + diff --git a/src/win32_fullscreen.c b/src/win32_fullscreen.c index 08f5e93e..682b6757 100644 --- a/src/win32_fullscreen.c +++ b/src/win32_fullscreen.c @@ -229,7 +229,7 @@ int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int ma } if (list && maxcount) - memcpy(list, vidModes, sizeof(GLFWvidmode) * min(vidModesCount, maxcount)); + memcpy(list, vidModes, sizeof(GLFWvidmode) * ((vidModesCount < maxcount) ? vidModesCount : maxcount)); free(vidModes); diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 7b03b9fb..452b347e 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -38,6 +38,11 @@ #define EDS_ROTATEDMODE 0x00000004 #endif +// The MinGW upstream lacks this +#ifndef DISPLAY_DEVICE_ACTIVE +#define DISPLAY_DEVICE_ACTIVE 0x00000001 +#endif + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -83,29 +88,21 @@ _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* _glfwCreateMonitors(void) { - _GLFWmonitor** curMonitor; - DISPLAY_DEVICE adapter; DWORD adapterNum; - DISPLAY_DEVICE monitor; - DEVMODE setting; - DWORD settingNum; - - curMonitor = &_glfwLibrary.monitorListHead; + _GLFWmonitor* monitorList; + _GLFWmonitor** curMonitor; adapter.cb = sizeof(DISPLAY_DEVICE); adapterNum = 0; - monitor.cb = sizeof(DISPLAY_DEVICE); setting.dmSize = sizeof(DEVMODE); - settingNum = 0; + monitorList = NULL; + curMonitor = &monitorList; while (EnumDisplayDevices(NULL, adapterNum++, &adapter, 0)) { @@ -121,111 +118,7 @@ void _glfwInitMonitors(void) curMonitor = _glfwCreateMonitor(curMonitor, &adapter, &monitor, &setting); } -} - -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) - _glfwLibrary.monitorListHead = _glfwDestroyMonitor(_glfwLibrary.monitorListHead); + + return monitorList; } diff --git a/src/win32_platform.h b/src/win32_platform.h index 0c4633c1..6c2f207d 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -49,7 +49,7 @@ #include #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 @@ -339,9 +339,8 @@ typedef struct _GLFWmonitorWin32 void _glfwInitTimer(void); // Monitor support -void _glfwInitMonitors(void); -void _glfwRefreshMonitors(void); -void _glfwTerminateMonitors(void); +_GLFWmonitor* _glfwCreateMonitors(void); +_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor); // Fullscreen support void _glfwSetVideoMode(int* width, int* height, diff --git a/src/x11_monitor.c b/src/x11_monitor.c index e827fb35..d22bcda7 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -77,9 +77,11 @@ _GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor) return result; } -void _glfwInitMonitors(void) +_GLFWmonitor* _glfwCreateMonitors(void) { - _glfwLibrary.monitorListHead = NULL; + _GLFWmonitor* monitorList; + + monitorList = NULL; if (_glfwLibrary.X11.RandR.available) { @@ -88,7 +90,7 @@ void _glfwInitMonitors(void) int outputIDX; _GLFWmonitor** curMonitor; - curMonitor = &_glfwLibrary.monitorListHead; + curMonitor = &monitorList; resources = XRRGetScreenResources(_glfwLibrary.X11.display, _glfwLibrary.X11.root); @@ -126,11 +128,7 @@ void _glfwInitMonitors(void) } #endif /*_GLFW_HAS_XRANDR*/ } -} - -void _glfwTerminateMonitors(void) -{ - while (_glfwLibrary.monitorListHead) - _glfwLibrary.monitorListHead = _glfwDestroyMonitor(_glfwLibrary.monitorListHead); + + return monitorList; } diff --git a/src/x11_platform.h b/src/x11_platform.h index 98bc7802..1163a53f 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -275,8 +275,8 @@ void _glfwInitJoysticks(void); void _glfwTerminateJoysticks(void); // Monitors -void _glfwInitMonitors(void); -void _glfwTerminateMonitors(void); +_GLFWmonitor* _glfwCreateMonitors(void); +_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor); // Unicode support long _glfwKeySym2Unicode(KeySym keysym); diff --git a/src/x11_window.c b/src/x11_window.c index 7ad34d05..9eb315fd 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1372,6 +1372,7 @@ static void processSingleEvent(void) { // Show XRandR that we really care XRRUpdateConfiguration(&event); + _glfwRefreshMonitors(); break; } } @@ -1429,18 +1430,18 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, if (!createWindow(window, wndconfig)) return GL_FALSE; - if (wndconfig->mode == GLFW_FULLSCREEN) - { #if defined(_GLFW_HAS_XRANDR) - // Request screen change notifications - if (_glfwLibrary.X11.RandR.available) - { - XRRSelectInput(_glfwLibrary.X11.display, - window->X11.handle, - RRScreenChangeNotifyMask); - } + // Request screen change notifications + if (_glfwLibrary.X11.RandR.available) + { + XRRSelectInput(_glfwLibrary.X11.display, + window->X11.handle, + RRScreenChangeNotifyMask); + } #endif /*_GLFW_HAS_XRANDR*/ + if (wndconfig->mode == GLFW_FULLSCREEN) + { enterFullscreenMode(window); } diff --git a/tests/events.c b/tests/events.c index 4bf4cbc1..a5a7bfa6 100644 --- a/tests/events.c +++ b/tests/events.c @@ -339,7 +339,7 @@ static void char_callback(GLFWwindow window, int character) void monitor_callback(GLFWmonitor monitor, int event) { - printf("%08x at %0.3f: Monitor %s %s", + printf("%08x at %0.3f: Monitor %s %s\n", counter++, glfwGetTime(), glfwGetMonitorString(monitor, GLFW_MONITOR_NAME),