Skip to content
This repository has been archived by the owner on Dec 19, 2023. It is now read-only.

Commit

Permalink
snap layout: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
wangwenx190 committed Aug 25, 2023
1 parent e0abdb0 commit e6a4849
Showing 1 changed file with 75 additions and 38 deletions.
113 changes: 75 additions & 38 deletions src/core/framelesshelper_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,28 @@ Q_GLOBAL_STATIC(FramelessWin32HelperInternal, g_framelessWin32HelperData)
return WindowPart::NotInterested;
}

[[nodiscard]] static inline bool listenForMouseLeave(const HWND hWnd, const bool nonClient)
{
Q_ASSERT(hWnd);
if (!hWnd) {
return false;
}
TRACKMOUSEEVENT tme;
SecureZeroMemory(&tme, sizeof(tme));
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
if (nonClient) {
tme.dwFlags |= TME_NONCLIENT;
}
tme.hwndTrack = hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
if (::TrackMouseEvent(&tme) == FALSE) {
WARNING << Utils::getSystemErrorMessage(kTrackMouseEvent);
return false;
}
return true;
}

FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {}

FramelessHelperWin::~FramelessHelperWin() = default;
Expand Down Expand Up @@ -772,31 +794,56 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
WARNING << Utils::getSystemErrorMessage(kScreenToClient);
break;
}
const QPoint qtScenePos = Utils::fromNativeLocalPosition(window, QPoint(nativeLocalPos.x, nativeLocalPos.y));

auto clientRect = RECT{ 0, 0, 0, 0 };
if (::GetClientRect(hWnd, &clientRect) == FALSE) {
WARNING << Utils::getSystemErrorMessage(kGetClientRect);
break;
}
const auto clientWidth = RECT_WIDTH(clientRect);
const auto clientHeight = RECT_HEIGHT(clientRect);

const QPoint qtScenePos = Utils::fromNativeLocalPosition(window, QPoint(nativeLocalPos.x, nativeLocalPos.y));
SystemButtonType sysButtonType = SystemButtonType::Unknown;
if (data.params.isInsideSystemButtons(qtScenePos, &sysButtonType)) {
// OK, we are now inside one of the chrome buttons, tell Windows the exact role of our button.
switch (sysButtonType) {
case SystemButtonType::WindowIcon:
*result = HTSYSMENU;
break;
case SystemButtonType::Help:
*result = HTHELP;
break;
case SystemButtonType::Minimize:
*result = HTREDUCE;
break;
case SystemButtonType::Maximize:
case SystemButtonType::Restore:
*result = HTZOOM;
break;
case SystemButtonType::Close:
*result = HTCLOSE;
break;
case SystemButtonType::Unknown:
*result = HTCLIENT; // Normally we'd never enter this branch.
break;
// Even if the mouse is inside the chrome button area now, we should still allow the user
// to be able to resize the window with the top or right window border, this is also the
// normal behavior of a native Win32 window.
static constexpr const int kTopBorderSize = 1;
const bool isTop = (nativeLocalPos.y <= kTopBorderSize);
const bool isRight = (nativeLocalPos.x >= (clientWidth - kTopBorderSize));
if (isTop || isRight) {
if (isTop && isRight) {
*result = HTTOPRIGHT;
} else if (isTop) {
*result = HTTOP;
} else {
*result = HTRIGHT;
}
} else {
// OK, we are now really inside one of the chrome buttons, tell Windows the exact role of our button.
// The Snap Layout feature introduced in Windows 11 won't work without this.
switch (sysButtonType) {
case SystemButtonType::WindowIcon:
*result = HTSYSMENU;
break;
case SystemButtonType::Help:
*result = HTHELP;
break;
case SystemButtonType::Minimize:
*result = HTREDUCE;
break;
case SystemButtonType::Maximize:
case SystemButtonType::Restore:
*result = HTZOOM;
break;
case SystemButtonType::Close:
*result = HTCLOSE;
break;
case SystemButtonType::Unknown:
*result = HTCLIENT; // Normally we'd never enter this branch.
break;
}
}
return true;
}
Expand Down Expand Up @@ -866,18 +913,13 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return true;
}
if (!isFixedSize) {
auto clientRect = RECT{ 0, 0, 0, 0 };
if (::GetClientRect(hWnd, &clientRect) == FALSE) {
WARNING << Utils::getSystemErrorMessage(kGetClientRect);
break;
}
const bool isBottom = (nativeLocalPos.y >= (RECT_HEIGHT(clientRect) - frameSizeY));
const bool isBottom = (nativeLocalPos.y >= (clientHeight - frameSizeY));
// Make the border a little wider to let the user easy to resize on corners.
const auto scaleFactor = ((isTop || isBottom) ? qreal(2) : qreal(1));
const int frameSizeX = Utils::getResizeBorderThickness(windowId, true, true);
const int scaledFrameSizeX = std::round(qreal(frameSizeX) * scaleFactor);
const bool isLeft = (nativeLocalPos.x < scaledFrameSizeX);
const bool isRight = (nativeLocalPos.x >= (RECT_WIDTH(clientRect) - scaledFrameSizeX));
const bool isRight = (nativeLocalPos.x >= (clientWidth - scaledFrameSizeX));
if (dontOverrideCursor && (isTop || isBottom || isLeft || isRight)) {
// Return HTCLIENT instead of HTBORDER here, because the mouse is
// inside the window now, return HTCLIENT to let the controls
Expand Down Expand Up @@ -950,16 +992,10 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
const bool isXButtonMessage = ((uMsg >= WM_NCXBUTTONDOWN) && (uMsg <= WM_NCXBUTTONDBLCLK));
const WindowPart nowWindowPart = getHittedWindowPart(isXButtonMessage ? GET_NCHITTEST_WPARAM(wParam) : wParam);
if (uMsg == WM_NCMOUSELEAVE) {
if (nowWindowPart == WindowPart::NotInterested) {
std::ignore = listenForMouseLeave(hWnd, false);
}
if ((previousWindowPart == WindowPart::ChromeButton) && (nowWindowPart == WindowPart::ClientArea)) {
TRACKMOUSEEVENT tme;
SecureZeroMemory(&tme, sizeof(tme));
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
if (::TrackMouseEvent(&tme) == FALSE) {
WARNING << Utils::getSystemErrorMessage(kTrackMouseEvent);
}
*result = FALSE;
return true;
}
Expand All @@ -977,6 +1013,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
}
if (nowWindowPart == WindowPart::ChromeButton) {
emulateClientAreaMessage();
std::ignore = listenForMouseLeave(hWnd, true);
*result = (isXButtonMessage ? TRUE : FALSE);
return true;
}
Expand Down

0 comments on commit e6a4849

Please sign in to comment.