forked from github_mirror/framelesshelper
parent
d1358c51f9
commit
5e3a3b7109
|
@ -190,11 +190,15 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
} else if (!m_framelessWindows.contains(msg->hwnd)) {
|
} else if (!m_framelessWindows.contains(msg->hwnd)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_windowData.contains(msg->hwnd)) {
|
LPWINDOW data = nullptr;
|
||||||
// We have to record every window's state.
|
const auto userData = reinterpret_cast<LPWINDOW>(GetWindowLongPtrW(msg->hwnd, GWLP_USERDATA));
|
||||||
m_windowData.insert(msg->hwnd, qMakePair(FALSE, FALSE));
|
if (userData) {
|
||||||
|
data = userData;
|
||||||
|
} else {
|
||||||
init(msg->hwnd);
|
init(msg->hwnd);
|
||||||
|
data = reinterpret_cast<LPWINDOW>(GetWindowLongPtrW(msg->hwnd, GWLP_USERDATA));
|
||||||
}
|
}
|
||||||
|
Q_ASSERT(data);
|
||||||
switch (msg->message) {
|
switch (msg->message) {
|
||||||
case WM_NCCREATE: {
|
case WM_NCCREATE: {
|
||||||
// Work-around a long-existing Windows bug.
|
// Work-around a long-existing Windows bug.
|
||||||
|
@ -269,7 +273,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
case WM_DWMCOMPOSITIONCHANGED: {
|
case WM_DWMCOMPOSITIONCHANGED: {
|
||||||
// Bring the frame shadow back through DWM.
|
// Bring the frame shadow back through DWM.
|
||||||
// Don't paint the shadow manually using QPainter or QGraphicsEffect.
|
// Don't paint the shadow manually using QPainter or QGraphicsEffect.
|
||||||
handleDwmCompositionChanged(msg->hwnd);
|
handleDwmCompositionChanged(data);
|
||||||
*result = 0;
|
*result = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -282,7 +286,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case WM_NCPAINT: {
|
case WM_NCPAINT: {
|
||||||
if (m_windowData.value(msg->hwnd).first) {
|
if (data->dwmCompositionEnabled) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Only block WM_NCPAINT when composition is disabled. If it's
|
// Only block WM_NCPAINT when composition is disabled. If it's
|
||||||
|
@ -379,8 +383,8 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
// composition and theming are disabled. These messages don't paint
|
// composition and theming are disabled. These messages don't paint
|
||||||
// when composition is enabled and blocking WM_NCUAHDRAWCAPTION should
|
// when composition is enabled and blocking WM_NCUAHDRAWCAPTION should
|
||||||
// be enough to prevent painting when theming is enabled.
|
// be enough to prevent painting when theming is enabled.
|
||||||
if (!m_windowData.value(msg->hwnd).first &&
|
if (!data->dwmCompositionEnabled &&
|
||||||
!m_windowData.value(msg->hwnd).second) {
|
!data->themeEnabled) {
|
||||||
const LONG_PTR oldStyle = GetWindowLongPtrW(msg->hwnd, GWL_STYLE);
|
const LONG_PTR oldStyle = GetWindowLongPtrW(msg->hwnd, GWL_STYLE);
|
||||||
// Prevent Windows from drawing the default title bar by temporarily
|
// Prevent Windows from drawing the default title bar by temporarily
|
||||||
// toggling the WS_VISIBLE style.
|
// toggling the WS_VISIBLE style.
|
||||||
|
@ -394,7 +398,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_THEMECHANGED: {
|
case WM_THEMECHANGED: {
|
||||||
handleThemeChanged(msg->hwnd);
|
handleThemeChanged(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_WINDOWPOSCHANGED: {
|
case WM_WINDOWPOSCHANGED: {
|
||||||
|
@ -408,6 +412,9 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinNativeEventFilter::init(HWND handle) {
|
void WinNativeEventFilter::init(HWND handle) {
|
||||||
|
LPWINDOW data = new WINDOW;
|
||||||
|
data->hWnd = handle;
|
||||||
|
SetWindowLongPtrW(handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(data));
|
||||||
// Make sure our window is a normal application window, we'll remove the
|
// Make sure our window is a normal application window, we'll remove the
|
||||||
// window frame later in Win32 events, don't use WS_POPUP to do this.
|
// window frame later in Win32 events, don't use WS_POPUP to do this.
|
||||||
SetWindowLongPtrW(handle, GWL_STYLE,
|
SetWindowLongPtrW(handle, GWL_STYLE,
|
||||||
|
@ -419,8 +426,8 @@ void WinNativeEventFilter::init(HWND handle) {
|
||||||
// Direct2D, Direct3D, DirectComposition, etc.
|
// Direct2D, Direct3D, DirectComposition, etc.
|
||||||
SetLayeredWindowAttributes(handle, RGB(255, 0, 255), 0, LWA_COLORKEY);
|
SetLayeredWindowAttributes(handle, RGB(255, 0, 255), 0, LWA_COLORKEY);
|
||||||
// Make sure our window has the frame shadow.
|
// Make sure our window has the frame shadow.
|
||||||
handleDwmCompositionChanged(handle);
|
handleDwmCompositionChanged(data);
|
||||||
handleThemeChanged(handle);
|
handleThemeChanged(data);
|
||||||
// For debug purposes.
|
// For debug purposes.
|
||||||
qDebug().noquote() << "Window handle:" << handle;
|
qDebug().noquote() << "Window handle:" << handle;
|
||||||
qDebug().noquote() << "Window DPI:" << windowDpi(handle)
|
qDebug().noquote() << "Window DPI:" << windowDpi(handle)
|
||||||
|
@ -430,11 +437,10 @@ void WinNativeEventFilter::init(HWND handle) {
|
||||||
<< "Window titlebar height:" << titlebarHeight(handle);
|
<< "Window titlebar height:" << titlebarHeight(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinNativeEventFilter::handleDwmCompositionChanged(HWND handle) {
|
void WinNativeEventFilter::handleDwmCompositionChanged(LPWINDOW data) {
|
||||||
BOOL enabled = FALSE;
|
BOOL enabled = FALSE;
|
||||||
DwmIsCompositionEnabled(&enabled);
|
DwmIsCompositionEnabled(&enabled);
|
||||||
const BOOL theme = m_windowData.value(handle).second;
|
data->dwmCompositionEnabled = enabled;
|
||||||
m_windowData[handle] = qMakePair(enabled, theme);
|
|
||||||
// We should not draw the frame shadow if DWM composition is disabled, in
|
// We should not draw the frame shadow if DWM composition is disabled, in
|
||||||
// other words, a window should not have frame shadow when Windows Aero is
|
// other words, a window should not have frame shadow when Windows Aero is
|
||||||
// not enabled.
|
// not enabled.
|
||||||
|
@ -444,27 +450,25 @@ void WinNativeEventFilter::handleDwmCompositionChanged(HWND handle) {
|
||||||
// The frame shadow is drawn on the non-client area and thus we have to
|
// The frame shadow is drawn on the non-client area and thus we have to
|
||||||
// make sure the non-client area rendering is enabled first.
|
// make sure the non-client area rendering is enabled first.
|
||||||
const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
|
const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
|
||||||
DwmSetWindowAttribute(handle, DWMWA_NCRENDERING_POLICY, &ncrp,
|
DwmSetWindowAttribute(data->hWnd, DWMWA_NCRENDERING_POLICY, &ncrp,
|
||||||
sizeof(ncrp));
|
sizeof(ncrp));
|
||||||
// Negative margins have special meaning to
|
// Negative margins have special meaning to
|
||||||
// DwmExtendFrameIntoClientArea. Negative margins create the "sheet of
|
// DwmExtendFrameIntoClientArea. Negative margins create the "sheet of
|
||||||
// glass" effect, where the client area is rendered as a solid surface
|
// glass" effect, where the client area is rendered as a solid surface
|
||||||
// with no window border.
|
// with no window border.
|
||||||
const MARGINS margins = {-1, -1, -1, -1};
|
const MARGINS margins = {-1, -1, -1, -1};
|
||||||
DwmExtendFrameIntoClientArea(handle, &margins);
|
DwmExtendFrameIntoClientArea(data->hWnd, &margins);
|
||||||
}
|
}
|
||||||
// handleBlurForWindow(handle, enabled);
|
// handleBlurForWindow(data);
|
||||||
refreshWindow(handle);
|
refreshWindow(data->hWnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinNativeEventFilter::handleThemeChanged(HWND handle) {
|
void WinNativeEventFilter::handleThemeChanged(LPWINDOW data) {
|
||||||
const BOOL dwm = m_windowData.value(handle).first;
|
data->themeEnabled = IsThemeActive();
|
||||||
m_windowData[handle] = qMakePair(dwm, IsThemeActive());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinNativeEventFilter::handleBlurForWindow(HWND handle,
|
void WinNativeEventFilter::handleBlurForWindow(LPWINDOW data) {
|
||||||
BOOL compositionEnabled) {
|
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows7) {
|
||||||
if (!handle || (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows7)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We prefer using DWM blur on Windows 7 because it has better appearance.
|
// We prefer using DWM blur on Windows 7 because it has better appearance.
|
||||||
|
@ -472,41 +476,41 @@ void WinNativeEventFilter::handleBlurForWindow(HWND handle,
|
||||||
// Windows Aero
|
// Windows Aero
|
||||||
DWM_BLURBEHIND dwmbb;
|
DWM_BLURBEHIND dwmbb;
|
||||||
dwmbb.dwFlags = DWM_BB_ENABLE;
|
dwmbb.dwFlags = DWM_BB_ENABLE;
|
||||||
dwmbb.fEnable = compositionEnabled;
|
dwmbb.fEnable = data->dwmCompositionEnabled;
|
||||||
dwmbb.hRgnBlur = nullptr;
|
dwmbb.hRgnBlur = nullptr;
|
||||||
dwmbb.fTransitionOnMaximized = FALSE;
|
dwmbb.fTransitionOnMaximized = FALSE;
|
||||||
DwmEnableBlurBehindWindow(handle, &dwmbb);
|
DwmEnableBlurBehindWindow(data->hWnd, &dwmbb);
|
||||||
} else if (m_SetWindowCompositionAttribute) {
|
} else if (m_SetWindowCompositionAttribute) {
|
||||||
ACCENT_POLICY accent;
|
ACCENT_POLICY accentPolicy;
|
||||||
accent.AccentFlags = 0;
|
accentPolicy.AccentFlags = 0;
|
||||||
// GradientColor only has effect when using with acrylic, so we can set it to zero in most cases.
|
// GradientColor only has effect when using with acrylic, so we can set it to zero in most cases.
|
||||||
// It's an AGBR unsigned int, for example, use 0xCC000000 for dark blur behind background.
|
// It's an AGBR unsigned int, for example, use 0xCC000000 for dark blur behind background.
|
||||||
accent.GradientColor = 0;
|
accentPolicy.GradientColor = 0;
|
||||||
accent.AnimationId = 0;
|
accentPolicy.AnimationId = 0;
|
||||||
WINDOWCOMPOSITIONATTRIBDATA data;
|
WINDOWCOMPOSITIONATTRIBDATA attribData;
|
||||||
data.dwAttribute = WCA_ACCENT_POLICY;
|
attribData.dwAttribute = WCA_ACCENT_POLICY;
|
||||||
data.pvAttribute = &accent;
|
attribData.pvAttribute = &accentPolicy;
|
||||||
data.cbAttribute = sizeof(accent);
|
attribData.cbAttribute = sizeof(accentPolicy);
|
||||||
if (compositionEnabled) {
|
if (data->dwmCompositionEnabled) {
|
||||||
// Windows 10, version 1709 (10.0.16299)
|
// Windows 10, version 1709 (10.0.16299)
|
||||||
if (QOperatingSystemVersion::current() >=
|
if (QOperatingSystemVersion::current() >=
|
||||||
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0,
|
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0,
|
||||||
16299)) {
|
16299)) {
|
||||||
// Acrylic (Will also blur but is completely different with Windows Aero)
|
// Acrylic (Will also blur but is completely different with Windows Aero)
|
||||||
accent.AccentState = ACCENT_ENABLE_ACRYLICBLURBEHIND;
|
accentPolicy.AccentState = ACCENT_ENABLE_ACRYLICBLURBEHIND;
|
||||||
} else if (QOperatingSystemVersion::current() >=
|
} else if (QOperatingSystemVersion::current() >=
|
||||||
QOperatingSystemVersion::Windows10) {
|
QOperatingSystemVersion::Windows10) {
|
||||||
// Blur (Something like Windows Aero in Windows 7)
|
// Blur (Something like Windows Aero in Windows 7)
|
||||||
accent.AccentState = ACCENT_ENABLE_BLURBEHIND;
|
accentPolicy.AccentState = ACCENT_ENABLE_BLURBEHIND;
|
||||||
} else if (QOperatingSystemVersion::current() >=
|
} else if (QOperatingSystemVersion::current() >=
|
||||||
QOperatingSystemVersion::Windows8) {
|
QOperatingSystemVersion::Windows8) {
|
||||||
// Transparent gradient color
|
// Transparent gradient color
|
||||||
accent.AccentState = ACCENT_ENABLE_TRANSPARENTGRADIENT;
|
accentPolicy.AccentState = ACCENT_ENABLE_TRANSPARENTGRADIENT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
accent.AccentState = ACCENT_DISABLED;
|
accentPolicy.AccentState = ACCENT_DISABLED;
|
||||||
}
|
}
|
||||||
m_SetWindowCompositionAttribute(handle, &data);
|
m_SetWindowCompositionAttribute(data->hWnd, &attribData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QAbstractNativeEventFilter>
|
#include <QAbstractNativeEventFilter>
|
||||||
#include <QHash>
|
|
||||||
#include <QPair>
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
@ -10,6 +8,11 @@ class WinNativeEventFilter : public QAbstractNativeEventFilter {
|
||||||
Q_DISABLE_COPY_MOVE(WinNativeEventFilter)
|
Q_DISABLE_COPY_MOVE(WinNativeEventFilter)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef struct tagWINDOW {
|
||||||
|
HWND hWnd = nullptr;
|
||||||
|
BOOL dwmCompositionEnabled = FALSE, themeEnabled = FALSE;
|
||||||
|
} WINDOW, *LPWINDOW;
|
||||||
|
|
||||||
explicit WinNativeEventFilter();
|
explicit WinNativeEventFilter();
|
||||||
~WinNativeEventFilter() override;
|
~WinNativeEventFilter() override;
|
||||||
|
|
||||||
|
@ -51,9 +54,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(HWND handle);
|
void init(HWND handle);
|
||||||
void handleDwmCompositionChanged(HWND handle);
|
void handleDwmCompositionChanged(LPWINDOW data);
|
||||||
void handleThemeChanged(HWND handle);
|
void handleThemeChanged(LPWINDOW data);
|
||||||
void handleBlurForWindow(HWND handle, BOOL compositionEnabled);
|
void handleBlurForWindow(LPWINDOW data);
|
||||||
UINT getDpiForWindow(HWND handle) const;
|
UINT getDpiForWindow(HWND handle) const;
|
||||||
qreal getDprForWindow(HWND handle) const;
|
qreal getDprForWindow(HWND handle) const;
|
||||||
int getSystemMetricsForWindow(HWND handle, int index) const;
|
int getSystemMetricsForWindow(HWND handle, int index) const;
|
||||||
|
@ -88,9 +91,6 @@ private:
|
||||||
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
||||||
};
|
};
|
||||||
|
|
||||||
// Window handle, DwmComposition, Theme
|
|
||||||
QHash<HWND, QPair<BOOL, BOOL>> m_windowData;
|
|
||||||
|
|
||||||
const UINT m_defaultDPI = 96;
|
const UINT m_defaultDPI = 96;
|
||||||
const qreal m_defaultDPR = 1.0;
|
const qreal m_defaultDPR = 1.0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue