mirror of
				https://github.com/glfw/glfw.git
				synced 2025-11-04 06:15:07 +00:00 
			
		
		
		
	Add content scale queries
This adds glfwGetWindowContentScale and glfwGetMonitorContentScale for querying the recommended drawing scale factor for DPI-aware rendering. Parts of this patch are based on code by @ferreiradaselva. Fixes #235. Fixes #439. Fixes #677. Fixes #845. Fixes #898.
This commit is contained in:
		
							parent
							
								
									1be81a1540
								
							
						
					
					
						commit
						16bf872117
					
				@ -136,6 +136,8 @@ information on what to include when reporting a bug.
 | 
			
		||||
  gamepad mapping (#900)
 | 
			
		||||
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
 | 
			
		||||
  for retrieving gamepad input state (#900)
 | 
			
		||||
- Added `glfwGetWindowContentScale` and `glfwGetMonitorContentScale` for
 | 
			
		||||
  DPI-aware rendering (#235,#439,#677,#845,#898)
 | 
			
		||||
- Added `glfwRequestWindowAttention` function for requesting attention from the
 | 
			
		||||
  user (#732,#988)
 | 
			
		||||
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
 | 
			
		||||
 | 
			
		||||
@ -131,17 +131,34 @@ current _resolution_, i.e. the width and height of its current
 | 
			
		||||
[video mode](@ref monitor_modes).
 | 
			
		||||
 | 
			
		||||
@code
 | 
			
		||||
int widthMM, heightMM;
 | 
			
		||||
glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
 | 
			
		||||
int width_mm, height_mm;
 | 
			
		||||
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
 | 
			
		||||
@endcode
 | 
			
		||||
 | 
			
		||||
This can, for example, be used together with the current video mode to calculate
 | 
			
		||||
the DPI of a monitor. 
 | 
			
		||||
While this can be used to calculate the raw DPI of a monitor, this is often not
 | 
			
		||||
useful.  Instead use the [monitor content scale](@ref monitor_scale) and
 | 
			
		||||
[window content scale](@ref window_scale) to scale your content.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@subsection monitor_scale Content scale
 | 
			
		||||
 | 
			
		||||
The content scale for a monitor can be retrieved with @ref
 | 
			
		||||
glfwGetMonitorContentScale.
 | 
			
		||||
 | 
			
		||||
@code
 | 
			
		||||
const double dpi = mode->width / (widthMM / 25.4);
 | 
			
		||||
float xscale, yscale;
 | 
			
		||||
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
 | 
			
		||||
@endcode
 | 
			
		||||
 | 
			
		||||
The content scale is the ratio between the current DPI and the platform's
 | 
			
		||||
default DPI.  If you scale all pixel dimensions by this scale then your content
 | 
			
		||||
should appear at an appropriate size.  This is especially important for text and
 | 
			
		||||
any UI elements.
 | 
			
		||||
 | 
			
		||||
The content scale may depend on both the monitor resolution and pixel density
 | 
			
		||||
and on user settings.  It may be very different from the raw DPI calculated from
 | 
			
		||||
the physical size and current resolution.    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@subsection monitor_pos Virtual position
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -58,6 +58,15 @@ windows with @ref glfwSetWindowAttrib.
 | 
			
		||||
@see @ref window_attribs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@subsection news_33_contentscale Content scale queries for DPI-aware rendering
 | 
			
		||||
 | 
			
		||||
GLFW now supports querying the window and monitor content scale, i.e. the ratio
 | 
			
		||||
between the current DPI and the platform's default DPI, with @ref
 | 
			
		||||
glfwGetWindowContentScale and @ref glfwGetMonitorContentScale.
 | 
			
		||||
 | 
			
		||||
@see @ref window_scale
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@subsection news_33_inithint Support for initialization hints
 | 
			
		||||
 | 
			
		||||
GLFW now supports setting library initialization hints with @ref glfwInitHint
 | 
			
		||||
 | 
			
		||||
@ -663,6 +663,26 @@ The size of a framebuffer may change independently of the size of a window, for
 | 
			
		||||
example if the window is dragged between a regular monitor and a high-DPI one.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@subsection window_scale Window content scale
 | 
			
		||||
 | 
			
		||||
The content scale for a window can be retrieved with @ref
 | 
			
		||||
glfwGetWindowContentScale.
 | 
			
		||||
 | 
			
		||||
@code
 | 
			
		||||
float xscale, yscale;
 | 
			
		||||
glfwGetWindowContentScale(window, &xscale, &yscale);
 | 
			
		||||
@endcode
 | 
			
		||||
 | 
			
		||||
The content scale of a window is the ratio between the current DPI and the
 | 
			
		||||
platform's default DPI.  If you scale all pixel dimensions by this scale then
 | 
			
		||||
your content should appear at an appropriate size.  This is especially important
 | 
			
		||||
for text and any UI elements.
 | 
			
		||||
 | 
			
		||||
On systems where each monitors can have its own content scale, the window
 | 
			
		||||
content scale will depend on which monitor the system considers the window to be
 | 
			
		||||
on.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@subsection window_sizelimits Window size limits
 | 
			
		||||
 | 
			
		||||
The minimum and maximum size of the client area of a windowed mode window can be
 | 
			
		||||
 | 
			
		||||
@ -1926,6 +1926,36 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
 | 
			
		||||
 */
 | 
			
		||||
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM);
 | 
			
		||||
 | 
			
		||||
/*! @brief Retrieves the content scale for the specified monitor.
 | 
			
		||||
 *
 | 
			
		||||
 *  This function retrieves the content scale for the specified monitor.  The
 | 
			
		||||
 *  content scale is the ratio between the current DPI and the platform's
 | 
			
		||||
 *  default DPI.  If you scale all pixel dimensions by this scale then your
 | 
			
		||||
 *  content should appear at an appropriate size.  This is especially important
 | 
			
		||||
 *  for text and any UI elements.
 | 
			
		||||
 *
 | 
			
		||||
 *  The content scale may depend on both the monitor resolution and pixel
 | 
			
		||||
 *  density and on user settings.  It may be very different from the raw DPI
 | 
			
		||||
 *  calculated from the physical size and current resolution.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param[in] monitor The monitor to query.
 | 
			
		||||
 *  @param[out] xscale Where to store the x-axis content scale, or `NULL`.
 | 
			
		||||
 *  @param[out] yscale Where to store the y-axis content scale, 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_scale
 | 
			
		||||
 *  @sa @ref glfwGetWindowContentScale
 | 
			
		||||
 *
 | 
			
		||||
 *  @since Added in version 3.3.
 | 
			
		||||
 *
 | 
			
		||||
 *  @ingroup monitor
 | 
			
		||||
 */
 | 
			
		||||
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale);
 | 
			
		||||
 | 
			
		||||
/*! @brief Returns the name of the specified monitor.
 | 
			
		||||
 *
 | 
			
		||||
 *  This function returns a human-readable name, encoded as UTF-8, of the
 | 
			
		||||
@ -2774,6 +2804,36 @@ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height)
 | 
			
		||||
 */
 | 
			
		||||
GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom);
 | 
			
		||||
 | 
			
		||||
/*! @brief Retrieves the content scale for the specified window.
 | 
			
		||||
 *
 | 
			
		||||
 *  This function retrieves the content scale for the specified window.  The
 | 
			
		||||
 *  content scale is the ratio between the current DPI and the platform's
 | 
			
		||||
 *  default DPI.  If you scale all pixel dimensions by this scale then your
 | 
			
		||||
 *  content should appear at an appropriate size.  This is especially important
 | 
			
		||||
 *  for text and any UI elements.
 | 
			
		||||
 *
 | 
			
		||||
 *  On systems where each monitors can have its own content scale, the window
 | 
			
		||||
 *  content scale will depend on which monitor the system considers the window
 | 
			
		||||
 *  to be on.
 | 
			
		||||
 *
 | 
			
		||||
 *  @param[in] window The window to query.
 | 
			
		||||
 *  @param[out] xscale Where to store the x-axis content scale, or `NULL`.
 | 
			
		||||
 *  @param[out] yscale Where to store the y-axis content scale, 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 window_scale
 | 
			
		||||
 *  @sa @ref glfwGetMonitorContentScale
 | 
			
		||||
 *
 | 
			
		||||
 *  @since Added in version 3.3.
 | 
			
		||||
 *
 | 
			
		||||
 *  @ingroup window
 | 
			
		||||
 */
 | 
			
		||||
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale);
 | 
			
		||||
 | 
			
		||||
