From 85e783997ffd9629cdaef44b7d482f23c8ca49cb Mon Sep 17 00:00:00 2001 From: Zhao Yuhang <2546789017@qq.com> Date: 周三, 08 5月 2024 21:10:52 +0800 Subject: [PATCH] improve qml demo --- src/core/contexts/win32windowcontext.cpp | 82 ++++++++++++++++++++++++++++++----------- 1 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 661e0e8..a75efe7 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -35,6 +35,12 @@ namespace QWK { + enum IconButtonClickLevelFlag { + IconButtonClicked = 1, + IconButtonDoubleClicked = 2, + IconButtonTriggersClose = 4, + }; + // The thickness of an auto-hide taskbar in pixels. static constexpr const quint8 kAutoHideTaskBarThickness = 2; @@ -693,9 +699,9 @@ auto hWnd = reinterpret_cast<HWND>(m_windowId); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const QPoint nativeGlobalPos = - QHighDpi::toNativeGlobalPosition(pos, m_windowHandle); + QHighDpi::toNativeGlobalPosition(pos, m_windowHandle.data()); #else - const QPoint nativeGlobalPos = QHighDpi::toNativePixels(pos, m_windowHandle); + const QPoint nativeGlobalPos = QHighDpi::toNativePixels(pos, m_windowHandle.data()); #endif std::ignore = showSystemMenu_sys(hWnd, qpoint2point(nativeGlobalPos), false, m_delegate->isHostSizeFixed(m_host)); @@ -1257,7 +1263,7 @@ POINT screenPoint{GET_X_LPARAM(dwScreenPos), GET_Y_LPARAM(dwScreenPos)}; ::ScreenToClient(hWnd, &screenPoint); QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(screenPoint), - m_windowHandle); + m_windowHandle.data()); auto dummy = WindowAgentBase::Unknown; if (isInSystemButtons(qtScenePos, &dummy)) { // We must record whether the last WM_MOUSELEAVE was filtered, because if @@ -1376,18 +1382,25 @@ if (lastHitTestResultRaw == HTSYSMENU) { switch (message) { case WM_NCLBUTTONDOWN: - if (iconButtonClickTime == 0) { + if (iconButtonClickLevel == 0) { // A message of WM_SYSCOMMAND with SC_MOUSEMENU will be sent by // Windows, and the current control flow will be blocked by the // menu while Windows will create and execute a new event loop // until the menu returns iconButtonClickTime = ::GetTickCount64(); - *result = - ::DefWindowProcW(hWnd, WM_NCLBUTTONDOWN, wParam, lParam); + *result = ::DefWindowProcW(hWnd, message, wParam, lParam); iconButtonClickTime = 0; + if (iconButtonClickLevel & IconButtonTriggersClose) { + ::PostMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0); + } + if (iconButtonClickLevel & IconButtonDoubleClicked) { + iconButtonClickLevel = 0; + } + // Otherwise, no need to reset `iconButtonClickLevel` if not to + // close, if it has value, there must be another incoming + // WM_NCLBUTTONDOWN } else { - *result = FALSE; - emulateClientAreaMessage(hWnd, message, wParam, lParam); + iconButtonClickLevel = 0; } break; case WM_NCLBUTTONDBLCLK: @@ -1550,8 +1563,8 @@ auto clientWidth = RECT_WIDTH(clientRect); auto clientHeight = RECT_HEIGHT(clientRect); - QPoint qtScenePos = - QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle); + QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), + m_windowHandle.data()); bool isFixedSize = m_delegate->isHostSizeFixed(m_host); bool isTitleBar = isInTitleBarDraggableArea(qtScenePos); @@ -2091,9 +2104,12 @@ switch (message) { case WM_RBUTTONUP: { const POINT nativeLocalPos = getNativePosFromMouse(); - const QPoint qtScenePos = - QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle); - if (isInTitleBarDraggableArea(qtScenePos)) { + const QPoint qtScenePos = QHighDpi::fromNativeLocalPosition( + point2qpoint(nativeLocalPos), m_windowHandle.data()); + WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown; + if (isInTitleBarDraggableArea(qtScenePos) || + (isInSystemButtons(qtScenePos, &sysButtonType) && + sysButtonType == WindowAgentBase::WindowIcon)) { shouldShowSystemMenu = true; nativeGlobalPos = nativeLocalPos; ::ClientToScreen(hWnd, &nativeGlobalPos); @@ -2143,7 +2159,10 @@ if (shouldShowSystemMenu) { static HHOOK mouseHook = nullptr; static std::optional<POINT> mouseClickPos; + static bool mouseDoubleClicked = false; bool mouseHookedLocal = false; + + // The menu is triggered by a click on icon button if (iconButtonClickTime > 0) { POINT menuPos{0, static_cast<LONG>(getTitleBarHeight(hWnd))}; if (const auto tb = titleBar()) { @@ -2160,11 +2179,23 @@ WH_MOUSE, [](int nCode, WPARAM wParam, LPARAM lParam) { if (nCode >= 0) { - if (wParam == WM_LBUTTONDOWN || wParam == WM_LBUTTONDBLCLK) { - auto pMouseStruct = reinterpret_cast<MOUSEHOOKSTRUCT *>(lParam); - if (pMouseStruct) { - mouseClickPos = pMouseStruct->pt; + switch (wParam) { + case WM_LBUTTONDBLCLK: + mouseDoubleClicked = true; + Q_FALLTHROUGH(); + + // case WM_POINTERDOWN: + + case WM_LBUTTONDOWN: { + auto pMouseStruct = + reinterpret_cast<MOUSEHOOKSTRUCT *>(lParam); + if (pMouseStruct) { + mouseClickPos = pMouseStruct->pt; + } + break; } + default: + break; } } return ::CallNextHookEx(nullptr, nCode, wParam, lParam); @@ -2173,6 +2204,7 @@ mouseHookedLocal = true; } } + bool res = showSystemMenu_sys(hWnd, nativeGlobalPos, broughtByKeyboard, m_delegate->isHostSizeFixed(m_host)); @@ -2181,22 +2213,28 @@ ::UnhookWindowsHookEx(mouseHook); // Emulate the Windows icon button's behavior - static uint32_t doubleClickTime = ::GetDoubleClickTime(); - if (!res && mouseClickPos.has_value() && - ::GetTickCount64() - iconButtonClickTime <= doubleClickTime) { + if (!res && mouseClickPos.has_value()) { POINT nativeLocalPos = mouseClickPos.value(); ::ScreenToClient(hWnd, &nativeLocalPos); QPoint qtScenePos = QHighDpi::fromNativeLocalPosition( - point2qpoint(nativeLocalPos), m_windowHandle); + point2qpoint(nativeLocalPos), m_windowHandle.data()); WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown; if (isInSystemButtons(qtScenePos, &sysButtonType) && sysButtonType == WindowAgentBase::WindowIcon) { - ::PostMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0); + iconButtonClickLevel |= IconButtonClicked; + if (::GetTickCount64() - iconButtonClickTime <= ::GetDoubleClickTime()) { + iconButtonClickLevel |= IconButtonTriggersClose; + } } + } + + if (mouseDoubleClicked) { + iconButtonClickLevel |= IconButtonDoubleClicked; } mouseHook = nullptr; mouseClickPos.reset(); + mouseDoubleClicked = false; } // QPA's internal code will handle system menu events separately, and its -- Gitblit v1.9.1