Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-03-19 15:23:18 +08:00
parent 79ea80ea74
commit b1f0e38fc8
8 changed files with 229 additions and 164 deletions

View File

@ -26,7 +26,6 @@
#include <QtCore/qdebug.h> #include <QtCore/qdebug.h>
#include <QtCore/qhash.h> #include <QtCore/qhash.h>
#include <QtCore/qmutex.h> #include <QtCore/qmutex.h>
#include <QtCore/qvariant.h>
#include <QtCore/qcoreapplication.h> #include <QtCore/qcoreapplication.h>
#include <QtGui/qwindow.h> #include <QtGui/qwindow.h>
#include "framelesswindowsmanager.h" #include "framelesswindowsmanager.h"
@ -41,7 +40,6 @@ struct Win32Helper
QScopedPointer<FramelessHelperWin> nativeEventFilter; QScopedPointer<FramelessHelperWin> nativeEventFilter;
QWindowList framelessWindows = {}; QWindowList framelessWindows = {};
QHash<WId, QWindow *> windowMapping = {}; QHash<WId, QWindow *> windowMapping = {};
QHash<HWND, WNDPROC> qtWindowProcs = {};
explicit Win32Helper() = default; explicit Win32Helper() = default;
~Win32Helper() = default; ~Win32Helper() = default;
@ -52,127 +50,6 @@ private:
Q_GLOBAL_STATIC(Win32Helper, g_win32Helper) Q_GLOBAL_STATIC(Win32Helper, g_win32Helper)
[[nodiscard]] static inline LRESULT CALLBACK HookWindowProc
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
{
g_win32Helper()->mutex.lock();
if (!g_win32Helper()->qtWindowProcs.contains(hWnd)) {
g_win32Helper()->mutex.unlock();
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
g_win32Helper()->mutex.unlock();
const auto winId = reinterpret_cast<WId>(hWnd);
const auto getGlobalPosFromMouse = [lParam]() -> QPointF {
return {qreal(GET_X_LPARAM(lParam)), qreal(GET_Y_LPARAM(lParam))};
};
const auto getGlobalPosFromKeyboard = [hWnd, winId]() -> QPointF {
RECT windowPos = {};
if (GetWindowRect(hWnd, &windowPos) == FALSE) {
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetWindowRect"));
return {};
}
const bool maxOrFull = (IsMaximized(hWnd) || Utils::isFullScreen(winId));
const int frameSizeX = Utils::getResizeBorderThickness(winId, true, true);
const int frameSizeY = Utils::getResizeBorderThickness(winId, false, true);
const int titleBarHeight = Utils::getTitleBarHeight(winId, true);
const int horizontalOffset = ((maxOrFull || !Utils::isWindowFrameBorderVisible()) ? 0 : frameSizeX);
const int verticalOffset = (maxOrFull ? titleBarHeight : (titleBarHeight - frameSizeY));
return {qreal(windowPos.left + horizontalOffset), qreal(windowPos.top + verticalOffset)};
};
bool shouldShowSystemMenu = false;
QPointF globalPos = {};
if (uMsg == WM_NCRBUTTONUP) {
if (wParam == HTCAPTION) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromMouse();
}
} else if (uMsg == WM_SYSCOMMAND) {
const WPARAM filteredWParam = (wParam & 0xFFF0);
if ((filteredWParam == SC_KEYMENU) && (lParam == VK_SPACE)) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromKeyboard();
}
} else if ((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN)) {
const bool altPressed = ((wParam == VK_MENU) || (GetKeyState(VK_MENU) < 0));
const bool spacePressed = ((wParam == VK_SPACE) || (GetKeyState(VK_SPACE) < 0));
if (altPressed && spacePressed) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromKeyboard();
}
}
if (shouldShowSystemMenu) {
Utils::showSystemMenu(winId, globalPos);
// QPA's internal code will handle system menu events separately, and its
// behavior is not what we would want to see because it doesn't know our
// window doesn't have any window frame now, so return early here to avoid
// entering Qt's own handling logic.
return 0; // Return 0 means we have handled this event.
}
g_win32Helper()->mutex.lock();
const WNDPROC originalWindowProc = g_win32Helper()->qtWindowProcs.value(hWnd);
g_win32Helper()->mutex.unlock();
Q_ASSERT(originalWindowProc);
if (originalWindowProc) {
// Hand over to Qt's original window proc function for events we are not
// interested in.
return CallWindowProcW(originalWindowProc, hWnd, uMsg, wParam, lParam);
} else {
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
}
[[nodiscard]] static inline bool installWindowHook(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return false;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
QMutexLocker locker(&g_win32Helper()->mutex);
if (g_win32Helper()->qtWindowProcs.contains(hwnd)) {
return false;
}
SetLastError(ERROR_SUCCESS);
const auto originalWindowProc = reinterpret_cast<WNDPROC>(GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
Q_ASSERT(originalWindowProc);
if (!originalWindowProc) {
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetWindowLongPtrW"));
return false;
}
SetLastError(ERROR_SUCCESS);
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(HookWindowProc)) == 0) {
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return false;
}
g_win32Helper()->qtWindowProcs.insert(hwnd, originalWindowProc);
return true;
}
[[nodiscard]] static inline bool uninstallWindowHook(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return false;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
QMutexLocker locker(&g_win32Helper()->mutex);
if (!g_win32Helper()->qtWindowProcs.contains(hwnd)) {
return false;
}
const WNDPROC originalWindowProc = g_win32Helper()->qtWindowProcs.value(hwnd);
Q_ASSERT(originalWindowProc);
if (!originalWindowProc) {
return false;
}
SetLastError(ERROR_SUCCESS);
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(originalWindowProc)) == 0) {
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return false;
}
g_win32Helper()->qtWindowProcs.remove(hwnd);
return true;
}
FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {} FramelessHelperWin::FramelessHelperWin() : QAbstractNativeEventFilter() {}
FramelessHelperWin::~FramelessHelperWin() FramelessHelperWin::~FramelessHelperWin()
@ -204,9 +81,6 @@ void FramelessHelperWin::addWindow(QWindow *window)
Utils::updateWindowFrameMargins(winId, false); Utils::updateWindowFrameMargins(winId, false);
const bool dark = Utils::shouldAppsUseDarkMode(); const bool dark = Utils::shouldAppsUseDarkMode();
Utils::updateWindowFrameBorderColor(winId, dark); Utils::updateWindowFrameBorderColor(winId, dark);
if (!installWindowHook(winId)) {
qWarning() << "Failed to hook the window proc function.";
}
} }
void FramelessHelperWin::removeWindow(QWindow *window) void FramelessHelperWin::removeWindow(QWindow *window)
@ -224,9 +98,6 @@ void FramelessHelperWin::removeWindow(QWindow *window)
const WId winId = window->winId(); const WId winId = window->winId();
g_win32Helper()->windowMapping.remove(winId); g_win32Helper()->windowMapping.remove(winId);
g_win32Helper()->mutex.unlock(); g_win32Helper()->mutex.unlock();
if (!uninstallWindowHook(winId)) {
qWarning() << "Failed to un-hook the window proc function.";
}
Utils::updateInternalWindowFrameMargins(window, false); Utils::updateInternalWindowFrameMargins(window, false);
Utils::updateWindowFrameMargins(winId, true); Utils::updateWindowFrameMargins(winId, true);
} }

