Update GLFW from upstream

This commit is contained in:
Kovid Goyal 2018-09-04 09:49:18 +05:30
parent e630b76fac
commit f5cc2fd8ad
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
10 changed files with 385 additions and 147 deletions

4
glfw/glfw3.h vendored
View File

@ -973,6 +973,10 @@ extern "C" {
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_CLIENT_API_attrib).
*/ */
#define GLFW_CONTEXT_CREATION_API 0x0002200B #define GLFW_CONTEXT_CREATION_API 0x0002200B
/*! @brief Window content area scaling window
* [window hint](@ref GLFW_SCALE_TO_MONITOR).
*/
#define GLFW_SCALE_TO_MONITOR 0x0002200C
#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001 #define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
#define GLFW_COCOA_FRAME_NAME 0x00023002 #define GLFW_COCOA_FRAME_NAME 0x00023002

1
glfw/internal.h vendored
View File

@ -271,6 +271,7 @@ struct _GLFWwndconfig
GLFWbool maximized; GLFWbool maximized;
GLFWbool centerCursor; GLFWbool centerCursor;
GLFWbool focusOnShow; GLFWbool focusOnShow;
GLFWbool scaleToMonitor;
struct { struct {
GLFWbool retina; GLFWbool retina;
char frameName[256]; char frameName[256];

20
glfw/wgl_context.c vendored
View File

@ -256,13 +256,21 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
static void swapBuffersWGL(_GLFWwindow* window) static void swapBuffersWGL(_GLFWwindow* window)
{ {
if (!window->monitor)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Use DwmFlush when desktop composition is enabled // HACK: Use DwmFlush when desktop composition is enabled
if (_glfwIsCompositionEnabledWin32() && !window->monitor) if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{ {
int count = abs(window->context.wgl.interval); int count = abs(window->context.wgl.interval);
while (count--) while (count--)
DwmFlush(); DwmFlush();
} }
}
}
SwapBuffers(window->context.wgl.dc); SwapBuffers(window->context.wgl.dc);
} }
@ -273,10 +281,18 @@ static void swapIntervalWGL(int interval)
window->context.wgl.interval = interval; window->context.wgl.interval = interval;
if (!window->monitor)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Disable WGL swap interval when desktop composition is enabled to // HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync // avoid interfering with DWM vsync
if (_glfwIsCompositionEnabledWin32() && !window->monitor) if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
interval = 0; interval = 0;
}
}
if (_glfw.wgl.EXT_swap_control) if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval); _glfw.wgl.SwapIntervalEXT(interval);

68
glfw/win32_init.c vendored
View File

@ -62,17 +62,6 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
#endif // _GLFW_BUILD_DLL #endif // _GLFW_BUILD_DLL
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
return VerifyVersionInfoW(&osvi, mask, cond);
}
// Load necessary libraries (DLLs) // Load necessary libraries (DLLs)
// //
static GLFWbool loadLibraries(void) static GLFWbool loadLibraries(void)
@ -100,6 +89,14 @@ static GLFWbool loadLibraries(void)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware"); GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx) _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
_glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
_glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll"); _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
if (_glfw.win32.dinput8.instance) if (_glfw.win32.dinput8.instance)
@ -155,6 +152,13 @@ static GLFWbool loadLibraries(void)
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor"); GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
} }
_glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
if (_glfw.win32.ntdll.instance)
{
_glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
}
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -179,6 +183,9 @@ static void freeLibraries(void)
if (_glfw.win32.shcore.instance) if (_glfw.win32.shcore.instance)
FreeLibrary(_glfw.win32.shcore.instance); FreeLibrary(_glfw.win32.shcore.instance);
if (_glfw.win32.ntdll.instance)
FreeLibrary(_glfw.win32.ntdll.instance);
} }
// Create key code translation tables // Create key code translation tables
@ -309,6 +316,7 @@ static void createKeyTables(void)
_glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL; _glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
_glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE; _glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
_glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER; _glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
_glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
_glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY; _glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT; _glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
@ -339,8 +347,8 @@ static HWND createHelperWindow(void)
return NULL; return NULL;
} }
// HACK: The first call to ShowWindow is ignored if the parent process // HACK: The command to the first ShowWindow call is ignored if the parent
// passed along a STARTUPINFO, so clear that flag with a no-op call // process passed along a STARTUPINFO, so clear that with a no-op call
ShowWindow(window, SW_HIDE); ShowWindow(window, SW_HIDE);
// Register for HID device notifications // Register for HID device notifications
@ -502,6 +510,36 @@ void _glfwUpdateKeyNamesWin32(void)
} }
} }
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
//
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
// latter lies unless the user knew to embedd a non-default manifest
// announcing support for Windows 10 via supportedOS GUID
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
}
// Checks whether we are on at least the specified build of Windows 10
//
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
// latter lies unless the user knew to embedd a non-default manifest
// announcing support for Windows 10 via supportedOS GUID
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
@ -523,7 +561,9 @@ int _glfwPlatformInit(void)
createKeyTables(); createKeyTables();
_glfwUpdateKeyNamesWin32(); _glfwUpdateKeyNamesWin32();
if (IsWindows8Point1OrGreater()) if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
else if (IsWindows8Point1OrGreater())
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
else if (IsWindowsVistaOrGreater()) else if (IsWindowsVistaOrGreater())
SetProcessDPIAware(); SetProcessDPIAware();

View File

@ -324,9 +324,9 @@ void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* ysc
} }
if (xscale) if (xscale)
*xscale = xdpi / 96.f; *xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
if (yscale) if (yscale)
*yscale = ydpi / 96.f; *yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
} }

52
glfw/win32_platform.h vendored
View File

@ -98,6 +98,12 @@
#ifndef _WIN32_WINNT_WINBLUE #ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0602 #define _WIN32_WINNT_WINBLUE 0x0602
#endif #endif
#ifndef WM_GETDPISCALEDSIZE
#define WM_GETDPISCALEDSIZE 0x02e4
#endif
#ifndef USER_DEFAULT_SCREEN_DPI
#define USER_DEFAULT_SCREEN_DPI 96
#endif
#if WINVER < 0x0601 #if WINVER < 0x0601
typedef struct typedef struct
@ -140,24 +146,33 @@ typedef enum
} MONITOR_DPI_TYPE; } MONITOR_DPI_TYPE;
#endif /*DPI_ENUMS_DECLARED*/ #endif /*DPI_ENUMS_DECLARED*/
#ifndef _DPI_AWARENESS_CONTEXTS_
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT) -4)
#endif /*_DPI_AWARENESS_CONTEXTS_*/
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header // HACK: Define versionhelpers.h functions manually as MinGW lacks the header
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp);
#define IsWindowsXPOrGreater() \ #define IsWindowsXPOrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), \ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
LOBYTE(_WIN32_WINNT_WINXP), 0) LOBYTE(_WIN32_WINNT_WINXP), 0)
#define IsWindowsVistaOrGreater() \ #define IsWindowsVistaOrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), \ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
LOBYTE(_WIN32_WINNT_VISTA), 0) LOBYTE(_WIN32_WINNT_VISTA), 0)
#define IsWindows7OrGreater() \ #define IsWindows7OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), \ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
LOBYTE(_WIN32_WINNT_WIN7), 0) LOBYTE(_WIN32_WINNT_WIN7), 0)
#define IsWindows8OrGreater() \ #define IsWindows8OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), \ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
LOBYTE(_WIN32_WINNT_WIN8), 0) LOBYTE(_WIN32_WINNT_WIN8), 0)
#define IsWindows8Point1OrGreater() \ #define IsWindows8Point1OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), \ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
LOBYTE(_WIN32_WINNT_WINBLUE), 0) LOBYTE(_WIN32_WINNT_WINBLUE), 0)
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(14393)
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(15063)
// HACK: Define macros that some xinput.h variants don't // HACK: Define macros that some xinput.h variants don't
#ifndef XINPUT_CAPS_WIRELESS #ifndef XINPUT_CAPS_WIRELESS
#define XINPUT_CAPS_WIRELESS 0x0002 #define XINPUT_CAPS_WIRELESS 0x0002
@ -209,8 +224,16 @@ typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*
// user32.dll function pointer typedefs // user32.dll function pointer typedefs
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void); typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*); typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_ #define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_ #define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
// dwmapi.dll function pointer typedefs // dwmapi.dll function pointer typedefs
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
@ -226,6 +249,10 @@ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_ #define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_ #define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
// ntdll.dll function pointer typedefs
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
typedef VkFlags VkWin32SurfaceCreateFlagsKHR; typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
typedef struct VkWin32SurfaceCreateInfoKHR typedef struct VkWin32SurfaceCreateInfoKHR
@ -279,6 +306,7 @@ typedef struct _GLFWwindowWin32
GLFWbool maximized; GLFWbool maximized;
// Whether to enable framebuffer transparency on DWM // Whether to enable framebuffer transparency on DWM
GLFWbool transparent; GLFWbool transparent;
GLFWbool scaleToMonitor;
// The last received cursor position, regardless of source // The last received cursor position, regardless of source
int lastCursorPosX, lastCursorPosY; int lastCursorPosX, lastCursorPosY;
@ -326,6 +354,10 @@ typedef struct _GLFWlibraryWin32
HINSTANCE instance; HINSTANCE instance;
PFN_SetProcessDPIAware SetProcessDPIAware_; PFN_SetProcessDPIAware SetProcessDPIAware_;
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_; PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
PFN_GetDpiForWindow GetDpiForWindow_;
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
} user32; } user32;
struct { struct {
@ -341,6 +373,11 @@ typedef struct _GLFWlibraryWin32
PFN_GetDpiForMonitor GetDpiForMonitor_; PFN_GetDpiForMonitor GetDpiForMonitor_;
} shcore; } shcore;
struct {
HINSTANCE instance;
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
} ntdll;
} _GLFWlibraryWin32; } _GLFWlibraryWin32;
// Win32-specific per-monitor data // Win32-specific per-monitor data
@ -396,10 +433,11 @@ typedef struct _GLFWmutexWin32
GLFWbool _glfwRegisterWindowClassWin32(void); GLFWbool _glfwRegisterWindowClassWin32(void);
void _glfwUnregisterWindowClassWin32(void); void _glfwUnregisterWindowClassWin32(void);
GLFWbool _glfwIsCompositionEnabledWin32(void);
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
void _glfwInputErrorWin32(int error, const char* description); void _glfwInputErrorWin32(int error, const char* description);
void _glfwUpdateKeyNamesWin32(void); void _glfwUpdateKeyNamesWin32(void);

