mirror of
				https://github.com/Ryujinx/SDL.git
				synced 2025-11-04 07:44:48 +00:00 
			
		
		
		
	Support PMv2 DPI awareness, add SDL_HINT_WINDOWS_DPI_AWARENESS
The hint allows setting a specific DPI awareness ("unaware", "system", "permonitor", "permonitorv2").
This is the first part of High-DPI support on Windows ( https://github.com/libsdl-org/SDL/issues/2119 ).
It doesn't implement a virtualized SDL coordinate system, which will be
addressed in a later commit. (This hint could be useful for SDL apps
that want 1 SDL unit = 1 pixel, though.)
Detecting and behaving correctly under per-monitor V2
(calling AdjustWindowRectExForDpi where needed) should fix the
following issues:
https://github.com/libsdl-org/SDL/issues/3286
https://github.com/libsdl-org/SDL/issues/4712
			
			
This commit is contained in:
		
							parent
							
								
									81d3adddbf
								
							
						
					
					
						commit
						51ebefeeee
					
				| 
						 | 
				
			
			@ -1808,6 +1808,36 @@ extern "C" {
 | 
			
		|||
 */
 | 
			
		||||
#define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Controls whether SDL will declare the process to be DPI aware.
 | 
			
		||||
 *
 | 
			
		||||
 *  This hint must be set before initializing the video subsystem.
 | 
			
		||||
 *
 | 
			
		||||
 *  The main purpose of declaring DPI awareness is to disable OS bitmap scaling of SDL windows on monitors with 
 | 
			
		||||
 *  a DPI scale factor.
 | 
			
		||||
 * 
 | 
			
		||||
 *  This hint is equivalent to requesting DPI awareness via external means (e.g. calling SetProcessDpiAwarenessContext)
 | 
			
		||||
 *  and does not cause SDL to use a virtualized coordinate system, so it will generally give you 1 SDL coordinate = 1 pixel
 | 
			
		||||
 *  even on high-DPI displays.
 | 
			
		||||
 * 
 | 
			
		||||
 *  For more information, see:
 | 
			
		||||
 *  https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
 | 
			
		||||
 * 
 | 
			
		||||
 *  This variable can be set to the following values:
 | 
			
		||||
 *    ""             - Do not change the DPI awareness (default).
 | 
			
		||||
 *    "unaware"      - Declare the process as DPI unaware. (Windows 8.1 and later).
 | 
			
		||||
 *    "system"       - Request system DPI awareness. (Vista and later).
 | 
			
		||||
 *    "permonitor"   - Request per-monitor DPI awareness. (Windows 8.1 and later).
 | 
			
		||||
 *    "permonitorv2" - Request per-monitor V2 DPI awareness. (Windows 10, version 1607 and later).
 | 
			
		||||
 *                     The most visible difference from "permonitor" is that window title bar will be scaled
 | 
			
		||||
 *                     to the visually correct size when dragging between monitors with different scale factors.
 | 
			
		||||
 *                     This is the preferred DPI awareness level.
 | 
			
		||||
 *
 | 
			
		||||
 * If the requested DPI awareness is not available on the currently running OS, SDL will try to request the best
 | 
			
		||||
 * available match.
 | 
			
		||||
 */
 | 
			
		||||
#define SDL_HINT_WINDOWS_DPI_AWARENESS "SDL_WINDOWS_DPI_AWARENESS"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  \brief  A variable controlling whether the window frame and title bar are interactive when the cursor is hidden 
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@
 | 
			
		|||
#include "../../events/SDL_touch_c.h"
 | 
			
		||||
#include "../../events/scancodes_windows.h"
 | 
			
		||||
#include "SDL_hints.h"
 | 
			
		||||
#include "SDL_log.h"
 | 
			
		||||
 | 
			
		||||
/* Dropfile support */
 | 
			
		||||
#include <shellapi.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +53,8 @@
 | 
			
		|||
#include "wmmsg.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* #define HIGHDPI_DEBUG */
 | 
			
		||||
 | 
			
		||||
/* Masks for processing the windows KEYDOWN and KEYUP messages */
 | 
			
		||||
#define REPEATED_KEYMASK    (1<<30)
 | 
			
		||||
#define EXTENDED_KEYMASK    (1<<24)
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +89,12 @@
 | 
			
		|||
#ifndef WM_UNICHAR
 | 
			
		||||
#define WM_UNICHAR 0x0109
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef WM_DPICHANGED
 | 
			
		||||
#define WM_DPICHANGED 0x02E0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef WM_GETDPISCALEDSIZE
 | 
			
		||||
#define WM_GETDPISCALEDSIZE 0x02E4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef IS_HIGH_SURROGATE
 | 
			
		||||
#define IS_HIGH_SURROGATE(x)   (((x) >= 0xd800) && ((x) <= 0xdbff))
 | 
			
		||||
| 
						 | 
				
			
			@ -1084,7 +1093,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 | 
			
		|||
                size.bottom = h;
 | 
			
		||||
                size.right = w;
 | 
			
		||||
 | 
			
		||||
                AdjustWindowRectEx(&size, style, menu, 0);
 | 
			
		||||
                if (WIN_IsPerMonitorV2DPIAware(SDL_GetVideoDevice())) {
 | 
			
		||||
                    UINT dpi = data->videodata->GetDpiForWindow(hwnd);
 | 
			
		||||
                    data->videodata->AdjustWindowRectExForDpi(&size, style, menu, 0, dpi);
 | 
			
		||||
                } else {
 | 
			
		||||
                    AdjustWindowRectEx(&size, style, menu, 0);
 | 
			
		||||
                }
 | 
			
		||||
                w = size.right - size.left;
 | 
			
		||||
                h = size.bottom - size.top;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1154,6 +1168,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 | 
			
		|||
            h = rect.bottom - rect.top;
 | 
			
		||||
            SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w, h);
 | 
			
		||||
 | 
			
		||||
#ifdef HIGHDPI_DEBUG
 | 
			
		||||
            SDL_Log("WM_WINDOWPOSCHANGED: Windows client rect (pixels): (%d, %d) (%d x %d)\tSDL client rect: (%d, %d) (%d x %d)\tGetDpiForWindow: %d",
 | 
			
		||||
                    rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
 | 
			
		||||
                    x, y, w, h, data->videodata->GetDpiForWindow ? (int)data->videodata->GetDpiForWindow(data->hwnd) : 0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            /* Forces a WM_PAINT event */
 | 
			
		||||
            InvalidateRect(hwnd, NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1399,6 +1419,120 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case WM_GETDPISCALEDSIZE:
 | 
			
		||||
        /* Windows 10 Creators Update+ */
 | 
			
		||||
        /* Documented as only being sent to windows that are per-monitor V2 DPI aware. */
 | 
			
		||||
        if (data->videodata->GetDpiForWindow && data->videodata->AdjustWindowRectExForDpi) {
 | 
			
		||||
            /* Windows expects applications to scale their window rects linearly
 | 
			
		||||
               when dragging between monitors with different DPI's.
 | 
			
		||||
               e.g. a 100x100 window dragged to a 200% scaled monitor
 | 
			
		||||
               becomes 200x200.
 | 
			
		||||
 | 
			
		||||
               For SDL, we instead want the client size to scale linearly.
 | 
			
		||||
               This is not the same as the window rect scaling linearly,
 | 
			
		||||
               because Windows doesn't scale the non-client area (titlebar etc.)
 | 
			
		||||
               linearly. So, we need to handle this message to request custom
 | 
			
		||||
               scaling. */
 | 
			
		||||
            
 | 
			
		||||
            const int nextDPI = (int)wParam;
 | 
			
		||||
            const int prevDPI = (int)data->videodata->GetDpiForWindow(hwnd);
 | 
			
		||||
            SIZE *sizeInOut = (SIZE *)lParam;
 | 
			
		||||
 | 
			
		||||
            int frame_w, frame_h;
 | 
			
		||||
            int query_client_w_win, query_client_h_win;
 | 
			
		||||
 | 
			
		||||
            const DWORD style = GetWindowLong(hwnd, GWL_STYLE);
 | 
			
		||||
            const BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
 | 
			
		||||
 | 
			
		||||
#ifdef HIGHDPI_DEBUG
 | 
			
		||||
            SDL_Log("WM_GETDPISCALEDSIZE: current DPI: %d potential DPI: %d input size: (%dx%d)",
 | 
			
		||||
                    prevDPI, nextDPI, sizeInOut->cx, sizeInOut->cy);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            /* Subtract the window frame size that would have been used at prevDPI */
 | 
			
		||||
            {
 | 
			
		||||
                RECT rect = {0};
 | 
			
		||||
 | 
			
		||||
                if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) {
 | 
			
		||||
                    data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, prevDPI);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                frame_w = -rect.left + rect.right;
 | 
			
		||||
                frame_h = -rect.top + rect.bottom;
 | 
			
		||||
 | 
			
		||||
                query_client_w_win = sizeInOut->cx - frame_w;
 | 
			
		||||
                query_client_h_win = sizeInOut->cy - frame_h;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Add the window frame size that would be used at nextDPI */
 | 
			
		||||
            {
 | 
			
		||||
                RECT rect = { 0, 0, query_client_w_win, query_client_h_win };
 | 
			
		||||
 | 
			
		||||
                if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) {
 | 
			
		||||
                    data->videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, nextDPI);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* This is supposed to control the suggested rect param of WM_DPICHANGED */
 | 
			
		||||
                sizeInOut->cx = rect.right - rect.left;
 | 
			
		||||
                sizeInOut->cy = rect.bottom - rect.top;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#ifdef HIGHDPI_DEBUG
 | 
			
		||||
            SDL_Log("WM_GETDPISCALEDSIZE: output size: (%dx%d)", sizeInOut->cx, sizeInOut->cy);
 | 
			
		||||
#endif
 | 
			
		||||
            return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case WM_DPICHANGED:
 | 
			
		||||
        /* Windows 8.1+ */
 | 
			
		||||
        {
 | 
			
		||||
            const int newDPI = HIWORD(wParam);
 | 
			
		||||
            RECT* const suggestedRect = (RECT*)lParam;
 | 
			
		||||
            int w, h;
 | 
			
		||||
 | 
			
		||||
#ifdef HIGHDPI_DEBUG
 | 
			
		||||
            SDL_Log("WM_DPICHANGED: to %d\tsuggested rect: (%d, %d), (%dx%d)\n", newDPI,
 | 
			
		||||
                suggestedRect->left, suggestedRect->top, suggestedRect->right - suggestedRect->left, suggestedRect->bottom - suggestedRect->top);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            /* DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 means that
 | 
			
		||||
               WM_GETDPISCALEDSIZE will have been called, so we can use suggestedRect. */
 | 
			
		||||
            if (WIN_IsPerMonitorV2DPIAware(SDL_GetVideoDevice())) {
 | 
			
		||||
                w = suggestedRect->right - suggestedRect->left;
 | 
			
		||||
                h = suggestedRect->bottom - suggestedRect->top;
 | 
			
		||||
            } else {
 | 
			
		||||
                RECT rect = { 0, 0, data->window->w, data->window->h };
 | 
			
		||||
                const DWORD style = GetWindowLong(hwnd, GWL_STYLE);
 | 
			
		||||
                const BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
 | 
			
		||||
 | 
			
		||||
                if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) {
 | 
			
		||||
                    AdjustWindowRectEx(&rect, style, menu, 0);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                w = rect.right - rect.left;
 | 
			
		||||
                h = rect.bottom - rect.top;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
#ifdef HIGHDPI_DEBUG
 | 
			
		||||
            SDL_Log("WM_DPICHANGED: current SDL window size: (%dx%d)\tcalling SetWindowPos: (%d, %d), (%dx%d)\n",
 | 
			
		||||
                data->window->w, data->window->h,
 | 
			
		||||
                suggestedRect->left, suggestedRect->top, w, h);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            data->expected_resize = SDL_TRUE;
 | 
			
		||||
            SetWindowPos(hwnd,
 | 
			
		||||
                NULL,
 | 
			
		||||
                suggestedRect->left,
 | 
			
		||||
                suggestedRect->top,
 | 
			
		||||
                w,
 | 
			
		||||
                h,
 | 
			
		||||
                SWP_NOZORDER | SWP_NOACTIVATE);
 | 
			
		||||
            data->expected_resize = SDL_FALSE;
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If there's a window proc, assume it's going to handle messages */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,6 +122,16 @@ WIN_CreateDevice(int devindex)
 | 
			
		|||
        data->CloseTouchInputHandle = (BOOL (WINAPI *)(HTOUCHINPUT)) SDL_LoadFunction(data->userDLL, "CloseTouchInputHandle");
 | 
			
		||||
        data->GetTouchInputInfo = (BOOL (WINAPI *)(HTOUCHINPUT, UINT, PTOUCHINPUT, int)) SDL_LoadFunction(data->userDLL, "GetTouchInputInfo");
 | 
			
		||||
        data->RegisterTouchWindow = (BOOL (WINAPI *)(HWND, ULONG)) SDL_LoadFunction(data->userDLL, "RegisterTouchWindow");
 | 
			
		||||
        data->SetProcessDPIAware = (BOOL (WINAPI *)(void)) SDL_LoadFunction(data->userDLL, "SetProcessDPIAware");
 | 
			
		||||
        data->SetProcessDpiAwarenessContext = (BOOL (WINAPI *)(DPI_AWARENESS_CONTEXT)) SDL_LoadFunction(data->userDLL, "SetProcessDpiAwarenessContext");
 | 
			
		||||
        data->SetThreadDpiAwarenessContext = (DPI_AWARENESS_CONTEXT (WINAPI *)(DPI_AWARENESS_CONTEXT)) SDL_LoadFunction(data->userDLL, "SetThreadDpiAwarenessContext");
 | 
			
		||||
        data->GetThreadDpiAwarenessContext = (DPI_AWARENESS_CONTEXT (WINAPI *)(void)) SDL_LoadFunction(data->userDLL, "GetThreadDpiAwarenessContext");
 | 
			
		||||
        data->GetAwarenessFromDpiAwarenessContext = (DPI_AWARENESS (WINAPI *)(DPI_AWARENESS_CONTEXT)) SDL_LoadFunction(data->userDLL, "GetAwarenessFromDpiAwarenessContext");
 | 
			
		||||
        data->EnableNonClientDpiScaling = (BOOL (WINAPI *)(HWND)) SDL_LoadFunction(data->userDLL, "EnableNonClientDpiScaling");
 | 
			
		||||
        data->AdjustWindowRectExForDpi = (BOOL (WINAPI *)(LPRECT, DWORD, BOOL, DWORD, UINT)) SDL_LoadFunction(data->userDLL, "AdjustWindowRectExForDpi");
 | 
			
		||||
        data->GetDpiForWindow = (UINT (WINAPI *)(HWND)) SDL_LoadFunction(data->userDLL, "GetDpiForWindow");
 | 
			
		||||
        data->AreDpiAwarenessContextsEqual = (BOOL (WINAPI *)(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT)) SDL_LoadFunction(data->userDLL, "AreDpiAwarenessContextsEqual");
 | 
			
		||||
        data->IsValidDpiAwarenessContext = (BOOL (WINAPI *)(DPI_AWARENESS_CONTEXT)) SDL_LoadFunction(data->userDLL, "IsValidDpiAwarenessContext");
 | 
			
		||||
    } else {
 | 
			
		||||
        SDL_ClearError();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +139,7 @@ WIN_CreateDevice(int devindex)
 | 
			
		|||
    data->shcoreDLL = SDL_LoadObject("SHCORE.DLL");
 | 
			
		||||
    if (data->shcoreDLL) {
 | 
			
		||||
        data->GetDpiForMonitor = (HRESULT (WINAPI *)(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *)) SDL_LoadFunction(data->shcoreDLL, "GetDpiForMonitor");
 | 
			
		||||
        data->SetProcessDpiAwareness = (HRESULT (WINAPI *)(PROCESS_DPI_AWARENESS)) SDL_LoadFunction(data->shcoreDLL, "SetProcessDpiAwareness");
 | 
			
		||||
    } else {
 | 
			
		||||
        SDL_ClearError();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -233,11 +244,103 @@ VideoBootStrap WINDOWS_bootstrap = {
 | 
			
		|||
    "windows", "SDL Windows video driver", WIN_CreateDevice
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static BOOL
 | 
			
		||||
WIN_DeclareDPIAwareUnaware(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    SDL_VideoData* data = (SDL_VideoData*)_this->driverdata;
 | 
			
		||||
 | 
			
		||||
    if (data->SetProcessDpiAwarenessContext) {
 | 
			
		||||
        return data->SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
 | 
			
		||||
    } else if (data->SetProcessDpiAwareness) {
 | 
			
		||||
        /* Windows 8.1 */
 | 
			
		||||
        return SUCCEEDED(data->SetProcessDpiAwareness(PROCESS_DPI_UNAWARE));
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BOOL
 | 
			
		||||
WIN_DeclareDPIAwareSystem(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    SDL_VideoData* data = (SDL_VideoData*)_this->driverdata;
 | 
			
		||||
 | 
			
		||||
    if (data->SetProcessDpiAwarenessContext) {
 | 
			
		||||
        /* Windows 10, version 1607 */
 | 
			
		||||
        return data->SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
 | 
			
		||||
    } else if (data->SetProcessDpiAwareness) {
 | 
			
		||||
        /* Windows 8.1 */
 | 
			
		||||
        return SUCCEEDED(data->SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE));
 | 
			
		||||
    } else if (data->SetProcessDPIAware) {
 | 
			
		||||
        /* Windows Vista */
 | 
			
		||||
        return data->SetProcessDPIAware();
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BOOL
 | 
			
		||||
WIN_DeclareDPIAwarePerMonitor(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
 | 
			
		||||
 | 
			
		||||
    if (data->SetProcessDpiAwarenessContext) {
 | 
			
		||||
        /* Windows 10, version 1607 */
 | 
			
		||||
        return data->SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
 | 
			
		||||
    } else if (data->SetProcessDpiAwareness) {
 | 
			
		||||
        /* Windows 8.1 */
 | 
			
		||||
        return SUCCEEDED(data->SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE));
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Older OS: fall back to system DPI aware */
 | 
			
		||||
        return WIN_DeclareDPIAwareSystem(_this);
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static BOOL
 | 
			
		||||
WIN_DeclareDPIAwarePerMonitorV2(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    SDL_VideoData* data = (SDL_VideoData*)_this->driverdata;
 | 
			
		||||
 | 
			
		||||
    /* Declare DPI aware(may have been done in external code or a manifest, as well) */
 | 
			
		||||
    if (data->SetProcessDpiAwarenessContext) {
 | 
			
		||||
        /* Windows 10, version 1607 */
 | 
			
		||||
 | 
			
		||||
        /* NOTE: SetThreadDpiAwarenessContext doesn't work here with OpenGL - the OpenGL contents
 | 
			
		||||
           end up still getting OS scaled. (tested on Windows 10 21H1 19043.1348, NVIDIA 496.49) */
 | 
			
		||||
        if (data->SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) {
 | 
			
		||||
            return TRUE;
 | 
			
		||||
        } else {
 | 
			
		||||
            return WIN_DeclareDPIAwarePerMonitor(_this);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Older OS: fall back to per-monitor (or system) */
 | 
			
		||||
        return WIN_DeclareDPIAwarePerMonitor(_this);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
WIN_InitDPIAwareness(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    const char* hint = SDL_GetHint(SDL_HINT_WINDOWS_DPI_AWARENESS);
 | 
			
		||||
 | 
			
		||||
    if (hint != NULL) {
 | 
			
		||||
        if (SDL_strcmp(hint, "permonitorv2") == 0) {
 | 
			
		||||
            WIN_DeclareDPIAwarePerMonitorV2(_this);
 | 
			
		||||
        } else if (SDL_strcmp(hint, "permonitor") == 0) {
 | 
			
		||||
            WIN_DeclareDPIAwarePerMonitor(_this);
 | 
			
		||||
        } else if (SDL_strcmp(hint, "system") == 0) {
 | 
			
		||||
            WIN_DeclareDPIAwareSystem(_this);
 | 
			
		||||
        } else if (SDL_strcmp(hint, "unaware") == 0) {
 | 
			
		||||
            WIN_DeclareDPIAwareUnaware(_this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
WIN_VideoInit(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
 | 
			
		||||
 | 
			
		||||
    WIN_InitDPIAwareness(_this);
 | 
			
		||||
 | 
			
		||||
    if (WIN_InitModes(_this) < 0) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -473,6 +576,19 @@ SDL_DXGIGetOutputInfo(int displayIndex, int *adapterIndex, int *outputIndex)
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SDL_bool
 | 
			
		||||
WIN_IsPerMonitorV2DPIAware(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    SDL_VideoData* data = (SDL_VideoData*) _this->driverdata;
 | 
			
		||||
    
 | 
			
		||||
    if (data->AreDpiAwarenessContextsEqual && data->GetThreadDpiAwarenessContext) {
 | 
			
		||||
        /* Windows 10, version 1607 */
 | 
			
		||||
        return (SDL_bool)data->AreDpiAwarenessContextsEqual(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,
 | 
			
		||||
                                                            data->GetThreadDpiAwarenessContext());
 | 
			
		||||
    }
 | 
			
		||||
    return SDL_FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
 | 
			
		||||
 | 
			
		||||
/* vim: set ts=4 sw=4 expandtab: */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,10 +86,40 @@ typedef enum MONITOR_DPI_TYPE {
 | 
			
		|||
    MDT_DEFAULT = MDT_EFFECTIVE_DPI
 | 
			
		||||
} MONITOR_DPI_TYPE;
 | 
			
		||||
 | 
			
		||||
typedef enum PROCESS_DPI_AWARENESS {
 | 
			
		||||
    PROCESS_DPI_UNAWARE = 0,
 | 
			
		||||
    PROCESS_SYSTEM_DPI_AWARE = 1,
 | 
			
		||||
    PROCESS_PER_MONITOR_DPI_AWARE = 2
 | 
			
		||||
} PROCESS_DPI_AWARENESS;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#include <shellscalingapi.h>
 | 
			
		||||
#endif /* WINVER < 0x0603 */
 | 
			
		||||
 | 
			
		||||
#ifndef _DPI_AWARENESS_CONTEXTS_
 | 
			
		||||
 | 
			
		||||
typedef enum DPI_AWARENESS {
 | 
			
		||||
    DPI_AWARENESS_INVALID = -1,
 | 
			
		||||
    DPI_AWARENESS_UNAWARE = 0,
 | 
			
		||||
    DPI_AWARENESS_SYSTEM_AWARE = 1,
 | 
			
		||||
    DPI_AWARENESS_PER_MONITOR_AWARE = 2
 | 
			
		||||
} DPI_AWARENESS;
 | 
			
		||||
 | 
			
		||||
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
 | 
			
		||||
 | 
			
		||||
#define DPI_AWARENESS_CONTEXT_UNAWARE           ((DPI_AWARENESS_CONTEXT)-1)
 | 
			
		||||
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE      ((DPI_AWARENESS_CONTEXT)-2)
 | 
			
		||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)
 | 
			
		||||
 | 
			
		||||
#endif /* _DPI_AWARENESS_CONTEXTS_ */
 | 
			
		||||
 | 
			
		||||
/* Windows 10 Creators Update */
 | 
			
		||||
#if NTDDI_VERSION < 0x0A000003
 | 
			
		||||
 | 
			
		||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
 | 
			
		||||
 | 
			
		||||
#endif /* NTDDI_VERSION < 0x0A000003 */
 | 
			
		||||
 | 
			
		||||
typedef BOOL  (*PFNSHFullScreen)(HWND, DWORD);
 | 
			
		||||
typedef void  (*PFCoordTransform)(SDL_Window*, POINT*);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -137,13 +167,24 @@ typedef struct SDL_VideoData
 | 
			
		|||
    BOOL (WINAPI *CloseTouchInputHandle)( HTOUCHINPUT );
 | 
			
		||||
    BOOL (WINAPI *GetTouchInputInfo)( HTOUCHINPUT, UINT, PTOUCHINPUT, int );
 | 
			
		||||
    BOOL (WINAPI *RegisterTouchWindow)( HWND, ULONG );
 | 
			
		||||
    BOOL (WINAPI *SetProcessDPIAware)( void );
 | 
			
		||||
    BOOL (WINAPI *SetProcessDpiAwarenessContext)( DPI_AWARENESS_CONTEXT );
 | 
			
		||||
    DPI_AWARENESS_CONTEXT (WINAPI *SetThreadDpiAwarenessContext)( DPI_AWARENESS_CONTEXT );
 | 
			
		||||
    DPI_AWARENESS_CONTEXT (WINAPI *GetThreadDpiAwarenessContext)( void );
 | 
			
		||||
    DPI_AWARENESS (WINAPI *GetAwarenessFromDpiAwarenessContext)( DPI_AWARENESS_CONTEXT );
 | 
			
		||||
    BOOL (WINAPI *EnableNonClientDpiScaling)( HWND );
 | 
			
		||||
    BOOL (WINAPI *AdjustWindowRectExForDpi)( LPRECT, DWORD, BOOL, DWORD, UINT );
 | 
			
		||||
    UINT (WINAPI *GetDpiForWindow)( HWND );
 | 
			
		||||
    BOOL (WINAPI *AreDpiAwarenessContextsEqual)(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT);
 | 
			
		||||
    BOOL (WINAPI *IsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
 | 
			
		||||
 | 
			
		||||
    void* shcoreDLL;
 | 
			
		||||
    HRESULT (WINAPI *GetDpiForMonitor)( HMONITOR         hmonitor,
 | 
			
		||||
                                        MONITOR_DPI_TYPE dpiType,
 | 
			
		||||
                                        UINT             *dpiX,
 | 
			
		||||
                                        UINT             *dpiY );
 | 
			
		||||
    
 | 
			
		||||
    HRESULT (WINAPI *SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS dpiAwareness);
 | 
			
		||||
 | 
			
		||||
    SDL_bool ime_com_initialized;
 | 
			
		||||
    struct ITfThreadMgr *ime_threadmgr;
 | 
			
		||||
    SDL_bool ime_initialized;
 | 
			
		||||
| 
						 | 
				
			
			@ -203,6 +244,8 @@ extern SDL_bool g_WindowFrameUsableWhileCursorHidden;
 | 
			
		|||
typedef struct IDirect3D9 IDirect3D9;
 | 
			
		||||
extern SDL_bool D3D_LoadDLL( void **pD3DDLL, IDirect3D9 **pDirect3D9Interface );
 | 
			
		||||
 | 
			
		||||
extern SDL_bool WIN_IsPerMonitorV2DPIAware(_THIS);
 | 
			
		||||
 | 
			
		||||
#endif /* SDL_windowsvideo_h_ */
 | 
			
		||||
 | 
			
		||||
/* vi: set ts=4 sw=4 expandtab: */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,8 +114,11 @@ GetWindowStyle(SDL_Window * window)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current)
 | 
			
		||||
WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current, 
 | 
			
		||||
                              SDL_bool force_ignore_window_dpi)
 | 
			
		||||
{
 | 
			
		||||
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
 | 
			
		||||
    SDL_VideoData* videodata = SDL_GetVideoDevice() ? SDL_GetVideoDevice()->driverdata : NULL;
 | 
			
		||||
    RECT rect;
 | 
			
		||||
 | 
			
		||||
    rect.left = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -126,8 +129,44 @@ WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x
 | 
			
		|||
    /* borderless windows will have WM_NCCALCSIZE return 0 for the non-client area. When this happens, it looks like windows will send a resize message
 | 
			
		||||
       expanding the window client area to the previous window + chrome size, so shouldn't need to adjust the window size for the set styles.
 | 
			
		||||
     */
 | 
			
		||||
    if (!(window->flags & SDL_WINDOW_BORDERLESS))
 | 
			
		||||
        AdjustWindowRectEx(&rect, style, menu, 0);
 | 
			
		||||
    if (!(window->flags & SDL_WINDOW_BORDERLESS)) {
 | 
			
		||||
        if (WIN_IsPerMonitorV2DPIAware(SDL_GetVideoDevice())) {
 | 
			
		||||
            /* With per-monitor v2, the window border/titlebar size depend on the DPI, so we need to call AdjustWindowRectExForDpi instead of 
 | 
			
		||||
               AdjustWindowRectEx. */
 | 
			
		||||
            UINT dpi;
 | 
			
		||||
 | 
			
		||||
            if (data && !force_ignore_window_dpi) {
 | 
			
		||||
                /* The usual case - we have a HWND, so we can look up the DPI to use. */
 | 
			
		||||
                dpi = videodata->GetDpiForWindow(data->hwnd);
 | 
			
		||||
            } else {
 | 
			
		||||
                /* In this case we guess the window DPI based on its rectangle on the screen.
 | 
			
		||||
                 
 | 
			
		||||
                   This happens at creation time of an SDL window, before we have a HWND, 
 | 
			
		||||
                   and also in a bug workaround (when force_ignore_window_dpi is SDL_TRUE
 | 
			
		||||
                   - see WIN_SetWindowFullscreen).
 | 
			
		||||
                */
 | 
			
		||||
                UINT unused;
 | 
			
		||||
                RECT screen_rect;
 | 
			
		||||
                HMONITOR mon;
 | 
			
		||||
 | 
			
		||||
                screen_rect.left = (use_current ? window->x : window->windowed.x);
 | 
			
		||||
                screen_rect.top = (use_current ? window->y : window->windowed.y);
 | 
			
		||||
                screen_rect.right = screen_rect.left + (use_current ? window->w : window->windowed.w);
 | 
			
		||||
                screen_rect.bottom  = screen_rect.top + (use_current ? window->h : window->windowed.h);
 | 
			
		||||
 | 
			
		||||
                mon = MonitorFromRect(&screen_rect, MONITOR_DEFAULTTONEAREST);
 | 
			
		||||
 | 
			
		||||
                /* GetDpiForMonitor docs promise to return the same hdpi / vdpi */
 | 
			
		||||
                if (videodata->GetDpiForMonitor(mon, MDT_EFFECTIVE_DPI, &dpi, &unused) != S_OK) {
 | 
			
		||||
                    dpi = 96;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            videodata->AdjustWindowRectExForDpi(&rect, style, menu, 0, dpi);
 | 
			
		||||
        } else {
 | 
			
		||||
            AdjustWindowRectEx(&rect, style, menu, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *x = (use_current ? window->x : window->windowed.x) + rect.left;
 | 
			
		||||
    *y = (use_current ? window->y : window->windowed.y) + rect.top;
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +184,7 @@ WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height
 | 
			
		|||
 | 
			
		||||
    style = GetWindowLong(hwnd, GWL_STYLE);
 | 
			
		||||
    menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
 | 
			
		||||
    WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current);
 | 
			
		||||
    WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current, SDL_FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +395,7 @@ WIN_CreateWindow(_THIS, SDL_Window * window)
 | 
			
		|||
    style |= GetWindowStyle(window);
 | 
			
		||||
 | 
			
		||||
    /* Figure out what the window area will be */
 | 
			
		||||
    WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE);
 | 
			
		||||
    WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE, SDL_FALSE);
 | 
			
		||||
 | 
			
		||||
    hwnd =
 | 
			
		||||
        CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
 | 
			
		||||
| 
						 | 
				
			
			@ -781,7 +820,13 @@ WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display,
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
 | 
			
		||||
        WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE);
 | 
			
		||||
        /* HighDPI bug workaround - when leaving exclusive fullscreen, the window DPI reported
 | 
			
		||||
           by GetDpiForWindow will be wrong. Pass SDL_TRUE for `force_ignore_window_dpi`
 | 
			
		||||
           makes us recompute the DPI based on the monitor we are restoring onto.
 | 
			
		||||
           Fixes windows shrinking slightly when going from exclusive fullscreen to windowed
 | 
			
		||||
           on a HighDPI monitor with scaling.
 | 
			
		||||
        */
 | 
			
		||||
        WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE, SDL_TRUE);
 | 
			
		||||
    }
 | 
			
		||||
    SetWindowLong(hwnd, GWL_STYLE, style);
 | 
			
		||||
    data->expected_resize = SDL_TRUE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue