From c8d4bae93a5345a9cc5a7d722a6c4b64d3feae0e Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 15 Sep 2014 18:18:51 +0200 Subject: [PATCH] Added glfwGetMirroredMonitor. --- README.md | 1 + include/GLFW/glfw3.h | 22 ++++++++++++++++++++++ src/cocoa_monitor.m | 4 ++-- src/init.c | 2 +- src/internal.h | 8 +++++--- src/monitor.c | 43 +++++++++++++++++++++++++++++-------------- src/win32_monitor.c | 15 +++++++++++---- src/wl_monitor.c | 4 ++-- src/x11_monitor.c | 17 +++++++++-------- tests/modes.c | 14 +++++++++++--- 10 files changed, 93 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 933076aba..d85d52c06 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ GLFW bundles a number of dependencies in the `deps/` directory. - Added `glfwSetCharModsCallback` for receiving character events with modifiers - Added `glfwGetWindowFrameSize` for retrieving the size of the frame around the client area of a window + - Added `glfwGetMirroredMonitor` for discovering monitor mirroring sets - Added `GLFW_AUTO_ICONIFY` for controlling whether full screen windows automatically iconify (and restore the previous video mode) on focus loss - Added `GLFW_DONT_CARE` for indicating that any value is acceptable diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 2cba521e8..efd8e8da1 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1279,6 +1279,28 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count); */ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void); +/*! @brief Returns the monitor mirrored by the specified monitor. + * + * This function returns the monitor that the specified monitor mirrors. + * + * @param[in] monitor The monitor to query. + * @return The monitor mirrored by the specified monitor, or `NULL` if the + * monitor does not mirror another monitor or an [error](@ref error_handling) + * occurred. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_monitors + * @sa glfwGetMonitors + * + * @par History + * Added in GLFW 3.1. + * + * @ingroup monitor + */ +GLFWAPI GLFWmonitor* glfwGetMirroredMonitor(GLFWmonitor* monitor); + /*! @brief Returns the position of the monitor's viewport on the virtual screen. * * This function returns the position, in screen coordinates, of the upper-left diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index db3cf7145..f9d5435a5 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -273,7 +273,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) const CGSize size = CGDisplayScreenSize(displays[i]); char* name = getDisplayName(displays[i]); - monitors[found] = _glfwAllocMonitor(name, size.width, size.height); + monitors[found] = _glfwCreateMonitor(name, size.width, size.height); monitors[found]->ns.displayID = displays[i]; free(name); @@ -295,7 +295,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) found++; else { - _glfwFreeMonitor(monitors[found]); + _glfwDestroyMonitor(monitors[found]); monitors[found] = NULL; } } diff --git a/src/init.c b/src/init.c index 4a044ed06..a52d8bec1 100644 --- a/src/init.c +++ b/src/init.c @@ -166,7 +166,7 @@ GLFWAPI void glfwTerminate(void) _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp); } - _glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount); + _glfwDestroyMonitors(_glfw.monitors, _glfw.monitorCount); _glfw.monitors = NULL; _glfw.monitorCount = 0; diff --git a/src/internal.h b/src/internal.h index 26fcf2a58..e3c84b73f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -286,6 +286,7 @@ struct _GLFWmonitor // Physical dimensions in millimeters. int widthMM, heightMM; + int mirroring; GLFWvidmode* modes; int modeCount; @@ -859,18 +860,19 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp); * @param[in] name The name of the monitor. * @param[in] widthMM The width, in mm, of the monitor's display area. * @param[in] heightMM The height, in mm, of the monitor's display area. + * @param[in] mirroring The monitor this monitor is mirroring, or `NULL`. * @return The newly created object. * @ingroup utility */ -_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM); +_GLFWmonitor* _glfwCreateMonitor(const char* name, int widthMM, int heightMM, int mirroring); /*! @brief Frees a monitor object and any data associated with it. * @ingroup utility */ -void _glfwFreeMonitor(_GLFWmonitor* monitor); +void _glfwDestroyMonitor(_GLFWmonitor* monitor); /*! @ingroup utility */ -void _glfwFreeMonitors(_GLFWmonitor** monitors, int count); +void _glfwDestroyMonitors(_GLFWmonitor** monitors, int count); #endif // _internal_h_ diff --git a/src/monitor.c b/src/monitor.c index ad353532f..39df02335 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -100,7 +100,8 @@ void _glfwInputMonitorChange(void) { if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j])) { - _glfwFreeMonitor(_glfw.monitors[i]); + monitors[j]->mirroring = _glfw.monitors[i]->mirroring; + _glfwDestroyMonitor(_glfw.monitors[i]); _glfw.monitors[i] = monitors[j]; break; } @@ -154,7 +155,7 @@ void _glfwInputMonitorChange(void) _glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED); } - _glfwFreeMonitors(monitors, monitorCount); + _glfwDestroyMonitors(monitors, monitorCount); } @@ -162,17 +163,20 @@ void _glfwInputMonitorChange(void) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM) +_GLFWmonitor* _glfwCreateMonitor(const char* name, + int widthMM, int heightMM, + int mirroring) { _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor)); monitor->name = strdup(name); monitor->widthMM = widthMM; monitor->heightMM = heightMM; + monitor->mirroring = mirroring; return monitor; } -void _glfwFreeMonitor(_GLFWmonitor* monitor) +void _glfwDestroyMonitor(_GLFWmonitor* monitor) { if (monitor == NULL) return; @@ -185,6 +189,16 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor) free(monitor); } +void _glfwDestroyMonitors(_GLFWmonitor** monitors, int count) +{ + int i; + + for (i = 0; i < count; i++) + _glfwDestroyMonitor(monitors[i]); + + free(monitors); +} + void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size) { ramp->red = calloc(size, sizeof(unsigned short)); @@ -202,16 +216,6 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp) memset(ramp, 0, sizeof(GLFWgammaramp)); } -void _glfwFreeMonitors(_GLFWmonitor** monitors, int count) -{ - int i; - - for (i = 0; i < count; i++) - _glfwFreeMonitor(monitors[i]); - - free(monitors); -} - const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) { @@ -307,6 +311,17 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void) return (GLFWmonitor*) _glfw.monitors[0]; } +GLFWAPI GLFWmonitor* glfwGetMirroredMonitor(GLFWmonitor* handle) +{ + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (monitor->mirroring == -1) + return NULL; + + return (GLFWmonitor*) _glfw.monitors[monitor->mirroring]; +} + GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 0690dc1fc..f97dd5afb 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -103,7 +103,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor) _GLFWmonitor** _glfwPlatformGetMonitors(int* count) { - int size = 0, found = 0; + int size = 0, found = 0, primaryIndex = 0, mirroring; _GLFWmonitor** monitors = NULL; DWORD adapterIndex, displayIndex; @@ -140,6 +140,9 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size); } + if (displayIndex == 0) + mirroring = -1; + name = _glfwCreateUTF8FromWideString(display.DeviceString); if (!name) { @@ -150,13 +153,17 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL); - monitors[found] = _glfwAllocMonitor(name, - GetDeviceCaps(dc, HORZSIZE), - GetDeviceCaps(dc, VERTSIZE)); + monitors[found] = _glfwCreateMonitor(name, + GetDeviceCaps(dc, HORZSIZE), + GetDeviceCaps(dc, VERTSIZE), + mirroring); DeleteDC(dc); free(name); + if (displayIndex == 0) + mirroring = found; + wcscpy(monitors[found]->win32.adapterName, adapter.DeviceName); wcscpy(monitors[found]->win32.displayName, display.DeviceName); diff --git a/src/wl_monitor.c b/src/wl_monitor.c index fbcefd38d..f3d2177a2 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -127,7 +127,7 @@ void _glfwAddOutput(uint32_t name, uint32_t version) return; } - monitor = _glfwAllocMonitor(name_str, 0, 0); + monitor = _glfwCreateMonitor(name_str, 0, 0); output = wl_registry_bind(_glfw.wl.registry, name, @@ -135,7 +135,7 @@ void _glfwAddOutput(uint32_t name, uint32_t version) 2); if (!output) { - _glfwFreeMonitor(monitor); + _glfwDestroyMonitor(monitor); return; } diff --git a/src/x11_monitor.c b/src/x11_monitor.c index fb6b0ef63..013264233 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -238,9 +238,9 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size); } - monitors[found] = _glfwAllocMonitor(oi->name, - oi->mm_width, - oi->mm_height); + monitors[found] = _glfwCreateMonitor(oi->name, + oi->mm_width, oi->mm_height, + -1); monitors[found]->x11.output = ci->outputs[j]; monitors[found]->x11.crtc = oi->crtc; @@ -284,11 +284,12 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) if (!monitors) { monitors = calloc(1, sizeof(_GLFWmonitor*)); - monitors[0] = _glfwAllocMonitor("Display", - DisplayWidthMM(_glfw.x11.display, - _glfw.x11.screen), - DisplayHeightMM(_glfw.x11.display, - _glfw.x11.screen)); + monitors[0] = _glfwCreateMonitor("Display", + DisplayWidthMM(_glfw.x11.display, + _glfw.x11.screen), + DisplayHeightMM(_glfw.x11.display, + _glfw.x11.screen), + -1); found = 1; } diff --git a/tests/modes.c b/tests/modes.c index 58067e3ea..442dce292 100644 --- a/tests/modes.c +++ b/tests/modes.c @@ -83,15 +83,23 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, static void list_modes(GLFWmonitor* monitor) { int count, x, y, widthMM, heightMM, dpi, i; + GLFWmonitor* mirrored; const GLFWvidmode* mode = glfwGetVideoMode(monitor); const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count); glfwGetMonitorPos(monitor, &x, &y); glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM); - printf("Name: %s (%s)\n", - glfwGetMonitorName(monitor), - glfwGetPrimaryMonitor() == monitor ? "primary" : "secondary"); + printf("Name: %s", glfwGetMonitorName(monitor)); + + mirrored = glfwGetMirroredMonitor(monitor); + if (mirrored) + printf(" (mirroring %s)\n", glfwGetMonitorName(mirrored)); + else if (glfwGetPrimaryMonitor() == monitor) + printf(" (primary)\n"); + else + printf(" (secondary)\n"); + printf("Current mode: %s\n", format_mode(mode)); printf("Virtual position: %i %i\n", x, y);