@@ -991,43 +991,80 @@ void Sys_Init( void ) {
991991
992992//#include <ShellScalingApi.h>
993993
994- typedef HANDLE ( WINAPI * SetThreadDpiAwarenessContextPtr )( HANDLE );
994+ typedef enum ETE_PROCESS_DPI_AWARENESS { //with out win header, some rename....
995+ ETE_PROCESS_DPI_UNAWARE = 0 ,
996+ ETE_PROCESS_SYSTEM_DPI_AWARE = 1 ,
997+ ETE_PROCESS_PER_MONITOR_DPI_AWARE = 2
998+ } ETE_PROCESS_DPI_AWARENESS ;
999+
1000+ typedef LONG ( WINAPI * RtlGetVersionPtr )( RTL_OSVERSIONINFOEXW * );
1001+ typedef BOOL ( WINAPI * SetProcessDpiAwarenessContextPtr )( HANDLE );
9951002typedef HRESULT ( WINAPI * SetProcessDpiAwarenessPtr )( int );
9961003typedef BOOL ( WINAPI * SetProcessDPIAwarePtr )( void );
9971004
998- // TODO print sucess/fail
999- static qboolean TryThreadHighDPI ( HANDLE value ) {
1000- SetThreadDpiAwarenessContextPtr set_thread_dpi_awareness_context_f = NULL ;
1005+ #define ETE_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE)-4)
1006+
1007+ // MSDN SetProcessDpiAwarenessContext
1008+ static qboolean EnablePerMonitorV2 ( void ) {
1009+ SetProcessDpiAwarenessContextPtr set_process_dpi_awareness_context_f = NULL ;
10011010 HMODULE u32dll = GetModuleHandle ( T ( "user32" ) );
10021011
10031012 if ( !u32dll ) {
10041013 return qfalse ;
10051014 }
10061015
1007- set_thread_dpi_awareness_context_f = (SetThreadDpiAwarenessContextPtr )GetProcAddress ( u32dll , "SetThreadDpiAwarenessContext" );
1016+ set_process_dpi_awareness_context_f = (SetProcessDpiAwarenessContextPtr )GetProcAddress ( u32dll , "SetProcessDpiAwarenessContext" );
1017+
1018+ if ( set_process_dpi_awareness_context_f ) {
1019+ return set_process_dpi_awareness_context_f ( ETE_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ) != FALSE ? qtrue : qfalse ;
1020+ }
1021+ return qfalse ;
1022+ }
1023+
1024+ // Ugly hack to detect Win10 without manifest
1025+ // http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe?msg=5080848#xx5080848xx
1026+ static qboolean IsWin10 ( void ) {
1027+ RtlGetVersionPtr rtl_get_version_f = NULL ;
1028+ HMODULE ntdll = GetModuleHandle ( T ( "ntdll" ) );
1029+ RTL_OSVERSIONINFOEXW osver ;
10081030
1009- if ( set_thread_dpi_awareness_context_f ) {
1010- HANDLE ret = set_thread_dpi_awareness_context_f ( value );
1011- if ( ret != NULL ) {
1031+ if ( !ntdll )
1032+ return qfalse ; // will never happen
1033+
1034+ rtl_get_version_f = (RtlGetVersionPtr )GetProcAddress ( ntdll , "RtlGetVersion" );
1035+
1036+ if ( !rtl_get_version_f )
1037+ return qfalse ; // will never happen
1038+
1039+ osver .dwOSVersionInfoSize = sizeof ( RTL_OSVERSIONINFOEXW );
1040+
1041+ if ( rtl_get_version_f ( & osver ) == 0 ) {
1042+ if ( osver .dwMajorVersion >= 10 )
10121043 return qtrue ;
1013- }
10141044 }
1045+
10151046 return qfalse ;
10161047}
10171048
1018- // TODO print sucess/fail
1019- static qboolean TryModernProcessHighDPI ( int value ) {
1049+
1050+ // secret sauce SetProcessDpiAwarenessInternal
1051+ // MSDN says SetProcessDpiAwareness but the actual symbol is with `Internal`
1052+ // We must check for Win10 to use Per Monitor support, otherwise use system
1053+ static qboolean EnablePerMonitor ( void ) {
10201054 SetProcessDpiAwarenessPtr set_process_dpi_awareness_f = NULL ;
10211055 HMODULE u32dll = GetModuleHandle ( T ( "user32" ) );
1056+ qboolean win10 = qfalse ;
10221057
10231058 if ( !u32dll ) {
10241059 return qfalse ;
10251060 }
10261061
10271062 set_process_dpi_awareness_f = (SetProcessDpiAwarenessPtr )GetProcAddress ( u32dll , "SetProcessDpiAwarenessInternal" );
10281063
1064+ win10 = IsWin10 ();
1065+
10291066 if ( set_process_dpi_awareness_f ) {
1030- HRESULT hr = set_process_dpi_awareness_f ( value );
1067+ HRESULT hr = set_process_dpi_awareness_f ( win10 ? ETE_PROCESS_PER_MONITOR_DPI_AWARE : ETE_PROCESS_SYSTEM_DPI_AWARE );
10311068
10321069 if ( SUCCEEDED ( hr ) ) {
10331070 return qtrue ;
@@ -1039,7 +1076,8 @@ static qboolean TryModernProcessHighDPI( int value ) {
10391076 return qfalse ;
10401077}
10411078
1042- static qboolean TryLegacyProcessHighDPI ( void ) {
1079+ // Legacy DPI awareness (Vista+) or all else fails
1080+ static qboolean EnableDPIAware ( void ) {
10431081 SetProcessDPIAwarePtr set_process_dpi_aware_f = NULL ;
10441082 HMODULE u32dll = GetModuleHandle ( T ( "user32" ) );
10451083
@@ -1055,25 +1093,27 @@ static qboolean TryLegacyProcessHighDPI( void ) {
10551093 return qfalse ;
10561094}
10571095
1058- static void SetupHighDPISupport ( void ) {
1059- //const HANDLE contextPerMonitorV2 = (HANDLE)-4;
1060- //const HANDLE contextPerMonitor = (HANDLE)-3;
1061-
1062-
1063- int dpiValue = 0 ;
1064- if ( qtrue ) { // If Windows 10 or greater TODO implement
1065- dpiValue = 2 ; // PROCESS_PER_MONITOR_DPI_AWARE
1096+ static void SetupDPIAwareness ( void ) {
1097+ Com_DPrintf ( "Setup DPI Awareness...\n" );
1098+ if ( !EnablePerMonitorV2 () ) {
1099+ Com_DPrintf ( " ...per monitor v2: failed\n" );
1100+ } else {
1101+ Com_DPrintf ( " ...per monitor v2: succeeded\n" );
1102+ return ;
1103+ }
1104+ if ( !EnablePerMonitor () ) {
1105+ Com_DPrintf ( " ...per monitor: failed\n" );
10661106 } else {
1067- dpiValue = 1 ; // PROCESS_SYSTEM_DPI_AWARE
1107+ Com_DPrintf ( " ...per monitor: succeeded\n" );
1108+ return ;
10681109 }
10691110
1070- //if ( !TryThreadHighDPI( contextPerMonitorV2 ) ) {
1071- // if ( !TryThreadHighDPI( contextPerMonitor ) ) {
1072- if ( !TryModernProcessHighDPI ( dpiValue ) ) {
1073- TryLegacyProcessHighDPI ();
1074- }
1075- // }
1076- //}
1111+ if ( !EnableDPIAware () ) {
1112+ Com_DPrintf ( " ...per process: failed\n" );
1113+ } else {
1114+ Com_DPrintf ( " ...per process: succeeded\n" );
1115+ return ;
1116+ }
10771117}
10781118
10791119
@@ -1117,7 +1157,7 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
11171157 return 0 ;
11181158 }
11191159
1120- SetupHighDPISupport ();
1160+ SetupDPIAwareness ();
11211161
11221162 g_wv .hInstance = hInstance ;
11231163 Q_strncpyz ( sys_cmdline , lpCmdLine , sizeof ( sys_cmdline ) );
0 commit comments