diff options
author | Chun-wei Fan <fanchunwei@src.gnome.org> | 2019-12-04 18:41:05 +0800 |
---|---|---|
committer | Chun-wei Fan <fanchunwei@src.gnome.org> | 2019-12-04 18:50:12 +0800 |
commit | 4a79484d2abc48fd8784ab62fa5cc40f8ad01024 (patch) | |
tree | 6f0da95b9a227559b78982b6bf476a28006d6793 | |
parent | 33bd8f322c4e538f20dbb625dec733283638dde9 (diff) | |
download | gtk+-master.win32.improve.hidpi.tar.gz |
GDK-Win32: Use SetProcessDpiAwarenessContext() where availablemaster.win32.improve.hidpi
This allows us to use DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 for the
DPI awareness mode, which will help us to better support use cases with
multiple monitors. This is actualy a more advaned version of the
current PROCESS_PER_MONITOR_DPI_AWARE via using SetProcessDpiAwareness().
Note that this is not enabled by default, but also enabled via using
GDK_WIN32_PER_MONITOR_HIDPI, as in the PROCESS_PER_MONITOR_DPI_AWARE
case.
Note also, that appliation compatibility settings and DPI-awareness
manifests takes precedence over this API call, as before.
-rw-r--r-- | gdk/win32/gdkdisplay-win32.c | 75 | ||||
-rw-r--r-- | gdk/win32/gdkdisplay-win32.h | 32 |
2 files changed, 101 insertions, 6 deletions
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c index 9cd080012c..4c0b4f9585 100644 --- a/gdk/win32/gdkdisplay-win32.c +++ b/gdk/win32/gdkdisplay-win32.c @@ -720,6 +720,9 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display) gboolean check_for_dpi_awareness = FALSE; gboolean have_hpi_disable_envvar = FALSE; + HMODULE user32; + user32 = GetModuleHandleW (L"user32.dll"); + enum dpi_aware_status { DPI_STATUS_PENDING, DPI_STATUS_SUCCESS, @@ -731,6 +734,17 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display) { /* If we are on Windows 8.1 or later, cache up functions from shcore.dll, by all means */ display->have_at_least_win81 = TRUE; + + if (user32 != NULL) + { + display->user32_dpi_funcs.setPDAC = + (funcSPDAC) GetProcAddress (user32, "SetProcessDpiAwarenessContext"); + display->user32_dpi_funcs.getTDAC = + (funcGTDAC) GetProcAddress (user32, "GetThreadDpiAwarenessContext"); + display->user32_dpi_funcs.areDACEqual = + (funcADACE) GetProcAddress (user32, "AreDpiAwarenessContextsEqual"); + } + display->shcore_funcs.hshcore = LoadLibraryW (L"shcore.dll"); if (display->shcore_funcs.hshcore != NULL) @@ -750,10 +764,8 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display) else { /* Windows Vista through 8: use functions from user32.dll directly */ - HMODULE user32; display->have_at_least_win81 = FALSE; - user32 = GetModuleHandleW (L"user32.dll"); if (user32 != NULL) { @@ -770,7 +782,42 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display) if (display->have_at_least_win81) { /* then make the GDK-using app DPI-aware */ - if (display->shcore_funcs.setDpiAwareFunc != NULL) + if (display->user32_dpi_funcs.setPDAC != NULL) + { + HANDLE hidpi_mode_ctx; + GdkWin32ProcessDpiAwareness hidpi_mode; + + /* TODO: See how per-monitor DPI awareness is done by the Wayland backend */ + if (g_getenv ("GDK_WIN32_PER_MONITOR_HIDPI") != NULL) + { + hidpi_mode_ctx = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2; + hidpi_mode = PROCESS_PER_MONITOR_DPI_AWARE; + } + else + { + hidpi_mode_ctx = DPI_AWARENESS_CONTEXT_SYSTEM_AWARE; + hidpi_mode = PROCESS_SYSTEM_DPI_AWARE; + } + + if (display->user32_dpi_funcs.setPDAC (hidpi_mode_ctx)) + { + display->dpi_aware_type = hidpi_mode; + status = DPI_STATUS_SUCCESS; + } + else + { + DWORD err = GetLastError (); + + if (err == ERROR_ACCESS_DENIED) + check_for_dpi_awareness = TRUE; + else + { + display->dpi_aware_type = PROCESS_DPI_UNAWARE; + status = DPI_STATUS_FAILED; + } + } + } + else if (display->shcore_funcs.setDpiAwareFunc != NULL) { GdkWin32ProcessDpiAwareness hidpi_mode; @@ -841,7 +888,25 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display) { if (display->have_at_least_win81) { - if (display->shcore_funcs.getDpiAwareFunc != NULL) + if (display->user32_dpi_funcs.getTDAC != NULL && + display->user32_dpi_funcs.areDACEqual != NULL) + { + HANDLE dpi_aware_ctx = display->user32_dpi_funcs.getTDAC (); + if (display->user32_dpi_funcs.areDACEqual (dpi_aware_ctx, + DPI_AWARENESS_CONTEXT_UNAWARE)) + /* This means the DPI awareness setting was forcefully disabled */ + status = DPI_STATUS_DISABLED; + else + { + status = DPI_STATUS_SUCCESS; + if (display->user32_dpi_funcs.areDACEqual (dpi_aware_ctx, + DPI_AWARENESS_CONTEXT_SYSTEM_AWARE)) + display->dpi_aware_type = PROCESS_SYSTEM_DPI_AWARE; + else + display->dpi_aware_type = PROCESS_PER_MONITOR_DPI_AWARE_V2; + } + } + else if (display->shcore_funcs.getDpiAwareFunc != NULL) { display->shcore_funcs.getDpiAwareFunc (NULL, &display->dpi_aware_type); @@ -884,7 +949,7 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display) /* The user setting or application manifest trumps over GDK_WIN32_DISABLE_HIDPI */ g_print ("Note: GDK_WIN32_DISABLE_HIDPI is ignored due to preset\n" " DPI awareness settings in user settings or application\n" - " manifest, DPI awareness is still enabled."); + " manifest, DPI awareness is still enabled.\n"); } } diff --git a/gdk/win32/gdkdisplay-win32.h b/gdk/win32/gdkdisplay-win32.h index a4d9cc7378..91ce0db238 100644 --- a/gdk/win32/gdkdisplay-win32.h +++ b/gdk/win32/gdkdisplay-win32.h @@ -29,9 +29,24 @@ typedef enum _GdkWin32ProcessDpiAwareness { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, - PROCESS_PER_MONITOR_DPI_AWARE = 2 + PROCESS_PER_MONITOR_DPI_AWARE = 2, + PROCESS_PER_MONITOR_DPI_AWARE_V2 = 3, /* Newer HiDPI type for Windows 10 1607+ */ } GdkWin32ProcessDpiAwareness; +/* From https://docs.microsoft.com/en-US/windows/win32/hidpi/dpi-awareness-context */ +/* DPI_AWARENESS_CONTEXT is declared by DEFINE_HANDLE */ +#ifndef DPI_AWARENESS_CONTEXT_UNAWARE +#define DPI_AWARENESS_CONTEXT_UNAWARE (HANDLE)-1 +#endif + +#ifndef DPI_AWARENESS_CONTEXT_SYSTEM_AWARE +#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE (HANDLE)-2 +#endif + +#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 +#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (HANDLE)-4 +#endif + typedef enum _GdkWin32MonitorDpiType { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, @@ -59,10 +74,25 @@ typedef struct _GdkWin32ShcoreFuncs typedef BOOL (WINAPI *funcSetProcessDPIAware) (void); typedef BOOL (WINAPI *funcIsProcessDPIAware) (void); +/* + * funcSPDAC is SetProcessDpiAwarenessContext() and + * funcGTDAC is GetThreadDpiAwarenessContext() and + * funcADACE is AreDpiAwarenessContextsEqual() provided by user32.dll, on + * Windows 10 Creator Edition and later. + * Treat HANDLE as void*, for convenience, since DPI_AWARENESS_CONTEXT is + * declared using DEFINE_HANDLE. + */ +typedef BOOL (WINAPI *funcSPDAC) (void *); +typedef HANDLE (WINAPI *funcGTDAC) (void); +typedef BOOL (WINAPI *funcADACE) (void *, void *); + typedef struct _GdkWin32User32DPIFuncs { funcSetProcessDPIAware setDpiAwareFunc; funcIsProcessDPIAware isDpiAwareFunc; + funcSPDAC setPDAC; + funcGTDAC getTDAC; + funcADACE areDACEqual; } GdkWin32User32DPIFuncs; struct _GdkWin32Display |