diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index df6e26f3..979c0650 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -529,15 +529,14 @@ GLFWAPI const char* glfwErrorString(int error); GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun); /* Monitor functions */ +GLFWAPI GLFWmonitor* glfwGetMonitors(int* count); +GLFWAPI GLFWmonitor glfwGetPrimaryMonitor(void); GLFWAPI int glfwGetMonitorParam(GLFWmonitor monitor, int param); GLFWAPI const char* glfwGetMonitorString(GLFWmonitor monitor, int param); GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor monitor, void* pointer); GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor monitor); GLFWAPI void glfwSetMonitorCallback(GLFWmonitorfun cbfun); -/* Monitor discovery */ -GLFWAPI GLFWmonitor glfwGetNextMonitor(GLFWmonitor iterator); - /* Video mode functions */ GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor monitor, int* count); GLFWAPI void glfwGetVideoMode(GLFWmonitor monitor, GLFWvidmode* mode); diff --git a/src/init.c b/src/init.c index d0882c49..453c2c66 100644 --- a/src/init.c +++ b/src/init.c @@ -130,6 +130,13 @@ GLFWAPI int glfwInit(void) return GL_FALSE; } + _glfwLibrary.monitors = _glfwPlatformGetMonitors(&_glfwLibrary.monitorCount); + if (!_glfwLibrary.monitors) + { + _glfwPlatformTerminate(); + return GL_FALSE; + } + atexit(glfwTerminate); _glfwInitialized = GL_TRUE; @@ -151,6 +158,8 @@ GLFWAPI void glfwTerminate(void) while (_glfwLibrary.windowListHead) glfwDestroyWindow(_glfwLibrary.windowListHead); + _glfwDestroyMonitors(); + if (!_glfwPlatformTerminate()) return; diff --git a/src/internal.h b/src/internal.h index 9cf29690..4acebe95 100755 --- a/src/internal.h +++ b/src/internal.h @@ -206,8 +206,6 @@ struct _GLFWwindow //------------------------------------------------------------------------ struct _GLFWmonitor { - struct _GLFWmonitor* next; - void* userPointer; char* name; @@ -234,7 +232,9 @@ struct _GLFWlibrary _GLFWwindow* windowListHead; _GLFWwindow* activeWindow; _GLFWwindow* cursorLockWindow; - _GLFWmonitor* monitorListHead; + + _GLFWmonitor** monitors; + int monitorCount; GLFWwindowsizefun windowSizeCallback; GLFWwindowclosefun windowCloseCallback; @@ -286,6 +286,10 @@ void _glfwPlatformDisableSystemKeys(_GLFWwindow* window); void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y); void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); +// Monitor support +_GLFWmonitor** _glfwPlatformGetMonitors(int* count); +void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor); + // Video mode support GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count); 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 _glfwInputCursorEnter(_GLFWwindow* window, int entered); +// Monitor event notification (monitor.c) +void _glfwInputMonitorChange(void); + //======================================================================== // Prototypes for internal utility functions @@ -385,8 +392,10 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig); GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig); // 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_ diff --git a/src/monitor.c b/src/monitor.c index e94da20e..65a41cbb 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -31,6 +31,7 @@ #include "internal.h" #include +#include ////////////////////////////////////////////////////////////////////////// @@ -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; + if (monitor == NULL) + return; - newMonitorList = _glfwCreateMonitors(); - curNewMonitor = newMonitorList; - curOldMonitor = _glfwLibrary.monitorListHead; + _glfwPlatformDestroyMonitor(monitor); - while (_glfwLibrary.monitorCallback && (curNewMonitor || curOldMonitor)) + free(monitor->modes); + free(monitor->name); + free(monitor); +} + + +//======================================================================== +// Enumerate monitors and notify user of changes +//======================================================================== + +void _glfwInputMonitorChange(void) +{ + int i, j, monitorCount; + _GLFWmonitor** monitors; + + monitors = _glfwPlatformGetMonitors(&monitorCount); + + for (i = 0; i < monitorCount; i++) { - _GLFWmonitor* lookAheadOldMonitor; - _GLFWmonitor* lookAheadNewMonitor; - - if (curOldMonitor && curNewMonitor && !strcmp(curOldMonitor->name, curOldMonitor->name)) + for (j = 0; j < _glfwLibrary.monitorCount; j++) { - curNewMonitor = curNewMonitor->next; - curOldMonitor = curOldMonitor->next; - continue; - } + if (_glfwLibrary.monitors[j] == NULL) + 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)) + 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) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); return NULL; } - if (iterator == NULL) - result = _glfwLibrary.monitorListHead; - else - result = iterator->next; + if (count == NULL) + { + _glfwSetError(GLFW_INVALID_VALUE, NULL); + return NULL; + } - return result; + *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 _glfwLibrary.monitors[0]; } diff --git a/src/win32_fullscreen.c b/src/win32_fullscreen.c index eb9c0c70..4eb65cb0 100644 --- a/src/win32_fullscreen.c +++ b/src/win32_fullscreen.c @@ -185,16 +185,8 @@ void _glfwRestoreVideoMode(void) GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { - int deviceModeIndex = 0, count = 0; + int modeIndex = 0, count = 0; 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; @@ -207,10 +199,10 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) ZeroMemory(&dm, sizeof(DEVMODE)); dm.dmSize = sizeof(DEVMODE); - if (!EnumDisplaySettings(deviceName, deviceModeIndex, &dm)) + if (!EnumDisplaySettings(monitor->Win32.name, modeIndex, &dm)) break; - deviceModeIndex++; + modeIndex++; if (dm.dmBitsPerPel < 15) { @@ -262,7 +254,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) (*found)++; } - free(deviceName); return result; } @@ -274,19 +265,11 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) { 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)); dm.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(deviceName, ENUM_REGISTRY_SETTINGS, &dm); + EnumDisplaySettings(monitor->Win32.name, ENUM_REGISTRY_SETTINGS, &dm); mode->width = dm.dmPelsWidth; mode->height = dm.dmPelsHeight; diff --git a/src/win32_init.c b/src/win32_init.c index a9c7b7af..41444b97 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -178,8 +178,6 @@ int _glfwPlatformInit(void) _glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp); _glfwLibrary.currentRamp = _glfwLibrary.originalRamp; - _glfwInitMonitors(); - _glfwInitTimer(); return GL_TRUE; @@ -196,8 +194,6 @@ int _glfwPlatformTerminate(void) if (_glfwLibrary.rampChanged) _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp); - _glfwTerminateMonitors(); - if (_glfwLibrary.Win32.classAtom) { UnregisterClass(_GLFW_WNDCLASSNAME, _glfwLibrary.Win32.instance); diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 2aba1ff1..f434a9f9 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -32,6 +32,7 @@ #include #include +#include // The MinGW package for Debian lacks this #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; + int size = 0, found = 0; + _GLFWmonitor** monitors = NULL; + DWORD adapterIndex = 0; - *current = malloc(sizeof(_GLFWmonitor)); - memset(*current, 0, sizeof(_GLFWmonitor)); + for (;;) + { + DISPLAY_DEVICE adapter; + DWORD monitorIndex = 0; - dc = CreateDC(L"DISPLAY", monitor->DeviceString, NULL, NULL); + ZeroMemory(&adapter, sizeof(DISPLAY_DEVICE)); + adapter.cb = sizeof(DISPLAY_DEVICE); - (*current)->physicalWidth = GetDeviceCaps(dc, HORZSIZE); - (*current)->physicalHeight = GetDeviceCaps(dc, VERTSIZE); + if (!EnumDisplayDevices(NULL, adapterIndex, &adapter, 0)) + break; - DeleteDC(dc); + adapterIndex++; - (*current)->name = _glfwCreateUTF8FromWideString(monitor->DeviceName); + if ((adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) || + !(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) + { + continue; + } - (*current)->screenX = setting->dmPosition.x; - (*current)->screenY = setting->dmPosition.y; + for (;;) + { + DISPLAY_DEVICE monitor; + DEVMODE settings; + const char* name; + HDC dc; - (*current)->Win32.name = _glfwCreateUTF8FromWideString(adapter->DeviceName); + ZeroMemory(&monitor, sizeof(DISPLAY_DEVICE)); + monitor.cb = sizeof(DISPLAY_DEVICE); - return &((*current)->next); + 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++; + } + } + + *count = found; + return monitors; } @@ -84,55 +153,8 @@ _GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current, // Destroy a monitor struct //======================================================================== -_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor) +void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor) { - _GLFWmonitor* result; - - result = monitor->next; - 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; } diff --git a/src/win32_platform.h b/src/win32_platform.h index aff0dc18..4f8642c7 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -219,7 +219,7 @@ typedef struct _GLFWlibraryWin32 //------------------------------------------------------------------------ typedef struct _GLFWmonitorWin32 { - char* name; + WCHAR* name; } _GLFWmonitorWin32; @@ -244,10 +244,6 @@ char* _glfwCreateUTF8FromWideString(const WCHAR* source); // Time void _glfwInitTimer(void); -// Monitor support -_GLFWmonitor* _glfwCreateMonitors(void); -_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor); - // OpenGL support int _glfwCreateContext(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, diff --git a/src/win32_window.c b/src/win32_window.c index a27687f2..9b84b9be 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -670,7 +670,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { if (DBT_DEVNODES_CHANGED == wParam) { - _glfwRefreshMonitors(); + _glfwInputMonitorChange(); return TRUE; } break; diff --git a/src/x11_init.c b/src/x11_init.c index 4f5ab060..666866de 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -651,8 +651,6 @@ int _glfwPlatformInit(void) if (!_glfwInitJoysticks()) return GL_FALSE; - _glfwInitMonitors(); - // Start the timer _glfwInitTimer(); @@ -676,8 +674,6 @@ int _glfwPlatformTerminate(void) terminateDisplay(); - _glfwTerminateMonitors(); - _glfwTerminateJoysticks(); _glfwTerminateOpenGL(); diff --git a/src/x11_monitor.c b/src/x11_monitor.c index bf2b8155..bab34445 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -34,111 +34,83 @@ #include -//======================================================================== -// 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 ////// ////////////////////////////////////////////////////////////////////////// -//======================================================================== -// 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 //======================================================================== -_GLFWmonitor* _glfwCreateMonitors(void) +_GLFWmonitor** _glfwPlatformGetMonitors(int* count) { - _GLFWmonitor* monitorList = NULL; + int found = 0; + _GLFWmonitor** monitors = NULL; if (_glfwLibrary.X11.RandR.available) { #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); - for (oi = 0; oi < resources->noutput; oi++) + monitors = (_GLFWmonitor**) calloc(sr->noutput, sizeof(_GLFWmonitor*)); + if (!monitors) { - // physical device - XRROutputInfo* outputInfo = NULL; - // logical surface - XRRCrtcInfo* crtcInfo = NULL; + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); + return NULL; + } - outputInfo = XRRGetOutputInfo(_glfwLibrary.X11.display, - resources, - resources->outputs[oi]); + for (i = 0; i < sr->noutput; i++) + { + XRROutputInfo* oi; + XRRCrtcInfo* ci; - if (outputInfo->connection == RR_Connected) + oi = XRRGetOutputInfo(_glfwLibrary.X11.display, sr, sr->outputs[i]); + if (oi->connection != RR_Connected) { - 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); + XRRFreeOutputInfo(oi); + continue; } + + ci = XRRGetCrtcInfo(_glfwLibrary.X11.display, sr, oi->crtc); + + monitors[found] = _glfwCreateMonitor(oi->name, + oi->mm_width, oi->mm_height, + ci->x, ci->y); + + XRRFreeCrtcInfo(ci); + + if (!monitors[found]) + { + // TODO: wat + return NULL; + } + + // This is retained until the monitor object is destroyed + monitors[found]->X11.output = oi; + + found++; } #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*/ } diff --git a/src/x11_platform.h b/src/x11_platform.h index 96f162f1..b864721a 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -325,10 +325,6 @@ void _glfwRestoreVideoMode(void); int _glfwInitJoysticks(void); void _glfwTerminateJoysticks(void); -// Monitors -_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 fae26e67..bea0c968 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -810,7 +810,7 @@ static void processEvent(XEvent *event) case RRScreenChangeNotify: { XRRUpdateConfiguration(event); - _glfwRefreshMonitors(); + _glfwInputMonitorChange(); break; } } diff --git a/tests/gamma.c b/tests/gamma.c index 37a78926..9e380783 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -120,7 +120,7 @@ int main(int argc, char** argv) if (mode == GLFW_FULLSCREEN) { GLFWvidmode mode; - glfwGetVideoMode(glfwGetNextMonitor(NULL), &mode); + glfwGetVideoMode(glfwGetPrimaryMonitor(), &mode); width = mode.width; height = mode.height; } diff --git a/tests/iconify.c b/tests/iconify.c index 845bfea3..615db16b 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -101,7 +101,7 @@ int main(int argc, char** argv) if (mode == GLFW_FULLSCREEN) { GLFWvidmode current_mode; - glfwGetVideoMode(glfwGetNextMonitor(NULL), ¤t_mode); + glfwGetVideoMode(glfwGetPrimaryMonitor(), ¤t_mode); width = current_mode.width; height = current_mode.height; } diff --git a/tests/modes.c b/tests/modes.c index 98837884..f204e19f 100644 --- a/tests/modes.c +++ b/tests/modes.c @@ -199,8 +199,8 @@ static void test_modes(GLFWmonitor monitor) 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) { @@ -226,12 +226,14 @@ int main(int argc, char** argv) if (!glfwInit()) exit(EXIT_FAILURE); - while ((monitor = glfwGetNextMonitor(monitor))) + monitors = glfwGetMonitors(&count); + + for (i = 0; i < count; i++) { if (mode == LIST_MODE) - list_modes(monitor); + list_modes(monitors[i]); else if (mode == TEST_MODE) - test_modes(monitor); + test_modes(monitors[i]); } exit(EXIT_SUCCESS);