summaryrefslogtreecommitdiffstats
path: root/src/nativewindow/native/win32/WindowsSHC.c
blob: 45cefb1263d61c8f6f674104dde8f89983d62a5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

#include <windows.h>
#include "WindowsSHC.h"

#include <stdlib.h>
#include <stdio.h>

// #define VERBOSE_ON 1

#ifdef VERBOSE_ON
    #define DBG_PRINT(args...) fprintf(stderr, args);
#else
    #define DBG_PRINT(args...)
#endif

/* GetProcAddress doesn't exist in A/W variants under desktop Windows */
#ifndef UNDER_CE
#define GetProcAddressA GetProcAddress
#endif

typedef HRESULT(WINAPI *GetDpiForMonitorPROCADDR)(HMONITOR, int, UINT*, UINT*);
#ifndef MDT_EFFECTIVE_DPI
    #define MDT_EFFECTIVE_DPI 0
#endif
// See also SetProcessDpiAwareness(..) and SetThreadDpiAwarenessContext(..)

#define INIT_CALLED_MASK          1 << 0
#define INIT_HAS_SHC_EXT_MASK     1 << 1

#define HAS_INIT(a)        ( 0 != ( INIT_CALLED_MASK & (a)  ) )
#define HAS_SHC_EXT(a)     ( 0 != ( INIT_HAS_SHC_EXT_MASK & (a)  ) )

static int _init = 0; // INIT_ bits, see above
static GetDpiForMonitorPROCADDR _GetDpiForMonitor = NULL;

static int initWindowsSHC() {
    if( !HAS_INIT(_init) ) {
        _init |= INIT_CALLED_MASK;
        HANDLE hShcAPI = LoadLibrary(TEXT("shcore.dll"));
        if (hShcAPI) {
            _GetDpiForMonitor = (GetDpiForMonitorPROCADDR) GetProcAddressA (hShcAPI, "GetDpiForMonitor");
            if(NULL != _GetDpiForMonitor ) {
                _init |= INIT_HAS_SHC_EXT_MASK;
            }
        }
        // FreeLibrary (hShcAPI);
        DBG_PRINT("DWM - initWindowsSHC: hasSHC %d\n", HAS_SHC_EXT(_init));
    }
    return _init;
}

BOOL ShcIsExtensionAvailable() {
    return HAS_SHC_EXT( initWindowsSHC() ) ? TRUE : FALSE;
}

BOOL ShcGetMonitorPixelScale1(HMONITOR hmon, float *psXY) {
    psXY[0] = 0;
    psXY[1] = 0;
    if( !ShcIsExtensionAvailable() ) {
        return FALSE;
    }
    if( NULL == hmon ) {
        return FALSE;
    }
    UINT dpiX=0, dpiY=0;
    if( S_OK != _GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) ) {
        return FALSE;
    }
    psXY[0] = (float)(dpiX) / 96.0f;
    psXY[1] = (float)(dpiY) / 96.0f;
    return TRUE;
}