From 7955f5b084aeae334a445136839160356c96de36 Mon Sep 17 00:00:00 2001 From: Sine Striker <trueful@163.com> Date: 周三, 20 12月 2023 03:59:57 +0800 Subject: [PATCH] Add comments --- src/widgets/widgetitemdelegate.cpp | 2 src/core/contexts/cocoawindowcontext.mm | 4 +- README.md | 2 src/core/contexts/win32windowcontext.cpp | 54 +++++++++++++++++++++++++- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f4aff2a..3951ff2 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ ## Dependencies -+ Qt 5.15 or higher ++ Qt 5.12 or higher + [qmsetup](https://github.com/stdware/qmsetup) ## Integrate diff --git a/src/core/contexts/cocoawindowcontext.mm b/src/core/contexts/cocoawindowcontext.mm index 9723d5a..5011e28 100644 --- a/src/core/contexts/cocoawindowcontext.mm +++ b/src/core/contexts/cocoawindowcontext.mm @@ -384,7 +384,7 @@ const auto &key = *static_cast<const QString *>(args[0]); const auto &newVar = *static_cast<const QVariant *>(args[1]); const auto &oldVar = *static_cast<const QVariant *>(args[2]); - + if (key == QStringLiteral("no-system-buttons")) { if (newVar.toBool()) { // TODO: set off @@ -392,7 +392,7 @@ // TODO: set on } } - break; + return; } default: diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 230bf5d..145b19c 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -902,7 +902,7 @@ const auto &key = *static_cast<const QString *>(args[0]); const auto &newVar = *static_cast<const QVariant *>(args[1]); const auto &oldVar = *static_cast<const QVariant *>(args[2]); - + if (key == QStringLiteral("no-frame-shadow")) { if (newVar.toBool()) { // TODO: set off @@ -911,7 +911,7 @@ } } - break; + return; } case DefaultColorsHook: { @@ -965,7 +965,6 @@ } default: { - // unreachable break; } } @@ -1268,6 +1267,53 @@ const WindowPart currentWindowPart = lastHitTestResult; if (message == WM_NCMOUSEMOVE) { if (currentWindowPart != WindowPart::ChromeButton) { + // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/widgets/kernel/qwidgetwindow.cpp#L472 + // When the mouse press event arrives, QWidgetWindow will implicitly grab + // the top widget right under the mouse, and set `qt_button_down` to this + // widget. At this time, no other widgets will accept the mouse event until + // QWidgetWindow receives the mouse release event, then set `qt_button_down` + // to null. + + // Imagine the following situation, now the main window has a pop-up menu, + // the focus is not on the main window, if we click outside the pop-up menu, + // the menu will close, which seems to be completely fine. But if we close + // the menu by clicking on the title bar draggable area, then other widgets + // won't accept the mouse message afterwards. + + // Here's the reason. + // When the mouse is placed in the draggable area of the title bar, there + // are two situations. + + // 1. If the focus is on the main window, and the last result of + // WM_NCHITTEST is HTCAPTION, the mouse click event in the title bar is + // taken over by Windows and Qt does not receive the mouse click event. + + // 2. If the main window has a pop-up menu, it is completely different. When + // the mouse is pressed on the title bar, Windows sends the WM_LBUTTONDOWN + // message to the window plane of the pop-up menu, the menu is closed, but + // Qt will continue to forward the event to the QWidget under the mouse, and + // the event will be processed by QWidgetWindow, causing the title bar + // widget to be implicitly grabbed. After the menu is closed, Windows + // immediately sends WM_NCHITTEST, because the mouse is in the title bar + // draggable area, the result is HTCAPTION, so when the mouse is released, + // Windows sends WM_NCLBUTTONUP, which is a non-client area message, and it + // will be ignored by Qt. As a consequence, QWidgetWindow can't receive a + // mouse release messages in the client area, so the grab remains, and other + // widgets cannot receive mouse events. + + // Since we didn't watch the menu window, we cannot capture any mouse + // press events sent by Windows, so we cannot solve this problem by + // recording mouse events. Fortunately, we found that the main window will + // receive a WM_NCMOUSEMOVE message immediately after the menu is closed, so + // we just manually send a mouse release event when this message arrives and + // set qt_button_down to null. Don't worry, when receiving WM_NCMOUSEMOVE, + // there shouldn't be any control in the state of being grabbed. + + // In the native window, although QWidgetWindow handles the forwarded mouse + // press event when the menu is closed, since the native title bar is not a + // QWidget, no widget will be grabbed, and `qt_button_down` remains empty, + // the above problems would not arise. + m_delegate->resetQtGrabbedControl(m_host); if (mouseLeaveBlocked) { emulateClientAreaMessage(hWnd, message, wParam, lParam, @@ -1330,6 +1376,8 @@ // window from client area, which means we will get previous window part as // HTCLIENT if the mouse leaves window from client area and enters window // from non-client area, but it has no bad effect. + + // Why do we need to call this function here? m_delegate->resetQtGrabbedControl(m_host); } } diff --git a/src/widgets/widgetitemdelegate.cpp b/src/widgets/widgetitemdelegate.cpp index 07c8aa3..214617b 100644 --- a/src/widgets/widgetitemdelegate.cpp +++ b/src/widgets/widgetitemdelegate.cpp @@ -4,7 +4,7 @@ #include <QtWidgets/QWidget> #include <QtWidgets/QApplication> -extern Q_WIDGETS_EXPORT QWidget *qt_button_down; +extern Q_DECL_IMPORT QWidget *qt_button_down; namespace QWK { -- Gitblit v1.9.1