parent
eb1c189c0f
commit
09100a1845
|
@ -26,6 +26,10 @@
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "winnativeeventfilter.h"
|
#include "winnativeeventfilter.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
@ -149,10 +153,41 @@ Q_DECLARE_METATYPE(QMargins)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using WINDOWCOMPOSITIONATTRIB = enum _WINDOWCOMPOSITIONATTRIB { WCA_ACCENT_POLICY = 19 };
|
||||||
|
|
||||||
|
using WINDOWCOMPOSITIONATTRIBDATA = struct _WINDOWCOMPOSITIONATTRIBDATA
|
||||||
|
{
|
||||||
|
WINDOWCOMPOSITIONATTRIB Attrib;
|
||||||
|
PVOID pvData;
|
||||||
|
SIZE_T cbData;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ACCENT_STATE = enum _ACCENT_STATE {
|
||||||
|
ACCENT_DISABLED = 0,
|
||||||
|
ACCENT_ENABLE_GRADIENT = 1,
|
||||||
|
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
|
||||||
|
ACCENT_ENABLE_BLURBEHIND = 3,
|
||||||
|
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
|
||||||
|
ACCENT_INVALID_STATE = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
using ACCENT_POLICY = struct _ACCENT_POLICY
|
||||||
|
{
|
||||||
|
ACCENT_STATE AccentState;
|
||||||
|
DWORD AccentFlags;
|
||||||
|
DWORD GradientColor;
|
||||||
|
DWORD AnimationId;
|
||||||
|
};
|
||||||
|
|
||||||
const UINT m_defaultDotsPerInch = USER_DEFAULT_SCREEN_DPI;
|
const UINT m_defaultDotsPerInch = USER_DEFAULT_SCREEN_DPI;
|
||||||
|
|
||||||
const qreal m_defaultDevicePixelRatio = 1.0;
|
const qreal m_defaultDevicePixelRatio = 1.0;
|
||||||
|
|
||||||
|
// These functions are undocumented APIs so we have to
|
||||||
|
// load them dynamically unconditionally.
|
||||||
|
WNEF_GENERATE_WINAPI(GetWindowCompositionAttribute, BOOL, HWND, WINDOWCOMPOSITIONATTRIBDATA *)
|
||||||
|
WNEF_GENERATE_WINAPI(SetWindowCompositionAttribute, BOOL, HWND, WINDOWCOMPOSITIONATTRIBDATA *)
|
||||||
|
|
||||||
bool isWin8OrGreater()
|
bool isWin8OrGreater()
|
||||||
{
|
{
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||||
|
@ -275,6 +310,21 @@ bool shouldHaveWindowFrame()
|
||||||
#define BPPF_NOCLIP 0x0002
|
#define BPPF_NOCLIP 0x0002
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DWM_BB_ENABLE
|
||||||
|
// Only available since Windows Vista
|
||||||
|
#define DWM_BB_ENABLE 0x00000001
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DWM_BB_BLURREGION
|
||||||
|
// Only available since Windows Vista
|
||||||
|
#define DWM_BB_BLURREGION 0x00000002
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DWM_BB_TRANSITIONONMAXIMIZED
|
||||||
|
// Only available since Windows Vista
|
||||||
|
#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004
|
||||||
|
#endif
|
||||||
|
|
||||||
using HPAINTBUFFER = HANDLE;
|
using HPAINTBUFFER = HANDLE;
|
||||||
|
|
||||||
using MONITOR_DPI_TYPE = enum _MONITOR_DPI_TYPE { MDT_EFFECTIVE_DPI = 0 };
|
using MONITOR_DPI_TYPE = enum _MONITOR_DPI_TYPE { MDT_EFFECTIVE_DPI = 0 };
|
||||||
|
@ -344,8 +394,17 @@ using D2D1_FACTORY_OPTIONS = struct _D2D1_FACTORY_OPTIONS
|
||||||
D2D1_DEBUG_LEVEL debugLevel;
|
D2D1_DEBUG_LEVEL debugLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using DWM_BLURBEHIND = struct _DWM_BLURBEHIND
|
||||||
|
{
|
||||||
|
DWORD dwFlags;
|
||||||
|
BOOL fEnable;
|
||||||
|
HRGN hRgnBlur;
|
||||||
|
BOOL fTransitionOnMaximized;
|
||||||
|
};
|
||||||
|
|
||||||
// Some of the following functions are not used by this code anymore,
|
// Some of the following functions are not used by this code anymore,
|
||||||
// but we don't remove them completely because we may still need them later.
|
// but we don't remove them completely because we may still need them later.
|
||||||
|
WNEF_GENERATE_WINAPI(DwmEnableBlurBehindWindow, HRESULT, HWND, CONST DWM_BLURBEHIND *)
|
||||||
WNEF_GENERATE_WINAPI(DwmExtendFrameIntoClientArea, HRESULT, HWND, CONST MARGINS *)
|
WNEF_GENERATE_WINAPI(DwmExtendFrameIntoClientArea, HRESULT, HWND, CONST MARGINS *)
|
||||||
WNEF_GENERATE_WINAPI(DwmIsCompositionEnabled, HRESULT, BOOL *)
|
WNEF_GENERATE_WINAPI(DwmIsCompositionEnabled, HRESULT, BOOL *)
|
||||||
WNEF_GENERATE_WINAPI(DwmSetWindowAttribute, HRESULT, HWND, DWORD, LPCVOID, DWORD)
|
WNEF_GENERATE_WINAPI(DwmSetWindowAttribute, HRESULT, HWND, DWORD, LPCVOID, DWORD)
|
||||||
|
@ -369,7 +428,7 @@ WNEF_GENERATE_WINAPI(GetWindowLongPtrW, LONG_PTR, HWND, int)
|
||||||
WNEF_GENERATE_WINAPI(SetWindowLongPtrW, LONG_PTR, HWND, int, LONG_PTR)
|
WNEF_GENERATE_WINAPI(SetWindowLongPtrW, LONG_PTR, HWND, int, LONG_PTR)
|
||||||
WNEF_GENERATE_WINAPI(GetClassLongPtrW, ULONG_PTR, HWND, int)
|
WNEF_GENERATE_WINAPI(GetClassLongPtrW, ULONG_PTR, HWND, int)
|
||||||
WNEF_GENERATE_WINAPI(SetClassLongPtrW, ULONG_PTR, HWND, int, LONG_PTR)
|
WNEF_GENERATE_WINAPI(SetClassLongPtrW, ULONG_PTR, HWND, int, LONG_PTR)
|
||||||
#else
|
#else // Q_PROCESSOR_X86_64
|
||||||
#ifdef LONG_PTR
|
#ifdef LONG_PTR
|
||||||
#undef LONG_PTR
|
#undef LONG_PTR
|
||||||
#endif
|
#endif
|
||||||
|
@ -390,7 +449,7 @@ WNEF_GENERATE_WINAPI(SetClassLongW, DWORD, HWND, int, LONG_PTR)
|
||||||
#undef GCLP_HBRBACKGROUND
|
#undef GCLP_HBRBACKGROUND
|
||||||
#endif
|
#endif
|
||||||
#define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND
|
#define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND
|
||||||
#endif
|
#endif // Q_PROCESSOR_X86_64
|
||||||
WNEF_GENERATE_WINAPI(FindWindowW, HWND, LPCWSTR, LPCWSTR)
|
WNEF_GENERATE_WINAPI(FindWindowW, HWND, LPCWSTR, LPCWSTR)
|
||||||
WNEF_GENERATE_WINAPI(MonitorFromWindow, HMONITOR, HWND, DWORD)
|
WNEF_GENERATE_WINAPI(MonitorFromWindow, HMONITOR, HWND, DWORD)
|
||||||
WNEF_GENERATE_WINAPI(GetMonitorInfoW, BOOL, HMONITOR, LPMONITORINFO)
|
WNEF_GENERATE_WINAPI(GetMonitorInfoW, BOOL, HMONITOR, LPMONITORINFO)
|
||||||
|
@ -431,7 +490,20 @@ WNEF_GENERATE_WINAPI(TrackPopupMenu, BOOL, HMENU, UINT, int, int, int, HWND, CON
|
||||||
WNEF_GENERATE_WINAPI(PostMessageW, BOOL, HWND, UINT, WPARAM, LPARAM)
|
WNEF_GENERATE_WINAPI(PostMessageW, BOOL, HWND, UINT, WPARAM, LPARAM)
|
||||||
WNEF_GENERATE_WINAPI(GetMessagePos, DWORD)
|
WNEF_GENERATE_WINAPI(GetMessagePos, DWORD)
|
||||||
|
|
||||||
#endif
|
#endif // WNEF_LINK_SYSLIB
|
||||||
|
|
||||||
|
void loadUndocumentedAPIs()
|
||||||
|
{
|
||||||
|
static bool resolved = false;
|
||||||
|
if (resolved) {
|
||||||
|
// Don't resolve twice.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolved = true;
|
||||||
|
// Available since Windows 7
|
||||||
|
WNEF_RESOLVE_WINAPI(User32, GetWindowCompositionAttribute)
|
||||||
|
WNEF_RESOLVE_WINAPI(User32, SetWindowCompositionAttribute)
|
||||||
|
}
|
||||||
|
|
||||||
// These functions were introduced in Win10 1607 or later (mostly),
|
// These functions were introduced in Win10 1607 or later (mostly),
|
||||||
// so we always load them dynamically.
|
// so we always load them dynamically.
|
||||||
|
@ -479,10 +551,11 @@ void ResolveWin32APIs()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolved = true;
|
resolved = true;
|
||||||
|
loadUndocumentedAPIs();
|
||||||
loadDPIFunctions();
|
loadDPIFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else // WNEF_LINK_SYSLIB
|
||||||
|
|
||||||
// Some APIs are not available on old systems, so we will load them
|
// Some APIs are not available on old systems, so we will load them
|
||||||
// dynamically at run-time to get maximum compatibility.
|
// dynamically at run-time to get maximum compatibility.
|
||||||
|
@ -535,12 +608,12 @@ void ResolveWin32APIs()
|
||||||
WNEF_RESOLVE_WINAPI(User32, SetWindowLongPtrW)
|
WNEF_RESOLVE_WINAPI(User32, SetWindowLongPtrW)
|
||||||
WNEF_RESOLVE_WINAPI(User32, GetClassLongPtrW)
|
WNEF_RESOLVE_WINAPI(User32, GetClassLongPtrW)
|
||||||
WNEF_RESOLVE_WINAPI(User32, SetClassLongPtrW)
|
WNEF_RESOLVE_WINAPI(User32, SetClassLongPtrW)
|
||||||
#else
|
#else // Q_PROCESSOR_X86_64
|
||||||
WNEF_RESOLVE_WINAPI(User32, GetWindowLongW)
|
WNEF_RESOLVE_WINAPI(User32, GetWindowLongW)
|
||||||
WNEF_RESOLVE_WINAPI(User32, SetWindowLongW)
|
WNEF_RESOLVE_WINAPI(User32, SetWindowLongW)
|
||||||
WNEF_RESOLVE_WINAPI(User32, GetClassLongW)
|
WNEF_RESOLVE_WINAPI(User32, GetClassLongW)
|
||||||
WNEF_RESOLVE_WINAPI(User32, SetClassLongW)
|
WNEF_RESOLVE_WINAPI(User32, SetClassLongW)
|
||||||
#endif
|
#endif // Q_PROCESSOR_X86_64
|
||||||
WNEF_RESOLVE_WINAPI(User32, FindWindowW)
|
WNEF_RESOLVE_WINAPI(User32, FindWindowW)
|
||||||
WNEF_RESOLVE_WINAPI(User32, MonitorFromWindow)
|
WNEF_RESOLVE_WINAPI(User32, MonitorFromWindow)
|
||||||
WNEF_RESOLVE_WINAPI(User32, GetMonitorInfoW)
|
WNEF_RESOLVE_WINAPI(User32, GetMonitorInfoW)
|
||||||
|
@ -559,16 +632,18 @@ void ResolveWin32APIs()
|
||||||
WNEF_RESOLVE_WINAPI(Dwmapi, DwmExtendFrameIntoClientArea)
|
WNEF_RESOLVE_WINAPI(Dwmapi, DwmExtendFrameIntoClientArea)
|
||||||
WNEF_RESOLVE_WINAPI(Dwmapi, DwmSetWindowAttribute)
|
WNEF_RESOLVE_WINAPI(Dwmapi, DwmSetWindowAttribute)
|
||||||
WNEF_RESOLVE_WINAPI(Dwmapi, DwmDefWindowProc)
|
WNEF_RESOLVE_WINAPI(Dwmapi, DwmDefWindowProc)
|
||||||
|
WNEF_RESOLVE_WINAPI(Dwmapi, DwmEnableBlurBehindWindow)
|
||||||
WNEF_RESOLVE_WINAPI(UxTheme, IsThemeActive)
|
WNEF_RESOLVE_WINAPI(UxTheme, IsThemeActive)
|
||||||
WNEF_RESOLVE_WINAPI(UxTheme, BufferedPaintSetAlpha)
|
WNEF_RESOLVE_WINAPI(UxTheme, BufferedPaintSetAlpha)
|
||||||
WNEF_RESOLVE_WINAPI(UxTheme, EndBufferedPaint)
|
WNEF_RESOLVE_WINAPI(UxTheme, EndBufferedPaint)
|
||||||
WNEF_RESOLVE_WINAPI(UxTheme, BeginBufferedPaint)
|
WNEF_RESOLVE_WINAPI(UxTheme, BeginBufferedPaint)
|
||||||
// Available since Windows 7.
|
// Available since Windows 7.
|
||||||
WNEF_RESOLVE_WINAPI(D2D1, D2D1CreateFactory)
|
WNEF_RESOLVE_WINAPI(D2D1, D2D1CreateFactory)
|
||||||
|
loadUndocumentedAPIs();
|
||||||
loadDPIFunctions();
|
loadDPIFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // WNEF_LINK_SYSLIB
|
||||||
|
|
||||||
BOOL IsDwmCompositionEnabled()
|
BOOL IsDwmCompositionEnabled()
|
||||||
{
|
{
|
||||||
|
@ -663,7 +738,7 @@ BOOL IsApplicationDpiAware()
|
||||||
UINT GetDotsPerInchForSystem()
|
UINT GetDotsPerInchForSystem()
|
||||||
{
|
{
|
||||||
const auto getScreenDpi = [](const UINT defaultValue) -> UINT {
|
const auto getScreenDpi = [](const UINT defaultValue) -> UINT {
|
||||||
#if 0
|
/*
|
||||||
if (m_lpD2D1CreateFactory) {
|
if (m_lpD2D1CreateFactory) {
|
||||||
// Using Direct2D to get the screen DPI.
|
// Using Direct2D to get the screen DPI.
|
||||||
// Available since Windows 7.
|
// Available since Windows 7.
|
||||||
|
@ -682,7 +757,7 @@ UINT GetDotsPerInchForSystem()
|
||||||
return qRound(dpiX == dpiY ? dpiY : dpiX);
|
return qRound(dpiX == dpiY ? dpiY : dpiX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
*/
|
||||||
// Available since Windows 2000.
|
// Available since Windows 2000.
|
||||||
const HDC hdc = WNEF_EXECUTE_WINAPI_RETURN(GetDC, nullptr, nullptr);
|
const HDC hdc = WNEF_EXECUTE_WINAPI_RETURN(GetDC, nullptr, nullptr);
|
||||||
if (hdc) {
|
if (hdc) {
|
||||||
|
@ -984,7 +1059,6 @@ void install()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void uninstall()
|
void uninstall()
|
||||||
{
|
{
|
||||||
if (!m_instance.isNull()) {
|
if (!m_instance.isNull()) {
|
||||||
|
@ -995,7 +1069,6 @@ void uninstall()
|
||||||
m_framelessWindows.clear();
|
m_framelessWindows.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void updateQtFrame_internal(const HWND handle)
|
void updateQtFrame_internal(const HWND handle)
|
||||||
{
|
{
|
||||||
|
@ -1234,6 +1307,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
0,
|
0,
|
||||||
LWA_COLORKEY)
|
LWA_COLORKEY)
|
||||||
}
|
}
|
||||||
|
setAcrylicEffectEnabled(msg->hwnd, data->enableBlurBehindWindow);
|
||||||
// Bring our frame shadow back through DWM, don't draw it manually.
|
// Bring our frame shadow back through DWM, don't draw it manually.
|
||||||
UpdateFrameMarginsForWindow(msg->hwnd);
|
UpdateFrameMarginsForWindow(msg->hwnd);
|
||||||
}
|
}
|
||||||
|
@ -1465,7 +1539,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
if (!shouldHaveWindowFrame() && !IsFullScreen(msg->hwnd) && !IsMaximized(msg->hwnd)
|
if (!shouldHaveWindowFrame() && !IsFullScreen(msg->hwnd) && !IsMaximized(msg->hwnd)
|
||||||
&& !IsMinimized(msg->hwnd)) {
|
&& !IsMinimized(msg->hwnd)) {
|
||||||
// Fix the flickering problem when resizing.
|
// Fix the flickering problem when resizing.
|
||||||
clientRect->bottom -= 1;
|
clientRect->top -= 1;
|
||||||
//*result = 0;
|
//*result = 0;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -2180,3 +2254,52 @@ bool WinNativeEventFilter::displaySystemMenu(void *handle,
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WinNativeEventFilter::setAcrylicEffectEnabled(void *handle, const bool enabled)
|
||||||
|
{
|
||||||
|
Q_ASSERT(handle);
|
||||||
|
ResolveWin32APIs();
|
||||||
|
const auto hwnd = reinterpret_cast<HWND>(handle);
|
||||||
|
if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, hwnd)) {
|
||||||
|
DWM_BLURBEHIND dwmBB;
|
||||||
|
SecureZeroMemory(&dwmBB, sizeof(dwmBB));
|
||||||
|
dwmBB.dwFlags = DWM_BB_ENABLE;
|
||||||
|
ACCENT_POLICY accentPolicy;
|
||||||
|
SecureZeroMemory(&accentPolicy, sizeof(accentPolicy));
|
||||||
|
WINDOWCOMPOSITIONATTRIBDATA wcaData;
|
||||||
|
SecureZeroMemory(&wcaData, sizeof(wcaData));
|
||||||
|
wcaData.Attrib = WCA_ACCENT_POLICY;
|
||||||
|
wcaData.pvData = &accentPolicy;
|
||||||
|
wcaData.cbData = sizeof(accentPolicy);
|
||||||
|
if (enabled) {
|
||||||
|
if (isWin10OrGreater(17134)) {
|
||||||
|
// Windows 10, version 1803 (10.0.17134)
|
||||||
|
// It's not allowed to enable the Acrylic effect for Win32
|
||||||
|
// applications until Win10 1803.
|
||||||
|
accentPolicy.AccentState = ACCENT_ENABLE_ACRYLICBLURBEHIND;
|
||||||
|
} else if (isWin10OrGreater(10240)) {
|
||||||
|
// Windows 10, version 1507 (10.0.10240)
|
||||||
|
// The initial version of Win10.
|
||||||
|
accentPolicy.AccentState = ACCENT_ENABLE_BLURBEHIND;
|
||||||
|
} else if (isWin8OrGreater()) {
|
||||||
|
accentPolicy.AccentState = ACCENT_ENABLE_TRANSPARENTGRADIENT;
|
||||||
|
} else {
|
||||||
|
// Windows 7
|
||||||
|
dwmBB.fEnable = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isWin8OrGreater()) {
|
||||||
|
accentPolicy.AccentState = ACCENT_DISABLED;
|
||||||
|
} else {
|
||||||
|
dwmBB.fEnable = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isWin8OrGreater()) {
|
||||||
|
return WNEF_EXECUTE_WINAPI_RETURN(SetWindowCompositionAttribute, FALSE, hwnd, &wcaData);
|
||||||
|
} else {
|
||||||
|
return SUCCEEDED(
|
||||||
|
WNEF_EXECUTE_WINAPI_RETURN(DwmEnableBlurBehindWindow, E_FAIL, hwnd, &dwmBB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
{
|
{
|
||||||
bool initialized = false /* Internal use only, don't modify it from outside */,
|
bool initialized = false /* Internal use only, don't modify it from outside */,
|
||||||
fixedSize = false, mouseTransparent = false, restoreDefaultWindowStyle = false,
|
fixedSize = false, mouseTransparent = false, restoreDefaultWindowStyle = false,
|
||||||
enableLayeredWindow = false, disableTitleBar = false;
|
enableLayeredWindow = false, disableTitleBar = false, enableBlurBehindWindow = false;
|
||||||
int borderWidth = -1, borderHeight = -1, titleBarHeight = -1;
|
int borderWidth = -1, borderHeight = -1, titleBarHeight = -1;
|
||||||
QList<QRect> ignoreAreas = {}, draggableAreas = {};
|
QList<QRect> ignoreAreas = {}, draggableAreas = {};
|
||||||
QList<QPointer<QObject>> ignoreObjects = {}, draggableObjects = {};
|
QList<QPointer<QObject>> ignoreObjects = {}, draggableObjects = {};
|
||||||
|
@ -137,6 +137,9 @@ public:
|
||||||
const int x,
|
const int x,
|
||||||
const int y);
|
const int y);
|
||||||
|
|
||||||
|
// a
|
||||||
|
static bool setAcrylicEffectEnabled(void *handle /* HWND */, const bool enabled = true);
|
||||||
|
|
||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
/// CORE FUNCTION - THE SOUL OF THIS CODE
|
/// CORE FUNCTION - THE SOUL OF THIS CODE
|
||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue