summaryrefslogtreecommitdiffstats
path: root/src/nativewindow/native/win32/WindowsDWM.c
blob: 925ddd1d118c90d8e30bd09388c708881c01362e (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

#include <windows.h>
#include "WindowsDWM.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 *DwmEnableCompositionPROCADDR)(UINT uCompositionAction);
typedef HRESULT (WINAPI *DwmIsCompositionEnabledPROCADDR)(BOOL * pfEnabled);
typedef HRESULT (WINAPI *DwmEnableBlurBehindWindowPROCADDR)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);  
typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaPROCADDR)(HWND hwnd, const MARGINS *pMarInset);  
typedef HRESULT (WINAPI *DwmGetWindowAttributePROCADDR)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
typedef HRESULT (WINAPI *DwmSetWindowAttributePROCADDR)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
typedef BOOL (WINAPI *GetWindowCompositionAttributePROCADDR)(HWND hwnd, WINCOMPATTRDATA* pAttrData);
typedef BOOL (WINAPI *SetWindowCompositionAttributePROCADDR)(HWND hwnd, WINCOMPATTRDATA* pAttrData);

#define INIT_CALLED_MASK          1 << 0
#define INIT_HAS_DWM_EXT_MASK     1 << 1
#define INIT_HAS_WINCOMP_EXT_MASK 1 << 2

#define HAS_INIT(a)        ( 0 != ( INIT_CALLED_MASK & (a)  ) )
#define HAS_DWM_EXT(a)     ( 0 != ( INIT_HAS_DWM_EXT_MASK & (a)  ) )
#define HAS_WINCOMP_EXT(a) ( 0 != ( INIT_HAS_WINCOMP_EXT_MASK & (a)  ) )

static int _init = 0; // INIT_ bits, see above
static DwmEnableCompositionPROCADDR _DwmEnableComposition = NULL;
static DwmIsCompositionEnabledPROCADDR _DwmIsCompositionEnabled = NULL;
static DwmEnableBlurBehindWindowPROCADDR _DwmEnableBlurBehindWindow = NULL;
static DwmExtendFrameIntoClientAreaPROCADDR _DwmExtendFrameIntoClientArea = NULL;
static DwmGetWindowAttributePROCADDR _DwmGetWindowAttribute = NULL;
static DwmSetWindowAttributePROCADDR _DwmSetWindowAttribute = NULL;
static GetWindowCompositionAttributePROCADDR _GetWindowCompositionAttribute = NULL;
static SetWindowCompositionAttributePROCADDR _SetWindowCompositionAttribute = NULL;

static int initWindowsDWM() {
    if( !HAS_INIT(_init) ) {
        _init |= INIT_CALLED_MASK;
        HANDLE hDwmAPI = LoadLibrary(TEXT("dwmapi.dll"));
        if (hDwmAPI) {
            _DwmEnableComposition = (DwmEnableCompositionPROCADDR) GetProcAddressA (hDwmAPI, "DwmEnableComposition");
            _DwmIsCompositionEnabled = (DwmIsCompositionEnabledPROCADDR) GetProcAddressA (hDwmAPI, "DwmIsCompositionEnabled");
            _DwmEnableBlurBehindWindow = (DwmEnableBlurBehindWindowPROCADDR) GetProcAddressA (hDwmAPI, "DwmEnableBlurBehindWindow");
            _DwmExtendFrameIntoClientArea = (DwmExtendFrameIntoClientAreaPROCADDR) GetProcAddressA (hDwmAPI, "DwmExtendFrameIntoClientArea");
            _DwmGetWindowAttribute = (DwmGetWindowAttributePROCADDR) GetProcAddressA (hDwmAPI, "DwmGetWindowAttribute");
            _DwmSetWindowAttribute = (DwmSetWindowAttributePROCADDR) GetProcAddressA (hDwmAPI, "DwmSetWindowAttribute");
            if(NULL != _DwmEnableComposition && NULL != _DwmIsCompositionEnabled && 
               NULL != _DwmEnableBlurBehindWindow && NULL != _DwmExtendFrameIntoClientArea &&
               NULL != _DwmGetWindowAttribute && NULL != _DwmSetWindowAttribute) {
                _init |= INIT_HAS_DWM_EXT_MASK;
            }
        }
        // FreeLibrary (hDwmAPI);  
        HANDLE hUser32 = LoadLibrary(TEXT("user32.dll"));
        if (hUser32) {
            _GetWindowCompositionAttribute = (GetWindowCompositionAttributePROCADDR) GetProcAddressA (hUser32, "GetWindowCompositionAttribute");
            _SetWindowCompositionAttribute = (SetWindowCompositionAttributePROCADDR) GetProcAddressA (hUser32, "SetWindowCompositionAttribute");
            if( NULL != _GetWindowCompositionAttribute &&
                NULL != _SetWindowCompositionAttribute ) {
                _init |= INIT_HAS_WINCOMP_EXT_MASK;
            }
        }
        // FreeLibrary (hUser32);  
        DBG_PRINT("DWM - initWindowsDWM: hasDWM %d, hasWinComp %d\n", HAS_DWM_EXT(_init), HAS_WINCOMP_EXT(_init));
    }
    return _init;
}

