From 577f9f9e6209e31d566213668363fc2e1fc8c5c2 Mon Sep 17 00:00:00 2001 From: Carsten Tewes Date: Sun, 20 Nov 2022 14:20:30 +0100 Subject: [PATCH 1/4] CHANGE: Added window API function glfwGetMonitorFromWindow. The function returns the monitor which has the largest area of intersection with the area of the specified window. --- include/GLFW/glfw3.h | 22 +++++++++++ src/window.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index d4b40dd4..96b623cb 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3890,6 +3890,28 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* window); */ GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); +/*! @brief Returns the monitor with the largest intersection area of the window + * + * This function returns the handle of the monitor which has the largest area of + * intersection with the area of the specified window + * + * @param[in] window The window to query. + * @return The monitor, or `NULL` + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref glfwGetWindowMonitor + * + * @since Added in version 3.4. + * + * @ingroup window + */ +GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is diff --git a/src/window.c b/src/window.c index 1c8519ff..90f2f30b 100644 --- a/src/window.c +++ b/src/window.c @@ -954,6 +954,94 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); } +typedef struct _rect { int x, y; int w, h; } _rect; + +#define RECT_INTERSECTS(ra, rb) \ + ((ra)->x <= ((rb)->x + (rb)->w) && ((ra)->x + (ra)->w) >= (rb)->x && \ + (ra)->y <= ((rb)->y + (rb)->h) && ((ra)->y + (ra)->h) >= (rb)->y) + +static _rect _get_intersection(_rect* ra, _rect* rb) +{ + _rect result = { 0, 0, 0, 0 }; + if (RECT_INTERSECTS(ra, rb)) + { + result.x = _glfw_max(ra->x, rb->x); + result.w = _glfw_min((ra->x + ra->w), (rb->x + rb->w)) - result.x; + result.y = _glfw_max(ra->y, rb->y); + result.h = _glfw_min((ra->y + ra->h), (rb->y + rb->h)) - result.y; + } + return result; +} + +GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window) +{ + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + GLFWmonitor* result = NULL; + + int monitorCount; + GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); + + if (monitorCount == 1) + { + result = monitors[0]; + } + else if (monitorCount > 1) + { + _rect windowRect; + glfwGetWindowPos(window, &windowRect.x, &windowRect.y); + int windowWidth, windowHeight; + glfwGetWindowSize(window, &windowWidth, &windowHeight); + windowRect.w = windowWidth; + windowRect.h = windowHeight; + + int windowFrameLeft, windowFrameTop, windowFrameRight, windowFrameBottom; + glfwGetWindowFrameSize(window, &windowFrameLeft, &windowFrameTop, + &windowFrameRight, &windowFrameBottom); + + windowRect.x -= windowFrameLeft; + windowRect.y -= windowFrameTop; + windowRect.w += windowFrameLeft + windowFrameRight; + windowRect.h += windowFrameTop + windowFrameBottom; + + _rect currentRect = { 0, 0, 0, 0 }; + _rect overlapRect = { 0, 0, 0, 0 }; + unsigned int currentDim, overlapDim; + int overlapMonitor = -1; + + int i; + for (i = 0; i < monitorCount; i++) + { + _rect monitorRect; + glfwGetMonitorPos(monitors[i], &monitorRect.x, &monitorRect.y); + + const GLFWvidmode* vidmode = glfwGetVideoMode(monitors[i]); + monitorRect.w = vidmode->width; + monitorRect.h = vidmode->height; + + currentRect = _get_intersection(&windowRect, &monitorRect); + + currentDim = currentRect.w * currentRect.h; + overlapDim = overlapRect.w * overlapRect.h; + + if (currentDim > 0 && currentDim > overlapDim) + { + overlapRect = currentRect; + overlapMonitor = i; + } + } + + if (overlapMonitor >= 0) + { + result = monitors[overlapMonitor]; + } + } + + return result; +} + GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; From 5cdc469a86dbcd148f7b4ea5d02d1287990229e7 Mon Sep 17 00:00:00 2001 From: Carsten Tewes Date: Sun, 20 Nov 2022 15:14:28 +0100 Subject: [PATCH 2/4] CHANGE: Updated changelog and guide doc --- README.md | 2 ++ docs/window.dox | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/README.md b/README.md index 8b4a1546..70bd9095 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,8 @@ information on what to include when reporting a bug. ## Changelog + - Added `glfwGetMonitorFromWindow` function to query the monitor where the + largest part of a window is currently located (#1699) - Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958) - Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to diff --git a/docs/window.dox b/docs/window.dox index 3cec6358..f58c1df2 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -907,6 +907,19 @@ glfwSetWindowIcon(window, 0, NULL); @endcode +@subsection window_monitor_from Window monitor + +Windows are always located on one or more monitors. You can get the +handle for the monitor were the biggest part of a specified window is +currently located with @ref glfwGetMonitorFromWindow + +@code +GLFWmonitor* monitor = glfwGetMonitorFromWindow(window); +@endcode + +This monitor handle is one of those returned by @ref glfwGetMonitors. + + @subsection window_monitor Window monitor Full screen windows are associated with a specific monitor. You can get the From e01fb0f6de7879f8f98ae412367742b40569268f Mon Sep 17 00:00:00 2001 From: Carsten Tewes Date: Sun, 20 Nov 2022 15:46:52 +0100 Subject: [PATCH 3/4] CHANGE: Changed code to alllow ISO C90 compilation, why do we compile using a 32 years old standard with has been replaced more than once --- src/window.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/window.c b/src/window.c index 90f2f30b..6d4561b3 100644 --- a/src/window.c +++ b/src/window.c @@ -974,15 +974,30 @@ static _rect _get_intersection(_rect* ra, _rect* rb) } GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window) -{ +{ + GLFWmonitor* result = NULL; + + int monitorCount; + GLFWmonitor** monitors; + const GLFWvidmode* vidmode; + + int windowWidth, windowHeight; + int windowFrameLeft, windowFrameTop, windowFrameRight, windowFrameBottom; + + unsigned int currentDim, overlapDim; + int overlapMonitor; + int i; + + _rect windowRect; + _rect monitorRect; + _rect currentRect = { 0, 0, 0, 0 }; + _rect overlapRect = { 0, 0, 0, 0 }; + assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - GLFWmonitor* result = NULL; - - int monitorCount; - GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); + monitors = glfwGetMonitors(&monitorCount); if (monitorCount == 1) { @@ -990,14 +1005,11 @@ GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window) } else if (monitorCount > 1) { - _rect windowRect; glfwGetWindowPos(window, &windowRect.x, &windowRect.y); - int windowWidth, windowHeight; glfwGetWindowSize(window, &windowWidth, &windowHeight); windowRect.w = windowWidth; windowRect.h = windowHeight; - int windowFrameLeft, windowFrameTop, windowFrameRight, windowFrameBottom; glfwGetWindowFrameSize(window, &windowFrameLeft, &windowFrameTop, &windowFrameRight, &windowFrameBottom); @@ -1006,18 +1018,13 @@ GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window) windowRect.w += windowFrameLeft + windowFrameRight; windowRect.h += windowFrameTop + windowFrameBottom; - _rect currentRect = { 0, 0, 0, 0 }; - _rect overlapRect = { 0, 0, 0, 0 }; - unsigned int currentDim, overlapDim; - int overlapMonitor = -1; + overlapMonitor = -1; - int i; for (i = 0; i < monitorCount; i++) { - _rect monitorRect; glfwGetMonitorPos(monitors[i], &monitorRect.x, &monitorRect.y); - const GLFWvidmode* vidmode = glfwGetVideoMode(monitors[i]); + vidmode = glfwGetVideoMode(monitors[i]); monitorRect.w = vidmode->width; monitorRect.h = vidmode->height; From 47d2e58e485b3fa77e6aa1c4e213444e91bc1c20 Mon Sep 17 00:00:00 2001 From: Carsten Tewes Date: Sun, 20 Nov 2022 17:05:36 +0100 Subject: [PATCH 4/4] CHANGE: Elimated variable overhead in glfwGetMonitorFromWindow. --- src/window.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/window.c b/src/window.c index 6d4561b3..96a6ec06 100644 --- a/src/window.c +++ b/src/window.c @@ -981,16 +981,12 @@ GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window) GLFWmonitor** monitors; const GLFWvidmode* vidmode; - int windowWidth, windowHeight; - int windowFrameLeft, windowFrameTop, windowFrameRight, windowFrameBottom; - unsigned int currentDim, overlapDim; - int overlapMonitor; - int i; + int overlapMonitor, i; _rect windowRect; _rect monitorRect; - _rect currentRect = { 0, 0, 0, 0 }; + _rect scratchRect = { 0, 0, 0, 0 }; _rect overlapRect = { 0, 0, 0, 0 }; assert(window != NULL); @@ -1006,17 +1002,15 @@ GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window) else if (monitorCount > 1) { glfwGetWindowPos(window, &windowRect.x, &windowRect.y); - glfwGetWindowSize(window, &windowWidth, &windowHeight); - windowRect.w = windowWidth; - windowRect.h = windowHeight; + glfwGetWindowSize(window, &windowRect.w, &windowRect.h); - glfwGetWindowFrameSize(window, &windowFrameLeft, &windowFrameTop, - &windowFrameRight, &windowFrameBottom); + glfwGetWindowFrameSize(window, &scratchRect.x, &scratchRect.y, + &scratchRect.w, &scratchRect.h); - windowRect.x -= windowFrameLeft; - windowRect.y -= windowFrameTop; - windowRect.w += windowFrameLeft + windowFrameRight; - windowRect.h += windowFrameTop + windowFrameBottom; + windowRect.x -= scratchRect.x; + windowRect.y -= scratchRect.y; + windowRect.w += scratchRect.x + scratchRect.w; + windowRect.h += scratchRect.y + scratchRect.h; overlapMonitor = -1; @@ -1028,14 +1022,14 @@ GLFWAPI GLFWmonitor* glfwGetMonitorFromWindow(GLFWwindow* window) monitorRect.w = vidmode->width; monitorRect.h = vidmode->height; - currentRect = _get_intersection(&windowRect, &monitorRect); + scratchRect = _get_intersection(&windowRect, &monitorRect); - currentDim = currentRect.w * currentRect.h; + currentDim = scratchRect.w * scratchRect.h; overlapDim = overlapRect.w * overlapRect.h; if (currentDim > 0 && currentDim > overlapDim) { - overlapRect = currentRect; + overlapRect = scratchRect; overlapMonitor = i; } }