Add glfwGetMonitorWorkarea
This function retrieves the work area rectangle of the specified
monitor.
Related to #920.
Closes #989.
diff --git a/README.md b/README.md
index 382b5b5..af7a3b1 100644
--- a/README.md
+++ b/README.md
@@ -141,6 +141,7 @@
(#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 7752a36..ce9c22d 100644
--- a/examples/simple.c
+++ b/examples/simple.c
@@ -79,6 +79,7 @@
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 @@
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 57d5c9c..3019b95 100644
--- a/include/GLFW/glfw3.h
+++ b/include/GLFW/glfw3.h
@@ -1931,6 +1931,31 @@
*/
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 5767d24..736a905 100644
--- a/src/cocoa_monitor.m
+++ b/src/cocoa_monitor.m
@@ -408,6 +408,24 @@
*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 abba5ba..3d5e22f 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -612,6 +612,7 @@
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 0ab865e..869fdfb 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -330,6 +330,25 @@
_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 45c4a10..9979737 100644
--- a/src/null_monitor.c
+++ b/src/null_monitor.c
@@ -49,6 +49,10 @@
*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 07b3614..a8fb4fc 100644
--- a/src/win32_monitor.c
+++ b/src/win32_monitor.c
@@ -361,6 +361,37 @@
_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 e3e3ad5..f1e7261 100644
--- a/src/x11_init.c
+++ b/src/x11_init.c
@@ -446,6 +446,8 @@
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 240e9fb..d0aa9f9 100644
--- a/src/x11_monitor.c
+++ b/src/x11_monitor.c
@@ -342,6 +342,22 @@
*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 c37c740..153daee 100644
--- a/src/x11_platform.h
+++ b/src/x11_platform.h
@@ -259,6 +259,7 @@
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;