Various fixes for monitor work area retrieval from upstream
This commit is contained in:
parent
2e0d39b512
commit
4c4c6ab0e6
@ -213,6 +213,30 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
||||
}
|
||||
}
|
||||
|
||||
// Finds and caches the NSScreen corresponding to the specified monitor
|
||||
//
|
||||
GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor)
|
||||
{
|
||||
if (monitor->ns.screen)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (NSScreen* screen in [NSScreen screens])
|
||||
{
|
||||
NSNumber* displayID = [screen deviceDescription][@"NSScreenNumber"];
|
||||
|
||||
// HACK: Compare unit numbers instead of display IDs to work around
|
||||
// display replacement on machines with automatic graphics
|
||||
// switching
|
||||
if (monitor->ns.unitNumber == CGDisplayUnitNumber([displayID unsignedIntValue]))
|
||||
{
|
||||
monitor->ns.screen = screen;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to find a screen for monitor");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
@ -429,35 +453,8 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (!monitor->ns.screen)
|
||||
{
|
||||
NSUInteger i;
|
||||
NSArray* screens = [NSScreen screens];
|
||||
|
||||
for (i = 0; i < [screens count]; i++)
|
||||
{
|
||||
NSScreen* screen = [screens objectAtIndex:i];
|
||||
NSNumber* displayID =
|
||||
[[screen deviceDescription] objectForKey:@"NSScreenNumber"];
|
||||
|
||||
// HACK: Compare unit numbers instead of display IDs to work around
|
||||
// display replacement on machines with automatic graphics
|
||||
// switching
|
||||
if (monitor->ns.unitNumber ==
|
||||
CGDisplayUnitNumber([displayID unsignedIntValue]))
|
||||
{
|
||||
monitor->ns.screen = screen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == [screens count])
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to find a screen for monitor");
|
||||
if (!refreshMonitorScreen(monitor))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const NSRect points = [monitor->ns.screen frame];
|
||||
const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
|
||||
@ -470,20 +467,20 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!refreshMonitorScreen(monitor))
|
||||
return;
|
||||
|
||||
NSRect frameRect = [[NSScreen resultScreen] visibleFrame];
|
||||
const NSRect frameRect = [monitor->ns.screen visibleFrame];
|
||||
|
||||
if (xpos)
|
||||
*xpos = frameRect.origin.x;
|
||||
if (ypos)
|
||||
*ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height);
|
||||
if (width)
|
||||
*width = frameRect.size.width;
|
||||
if (height)
|
||||
*height = frameRect.size.height;
|
||||
|
||||
*xpos = NSMinX(frameRect);
|
||||
*ypos = NSMinY(frameRect);
|
||||
*width = NSMaxX(frameRect);
|
||||
*height = NSMaxY(frameRect);
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
|
||||
1
glfw/cocoa_platform.h
vendored
1
glfw/cocoa_platform.h
vendored
@ -202,6 +202,7 @@ void _glfwInitTimerNS(void);
|
||||
void _glfwPollMonitorsNS(void);
|
||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||
float _glfwTransformYNS(float y);
|
||||
void _glfwClearDisplayLinks();
|
||||
void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start);
|
||||
void _glfwDispatchTickCallback();
|
||||
|
||||
@ -149,14 +149,6 @@ static void updateCursorMode(_GLFWwindow* window)
|
||||
updateCursorImage(window);
|
||||
}
|
||||
|
||||
// Transforms the specified y-coordinate between the CG display and NS screen
|
||||
// coordinate systems
|
||||
//
|
||||
static float transformY(float y)
|
||||
{
|
||||
return CGDisplayBounds(CGMainDisplayID()).size.height - y;
|
||||
}
|
||||
|
||||
// Make the specified window and its video mode active on its monitor
|
||||
//
|
||||
static void acquireMonitor(_GLFWwindow* window)
|
||||
@ -164,7 +156,7 @@ static void acquireMonitor(_GLFWwindow* window)
|
||||
_glfwSetVideoModeNS(window->monitor, &window->videoMode);
|
||||
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
|
||||
const NSRect frame = NSMakeRect(bounds.origin.x,
|
||||
transformY(bounds.origin.y + bounds.size.height),
|
||||
_glfwTransformYNS(bounds.origin.y + bounds.size.height),
|
||||
bounds.size.width,
|
||||
bounds.size.height);
|
||||
|
||||
@ -1039,7 +1031,7 @@ is_ascii_control_char(char x) {
|
||||
int xpos, ypos;
|
||||
_glfwPlatformGetWindowPos(window, &xpos, &ypos);
|
||||
const NSRect contentRect = [window->ns.view frame];
|
||||
return NSMakeRect(xpos, transformY(ypos + contentRect.size.height), 0.0, 0.0);
|
||||
return NSMakeRect(xpos, _glfwTransformYNS(ypos + contentRect.size.height), 0.0, 0.0);
|
||||
}
|
||||
|
||||
- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
|
||||
@ -1437,13 +1429,13 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
if (xpos)
|
||||
*xpos = contentRect.origin.x;
|
||||
if (ypos)
|
||||
*ypos = transformY(contentRect.origin.y + contentRect.size.height);
|
||||
*ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y)
|
||||
{
|
||||
const NSRect contentRect = [window->ns.view frame];
|
||||
const NSRect dummyRect = NSMakeRect(x, transformY(y + contentRect.size.height), 0, 0);
|
||||
const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height), 0, 0);
|
||||
const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect];
|
||||
[window->ns.object setFrameOrigin:frameRect.origin];
|
||||
}
|
||||
@ -1606,7 +1598,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
else
|
||||
{
|
||||
const NSRect contentRect =
|
||||
NSMakeRect(xpos, transformY(ypos + height), width, height);
|
||||
NSMakeRect(xpos, _glfwTransformYNS(ypos + height), width, height);
|
||||
const NSRect frameRect =
|
||||
[window->ns.object frameRectForContentRect:contentRect
|
||||
styleMask:getStyleMask(window)];
|
||||
@ -1636,7 +1628,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
}
|
||||
else
|
||||
{
|
||||
NSRect contentRect = NSMakeRect(xpos, transformY(ypos + height),
|
||||
NSRect contentRect = NSMakeRect(xpos, _glfwTransformYNS(ypos + height),
|
||||
width, height);
|
||||
NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
|
||||
styleMask:styleMask];
|
||||
@ -1864,7 +1856,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||
const NSPoint globalPoint = globalRect.origin;
|
||||
|
||||
CGWarpMouseCursorPosition(CGPointMake(globalPoint.x,
|
||||
transformY(globalPoint.y)));
|
||||
_glfwTransformYNS(globalPoint.y)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2225,3 +2217,14 @@ GLFWAPI void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, unsigned sho
|
||||
#undef K
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Transforms a y-coordinate between the CG display and NS screen spaces
|
||||
//
|
||||
float _glfwTransformYNS(float y)
|
||||
{
|
||||
return CGDisplayBounds(CGMainDisplayID()).size.height - y;
|
||||
}
|
||||
|
||||
14
glfw/glfw3.h
vendored
14
glfw/glfw3.h
vendored
@ -1940,23 +1940,27 @@ 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.
|
||||
* corner of the specified monitor alongwith the work area size in screen co-ordinates.
|
||||
* The work area is defined as the area of the monitor not occluded by the operating
|
||||
* system chrome (task bar, global menubar, etc.).
|
||||
*
|
||||
* Any or all of the position arguments may be `NULL`. If an error occurs, all
|
||||
* non-`NULL` position arguments will be set to zero.
|
||||
* Any or all of the position and size arguments may be `NULL`. If an error occurs, all
|
||||
* non-`NULL` position and size 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`.
|
||||
* @param[out] width Where to store the monitor width, or `NULL`.
|
||||
* @param[out] height Where to store the monitor height, 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
|
||||
* @sa @ref monitor_workarea
|
||||
*
|
||||
* @since Added in version 3.0.
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup monitor
|
||||
*/
|
||||
|
||||
4
glfw/monitor.c
vendored
4
glfw/monitor.c
vendored
@ -341,8 +341,8 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, int* xpos, int* ypos, i
|
||||
*ypos = 0;
|
||||
if (width)
|
||||
*width = 0;
|
||||
if (width)
|
||||
*width = 0;
|
||||
if (height)
|
||||
*height = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
|
||||
12
glfw/wl_monitor.c
vendored
12
glfw/wl_monitor.c
vendored
@ -170,6 +170,18 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
*yscale = (float) monitor->wl.scale;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
||||
{
|
||||
if (xpos)
|
||||
*xpos = monitor->wl.x;
|
||||
if (ypos)
|
||||
*ypos = monitor->wl.y;
|
||||
if (width)
|
||||
*width = monitor->modes[monitor->wl.currentMode].width;
|
||||
if (height)
|
||||
*height = monitor->modes[monitor->wl.currentMode].height;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
*found = monitor->modeCount;
|
||||
|
||||
2
glfw/x11_init.c
vendored
2
glfw/x11_init.c
vendored
@ -139,6 +139,8 @@ static void detectEWMH(void)
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
_glfw.x11.NET_WORKAREA =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");
|
||||
_glfw.x11.NET_CURRENT_DESKTOP =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
||||
_glfw.x11.NET_ACTIVE_WINDOW =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||
_glfw.x11.NET_FRAME_EXTENTS =
|
||||
|
||||
92
glfw/x11_monitor.c
vendored
92
glfw/x11_monitor.c
vendored
@ -351,18 +351,96 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
|
||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
||||
{
|
||||
int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
|
||||
|
||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||
{
|
||||
Atom* extents = NULL;
|
||||
XRRScreenResources* sr;
|
||||
XRRCrtcInfo* ci;
|
||||
|
||||
_glfwGetWindowPropertyX11(_glfw.x11.root, _glfw.x11.NET_WORKAREA, XA_CARDINAL, (unsigned char**) &extents);
|
||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||
|
||||
*xpos = extents[0];
|
||||
*ypos = extents[1];
|
||||
*width = extents[2];
|
||||
*height = extents[3];
|
||||
XFree(extents);
|
||||
areaX = ci->x;
|
||||
areaY = ci->y;
|
||||
|
||||
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
||||
|
||||
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||
{
|
||||
areaWidth = mi->height;
|
||||
areaHeight = mi->width;
|
||||
}
|
||||
else
|
||||
{
|
||||
areaWidth = mi->width;
|
||||
areaHeight = mi->height;
|
||||
}
|
||||
|
||||
XRRFreeCrtcInfo(ci);
|
||||
XRRFreeScreenResources(sr);
|
||||
}
|
||||
else
|
||||
{
|
||||
areaWidth = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
|
||||
areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
|
||||
}
|
||||
|
||||
if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP)
|
||||
{
|
||||
Atom* extents = NULL;
|
||||
Atom* desktop = NULL;
|
||||
const unsigned long extentCount =
|
||||
_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||
_glfw.x11.NET_WORKAREA,
|
||||
XA_CARDINAL,
|
||||
(unsigned char**) &extents);
|
||||
|
||||
if (_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||
_glfw.x11.NET_CURRENT_DESKTOP,
|
||||
XA_CARDINAL,
|
||||
(unsigned char**) &desktop) > 0)
|
||||
{
|
||||
if (extentCount >= 4 && *desktop < extentCount / 4)
|
||||
{
|
||||
const int globalX = extents[*desktop * 4 + 0];
|
||||
const int globalY = extents[*desktop * 4 + 1];
|
||||
const int globalWidth = extents[*desktop * 4 + 2];
|
||||
const int globalHeight = extents[*desktop * 4 + 3];
|
||||
|
||||
if (areaX < globalX)
|
||||
{
|
||||
areaWidth -= globalX - areaX;
|
||||
areaX = globalX;
|
||||
}
|
||||
|
||||
if (areaY < globalY)
|
||||
{
|
||||
areaHeight -= globalY - areaY;
|
||||
areaY = globalY;
|
||||
}
|
||||
|
||||
if (areaX + areaWidth > globalX + globalWidth)
|
||||
areaWidth = globalX - areaX + globalWidth;
|
||||
if (areaY + areaHeight > globalY + globalHeight)
|
||||
areaHeight = globalY - areaY + globalHeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (extents)
|
||||
XFree(extents);
|
||||
if (desktop)
|
||||
XFree(desktop);
|
||||
}
|
||||
|
||||
if (xpos)
|
||||
*xpos = areaX;
|
||||
if (ypos)
|
||||
*ypos = areaY;
|
||||
if (width)
|
||||
*width = areaWidth;
|
||||
if (height)
|
||||
*height = areaHeight;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
|
||||
1
glfw/x11_platform.h
vendored
1
glfw/x11_platform.h
vendored
@ -249,6 +249,7 @@ typedef struct _GLFWlibraryX11
|
||||
Atom NET_WM_WINDOW_OPACITY;
|
||||
Atom NET_WM_CM_Sx;
|
||||
Atom NET_WORKAREA;
|
||||
Atom NET_CURRENT_DESKTOP;
|
||||
Atom NET_ACTIVE_WINDOW;
|
||||
Atom NET_FRAME_EXTENTS;
|
||||
Atom NET_REQUEST_FRAME_EXTENTS;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user