forked from github_mirror/framelesshelper
win32: minor refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
04f31f7b42
commit
39ec7efcf3
|
@ -381,76 +381,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// is not correct. It confuses QPA's internal logic.
|
// is not correct. It confuses QPA's internal logic.
|
||||||
clientRect->bottom += 1;
|
clientRect->bottom += 1;
|
||||||
#endif
|
#endif
|
||||||
if (Utilities::isDwmCompositionAvailable()) {
|
Utilities::syncWmPaintWithDwm();
|
||||||
QSystemLibrary winmmLib(QStringLiteral("winmm"));
|
|
||||||
static const auto ptimeGetDevCaps =
|
|
||||||
reinterpret_cast</*MMRESULT*/UINT(WINAPI *)(flh_LPTIMECAPS, UINT)>(winmmLib.resolve("timeGetDevCaps"));
|
|
||||||
static const auto ptimeBeginPeriod =
|
|
||||||
reinterpret_cast</*MMRESULT*/UINT(WINAPI *)(UINT)>(winmmLib.resolve("timeBeginPeriod"));
|
|
||||||
static const auto ptimeEndPeriod =
|
|
||||||
reinterpret_cast</*MMRESULT*/UINT(WINAPI *)(UINT)>(winmmLib.resolve("timeEndPeriod"));
|
|
||||||
static const auto pDwmGetCompositionTimingInfo =
|
|
||||||
reinterpret_cast<HRESULT(WINAPI *)(HWND, DWM_TIMING_INFO *)>(QSystemLibrary::resolve(QStringLiteral("dwmapi"), "DwmGetCompositionTimingInfo"));
|
|
||||||
if (ptimeGetDevCaps && ptimeBeginPeriod && ptimeEndPeriod && pDwmGetCompositionTimingInfo) {
|
|
||||||
// Dirty hack to workaround the resize flicker caused by DWM.
|
|
||||||
LARGE_INTEGER freq = {};
|
|
||||||
if (QueryPerformanceFrequency(&freq) == FALSE) {
|
|
||||||
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("QueryPerformanceFrequency"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
flh_TIMECAPS tc = {};
|
|
||||||
if (ptimeGetDevCaps(&tc, sizeof(tc)) != /*MMSYSERR_NOERROR*/0) {
|
|
||||||
qWarning() << "timeGetDevCaps() failed.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const UINT ms_granularity = tc.wPeriodMin;
|
|
||||||
if (ptimeBeginPeriod(ms_granularity) != /*TIMERR_NOERROR*/0) {
|
|
||||||
qWarning() << "timeBeginPeriod() failed.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LARGE_INTEGER now0 = {};
|
|
||||||
if (QueryPerformanceCounter(&now0) == FALSE) {
|
|
||||||
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("QueryPerformanceCounter"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// ask DWM where the vertical blank falls
|
|
||||||
DWM_TIMING_INFO dti;
|
|
||||||
SecureZeroMemory(&dti, sizeof(dti));
|
|
||||||
dti.cbSize = sizeof(dti);
|
|
||||||
const HRESULT hr = pDwmGetCompositionTimingInfo(nullptr, &dti);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("DwmGetCompositionTimingInfo"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LARGE_INTEGER now1 = {};
|
|
||||||
if (QueryPerformanceCounter(&now1) == FALSE) {
|
|
||||||
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("QueryPerformanceCounter"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// - DWM told us about SOME vertical blank
|
|
||||||
// - past or future, possibly many frames away
|
|
||||||
// - convert that into the NEXT vertical blank
|
|
||||||
const LONGLONG period = dti.qpcRefreshPeriod;
|
|
||||||
const LONGLONG dt = dti.qpcVBlank - now1.QuadPart;
|
|
||||||
LONGLONG w = 0, m = 0;
|
|
||||||
if (dt >= 0) {
|
|
||||||
w = dt / period;
|
|
||||||
} else {
|
|
||||||
// reach back to previous period
|
|
||||||
// - so m represents consistent position within phase
|
|
||||||
w = -1 + dt / period;
|
|
||||||
}
|
|
||||||
m = dt - (period * w);
|
|
||||||
Q_ASSERT(m >= 0);
|
|
||||||
Q_ASSERT(m < period);
|
|
||||||
const qreal m_ms = 1000.0 * static_cast<qreal>(m) / static_cast<qreal>(freq.QuadPart);
|
|
||||||
Sleep(static_cast<DWORD>(qRound(m_ms)));
|
|
||||||
if (ptimeEndPeriod(ms_granularity) != /*TIMERR_NOERROR*/0) {
|
|
||||||
qWarning() << "timeEndPeriod() failed.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We cannot return WVR_REDRAW otherwise Windows exhibits bugs where
|
// We cannot return WVR_REDRAW otherwise Windows exhibits bugs where
|
||||||
// client pixels and child windows are mispositioned by the width/height
|
// client pixels and child windows are mispositioned by the width/height
|
||||||
// of the upper-left nonclient area.
|
// of the upper-left nonclient area.
|
||||||
|
@ -681,6 +612,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
Utilities::updateQtFrameMargins(const_cast<QWindow *>(window), true);
|
Utilities::updateQtFrameMargins(const_cast<QWindow *>(window), true);
|
||||||
Utilities::triggerFrameChange(reinterpret_cast<WId>(msg->hwnd));
|
Utilities::triggerFrameChange(reinterpret_cast<WId>(msg->hwnd));
|
||||||
} break;
|
} break;
|
||||||
|
case WM_DWMCOMPOSITIONCHANGED: {
|
||||||
|
Utilities::updateFrameMargins(reinterpret_cast<WId>(msg->hwnd), false);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,10 @@
|
||||||
#define WM_NCUAHDRAWFRAME (0x00AF)
|
#define WM_NCUAHDRAWFRAME (0x00AF)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef WM_DWMCOMPOSITIONCHANGED
|
||||||
|
#define WM_DWMCOMPOSITIONCHANGED (0x031E)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
|
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
|
||||||
#define WM_DWMCOLORIZATIONCOLORCHANGED (0x0320)
|
#define WM_DWMCOLORIZATIONCOLORCHANGED (0x0320)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -57,6 +57,7 @@ FRAMELESSHELPER_API void updateQtFrameMargins(QWindow *window, const bool enable
|
||||||
[[nodiscard]] FRAMELESSHELPER_API QString getSystemErrorMessage(const QString &function);
|
[[nodiscard]] FRAMELESSHELPER_API QString getSystemErrorMessage(const QString &function);
|
||||||
[[nodiscard]] FRAMELESSHELPER_API bool isFullScreen(const WId winId);
|
[[nodiscard]] FRAMELESSHELPER_API bool isFullScreen(const WId winId);
|
||||||
[[nodiscard]] FRAMELESSHELPER_API bool isWindowNoState(const WId winId);
|
[[nodiscard]] FRAMELESSHELPER_API bool isWindowNoState(const WId winId);
|
||||||
|
FRAMELESSHELPER_API void syncWmPaintWithDwm();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -593,4 +593,80 @@ bool Utilities::isWindowNoState(const WId winId)
|
||||||
return ((wp.showCmd == SW_NORMAL) || (wp.showCmd == SW_RESTORE));
|
return ((wp.showCmd == SW_NORMAL) || (wp.showCmd == SW_RESTORE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Utilities::syncWmPaintWithDwm()
|
||||||
|
{
|
||||||
|
// No need to sync with DWM if DWM composition is disabled.
|
||||||
|
if (!isDwmCompositionAvailable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QSystemLibrary winmmLib(QStringLiteral("winmm"));
|
||||||
|
static const auto ptimeGetDevCaps =
|
||||||
|
reinterpret_cast</*MMRESULT*/UINT(WINAPI *)(flh_LPTIMECAPS, UINT)>(winmmLib.resolve("timeGetDevCaps"));
|
||||||
|
static const auto ptimeBeginPeriod =
|
||||||
|
reinterpret_cast</*MMRESULT*/UINT(WINAPI *)(UINT)>(winmmLib.resolve("timeBeginPeriod"));
|
||||||
|
static const auto ptimeEndPeriod =
|
||||||
|
reinterpret_cast</*MMRESULT*/UINT(WINAPI *)(UINT)>(winmmLib.resolve("timeEndPeriod"));
|
||||||
|
static const auto pDwmGetCompositionTimingInfo =
|
||||||
|
reinterpret_cast<HRESULT(WINAPI *)(HWND, DWM_TIMING_INFO *)>(QSystemLibrary::resolve(QStringLiteral("dwmapi"), "DwmGetCompositionTimingInfo"));
|
||||||
|
if (!ptimeGetDevCaps || !ptimeBeginPeriod || !ptimeEndPeriod || !pDwmGetCompositionTimingInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Dirty hack to workaround the resize flicker caused by DWM.
|
||||||
|
LARGE_INTEGER freq = {};
|
||||||
|
if (QueryPerformanceFrequency(&freq) == FALSE) {
|
||||||
|
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("QueryPerformanceFrequency"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flh_TIMECAPS tc = {};
|
||||||
|
if (ptimeGetDevCaps(&tc, sizeof(tc)) != /*MMSYSERR_NOERROR*/0) {
|
||||||
|
qWarning() << "timeGetDevCaps() failed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const UINT ms_granularity = tc.wPeriodMin;
|
||||||
|
if (ptimeBeginPeriod(ms_granularity) != /*TIMERR_NOERROR*/0) {
|
||||||
|
qWarning() << "timeBeginPeriod() failed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LARGE_INTEGER now0 = {};
|
||||||
|
if (QueryPerformanceCounter(&now0) == FALSE) {
|
||||||
|
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("QueryPerformanceCounter"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ask DWM where the vertical blank falls
|
||||||
|
DWM_TIMING_INFO dti;
|
||||||
|
SecureZeroMemory(&dti, sizeof(dti));
|
||||||
|
dti.cbSize = sizeof(dti);
|
||||||
|
const HRESULT hr = pDwmGetCompositionTimingInfo(nullptr, &dti);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("DwmGetCompositionTimingInfo"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LARGE_INTEGER now1 = {};
|
||||||
|
if (QueryPerformanceCounter(&now1) == FALSE) {
|
||||||
|
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("QueryPerformanceCounter"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// - DWM told us about SOME vertical blank
|
||||||
|
// - past or future, possibly many frames away
|
||||||
|
// - convert that into the NEXT vertical blank
|
||||||
|
const LONGLONG period = dti.qpcRefreshPeriod;
|
||||||
|
const LONGLONG dt = dti.qpcVBlank - now1.QuadPart;
|
||||||
|
LONGLONG w = 0, m = 0;
|
||||||
|
if (dt >= 0) {
|
||||||
|
w = dt / period;
|
||||||
|
} else {
|
||||||
|
// reach back to previous period
|
||||||
|
// - so m represents consistent position within phase
|
||||||
|
w = -1 + dt / period;
|
||||||
|
}
|
||||||
|
m = dt - (period * w);
|
||||||
|
Q_ASSERT(m >= 0);
|
||||||
|
Q_ASSERT(m < period);
|
||||||
|
const qreal m_ms = 1000.0 * static_cast<qreal>(m) / static_cast<qreal>(freq.QuadPart);
|
||||||
|
Sleep(static_cast<DWORD>(qRound(m_ms)));
|
||||||
|
if (ptimeEndPeriod(ms_granularity) != /*TIMERR_NOERROR*/0) {
|
||||||
|
qWarning() << "timeEndPeriod() failed.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
Loading…
Reference in New Issue