From be295ccbea6a9b1cfdbe0dc700fe04d9be202879 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Thu, 6 Apr 2017 16:48:08 -0300 Subject: [PATCH] Add glfwGetMonitorWorkarea This function retrieves the work area rectangle of the specified monitor. Related to #920. Closes #989. --- README.md | 1 + examples/simple.c | 3 +++ include/GLFW/glfw3.h | 25 +++++++++++++++++++++++++ src/cocoa_monitor.m | 18 ++++++++++++++++++ src/internal.h | 1 + src/monitor.c | 19 +++++++++++++++++++ src/null_monitor.c | 4 ++++ src/win32_monitor.c | 31 +++++++++++++++++++++++++++++++ src/x11_init.c | 2 ++ src/x11_monitor.c | 16 ++++++++++++++++ src/x11_platform.h | 1 + 11 files changed, 121 insertions(+) diff --git a/README.md b/README.md index 382b5b5d..af7a3b1a 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ information on what to include when reporting a bug. (#235,#439,#677,#845,#898) - Added `glfwRequestWindowAttention` function for requesting attention from the user (#732,#988) +- Added `glfwGetMonitorWorkarea` function for querying the monitor work area - Added `glfwGetKeyScancode` function that allows retrieving platform dependent scancodes for keys (#830) - Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for diff --git a/examples/simple.c b/examples/simple.c index 7752a365..ce9c22d7 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -79,6 +79,7 @@ int main(void) GLFWwindow* window; GLuint vertex_buffer, vertex_shader, fragment_shader, program; GLint mvp_location, vpos_location, vcol_location; + int workarea_x, workarea_y, workarea_width, workarea_height; glfwSetErrorCallback(error_callback); @@ -131,6 +132,8 @@ int main(void) glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (void*) (sizeof(float) * 2)); + glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &workarea_x, &workarea_y, &workarea_width, &workarea_height); + printf("Monitor work area: %d, %d, %d, %d\n", workarea_x, workarea_y, workarea_width, workarea_height); while (!glfwWindowShouldClose(window)) { float ratio; diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 57d5c9c0..3019b951 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1931,6 +1931,31 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void); */ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); +/*! @brief Returns the work area of the monitor. + * + * This function returns the position, in screen coordinates, of the upper-left + * corner of the specified monitor. + * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. + * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height); + /*! @brief Returns the physical size of the monitor. * * This function returns the size, in millimetres, of the display area of the diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 5767d24f..736a9053 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -408,6 +408,24 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, *yscale = (float) (pixels.size.height / points.size.height); } +void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height) +{ + NSScreen *resultScreen; + for (NSScreen *screen in [NSScreen screens]) { + if ([[[screen deviceDescription] valueForKey:@"NSScreenNumber"] intValue] == monitor->ns.displayID) { + resultScreen = screen; + break; + } + } + + NSRect frameRect = [[NSScreen resultScreen] visibleFrame]; + + *xpos = NSMinX(frameRect); + *ypos = NSMinY(frameRect); + *width = NSMaxX(frameRect); + *height = NSMaxY(frameRect); +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { CFArrayRef modes; diff --git a/src/internal.h b/src/internal.h index abba5baf..3d5e22f7 100644 --- a/src/internal.h +++ b/src/internal.h @@ -612,6 +612,7 @@ void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor); void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos); void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height); GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count); void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode); GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp); diff --git a/src/monitor.c b/src/monitor.c index 0ab865e3..869fdfb7 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -330,6 +330,25 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) _glfwPlatformGetMonitorPos(monitor, xpos, ypos); } +GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, int* xpos, int* ypos, int* width, int* height) +{ + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + + if (xpos) + *xpos = 0; + if (ypos) + *ypos = 0; + if (width) + *width = 0; + if (width) + *width = 0; + + _GLFW_REQUIRE_INIT(); + + _glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height); +} + GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; diff --git a/src/null_monitor.c b/src/null_monitor.c index 45c4a10f..99797375 100644 --- a/src/null_monitor.c +++ b/src/null_monitor.c @@ -49,6 +49,10 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, *yscale = 1.f; } +void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height) +{ +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { return NULL; diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 07b3614b..a8fb4fc7 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -361,6 +361,37 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale); } +static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + RECT *workarea = (RECT *)dwData; + MONITORINFO monitorInfo; + monitorInfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(hMonitor, &monitorInfo); + workarea->left = monitorInfo.rcWork.left; + workarea->top = monitorInfo.rcWork.top; + workarea->right = monitorInfo.rcWork.right; + workarea->bottom = monitorInfo.rcWork.bottom; + return TRUE; +} + +void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height) +{ + HDC dc; + RECT workarea; + + dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL); + + if (!EnumDisplayMonitors(dc, NULL, MonitorEnumProc, (LPARAM)&workarea)) + return; + + DeleteDC(dc); + + *xpos = workarea.left; + *ypos = workarea.top; + *width = workarea.right; + *height = workarea.bottom; +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { int modeIndex = 0, size = 0; diff --git a/src/x11_init.c b/src/x11_init.c index e3e3ad51..f1e72614 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -446,6 +446,8 @@ static void detectEWMH(void) getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE"); _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL = getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL"); + _glfw.x11.NET_WORKAREA = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA"); _glfw.x11.NET_ACTIVE_WINDOW = getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW"); _glfw.x11.NET_FRAME_EXTENTS = diff --git a/src/x11_monitor.c b/src/x11_monitor.c index 240e9fb0..d0aa9f9c 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -342,6 +342,22 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, *yscale = _glfw.x11.contentScaleY; } +void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height) +{ + if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) + { + Atom* extents = NULL; + + _glfwGetWindowPropertyX11(_glfw.x11.root, _glfw.x11.NET_WORKAREA, XA_CARDINAL, (unsigned char**) &extents); + + *xpos = extents[0]; + *ypos = extents[1]; + *width = extents[2]; + *height = extents[3]; + XFree(extents); + } +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { GLFWvidmode* result; diff --git a/src/x11_platform.h b/src/x11_platform.h index c37c740e..153daee1 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -259,6 +259,7 @@ typedef struct _GLFWlibraryX11 Atom NET_WM_FULLSCREEN_MONITORS; Atom NET_WM_WINDOW_OPACITY; Atom NET_WM_CM_Sx; + Atom NET_WORKAREA; Atom NET_ACTIVE_WINDOW; Atom NET_FRAME_EXTENTS; Atom NET_REQUEST_FRAME_EXTENTS;