mirror of
https://github.com/gwm17/glfw.git
synced 2024-11-23 02:38:52 -05: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)
|
gamepad mapping (#900)
|
||||||
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
|
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
|
||||||
for retrieving gamepad input state (#900)
|
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
|
- Added `glfwRequestWindowAttention` function for requesting attention from the
|
||||||
user (#732,#988)
|
user (#732,#988)
|
||||||
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
|
- 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).
|
[video mode](@ref monitor_modes).
|
||||||
|
|
||||||
@code
|
@code
|
||||||
int widthMM, heightMM;
|
int width_mm, height_mm;
|
||||||
glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
|
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
This can, for example, be used together with the current video mode to calculate
|
While this can be used to calculate the raw DPI of a monitor, this is often not
|
||||||
the DPI of a monitor.
|
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
|
@code
|
||||||
const double dpi = mode->width / (widthMM / 25.4);
|
float xscale, yscale;
|
||||||
|
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||||
@endcode
|
@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
|
@subsection monitor_pos Virtual position
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,15 @@ windows with @ref glfwSetWindowAttrib.
|
||||||
@see @ref window_attribs
|
@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
|
@subsection news_33_inithint Support for initialization hints
|
||||||
|
|
||||||
GLFW now supports setting library initialization hints with @ref glfwInitHint
|
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.
|
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
|
@subsection window_sizelimits Window size limits
|
||||||
|
|
||||||
The minimum and maximum size of the client area of a windowed mode window can be
|
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);
|
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.
|
/*! @brief Returns the name of the specified monitor.
|
||||||
*
|
*
|
||||||
* This function returns a human-readable name, encoded as UTF-8, of the
|
* 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);
|
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.
|
/*! @brief Iconifies the specified window.
|
||||||
*
|
*
|
||||||
* This function iconifies (minimizes) the specified window if it was
|
* This function iconifies (minimizes) the specified window if it was
|
||||||
|
|
|
@ -229,6 +229,9 @@ void _glfwPollMonitorsNS(void)
|
||||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
_glfw.monitors[i]->ns.screen = nil;
|
||||||
|
|
||||||
disconnectedCount = _glfw.monitorCount;
|
disconnectedCount = _glfw.monitorCount;
|
||||||
if (disconnectedCount)
|
if (disconnectedCount)
|
||||||
{
|
{
|
||||||
|
@ -371,6 +374,48 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
*ypos = (int) bounds.origin.y;
|
*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)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
CFArrayRef modes;
|
CFArrayRef modes;
|
||||||
|
|
|
@ -135,6 +135,7 @@ typedef struct _GLFWmonitorNS
|
||||||
CGDirectDisplayID displayID;
|
CGDirectDisplayID displayID;
|
||||||
CGDisplayModeRef previousMode;
|
CGDisplayModeRef previousMode;
|
||||||
uint32_t unitNumber;
|
uint32_t unitNumber;
|
||||||
|
id screen;
|
||||||
|
|
||||||
} _GLFWmonitorNS;
|
} _GLFWmonitorNS;
|
||||||
|
|
||||||
|
|
|
@ -1288,6 +1288,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
*bottom = contentRect.origin.y - frameRect.origin.y;
|
*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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
[window->ns.object miniaturize:nil];
|
[window->ns.object miniaturize:nil];
|
||||||
|
|
|
@ -641,6 +641,7 @@ const char* _glfwPlatformGetScancodeName(int scancode);
|
||||||
int _glfwPlatformGetKeyScancode(int key);
|
int _glfwPlatformGetKeyScancode(int key);
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, float* xscale, float* yscale);
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
||||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
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 _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
||||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
||||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom);
|
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 _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
||||||
|
|
|
@ -88,6 +88,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
*ypos = monitor->mir.y;
|
*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)
|
static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
|
||||||
{
|
{
|
||||||
switch (pf)
|
switch (pf)
|
||||||
|
|
|
@ -515,6 +515,15 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||||
*height = window->mir.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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirWindowSpec* spec;
|
MirWindowSpec* spec;
|
||||||
|
|
|
@ -314,6 +314,21 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
|
||||||
*heightMM = monitor->heightMM;
|
*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)
|
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor = (_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)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
return NULL;
|
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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,6 +151,8 @@ static GLFWbool loadLibraries(void)
|
||||||
{
|
{
|
||||||
_glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
|
_glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
|
||||||
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
||||||
|
_glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
|
||||||
|
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
|
|
@ -60,6 +60,7 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||||
DISPLAY_DEVICEW* display)
|
DISPLAY_DEVICEW* display)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor;
|
_GLFWmonitor* monitor;
|
||||||
|
int widthMM, heightMM;
|
||||||
char* name;
|
char* name;
|
||||||
HDC dc;
|
HDC dc;
|
||||||
DEVMODEW dm;
|
DEVMODEW dm;
|
||||||
|
@ -72,13 +73,26 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||||
if (!name)
|
if (!name)
|
||||||
return NULL;
|
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);
|
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
||||||
|
|
||||||
monitor = _glfwAllocMonitor(name,
|
if (IsWindows8Point1OrGreater())
|
||||||
GetDeviceCaps(dc, HORZSIZE),
|
{
|
||||||
GetDeviceCaps(dc, VERTSIZE));
|
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);
|
DeleteDC(dc);
|
||||||
|
|
||||||
|
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
||||||
|
@ -101,10 +115,6 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
|
|
||||||
|
|
||||||
rect.left = dm.dmPosition.x;
|
rect.left = dm.dmPosition.x;
|
||||||
rect.top = dm.dmPosition.y;
|
rect.top = dm.dmPosition.y;
|
||||||
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
|
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 //////
|
////// GLFW platform API //////
|
||||||
|
@ -324,6 +354,12 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
*ypos = dm.dmPosition.y;
|
*ypos = dm.dmPosition.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
_glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
|
||||||
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
int modeIndex = 0, size = 0;
|
int modeIndex = 0, size = 0;
|
||||||
|
|
|
@ -135,6 +135,13 @@ typedef enum PROCESS_DPI_AWARENESS
|
||||||
PROCESS_SYSTEM_DPI_AWARE = 1,
|
PROCESS_SYSTEM_DPI_AWARE = 1,
|
||||||
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
||||||
} PROCESS_DPI_AWARENESS;
|
} 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*/
|
#endif /*DPI_ENUMS_DECLARED*/
|
||||||
|
|
||||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
// 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
|
// shcore.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
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 SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
|
||||||
|
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
|
||||||
|
|
||||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
||||||
|
|
||||||
|
@ -326,6 +335,7 @@ typedef struct _GLFWlibraryWin32
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
|
PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
|
||||||
|
PFN_GetDpiForMonitor GetDpiForMonitor_;
|
||||||
} shcore;
|
} shcore;
|
||||||
|
|
||||||
} _GLFWlibraryWin32;
|
} _GLFWlibraryWin32;
|
||||||
|
@ -395,4 +405,5 @@ void _glfwInitTimerWin32(void);
|
||||||
void _glfwPollMonitorsWin32(void);
|
void _glfwPollMonitorsWin32(void);
|
||||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
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;
|
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:
|
case WM_DROPFILES:
|
||||||
{
|
{
|
||||||
HDROP drop = (HDROP) wParam;
|
HDROP drop = (HDROP) wParam;
|
||||||
|
@ -1415,6 +1402,14 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
*bottom = rect.bottom - height;
|
*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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
ShowWindow(window->win32.handle, SW_MINIMIZE);
|
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);
|
_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)
|
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
|
|
@ -153,6 +153,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
*ypos = monitor->wl.y;
|
*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)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
*found = monitor->modeCount;
|
*found = monitor->modeCount;
|
||||||
|
|
|
@ -550,6 +550,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
// implemented, but for now just leave everything as 0.
|
// 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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// TODO: move to xdg_shell instead of wl_shell.
|
// TODO: move to xdg_shell instead of wl_shell.
|
||||||
|
|
|
@ -743,6 +743,43 @@ static GLFWbool initExtensions(void)
|
||||||
return GLFW_TRUE;
|
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
|
// Create a blank cursor for hidden and disabled cursor modes
|
||||||
//
|
//
|
||||||
static Cursor createHiddenCursor(void)
|
static Cursor createHiddenCursor(void)
|
||||||
|
@ -861,6 +898,7 @@ int _glfwPlatformInit(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XInitThreads();
|
XInitThreads();
|
||||||
|
XrmInitialize();
|
||||||
|
|
||||||
_glfw.x11.display = XOpenDisplay(NULL);
|
_glfw.x11.display = XOpenDisplay(NULL);
|
||||||
if (!_glfw.x11.display)
|
if (!_glfw.x11.display)
|
||||||
|
@ -884,6 +922,8 @@ int _glfwPlatformInit(void)
|
||||||
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
|
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
|
||||||
_glfw.x11.context = XUniqueContext();
|
_glfw.x11.context = XUniqueContext();
|
||||||
|
|
||||||
|
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
|
||||||
|
|
||||||
if (!initExtensions())
|
if (!initExtensions())
|
||||||
return GLFW_FALSE;
|
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* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
GLFWvidmode* result;
|
GLFWvidmode* result;
|
||||||
|
|
|
@ -211,6 +211,8 @@ typedef struct _GLFWlibraryX11
|
||||||
int screen;
|
int screen;
|
||||||
Window root;
|
Window root;
|
||||||
|
|
||||||
|
// System content scale
|
||||||
|
float contentScaleX, contentScaleY;
|
||||||
// Helper window for IPC
|
// Helper window for IPC
|
||||||
Window helperWindowHandle;
|
Window helperWindowHandle;
|
||||||
// Invisible cursor for hidden cursor mode
|
// Invisible cursor for hidden cursor mode
|
||||||
|
|
|
@ -2240,6 +2240,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
XFree(extents);
|
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)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->x11.overrideRedirect)
|
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)
|
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* mode = glfwGetVideoMode(monitor);
|
||||||
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
|
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
|
||||||
|
|
||||||
glfwGetMonitorPos(monitor, &x, &y);
|
glfwGetMonitorPos(monitor, &x, &y);
|
||||||
glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
|
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
|
||||||
|
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||||
|
|
||||||
printf("Name: %s (%s)\n",
|
printf("Name: %s (%s)\n",
|
||||||
glfwGetMonitorName(monitor),
|
glfwGetMonitorName(monitor),
|
||||||
glfwGetPrimaryMonitor() == monitor ? "primary" : "secondary");
|
glfwGetPrimaryMonitor() == monitor ? "primary" : "secondary");
|
||||||
printf("Current mode: %s\n", format_mode(mode));
|
printf("Current mode: %s\n", format_mode(mode));
|
||||||
printf("Virtual position: %i %i\n", x, y);
|
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",
|
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");
|
printf("Modes:\n");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user