/*! @brief Iconifies the specified window.
 | 
			
		||||
 *
 | 
			
		||||
 *  This function iconifies (minimizes) the specified window if it was
 | 
			
		||||
 | 
			
		||||
@ -229,6 +229,9 @@ void _glfwPollMonitorsNS(void)
 | 
			
		||||
    displays = calloc(displayCount, sizeof(CGDirectDisplayID));
 | 
			
		||||
    CGGetOnlineDisplayList(displayCount, displays, &displayCount);
 | 
			
		||||
 | 
			
		||||
    for (i = 0;  i < _glfw.monitorCount;  i++)
 | 
			
		||||
        _glfw.monitors[i]->ns.screen = nil;
 | 
			
		||||
 | 
			
		||||
    disconnectedCount = _glfw.monitorCount;
 | 
			
		||||
    if (disconnectedCount)
 | 
			
		||||
    {
 | 
			
		||||
@ -371,6 +374,48 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
 | 
			
		||||
        *ypos = (int) bounds.origin.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const NSRect points = [monitor->ns.screen frame];
 | 
			
		||||
    const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
 | 
			
		||||
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = (float) (pixels.size.width / points.size.width);
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = (float) (pixels.size.height / points.size.height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
 | 
			
		||||
{
 | 
			
		||||
    CFArrayRef modes;
 | 
			
		||||
 | 
			
		||||
@ -135,6 +135,7 @@ typedef struct _GLFWmonitorNS
 | 
			
		||||
    CGDirectDisplayID   displayID;
 | 
			
		||||
    CGDisplayModeRef    previousMode;
 | 
			
		||||
    uint32_t            unitNumber;
 | 
			
		||||
    id                  screen;
 | 
			
		||||
 | 
			
		||||
} _GLFWmonitorNS;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1288,6 +1288,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
 | 
			
		||||
        *bottom = contentRect.origin.y - frameRect.origin.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
 | 
			
		||||
                                        float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    const NSRect points = [window->ns.view frame];
 | 
			
		||||
    const NSRect pixels = [window->ns.view convertRectToBacking:points];
 | 
			
		||||
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = (float) (pixels.size.width / points.size.width);
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = (float) (pixels.size.height / points.size.height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 | 
			
		||||
{
 | 
			
		||||
    [window->ns.object miniaturize:nil];
 | 
			
		||||
 | 
			
		||||
@ -641,6 +641,7 @@ const char* _glfwPlatformGetScancodeName(int scancode);
 | 
			
		||||
int _glfwPlatformGetKeyScancode(int key);
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
 | 
			
		||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, float* xscale, float* yscale);
 | 
			
		||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
 | 
			
		||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
 | 
			
		||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
 | 
			
		||||
@ -670,6 +671,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int min
 | 
			
		||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
 | 
			
		||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
 | 
			
		||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom);
 | 
			
		||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, float* xscale, float* yscale);
 | 
			
		||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
 | 
			
		||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
 | 
			
		||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
 | 
			
		||||
        *ypos = monitor->mir.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
 | 
			
		||||
                                         float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = 1.f;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = 1.f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
 | 
			
		||||
{
 | 
			
		||||
    switch (pf)
 | 
			
		||||
 | 
			
		||||
@ -515,6 +515,15 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
 | 
			
		||||
        *height = window->mir.height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
 | 
			
		||||
                                        float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = 1.f;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = 1.f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 | 
			
		||||
{
 | 
			
		||||
    MirWindowSpec* spec;
 | 
			
		||||
 | 
			
		||||
@ -314,6 +314,21 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
 | 
			
		||||
        *heightMM = monitor->heightMM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
 | 
			
		||||
                                        float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
 | 
			
		||||
    assert(monitor != NULL);
 | 
			
		||||
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = 0.f;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = 0.f;
 | 
			
		||||
 | 
			
		||||
    _GLFW_REQUIRE_INIT();
 | 
			
		||||
    _glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
 | 
			
		||||
{
 | 
			
		||||
    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
 | 
			
		||||
 | 
			
		||||
@ -36,6 +36,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
 | 
			
		||||
                                         float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = 1.f;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = 1.f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
@ -139,6 +139,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
 | 
			
		||||
                                        float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = 1.f;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = 1.f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -151,6 +151,8 @@ static GLFWbool loadLibraries(void)
 | 
			
		||||
    {
 | 
			
		||||
        _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
 | 
			
		||||
            GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
 | 
			
		||||
        _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
 | 
			
		||||
            GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return GLFW_TRUE;
 | 
			
		||||
 | 
			
		||||
@ -60,6 +60,7 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
 | 
			
		||||
                                   DISPLAY_DEVICEW* display)
 | 
			
		||||
{
 | 
			
		||||
    _GLFWmonitor* monitor;
 | 
			
		||||
    int widthMM, heightMM;
 | 
			
		||||
    char* name;
 | 
			
		||||
    HDC dc;
 | 
			
		||||
    DEVMODEW dm;
 | 
			
		||||
@ -72,13 +73,26 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
 | 
			
		||||
    if (!name)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    ZeroMemory(&dm, sizeof(dm));
 | 
			
		||||
    dm.dmSize = sizeof(dm);
 | 
			
		||||
    EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
 | 
			
		||||
 | 
			
		||||
    dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    monitor = _glfwAllocMonitor(name,
 | 
			
		||||
                                GetDeviceCaps(dc, HORZSIZE),
 | 
			
		||||
                                GetDeviceCaps(dc, VERTSIZE));
 | 
			
		||||
    if (IsWindows8Point1OrGreater())
 | 
			
		||||
    {
 | 
			
		||||
        widthMM  = GetDeviceCaps(dc, HORZSIZE);
 | 
			
		||||
        heightMM = GetDeviceCaps(dc, VERTSIZE);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        widthMM  = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
 | 
			
		||||
        heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DeleteDC(dc);
 | 
			
		||||
 | 
			
		||||
    monitor = _glfwAllocMonitor(name, widthMM, heightMM);
 | 
			
		||||
    free(name);
 | 
			
		||||
 | 
			
		||||
    if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
 | 
			
		||||
@ -101,10 +115,6 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
 | 
			
		||||
                            NULL, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ZeroMemory(&dm, sizeof(dm));
 | 
			
		||||
    dm.dmSize = sizeof(dm);
 | 
			
		||||
    EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
 | 
			
		||||
 | 
			
		||||
    rect.left   = dm.dmPosition.x;
 | 
			
		||||
    rect.top    = dm.dmPosition.y;
 | 
			
		||||
    rect.right  = dm.dmPosition.x + dm.dmPelsWidth;
 | 
			
		||||
@ -302,6 +312,26 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    UINT xdpi, ydpi;
 | 
			
		||||
 | 
			
		||||
    if (IsWindows8Point1OrGreater())
 | 
			
		||||
        GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        const HDC dc = GetDC(NULL);
 | 
			
		||||
        xdpi = GetDeviceCaps(dc, LOGPIXELSX);
 | 
			
		||||
        ydpi = GetDeviceCaps(dc, LOGPIXELSY);
 | 
			
		||||
        ReleaseDC(NULL, dc);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = xdpi / 96.f;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = ydpi / 96.f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//////                       GLFW platform API                      //////
 | 
			
		||||
@ -324,6 +354,12 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
 | 
			
		||||
        *ypos = dm.dmPosition.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
 | 
			
		||||
                                         float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
 | 
			
		||||
{
 | 
			
		||||
    int modeIndex = 0, size = 0;
 | 
			
		||||
 | 
			
		||||
@ -135,6 +135,13 @@ typedef enum PROCESS_DPI_AWARENESS
 | 
			
		||||
    PROCESS_SYSTEM_DPI_AWARE = 1,
 | 
			
		||||
    PROCESS_PER_MONITOR_DPI_AWARE = 2
 | 
			
		||||
} PROCESS_DPI_AWARENESS;
 | 
			
		||||
typedef enum MONITOR_DPI_TYPE
 | 
			
		||||
{
 | 
			
		||||
    MDT_EFFECTIVE_DPI = 0,
 | 
			
		||||
    MDT_ANGULAR_DPI = 1,
 | 
			
		||||
    MDT_RAW_DPI = 2,
 | 
			
		||||
    MDT_DEFAULT = MDT_EFFECTIVE_DPI
 | 
			
		||||
} MONITOR_DPI_TYPE;
 | 
			
		||||
#endif /*DPI_ENUMS_DECLARED*/
 | 
			
		||||
 | 
			
		||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
 | 
			
		||||