241
glfw/win32_window.c vendored
View File

@ -186,14 +186,20 @@ static HICON createIcon(const GLFWimage* image,
return handle; return handle;
} }
// Translate client window size to full window size according to styles // Translate client window size to full window size according to styles and DPI
// //
static void getFullWindowSize(DWORD style, DWORD exStyle, static void getFullWindowSize(DWORD style, DWORD exStyle,
int clientWidth, int clientHeight, int clientWidth, int clientHeight,
int* fullWidth, int* fullHeight) int* fullWidth, int* fullHeight,
UINT dpi)
{ {
RECT rect = { 0, 0, clientWidth, clientHeight }; RECT rect = { 0, 0, clientWidth, clientHeight };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle); AdjustWindowRectEx(&rect, style, FALSE, exStyle);
*fullWidth = rect.right - rect.left; *fullWidth = rect.right - rect.left;
*fullHeight = rect.bottom - rect.top; *fullHeight = rect.bottom - rect.top;
} }
@ -206,7 +212,8 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
const float ratio = (float) window->numer / (float) window->denom; const float ratio = (float) window->numer / (float) window->denom;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff); 0, 0, &xoff, &yoff,
GetDpiForWindow(window->win32.handle));
if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT || if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT) edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
@ -337,7 +344,16 @@ static void updateWindowStyles(const _GLFWwindow* window)
style |= getWindowStyle(window); style |= getWindowStyle(window);
GetClientRect(window->win32.handle, &rect); GetClientRect(window->win32.handle, &rect);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE,
getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window)); AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
ClientToScreen(window->win32.handle, (POINT*) &rect.left); ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right); ClientToScreen(window->win32.handle, (POINT*) &rect.right);
SetWindowLongW(window->win32.handle, GWL_STYLE, style); SetWindowLongW(window->win32.handle, GWL_STYLE, style);
@ -351,10 +367,12 @@ static void updateWindowStyles(const _GLFWwindow* window)
// //
static void updateFramebufferTransparency(const _GLFWwindow* window) static void updateFramebufferTransparency(const _GLFWwindow* window)
{ {
BOOL enabled;
if (!IsWindowsVistaOrGreater()) if (!IsWindowsVistaOrGreater())
return; return;
if (_glfwIsCompositionEnabledWin32()) if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{ {
HRGN region = CreateRectRgn(0, 0, -1, -1); HRGN region = CreateRectRgn(0, 0, -1, -1);
DWM_BLURBEHIND bb = {0}; DWM_BLURBEHIND bb = {0};
@ -396,29 +414,6 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
} }
} }
// Translates a GLFW standard cursor to a resource ID
//
static LPWSTR translateCursorShape(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return IDC_ARROW;
case GLFW_IBEAM_CURSOR:
return IDC_IBEAM;
case GLFW_CROSSHAIR_CURSOR:
return IDC_CROSS;
case GLFW_HAND_CURSOR:
return IDC_HAND;
case GLFW_HRESIZE_CURSOR:
return IDC_SIZEWE;
case GLFW_VRESIZE_CURSOR:
return IDC_SIZENS;
}
return NULL;
}
// Retrieves and translates modifier keys // Retrieves and translates modifier keys
// //
static int getKeyMods(void) static int getKeyMods(void)
@ -578,9 +573,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (!window) if (!window)
{ {
// This is the message handling for the hidden helper window // This is the message handling for the hidden helper window
// and for a regular window during its initial creation
switch (uMsg) switch (uMsg)
{ {
case WM_NCCREATE:
{
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
EnableNonClientDpiScaling(hWnd);
break;
}
case WM_DISPLAYCHANGE: case WM_DISPLAYCHANGE:
_glfwPollMonitorsWin32(); _glfwPollMonitorsWin32();
break; break;
@ -1003,7 +1007,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break; break;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff); 0, 0, &xoff, &yoff,
GetDpiForWindow(window->win32.handle));
if (window->minwidth != GLFW_DONT_CARE && if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE) window->minheight != GLFW_DONT_CARE)
@ -1056,10 +1061,52 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return 0; return 0;
} }
case WM_GETDPISCALEDSIZE:
{
if (window->win32.scaleToMonitor)
break;
// Adjust the window size to keep the client area size constant
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
{
RECT source = {0}, target = {0};
SIZE* size = (SIZE*) lParam;
AdjustWindowRectExForDpi(&source, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
AdjustWindowRectExForDpi(&target, getWindowStyle(window),
FALSE, getWindowExStyle(window),
LOWORD(wParam));
size->cx += (target.right - target.left) -
(source.right - source.left);
size->cy += (target.bottom - target.top) -
(source.bottom - source.top);
return TRUE;
}
break;
}
case WM_DPICHANGED: case WM_DPICHANGED:
{ {
const float xscale = HIWORD(wParam) / 96.f; const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
const float yscale = LOWORD(wParam) / 96.f; const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
// Only apply the suggested size if the OS is new enough to have
// sent a WM_GETDPISCALEDSIZE before this
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
{
RECT* suggested = (RECT*) lParam;
SetWindowPos(window->win32.handle, HWND_TOP,
suggested->left,
suggested->top,
suggested->right - suggested->left,
suggested->bottom - suggested->top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
_glfwInputWindowContentScale(window, xscale, yscale); _glfwInputWindowContentScale(window, xscale, yscale);
break; break;
} }
@ -1146,7 +1193,8 @@ static int createNativeWindow(_GLFWwindow* window,
getFullWindowSize(style, exStyle, getFullWindowSize(style, exStyle,
wndconfig->width, wndconfig->height, wndconfig->width, wndconfig->height,
&fullWidth, &fullHeight); &fullWidth, &fullHeight,
USER_DEFAULT_SCREEN_DPI);
} }
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
@ -1185,6 +1233,40 @@ static int createNativeWindow(_GLFWwindow* window,
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL); WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
} }
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
// Adjust window size to account for DPI scaling of the window frame and
// optionally DPI scaling of the client area
// This cannot be done until we know what monitor it was placed on
if (!window->monitor)
{
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
if (wndconfig->scaleToMonitor)
{
float xscale, yscale;
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
rect.right = (int) (rect.right * xscale);
rect.bottom = (int) (rect.bottom * yscale);
}
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
GetDpiForWindow(window->win32.handle));
}
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
SetWindowPos(window->win32.handle, NULL,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
DragAcceptFiles(window->win32.handle, TRUE); DragAcceptFiles(window->win32.handle, TRUE);
if (fbconfig->transparent) if (fbconfig->transparent)
@ -1244,20 +1326,6 @@ void _glfwUnregisterWindowClassWin32(void)
UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL)); UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
} }
// Returns whether desktop compositing is enabled
//
GLFWbool _glfwIsCompositionEnabledWin32(void)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)))
return enabled;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
@ -1395,8 +1463,19 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{ {
RECT rect = { xpos, ypos, xpos, ypos }; RECT rect = { xpos, ypos, xpos, ypos };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window), AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window)); FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0, SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
} }
@ -1425,8 +1504,19 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
else else
{ {
RECT rect = { 0, 0, width, height }; RECT rect = { 0, 0, width, height };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window), AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window)); FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, HWND_TOP, SetWindowPos(window->win32.handle, HWND_TOP,
0, 0, rect.right - rect.left, rect.bottom - rect.top, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER); SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
@ -1481,8 +1571,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
_glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformGetWindowSize(window, &width, &height);
SetRect(&rect, 0, 0, width, height); SetRect(&rect, 0, 0, width, height);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window), AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window)); FALSE, getWindowExStyle(window));
}
if (left) if (left)
*left = -rect.left; *left = -rect.left;
@ -1563,8 +1663,19 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else else
{ {
RECT rect = { xpos, ypos, xpos + width, ypos + height }; RECT rect = { xpos, ypos, xpos + width, ypos + height };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window), AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window)); FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, HWND_TOP, SetWindowPos(window->win32.handle, HWND_TOP,
rect.left, rect.top, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, rect.right - rect.left, rect.bottom - rect.top,
@ -1624,8 +1735,18 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else else
after = HWND_NOTOPMOST; after = HWND_NOTOPMOST;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window), AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window)); FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, after, SetWindowPos(window->win32.handle, after,
rect.left, rect.top, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, rect.right - rect.left, rect.bottom - rect.top,
@ -1660,7 +1781,15 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{ {
return window->win32.transparent && _glfwIsCompositionEnabledWin32(); BOOL enabled;
if (!window->win32.transparent)
return GLFW_FALSE;
if (!IsWindowsVistaOrGreater())
return GLFW_FALSE;
return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
} }
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
@ -1867,8 +1996,24 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{ {
cursor->win32.handle = LPCWSTR name = NULL;
CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
if (shape == GLFW_ARROW_CURSOR)
name = IDC_ARROW;
else if (shape == GLFW_IBEAM_CURSOR)
name = IDC_IBEAM;
else if (shape == GLFW_CROSSHAIR_CURSOR)
name = IDC_CROSS;
else if (shape == GLFW_HAND_CURSOR)
name = IDC_HAND;
else if (shape == GLFW_HRESIZE_CURSOR)
name = IDC_SIZEWE;
else if (shape == GLFW_VRESIZE_CURSOR)
name = IDC_SIZENS;
else
return GLFW_FALSE;
cursor->win32.handle = CopyCursor(LoadCursorW(NULL, name));
if (!cursor->win32.handle) if (!cursor->win32.handle)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,

3
glfw/window.c vendored
View File

@ -393,6 +393,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_COCOA_GRAPHICS_SWITCHING: case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
return; return;
case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CENTER_CURSOR: case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
return; return;

79
glfw/x11_window.c vendored
View File

@ -161,29 +161,6 @@ static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer po
event->xproperty.atom == notification->xselection.property; event->xproperty.atom == notification->xselection.property;
} }
// Translates a GLFW standard cursor to a font cursor shape
//
static int translateCursorShape(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return XC_left_ptr;
case GLFW_IBEAM_CURSOR:
return XC_xterm;
case GLFW_CROSSHAIR_CURSOR:
return XC_crosshair;
case GLFW_HAND_CURSOR:
return XC_hand1;
case GLFW_HRESIZE_CURSOR:
return XC_sb_h_double_arrow;
case GLFW_VRESIZE_CURSOR:
return XC_sb_v_double_arrow;
}
return 0;
}
// Translates an X event modifier state mask // Translates an X event modifier state mask
// //
static int translateState(int state) static int translateState(int state)
@ -206,23 +183,6 @@ static int translateState(int state)
return mods; return mods;
} }
// Return the GLFW window corresponding to the specified X11 window
//
static _GLFWwindow* findWindowByHandle(Window handle)
{
_GLFWwindow* window;
if (XFindContext(_glfw.x11.display,
handle,
_glfw.x11.context,
(XPointer*) &window) != 0)
{
return NULL;
}
return window;
}
// Sends an EWMH or ICCCM event to the window manager // Sends an EWMH or ICCCM event to the window manager
// //
static void sendEventToWM(_GLFWwindow* window, Atom type, static void sendEventToWM(_GLFWwindow* window, Atom type,
@ -582,6 +542,15 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig, const _GLFWwndconfig* wndconfig,
Visual* visual, int depth) Visual* visual, int depth)
{ {
int width = wndconfig->width;
int height = wndconfig->height;
if (wndconfig->scaleToMonitor)
{
width *= _glfw.x11.contentScaleX;
height *= _glfw.x11.contentScaleY;
}
// Create a colormap based on the visual used by the current context // Create a colormap based on the visual used by the current context
window->x11.colormap = XCreateColormap(_glfw.x11.display, window->x11.colormap = XCreateColormap(_glfw.x11.display,
_glfw.x11.root, _glfw.x11.root,
@ -607,7 +576,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
window->x11.handle = XCreateWindow(_glfw.x11.display, window->x11.handle = XCreateWindow(_glfw.x11.display,
_glfw.x11.root, _glfw.x11.root,
0, 0, 0, 0,
wndconfig->width, wndconfig->height, width, height,
0, // Border width 0, // Border width
depth, // Color depth depth, // Color depth
InputOutput, InputOutput,
@ -710,7 +679,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
XFree(hints); XFree(hints);
} }
updateNormalHints(window, wndconfig->width, wndconfig->height); updateNormalHints(window, width, height);
// Set ICCCM WM_CLASS property // Set ICCCM WM_CLASS property
{ {
@ -1243,8 +1212,10 @@ static void processEvent(XEvent *event)
return; return;
} }
window = findWindowByHandle(event->xany.window); if (XFindContext(_glfw.x11.display,
if (window == NULL) event->xany.window,
_glfw.x11.context,
(XPointer*) &window) != 0)
{ {
// This is an event for a window that has already been destroyed // This is an event for a window that has already been destroyed
return; return;
@ -2680,8 +2651,24 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{ {
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, int native = 0;
translateCursorShape(shape));
if (shape == GLFW_ARROW_CURSOR)
native = XC_left_ptr;
else if (shape == GLFW_IBEAM_CURSOR)
native = XC_xterm;
else if (shape == GLFW_CROSSHAIR_CURSOR)
native = XC_crosshair;
else if (shape == GLFW_HAND_CURSOR)
native = XC_hand1;
else if (shape == GLFW_HRESIZE_CURSOR)
native = XC_sb_h_double_arrow;
else if (shape == GLFW_VRESIZE_CURSOR)
native = XC_sb_v_double_arrow;
else
return GLFW_FALSE;
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
if (!cursor->x11.handle) if (!cursor->x11.handle)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,

4
kitty/glfw-wrapper.h generated
View File

@ -734,6 +734,10 @@ typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_CLIENT_API_attrib).
*/ */
#define GLFW_CONTEXT_CREATION_API 0x0002200B #define GLFW_CONTEXT_CREATION_API 0x0002200B
/*! @brief Window content area scaling window
* [window hint](@ref GLFW_SCALE_TO_MONITOR).
*/
#define GLFW_SCALE_TO_MONITOR 0x0002200C
#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001 #define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
#define GLFW_COCOA_FRAME_NAME 0x00023002 #define GLFW_COCOA_FRAME_NAME 0x00023002