View File

@ -34,12 +34,6 @@
FRAMELESSHELPER_BEGIN_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE
#ifdef Q_OS_WINDOWS
static const bool g_usePureQtImplementation = (qEnvironmentVariableIntValue("FRAMELESSHELPER_PURE_QT_IMPL") != 0);
#else
static constexpr const bool g_usePureQtImplementation = true;
#endif
Q_GLOBAL_STATIC(FramelessWindowsManager, g_manager) Q_GLOBAL_STATIC(FramelessWindowsManager, g_manager)
FramelessWindowsManagerPrivate::FramelessWindowsManagerPrivate(FramelessWindowsManager *q) FramelessWindowsManagerPrivate::FramelessWindowsManagerPrivate(FramelessWindowsManager *q)
@ -52,6 +46,25 @@ FramelessWindowsManagerPrivate::FramelessWindowsManagerPrivate(FramelessWindowsM
FramelessWindowsManagerPrivate::~FramelessWindowsManagerPrivate() = default; FramelessWindowsManagerPrivate::~FramelessWindowsManagerPrivate() = default;
FramelessWindowsManagerPrivate *FramelessWindowsManagerPrivate::get(FramelessWindowsManager *manager)
{
Q_ASSERT(manager);
if (!manager) {
return nullptr;
}
return manager->d_func();
}
bool FramelessWindowsManagerPrivate::usePureQtImplementation() const
{
#ifdef Q_OS_WINDOWS
static const bool result = (qEnvironmentVariableIntValue("FRAMELESSHELPER_PURE_QT_IMPL") != 0);
#else
static constexpr const bool result = true;
#endif
return result;
}
QUuid FramelessWindowsManagerPrivate::findIdByWindow(QWindow *value) const QUuid FramelessWindowsManagerPrivate::findIdByWindow(QWindow *value) const
{ {
Q_ASSERT(value); Q_ASSERT(value);
@ -140,16 +153,18 @@ void FramelessWindowsManager::addWindow(QWindow *window)
} }
const QUuid uuid = QUuid::createUuid(); const QUuid uuid = QUuid::createUuid();
d->windowMapping.insert(window, uuid); d->windowMapping.insert(window, uuid);
d->winIdMapping.insert(window->winId(), uuid); const WId winId = window->winId();
d->winIdMapping.insert(winId, uuid);
static const bool pureQt = d->usePureQtImplementation();
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
if (!g_usePureQtImplementation) { if (!pureQt) {
// Work-around Win32 multi-monitor artifacts. // Work-around Win32 multi-monitor artifacts.
const QMetaObject::Connection workaroundConnection = const QMetaObject::Connection workaroundConnection =
connect(window, &QWindow::screenChanged, window, [window](QScreen *screen){ connect(window, &QWindow::screenChanged, window, [winId, window](QScreen *screen){
Q_UNUSED(screen); Q_UNUSED(screen);
// Force a WM_NCCALCSIZE event to inform Windows about our custom window frame, // Force a WM_NCCALCSIZE event to inform Windows about our custom window frame,
// this is only necessary when the window is being moved cross monitors. // this is only necessary when the window is being moved cross monitors.
Utils::triggerFrameChange(window->winId()); Utils::triggerFrameChange(winId);
// For some reason the window is not repainted correctly when moving cross monitors, // For some reason the window is not repainted correctly when moving cross monitors,
// we workaround this issue by force a re-paint and re-layout of the window by triggering // we workaround this issue by force a re-paint and re-layout of the window by triggering
// a resize event manually. Although the actual size does not change, the issue we // a resize event manually. Although the actual size does not change, the issue we
@ -160,13 +175,14 @@ void FramelessWindowsManager::addWindow(QWindow *window)
} }
#endif #endif
d->mutex.unlock(); d->mutex.unlock();
if (g_usePureQtImplementation) { if (pureQt) {
FramelessHelperQt::addWindow(window); FramelessHelperQt::addWindow(window);
} }
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
if (!g_usePureQtImplementation) { if (!pureQt) {
FramelessHelperWin::addWindow(window); FramelessHelperWin::addWindow(window);
} }
Utils::installSystemMenuHook(winId);
#endif #endif
} }
@ -186,20 +202,25 @@ void FramelessWindowsManager::removeWindow(QWindow *window)
if (uuid.isNull()) { if (uuid.isNull()) {
return; return;
} }
if (g_usePureQtImplementation) { const WId winId = window->winId();
FramelessHelperQt::removeWindow(window);
}
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
if (!g_usePureQtImplementation) {
FramelessHelperWin::removeWindow(window);
}
if (d->win32WorkaroundConnections.contains(uuid)) { if (d->win32WorkaroundConnections.contains(uuid)) {
disconnect(d->win32WorkaroundConnections.value(uuid)); disconnect(d->win32WorkaroundConnections.value(uuid));
d->win32WorkaroundConnections.remove(uuid); d->win32WorkaroundConnections.remove(uuid);
} }
Utils::uninstallSystemMenuHook(winId);
#endif
static const bool pureQt = d->usePureQtImplementation();
if (pureQt) {
FramelessHelperQt::removeWindow(window);
}
#ifdef Q_OS_WINDOWS
if (!pureQt) {
FramelessHelperWin::removeWindow(window);
}
#endif #endif
d->windowMapping.remove(window); d->windowMapping.remove(window);
d->winIdMapping.remove(window->winId()); d->winIdMapping.remove(winId);
} }
FRAMELESSHELPER_END_NAMESPACE FRAMELESSHELPER_END_NAMESPACE

View File

@ -43,6 +43,10 @@ public:
explicit FramelessWindowsManagerPrivate(FramelessWindowsManager *q); explicit FramelessWindowsManagerPrivate(FramelessWindowsManager *q);
~FramelessWindowsManagerPrivate(); ~FramelessWindowsManagerPrivate();
[[nodiscard]] static FramelessWindowsManagerPrivate *get(FramelessWindowsManager *manager);
[[nodiscard]] bool usePureQtImplementation() const;
[[nodiscard]] QUuid findIdByWindow(QWindow *value) const; [[nodiscard]] QUuid findIdByWindow(QWindow *value) const;
[[nodiscard]] QUuid findIdByWinId(const WId value) const; [[nodiscard]] QUuid findIdByWinId(const WId value) const;

View File

@ -109,6 +109,8 @@ FRAMELESSHELPER_CORE_API void fixupQtInternals(const WId winId);
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible();
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized();
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized(); [[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized();
FRAMELESSHELPER_CORE_API void installSystemMenuHook(const WId winId);
FRAMELESSHELPER_CORE_API void uninstallSystemMenuHook(const WId winId);
#endif // Q_OS_WINDOWS #endif // Q_OS_WINDOWS
} // namespace Utils } // namespace Utils

View File

@ -24,6 +24,8 @@
#include "utils.h" #include "utils.h"
#include <QtCore/qdebug.h> #include <QtCore/qdebug.h>
#include <QtCore/qmutex.h>
#include <QtCore/qhash.h>
#include <QtGui/qguiapplication.h> #include <QtGui/qguiapplication.h>
#include <QtCore/private/qsystemlibrary_p.h> #include <QtCore/private/qsystemlibrary_p.h>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
@ -39,6 +41,8 @@
#endif #endif
#include "qwinregistry_p.h" #include "qwinregistry_p.h"
#include "framelesshelper_windows.h" #include "framelesshelper_windows.h"
#include "framelesswindowsmanager.h"
#include "framelesswindowsmanager_p.h"
#if 0 #if 0
#include <atlbase.h> #include <atlbase.h>
#include <d2d1.h> #include <d2d1.h>
@ -48,6 +52,20 @@ Q_DECLARE_METATYPE(QMargins)
FRAMELESSHELPER_BEGIN_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE
struct Win32UtilsHelper
{
QMutex mutex = {};
QHash<HWND, WNDPROC> qtWindowProcs = {};
explicit Win32UtilsHelper() = default;
~Win32UtilsHelper() = default;
private:
Q_DISABLE_COPY_MOVE(Win32UtilsHelper)
};
Q_GLOBAL_STATIC(Win32UtilsHelper, g_utilsHelper)
static const QString successErrorText = QStringLiteral("The operation completed successfully."); static const QString successErrorText = QStringLiteral("The operation completed successfully.");
#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0)) #if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
@ -154,6 +172,90 @@ static const QString successErrorText = QStringLiteral("The operation completed
} }
#endif #endif
[[nodiscard]] static inline LRESULT CALLBACK SystemMenuHookWindowProc
(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
{
g_utilsHelper()->mutex.lock();
if (!g_utilsHelper()->qtWindowProcs.contains(hWnd)) {
g_utilsHelper()->mutex.unlock();
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
g_utilsHelper()->mutex.unlock();
const auto winId = reinterpret_cast<WId>(hWnd);
const auto getGlobalPosFromMouse = [lParam]() -> QPointF {
return {qreal(GET_X_LPARAM(lParam)), qreal(GET_Y_LPARAM(lParam))};
};
const auto getGlobalPosFromKeyboard = [hWnd, winId]() -> QPointF {
RECT windowPos = {};
if (GetWindowRect(hWnd, &windowPos) == FALSE) {
qWarning() << Utils::getSystemErrorMessage(QStringLiteral("GetWindowRect"));
return {};
}
const bool maxOrFull = (IsMaximized(hWnd) || Utils::isFullScreen(winId));
const int frameSizeX = Utils::getResizeBorderThickness(winId, true, true);
const bool frameBorderVisible = Utils::isWindowFrameBorderVisible();
const int horizontalOffset = ((maxOrFull || !frameBorderVisible) ? 0 : frameSizeX);
const int verticalOffset = [winId, frameBorderVisible, maxOrFull]() -> int {
const int titleBarHeight = Utils::getTitleBarHeight(winId, true);
if (!frameBorderVisible) {
return titleBarHeight;
}
const int frameSizeY = Utils::getResizeBorderThickness(winId, false, true);
if (Utils::isWin11OrGreater()) {
if (maxOrFull) {
return (titleBarHeight + frameSizeY);
}
return titleBarHeight;
}
if (maxOrFull) {
return titleBarHeight;
}
return (titleBarHeight - frameSizeY);
}();
return {qreal(windowPos.left + horizontalOffset), qreal(windowPos.top + verticalOffset)};
};
bool shouldShowSystemMenu = false;
QPointF globalPos = {};
if (uMsg == WM_NCRBUTTONUP) {
if (wParam == HTCAPTION) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromMouse();
}
} else if (uMsg == WM_SYSCOMMAND) {
const WPARAM filteredWParam = (wParam & 0xFFF0);
if ((filteredWParam == SC_KEYMENU) && (lParam == VK_SPACE)) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromKeyboard();
}
} else if ((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN)) {
const bool altPressed = ((wParam == VK_MENU) || (GetKeyState(VK_MENU) < 0));
const bool spacePressed = ((wParam == VK_SPACE) || (GetKeyState(VK_SPACE) < 0));
if (altPressed && spacePressed) {
shouldShowSystemMenu = true;
globalPos = getGlobalPosFromKeyboard();
}
}
if (shouldShowSystemMenu) {
Utils::showSystemMenu(winId, globalPos);
// QPA's internal code will handle system menu events separately, and its
// behavior is not what we would want to see because it doesn't know our
// window doesn't have any window frame now, so return early here to avoid
// entering Qt's own handling logic.
return 0; // Return 0 means we have handled this event.
}
g_utilsHelper()->mutex.lock();
const WNDPROC originalWindowProc = g_utilsHelper()->qtWindowProcs.value(hWnd);
g_utilsHelper()->mutex.unlock();
Q_ASSERT(originalWindowProc);
if (originalWindowProc) {
// Hand over to Qt's original window proc function for events we are not
// interested in.
return CallWindowProcW(originalWindowProc, hWnd, uMsg, wParam, lParam);
} else {
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
}
bool Utils::isWin8OrGreater() bool Utils::isWin8OrGreater()
{ {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
@ -860,12 +962,24 @@ void Utils::startSystemResize(QWindow *window, const Qt::Edges edges)
bool Utils::isWindowFrameBorderVisible() bool Utils::isWindowFrameBorderVisible()
{ {
static const bool result = []() -> bool { static const bool result = []() -> bool {
if (qEnvironmentVariableIntValue("FRAMELESSHELPER_FORCE_SHOW_FRAME_BORDER") != 0) { FramelessWindowsManager *manager = FramelessWindowsManager::instance();
return true; Q_ASSERT(manager);
if (manager) {
FramelessWindowsManagerPrivate *internal = FramelessWindowsManagerPrivate::get(manager);
Q_ASSERT(internal);
if (internal) {
if (internal->usePureQtImplementation()) {
return false;
}
}
} }
// If we preserve the window frame border on systems prior to Windows 10, // If we preserve the window frame border on systems prior to Windows 10,
// the window will look rather ugly and I guess no one would like to see // the window will look rather ugly and I guess no one would like to see
// such weired windows. // such weired windows. But for the ones who really want to see what the
// window look like, I still provide a way to enter such scenarios.
if (qEnvironmentVariableIntValue("FRAMELESSHELPER_FORCE_SHOW_FRAME_BORDER") != 0) {
return true;
}
return (isWin10OrGreater() && !qEnvironmentVariableIsSet("FRAMELESSHELPER_HIDE_FRAME_BORDER")); return (isWin10OrGreater() && !qEnvironmentVariableIsSet("FRAMELESSHELPER_HIDE_FRAME_BORDER"));
}(); }();
return result; return result;
@ -886,4 +1000,54 @@ bool Utils::isFrameBorderColorized()
return isTitleBarColorized(); return isTitleBarColorized();
} }
void Utils::installSystemMenuHook(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
QMutexLocker locker(&g_utilsHelper()->mutex);
if (g_utilsHelper()->qtWindowProcs.contains(hwnd)) {
return;
}
SetLastError(ERROR_SUCCESS);
const auto originalWindowProc = reinterpret_cast<WNDPROC>(GetWindowLongPtrW(hwnd, GWLP_WNDPROC));
Q_ASSERT(originalWindowProc);
if (!originalWindowProc) {
qWarning() << getSystemErrorMessage(QStringLiteral("GetWindowLongPtrW"));
return;
}
SetLastError(ERROR_SUCCESS);
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SystemMenuHookWindowProc)) == 0) {
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return;
}
g_utilsHelper()->qtWindowProcs.insert(hwnd, originalWindowProc);
}
void Utils::uninstallSystemMenuHook(const WId winId)
{
Q_ASSERT(winId);
if (!winId) {
return;
}
const auto hwnd = reinterpret_cast<HWND>(winId);
QMutexLocker locker(&g_utilsHelper()->mutex);
if (!g_utilsHelper()->qtWindowProcs.contains(hwnd)) {
return;
}
const WNDPROC originalWindowProc = g_utilsHelper()->qtWindowProcs.value(hwnd);
Q_ASSERT(originalWindowProc);
if (!originalWindowProc) {
return;
}
SetLastError(ERROR_SUCCESS);
if (SetWindowLongPtrW(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(originalWindowProc)) == 0) {
qWarning() << getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return;
}
g_utilsHelper()->qtWindowProcs.remove(hwnd);
}
FRAMELESSHELPER_END_NAMESPACE FRAMELESSHELPER_END_NAMESPACE

View File

@ -200,9 +200,11 @@ bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
#else #else
const QPointF scenePos = mouseEvent->windowPos(); const QPointF scenePos = mouseEvent->windowPos();
#endif #endif
if ((scenePos.x() < kDefaultResizeBorderThickness) const QQuickWindow::Visibility visibility = window->visibility();
|| (scenePos.x() >= (window->width() - kDefaultResizeBorderThickness)) if ((visibility == QQuickWindow::Windowed)
|| (scenePos.y() < kDefaultResizeBorderThickness)) { && ((scenePos.x() < kDefaultResizeBorderThickness)
|| (scenePos.x() >= (window->width() - kDefaultResizeBorderThickness))
|| (scenePos.y() < kDefaultResizeBorderThickness))) {
return false; return false;
} }
const bool titleBar = isInTitleBarDraggableArea(window, scenePos); const bool titleBar = isInTitleBarDraggableArea(window, scenePos);
@ -240,7 +242,6 @@ bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
if (!titleBar) { if (!titleBar) {
return false; return false;
} }
const QQuickWindow::Visibility visibility = window->visibility();
if ((visibility == QQuickWindow::Maximized) || (visibility == QQuickWindow::FullScreen)) { if ((visibility == QQuickWindow::Maximized) || (visibility == QQuickWindow::FullScreen)) {
window->showNormal(); window->showNormal();
} else { } else {

View File

@ -212,9 +212,7 @@ void FramelessWidgetsHelper::mousePressEventHandler(QMouseEvent *event)
#else #else
const QPoint scenePos = event->windowPos(); const QPoint scenePos = event->windowPos();
#endif #endif
if ((scenePos.x() < kDefaultResizeBorderThickness) if (shouldIgnoreMouseEvents(scenePos)) {
|| (scenePos.x() >= (q->width() - kDefaultResizeBorderThickness))
|| (scenePos.y() < kDefaultResizeBorderThickness)) {
return; return;
} }
if (!isInTitleBarDraggableArea(scenePos)) { if (!isInTitleBarDraggableArea(scenePos)) {
@ -237,9 +235,7 @@ void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
#else #else
const QPoint scenePos = event->windowPos(); const QPoint scenePos = event->windowPos();
#endif #endif
if ((scenePos.x() < kDefaultResizeBorderThickness) if (shouldIgnoreMouseEvents(scenePos)) {
|| (scenePos.x() >= (q->width() - kDefaultResizeBorderThickness))
|| (scenePos.y() < kDefaultResizeBorderThickness)) {
return; return;
} }
if (!isInTitleBarDraggableArea(scenePos)) { if (!isInTitleBarDraggableArea(scenePos)) {
@ -270,9 +266,7 @@ void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event)
#else #else
const QPoint scenePos = event->windowPos(); const QPoint scenePos = event->windowPos();
#endif #endif
if ((scenePos.x() < kDefaultResizeBorderThickness) if (shouldIgnoreMouseEvents(scenePos)) {
|| (scenePos.x() >= (q->width() - kDefaultResizeBorderThickness))
|| (scenePos.y() < kDefaultResizeBorderThickness)) {
return; return;
} }
if (!isInTitleBarDraggableArea(scenePos)) { if (!isInTitleBarDraggableArea(scenePos)) {
@ -439,6 +433,13 @@ bool FramelessWidgetsHelper::isCustomLayout() const
return (m_windowLayout == WindowLayout::Custom); return (m_windowLayout == WindowLayout::Custom);
} }
bool FramelessWidgetsHelper::shouldIgnoreMouseEvents(const QPoint &pos) const
{
return (isNormal() && ((pos.x() < kDefaultResizeBorderThickness)
|| (pos.x() >= (q->width() - kDefaultResizeBorderThickness))
|| (pos.y() < kDefaultResizeBorderThickness)));
}
void FramelessWidgetsHelper::updateContentsMargins() void FramelessWidgetsHelper::updateContentsMargins()
{ {
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS

View File

@ -78,6 +78,7 @@ private:
Q_NODISCARD bool shouldDrawFrameBorder() const; Q_NODISCARD bool shouldDrawFrameBorder() const;
Q_NODISCARD bool isStandardLayout() const; Q_NODISCARD bool isStandardLayout() const;
Q_NODISCARD bool isCustomLayout() const; Q_NODISCARD bool isCustomLayout() const;
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
private Q_SLOTS: private Q_SLOTS:
void updateContentsMargins(); void updateContentsMargins();