Compare commits

..

No commits in common. "2db829884decaec5a4c469f0ddef39c9e13512d8" and "6ff0bc9300a7ce26c6b86700da79b08eaf61d245" have entirely different histories.

4 changed files with 29 additions and 75 deletions

View File

@ -63,7 +63,7 @@ using SetCursorCallback = std::function<void(const QCursor &)>;
using UnsetCursorCallback = std::function<void()>;
using GetWidgetHandleCallback = std::function<QObject *()>;
using ForceChildrenRepaintCallback = std::function<void(const int)>;
using ResetQtGrabbedControlCallback = std::function<bool()>;
using ResetQtGrabbedControlCallback = std::function<void()>;
struct SystemParameters
{

View File

@ -317,9 +317,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
case WM_CLOSE:
case WM_DESTROY:
case WM_NCDESTROY:
// undocumented messages
case WM_UNREGISTER_WINDOW_SERVICES:
case WM_UAHDESTROYWINDOW:
case 144:
case 626:
return false;
default:
break;
@ -917,6 +916,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return true;
}
*result = HTCLIENT;
return true;
} else {
if (full) {
*result = HTCLIENT;
@ -979,16 +979,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return true;
}
*result = HTCLIENT;
}
return true;
}
case WM_MOUSEMOVE: {
const WindowPart previousWindowPart = getHittedWindowPart(data.hitTestResult.first.value_or(HTNOWHERE));
const WindowPart currentWindowPart = getHittedWindowPart(data.hitTestResult.second.value_or(HTNOWHERE));
if (previousWindowPart == WindowPart::ChromeButton && currentWindowPart == WindowPart::ClientArea) {
std::ignore = listenForMouseLeave(hWnd, false);
}
break;
}
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONDOWN:
@ -1016,12 +1008,24 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
const WindowPart previousWindowPart = getHittedWindowPart(data.hitTestResult.first.value_or(HTNOWHERE));
const WindowPart currentWindowPart = getHittedWindowPart(data.hitTestResult.second.value_or(HTNOWHERE));
if (uMsg == WM_NCMOUSELEAVE) {
if (previousWindowPart == WindowPart::ChromeButton && currentWindowPart == WindowPart::NotInterested) {
// If current window part is chrome button, it indicates that we must have clicked
// the minimize button or maximize button, we also should send the client leave
// message to Qt.
if (previousWindowPart == WindowPart::ChromeButton) {
if (currentWindowPart == WindowPart::ClientArea) {
// Since we filter the WM_MOUSELEAVE event when the mouse is above the buttons,
// Qt will always think it's tracking the mouse.
// If we don't track the mouse after the mouse enter client area, there will
// be no WM_MOUSELEAVE sent by Windows which should be sent.
std::ignore = listenForMouseLeave(hWnd, false);
// According to numerous experiments we've conducted, Windows maintains the mouse
// state internally, we must eventually let Windows handle the WM_NCMOUSELEAVE
// otherwise the internal state will be broken so that Windows may fail to send
// the WM_NCMOUSELEAVE messages which we need.
*result = ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
return true;
} else if (currentWindowPart == WindowPart::NotInterested) {
emulateClientAreaMessage(WM_NCMOUSELEAVE);
}
}
if (currentWindowPart == WindowPart::NotInterested) {
// The mouse is leaving window from non-client area, clear window part caches
@ -1033,13 +1037,11 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
// 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.
std::ignore = data.params.resetQtGrabbedControl();
}
} else {
if (uMsg == WM_NCMOUSEMOVE) {
if (currentWindowPart != WindowPart::ChromeButton) {
std::ignore = data.params.resetQtGrabbedControl();
data.params.resetQtGrabbedControl();
}
if ((previousWindowPart == WindowPart::ChromeButton)
&& ((currentWindowPart == WindowPart::TitleBar)
@ -1047,7 +1049,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|| (currentWindowPart == WindowPart::FixedBorder))) {
emulateClientAreaMessage(WM_NCMOUSELEAVE);
}
}
{
// We need to make sure we get the correct window part when a WM_NCMOUSELEAVE come,
// so we reset current window part to null when we receive a WM_NCMOUSEMOVE.
@ -1064,6 +1068,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
if (currentWindowPart == WindowPart::ChromeButton) {
emulateClientAreaMessage();
if (uMsg == WM_NCMOUSEMOVE) {
// We should pass WM_NCMOUSEMOVE to Windows as well as WM_NCMOUSELEAVE
*result = ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
} else {
*result = ((uMsg >= WM_NCXBUTTONDOWN) && (uMsg <= WM_NCXBUTTONDBLCLK)) ? TRUE : FALSE;
@ -1150,43 +1155,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
case WM_EXITSIZEMOVE: // Sent to a window when the user releases the mouse button (from dragging the title bar or the resize border).
updateRestoreGeometry(false);
break;
case WM_ACTIVATE: {
auto filteredWParam = LOWORD(wParam);
if (filteredWParam == WA_INACTIVE) {
if (getHittedWindowPart(data.hitTestResult.second.value_or(HTNOWHERE)) == WindowPart::ChromeButton) {
emulateClientAreaMessage(WM_NCMOUSELEAVE);
// Clear window part cache
auto &hitTestResult = muData.hitTestResult;
hitTestResult.first.reset();
hitTestResult.second.reset();
}
}
break;
}
case WM_INITMENU:{
if (getHittedWindowPart(data.hitTestResult.second.value_or(HTNOWHERE)) == WindowPart::ChromeButton) {
emulateClientAreaMessage(WM_NCMOUSELEAVE);
// Clear window part cache
auto &hitTestResult = muData.hitTestResult;
hitTestResult.first.reset();
hitTestResult.second.reset();
}
break;
}
case WM_SIZE: {
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED) {
if (getHittedWindowPart(data.hitTestResult.second.value_or(HTNOWHERE)) == WindowPart::ChromeButton) {
emulateClientAreaMessage(WM_NCMOUSELEAVE);
// Clear window part cache
auto &hitTestResult = muData.hitTestResult;
hitTestResult.first.reset();
hitTestResult.second.reset();
}
break;
}
if (wParam != SIZE_MAXIMIZED) {
break;
}

View File

@ -168,7 +168,7 @@ void FramelessQuickHelperPrivate::attach()
params.unsetCursor = [window]() -> void { window->unsetCursor(); };
params.getWidgetHandle = []() -> QObject * { return nullptr; };
params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); };
params.resetQtGrabbedControl = []() -> bool { return false; };
params.resetQtGrabbedControl = []() -> void {};
FramelessManager::instance()->addWindow(&params);

View File

@ -42,9 +42,7 @@
#include <QtGui/qwindow.h>
#include <QtGui/qpalette.h>
#include <QtGui/qcursor.h>
#include <QtGui/qevent.h>
#include <QtWidgets/qwidget.h>
#include <QtWidgets/qapplication.h>
#ifndef QWIDGETSIZE_MAX
# define QWIDGETSIZE_MAX ((1 << 24) - 1)
@ -411,20 +409,7 @@ void FramelessWidgetsHelperPrivate::attach()
params.unsetCursor = [this]() -> void { window->unsetCursor(); };
params.getWidgetHandle = [this]() -> QObject * { return window; };
params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); };
params.resetQtGrabbedControl = []() -> bool {
if (qt_button_down) {
QMouseEvent e(QEvent::MouseButtonRelease,
{-999, -999},
Qt::LeftButton,
Qt::NoButton,
QApplication::keyboardModifiers()
);
QApplication::sendEvent(qt_button_down, &e);
qt_button_down = nullptr;
return true;
}
return false;
};
params.resetQtGrabbedControl = []() -> void { qt_button_down = nullptr; };
FramelessManager::instance()->addWindow(&params);