BOOL DwmIsExtensionAvailable() {
    return HAS_DWM_EXT( initWindowsDWM() ) ? TRUE : FALSE;
}

BOOL DwmIsCompositionEnabled( ) {
    if( HAS_DWM_EXT( initWindowsDWM() ) ) {
        BOOL fEnabled = FALSE;
        if( 0 == _DwmIsCompositionEnabled(&fEnabled) ) {
            DBG_PRINT("DWM - DwmIsCompositionEnabled: %d\n", fEnabled);
            return fEnabled;
        }
    }
    DBG_PRINT("DWM - DwmIsCompositionEnabled failed\n");
    return FALSE;
}

BOOL DwmEnableComposition( UINT uCompositionAction ) {
    if( HAS_DWM_EXT( initWindowsDWM() ) ) {
        return 0 == _DwmEnableComposition(uCompositionAction) ? TRUE : FALSE;
    }
    return FALSE;
}

BOOL DwmEnableBlurBehindWindow(HWND hwnd, const DWM_BLURBEHIND* pBlurBehind) {  
    if( HAS_DWM_EXT( initWindowsDWM() ) ) {
        _DwmEnableBlurBehindWindow(hwnd, pBlurBehind);
        DBG_PRINT("DWM - DwmEnableBlurBehindWindow: hwnd %p, f %d, on %d, %p\n", 
            (void *)hwnd, 
            (int) pBlurBehind->dwFlags,
            (int) pBlurBehind->fEnable,
            (void *)pBlurBehind->hRgnBlur);
        return TRUE;
    }
    DBG_PRINT("DWM - DwmEnableBlurBehindWindow: n/a\n");
    return FALSE;
}  

BOOL DwmExtendFrameIntoClientArea(HWND hwnd, const MARGINS *pMarInset) {
    if( HAS_DWM_EXT( initWindowsDWM() ) ) {
        _DwmExtendFrameIntoClientArea(hwnd, pMarInset);
        return TRUE;
    }
    return FALSE;
}  
  
HRESULT DwmGetWindowAttribute(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute) {
    if( HAS_DWM_EXT( initWindowsDWM() ) ) {
        return _DwmGetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute);
    }
    return E_NOINTERFACE;
}

HRESULT DwmSetWindowAttribute(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute) {
    if( HAS_DWM_EXT( initWindowsDWM() ) ) {
        return _DwmSetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute);
    }
    return E_NOINTERFACE;
}

BOOL IsWindowCompositionExtensionAvailable() {
    return HAS_WINCOMP_EXT( initWindowsDWM() ) ? TRUE : FALSE;
}

BOOL GetWindowCompositionAccentPolicy(HWND hwnd, AccentPolicy* pAccentPolicy) {
    if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) {
        WINCOMPATTRDATA attrData = { WCA_ACCENT_POLICY, pAccentPolicy, sizeof(AccentPolicy) };
        return _GetWindowCompositionAttribute(hwnd, &attrData);
    }
    return FALSE;
}
BOOL SetWindowCompositionAccentPolicy(HWND hwnd, const AccentPolicy* pAccentPolicy) {
    if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) {
        WINCOMPATTRDATA attrData = { WCA_ACCENT_POLICY, (AccentPolicy*)pAccentPolicy, sizeof(AccentPolicy) };
        return _SetWindowCompositionAttribute(hwnd, &attrData);
    }
    return FALSE;
}

#if 0
BOOL GetWindowCompositionAttribute(HWND hwnd, WINCOMPATTRDATA* pAttrData) {
    if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) {
        return _GetWindowCompositionAttribute(hwnd, pAttrData);
    }
    return FALSE;
}

BOOL SetWindowCompositionAttribute(HWND hwnd, WINCOMPATTRDATA* pAttrData) {
    if( HAS_WINCOMP_EXT( initWindowsDWM() ) ) {
        return _SetWindowCompositionAttribute(hwnd, pAttrData);
    }
    return FALSE;
}
#endif