Win32: use Win32 APIs instead of Qt APIs

Our native event filter happens before QPA's internal
handling, so the window state won't change if we query
for them in the native event filter. To fix this, use
Win32 API instead.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-01-20 13:16:45 +08:00
parent e0c00bce35
commit ebe7da1a9f
3 changed files with 54 additions and 3 deletions

View File

@ -247,7 +247,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
? reinterpret_cast<LPRECT>(msg->lParam)
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam))->rgrc[0]);
const bool max = IsMaximized(msg->hwnd);
const bool full = window->windowState() == Qt::WindowFullScreen;
const bool full = Utilities::isFullScreen(reinterpret_cast<WId>(msg->hwnd));
// We don't need this correction when we're fullscreen. We will
// have the WS_POPUP size, so we don't have to worry about
// borders, and the default frame will be fine.
@ -574,12 +574,12 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
const int titleBarHeight = Utilities::getSystemMetric(window, SystemMetric::TitleBarHeight, true);
bool isTitleBar = false;
const bool max = IsMaximized(msg->hwnd);
if (max || (window->windowState() == Qt::WindowFullScreen)) {
if (max || Utilities::isFullScreen(reinterpret_cast<WId>(msg->hwnd))) {
isTitleBar = (localMouse.y() >= 0) && (localMouse.y() <= titleBarHeight)
&& (localMouse.x() >= 0) && (localMouse.x() <= windowWidth)
&& !Utilities::isHitTestVisible(window);
}
if (window->windowState() == Qt::WindowNoState) {
if (Utilities::isWindowNoState(reinterpret_cast<WId>(msg->hwnd))) {
isTitleBar = (localMouse.y() > resizeBorderThickness) && (localMouse.y() <= titleBarHeight)
&& (localMouse.x() > resizeBorderThickness) && (localMouse.x() < (windowWidth - resizeBorderThickness))
&& !Utilities::isHitTestVisible(window);

View File

@ -55,6 +55,8 @@ FRAMELESSHELPER_API void triggerFrameChange(const WId winId);
FRAMELESSHELPER_API void updateFrameMargins(const WId winId, const bool reset);
FRAMELESSHELPER_API void updateQtFrameMargins(QWindow *window, const bool enable);
[[nodiscard]] FRAMELESSHELPER_API QString getSystemErrorMessage(const QString &function);
[[nodiscard]] FRAMELESSHELPER_API bool isFullScreen(const WId winId);
[[nodiscard]] FRAMELESSHELPER_API bool isWindowNoState(const WId winId);
#endif
}

View File

@ -547,4 +547,53 @@ bool Utilities::showSystemMenu(const WId winId, const QPointF &pos)
return true;
}
bool Utilities::isFullScreen(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return false;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
RECT wndRect = {};
if (GetWindowRect(hwnd, &wndRect) == FALSE) {
qWarning() << getSystemErrorMessage(QStringLiteral("GetWindowRect"));
return false;
}
// According to Microsoft Docs, we should compare to primary
// screen's geometry.
const HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
if (!mon) {
qWarning() << getSystemErrorMessage(QStringLiteral("MonitorFromWindow"));
return false;
}
MONITORINFO mi;
SecureZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);
if (GetMonitorInfoW(mon, &mi) == FALSE) {
qWarning() << getSystemErrorMessage(QStringLiteral("GetMonitorInfoW"));
return false;
}
// Compare to the full area of the screen, not the work area.
const RECT scrRect = mi.rcMonitor;
return ((wndRect.left == scrRect.left) && (wndRect.top == scrRect.top)
&& (wndRect.right == scrRect.right) && (wndRect.bottom == scrRect.bottom));
}
bool Utilities::isWindowNoState(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return false;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
WINDOWPLACEMENT wp;
SecureZeroMemory(&wp, sizeof(wp));
wp.length = sizeof(wp);
if (GetWindowPlacement(hwnd, &wp) == FALSE) {
qWarning() << getSystemErrorMessage(QStringLiteral("GetWindowPlacement"));
return false;
}
return ((wp.showCmd == SW_NORMAL) || (wp.showCmd == SW_RESTORE));
}
FRAMELESSHELPER_END_NAMESPACE