@ -216,7 +223,9 @@ typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIN
 | 
			
		||||
 | 
			
		||||
// shcore.dll function pointer typedefs
 | 
			
		||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
 | 
			
		||||
typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
 | 
			
		||||
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
 | 
			
		||||
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
 | 
			
		||||
 | 
			
		||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
 | 
			
		||||
 | 
			
		||||
@ -326,6 +335,7 @@ typedef struct _GLFWlibraryWin32
 | 
			
		||||
    struct {
 | 
			
		||||
        HINSTANCE                       instance;
 | 
			
		||||
        PFN_SetProcessDpiAwareness      SetProcessDpiAwareness_;
 | 
			
		||||
        PFN_GetDpiForMonitor            GetDpiForMonitor_;
 | 
			
		||||
    } shcore;
 | 
			
		||||
 | 
			
		||||
} _GLFWlibraryWin32;
 | 
			
		||||
@ -395,4 +405,5 @@ void _glfwInitTimerWin32(void);
 | 
			
		||||
void _glfwPollMonitorsWin32(void);
 | 
			
		||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
 | 
			
		||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
 | 
			
		||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -983,19 +983,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case WM_DPICHANGED:
 | 
			
		||||
        {
 | 
			
		||||
            RECT* rect = (RECT*) lParam;
 | 
			
		||||
            SetWindowPos(window->win32.handle,
 | 
			
		||||
                         HWND_TOP,
 | 
			
		||||
                         rect->left,
 | 
			
		||||
                         rect->top,
 | 
			
		||||
                         rect->right - rect->left,
 | 
			
		||||
                         rect->bottom - rect->top,
 | 
			
		||||
                         SWP_NOACTIVATE | SWP_NOZORDER);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case WM_DROPFILES:
 | 
			
		||||
        {
 | 
			
		||||
            HDROP drop = (HDROP) wParam;
 | 
			
		||||
@ -1415,6 +1402,14 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
 | 
			
		||||
        *bottom = rect.bottom - height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
 | 
			
		||||
                                        float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    const HANDLE handle = MonitorFromWindow(window->win32.handle,
 | 
			
		||||
                                            MONITOR_DEFAULTTONEAREST);
 | 
			
		||||
    _glfwGetMonitorContentScaleWin32(handle, xscale, yscale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 | 
			
		||||
{
 | 
			
		||||
    ShowWindow(window->win32.handle, SW_MINIMIZE);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								src/window.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/window.c
									
									
									
									
									
								
							@ -632,6 +632,21 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
 | 
			
		||||
    _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
 | 
			
		||||
                                       float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    _GLFWwindow* window = (_GLFWwindow*) handle;
 | 
			
		||||
    assert(window != NULL);
 | 
			
		||||
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = 0.f;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = 0.f;
 | 
			
		||||
 | 
			
		||||
    _GLFW_REQUIRE_INIT();
 | 
			
		||||
    _glfwPlatformGetWindowContentScale(window, xscale, yscale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
 | 
			
		||||
{
 | 
			
		||||
    _GLFWwindow* window = (_GLFWwindow*) handle;
 | 
			
		||||
 | 
			
		||||
@ -153,6 +153,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
 | 
			
		||||
        *ypos = monitor->wl.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
 | 
			
		||||
                                         float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = (float) monitor->wl.scale;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = (float) monitor->wl.scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
 | 
			
		||||
{
 | 
			
		||||
    *found = monitor->modeCount;
 | 
			
		||||
 | 
			
		||||
@ -550,6 +550,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
 | 
			
		||||
    // implemented, but for now just leave everything as 0.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
 | 
			
		||||
                                        float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = (float) window->wl.scale;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = (float) window->wl.scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 | 
			
		||||
{
 | 
			
		||||
    // TODO: move to xdg_shell instead of wl_shell.
 | 
			
		||||
 | 
			
		||||
@ -743,6 +743,43 @@ static GLFWbool initExtensions(void)
 | 
			
		||||
    return GLFW_TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retrieve system content scale via folklore heuristics
 | 
			
		||||
//
 | 
			
		||||
static void getSystemContentScale(float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    // NOTE: Default to the display-wide DPI as we don't currently have a policy
 | 
			
		||||
    //       for which monitor a window is considered to be on
 | 
			
		||||
    float xdpi = DisplayWidth(_glfw.x11.display, _glfw.x11.screen) *
 | 
			
		||||
        25.4f / DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
 | 
			
		||||
    float ydpi = DisplayHeight(_glfw.x11.display, _glfw.x11.screen) *
 | 
			
		||||
        25.4f / DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
 | 
			
		||||
 | 
			
		||||
    // NOTE: Basing the scale on Xft.dpi where available should provide the most
 | 
			
		||||
    //       consistent user experience (matches Qt, Gtk, etc), although not
 | 
			
		||||
    //       always the most accurate one
 | 
			
		||||
    char* rms = XResourceManagerString(_glfw.x11.display);
 | 
			
		||||
    if (rms)
 | 
			
		||||
    {
 | 
			
		||||
        XrmDatabase db = XrmGetStringDatabase(rms);
 | 
			
		||||
        if (db)
 | 
			
		||||
        {
 | 
			
		||||
            XrmValue value;
 | 
			
		||||
            char* type = NULL;
 | 
			
		||||
 | 
			
		||||
            if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
 | 
			
		||||
            {
 | 
			
		||||
                if (type && strcmp(type, "String") == 0)
 | 
			
		||||
                    xdpi = ydpi = atof(value.addr);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            XrmDestroyDatabase(db);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *xscale = xdpi / 96.f;
 | 
			
		||||
    *yscale = ydpi / 96.f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a blank cursor for hidden and disabled cursor modes
 | 
			
		||||
//
 | 
			
		||||
static Cursor createHiddenCursor(void)
 | 
			
		||||
@ -861,6 +898,7 @@ int _glfwPlatformInit(void)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    XInitThreads();
 | 
			
		||||
    XrmInitialize();
 | 
			
		||||
 | 
			
		||||
    _glfw.x11.display = XOpenDisplay(NULL);
 | 
			
		||||
    if (!_glfw.x11.display)
 | 
			
		||||
@ -884,6 +922,8 @@ int _glfwPlatformInit(void)
 | 
			
		||||
    _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
 | 
			
		||||
    _glfw.x11.context = XUniqueContext();
 | 
			
		||||
 | 
			
		||||
    getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
 | 
			
		||||
 | 
			
		||||
    if (!initExtensions())
 | 
			
		||||
        return GLFW_FALSE;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -338,6 +338,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
 | 
			
		||||
                                         float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = _glfw.x11.contentScaleX;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = _glfw.x11.contentScaleY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
 | 
			
		||||
{
 | 
			
		||||
    GLFWvidmode* result;
 | 
			
		||||
 | 
			
		||||
@ -211,6 +211,8 @@ typedef struct _GLFWlibraryX11
 | 
			
		||||
    int             screen;
 | 
			
		||||
    Window          root;
 | 
			
		||||
 | 
			
		||||
    // System content scale
 | 
			
		||||
    float           contentScaleX, contentScaleY;
 | 
			
		||||
    // Helper window for IPC
 | 
			
		||||
    Window          helperWindowHandle;
 | 
			
		||||
    // Invisible cursor for hidden cursor mode
 | 
			
		||||
 | 
			
		||||
@ -2240,6 +2240,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
 | 
			
		||||
        XFree(extents);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
 | 
			
		||||
                                        float* xscale, float* yscale)
 | 
			
		||||
{
 | 
			
		||||
    if (xscale)
 | 
			
		||||
        *xscale = _glfw.x11.contentScaleX;
 | 
			
		||||
    if (yscale)
 | 
			
		||||
        *yscale = _glfw.x11.contentScaleY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 | 
			
		||||
{
 | 
			
		||||
    if (window->x11.overrideRedirect)
 | 
			
		||||
 | 
			
		||||
@ -92,21 +92,24 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
 | 
			
		||||
 | 
			
		||||
static void list_modes(GLFWmonitor* monitor)
 | 
			
		||||
{
 | 
			
		||||
    int count, x, y, widthMM, heightMM, i;
 | 
			
		||||
    int count, x, y, width_mm, height_mm, i;
 | 
			
		||||
    float xscale, yscale;
 | 
			
		||||
    const GLFWvidmode* mode = glfwGetVideoMode(monitor);
 | 
			
		||||
    const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
 | 
			
		||||
 | 
			
		||||
    glfwGetMonitorPos(monitor, &x, &y);
 | 
			
		||||
    glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
 | 
			
		||||
    glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
 | 
			
		||||
    glfwGetMonitorContentScale(monitor, &xscale, &yscale);
 | 
			
		||||
 | 
			
		||||
    printf("Name: %s (%s)\n",
 | 
			
		||||
           glfwGetMonitorName(monitor),
 | 
			
		||||
           glfwGetPrimaryMonitor() == monitor ? "primary" : "secondary");
 | 
			
		||||
    printf("Current mode: %s\n", format_mode(mode));
 | 
			
		||||
    printf("Virtual position: %i %i\n", x, y);
 | 
			
		||||
    printf("Content scale: %f %f\n", xscale, yscale);
 | 
			
		||||
 | 
			
		||||
    printf("Physical size: %i x %i mm (%0.2f dpi)\n",
 | 
			
		||||
           widthMM, heightMM, mode->width * 25.4f / widthMM);
 | 
			
		||||
           width_mm, height_mm, mode->width * 25.4f / width_mm);
 | 
			
		||||
 | 
			
		||||
    printf("Modes:\n");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user