parent
79ea80ea74
commit
b1f0e38fc8
|
@ -26,7 +26,6 @@
|
|||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include "framelesswindowsmanager.h"
|
||||
|
@ -41,7 +40,6 @@ struct Win32Helper
|
|||
QScopedPointer<FramelessHelperWin> nativeEventFilter;
|
||||
QWindowList framelessWindows = {};
|
||||
QHash<WId, QWindow *> windowMapping = {};
|
||||
QHash<HWND, WNDPROC> qtWindowProcs = {};
|
||||
|
||||
explicit Win32Helper() = default;
|
||||
~Win32Helper() = default;
|
||||
|
@ -52,127 +50,6 @@ private:
|
|||
|
||||
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()
|
||||
|
@ -204,9 +81,6 @@ void FramelessHelperWin::addWindow(QWindow *window)
|
|||
Utils::updateWindowFrameMargins(winId, false);
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
Utils::updateWindowFrameBorderColor(winId, dark);
|
||||
if (!installWindowHook(winId)) {
|
||||
qWarning() << "Failed to hook the window proc function.";
|
||||
}
|
||||
}
|
||||
|
||||
void FramelessHelperWin::removeWindow(QWindow *window)
|
||||
|
@ -224,9 +98,6 @@ void FramelessHelperWin::removeWindow(QWindow *window)
|
|||
const WId winId = window->winId();
|
||||
g_win32Helper()->windowMapping.remove(winId);
|
||||
g_win32Helper()->mutex.unlock();
|
||||
if (!uninstallWindowHook(winId)) {
|
||||
qWarning() << "Failed to un-hook the window proc function.";
|
||||
}
|
||||
Utils::updateInternalWindowFrameMargins(window, false);
|
||||
Utils::updateWindowFrameMargins(winId, true);
|
||||
}
|
||||
|
|
|
@ -34,12 +34,6 @@
|
|||
|
||||
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)
|
||||
|
||||
FramelessWindowsManagerPrivate::FramelessWindowsManagerPrivate(FramelessWindowsManager *q)
|
||||
|
@ -52,6 +46,25 @@ FramelessWindowsManagerPrivate::FramelessWindowsManagerPrivate(FramelessWindowsM
|
|||
|
||||
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
|
||||
{
|
||||
Q_ASSERT(value);
|
||||
|
@ -140,16 +153,18 @@ void FramelessWindowsManager::addWindow(QWindow *window)
|
|||
}
|
||||
const QUuid uuid = QUuid::createUuid();
|
||||
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
|
||||
if (!g_usePureQtImplementation) {
|
||||
if (!pureQt) {
|
||||
// Work-around Win32 multi-monitor artifacts.
|
||||
const QMetaObject::Connection workaroundConnection =
|
||||
connect(window, &QWindow::screenChanged, window, [window](QScreen *screen){
|
||||
connect(window, &QWindow::screenChanged, window, [winId, window](QScreen *screen){
|
||||
Q_UNUSED(screen);
|
||||
// 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.
|
||||
Utils::triggerFrameChange(window->winId());
|
||||
Utils::triggerFrameChange(winId);
|
||||
// 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
|
||||
// a resize event manually. Although the actual size does not change, the issue we
|
||||
|
@ -160,13 +175,14 @@ void FramelessWindowsManager::addWindow(QWindow *window)
|
|||
}
|
||||
#endif
|
||||
d->mutex.unlock();
|
||||
if (g_usePureQtImplementation) {
|
||||
if (pureQt) {
|
||||
FramelessHelperQt::addWindow(window);
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (!g_usePureQtImplementation) {
|
||||
if (!pureQt) {
|
||||
FramelessHelperWin::addWindow(window);
|
||||
}
|
||||
Utils::installSystemMenuHook(winId);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -186,20 +202,25 @@ void FramelessWindowsManager::removeWindow(QWindow *window)
|
|||
if (uuid.isNull()) {
|
||||
return;
|
||||
}
|
||||
if (g_usePureQtImplementation) {
|
||||
FramelessHelperQt::removeWindow(window);
|
||||
}
|
||||
const WId winId = window->winId();
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (!g_usePureQtImplementation) {
|
||||
FramelessHelperWin::removeWindow(window);
|
||||
}
|
||||
if (d->win32WorkaroundConnections.contains(uuid)) {
|
||||
disconnect(d->win32WorkaroundConnections.value(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
|
||||
d->windowMapping.remove(window);
|
||||
d->winIdMapping.remove(window->winId());
|
||||
d->winIdMapping.remove(winId);
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -43,6 +43,10 @@ public:
|
|||
explicit FramelessWindowsManagerPrivate(FramelessWindowsManager *q);
|
||||
~FramelessWindowsManagerPrivate();
|
||||
|
||||
[[nodiscard]] static FramelessWindowsManagerPrivate *get(FramelessWindowsManager *manager);
|
||||
|
||||
[[nodiscard]] bool usePureQtImplementation() const;
|
||||
|
||||
[[nodiscard]] QUuid findIdByWindow(QWindow *value) const;
|
||||
[[nodiscard]] QUuid findIdByWinId(const WId value) const;
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@ FRAMELESSHELPER_CORE_API void fixupQtInternals(const WId winId);
|
|||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isTitleBarColorized();
|
||||
[[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
|
||||
|
||||
} // namespace Utils
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "utils.h"
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qhash.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtCore/private/qsystemlibrary_p.h>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
|
||||
|
@ -39,6 +41,8 @@
|
|||
#endif
|
||||
#include "qwinregistry_p.h"
|
||||
#include "framelesshelper_windows.h"
|
||||
#include "framelesswindowsmanager.h"
|
||||
#include "framelesswindowsmanager_p.h"
|
||||
#if 0
|
||||
#include <atlbase.h>
|
||||
#include <d2d1.h>
|
||||
|
@ -48,6 +52,20 @@ Q_DECLARE_METATYPE(QMargins)
|
|||
|
||||
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.");
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
|
||||
|
@ -154,6 +172,90 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
|||
}
|
||||
#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()
|
||||
{
|
||||
#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()
|
||||
{
|
||||
static const bool result = []() -> bool {
|
||||
if (qEnvironmentVariableIntValue("FRAMELESSHELPER_FORCE_SHOW_FRAME_BORDER") != 0) {
|
||||
return true;
|
||||
FramelessWindowsManager *manager = FramelessWindowsManager::instance();
|
||||
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,
|
||||
// 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 result;
|
||||
|
@ -886,4 +1000,54 @@ bool Utils::isFrameBorderColorized()
|
|||
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
|
||||
|
|
|
@ -200,9 +200,11 @@ bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
|
|||
#else
|
||||
const QPointF scenePos = mouseEvent->windowPos();
|
||||
#endif
|
||||
if ((scenePos.x() < kDefaultResizeBorderThickness)
|
||||
|| (scenePos.x() >= (window->width() - kDefaultResizeBorderThickness))
|
||||
|| (scenePos.y() < kDefaultResizeBorderThickness)) {
|
||||
const QQuickWindow::Visibility visibility = window->visibility();
|
||||
if ((visibility == QQuickWindow::Windowed)
|
||||
&& ((scenePos.x() < kDefaultResizeBorderThickness)
|
||||
|| (scenePos.x() >= (window->width() - kDefaultResizeBorderThickness))
|
||||
|| (scenePos.y() < kDefaultResizeBorderThickness))) {
|
||||
return false;
|
||||
}
|
||||
const bool titleBar = isInTitleBarDraggableArea(window, scenePos);
|
||||
|
@ -240,7 +242,6 @@ bool FramelessQuickEventFilter::eventFilter(QObject *object, QEvent *event)
|
|||
if (!titleBar) {
|
||||
return false;
|
||||
}
|
||||
const QQuickWindow::Visibility visibility = window->visibility();
|
||||
if ((visibility == QQuickWindow::Maximized) || (visibility == QQuickWindow::FullScreen)) {
|
||||
window->showNormal();
|
||||
} else {
|
||||
|
|
|
@ -212,9 +212,7 @@ void FramelessWidgetsHelper::mousePressEventHandler(QMouseEvent *event)
|
|||
#else
|
||||
const QPoint scenePos = event->windowPos();
|
||||
#endif
|
||||
if ((scenePos.x() < kDefaultResizeBorderThickness)
|
||||
|| (scenePos.x() >= (q->width() - kDefaultResizeBorderThickness))
|
||||
|| (scenePos.y() < kDefaultResizeBorderThickness)) {
|
||||
if (shouldIgnoreMouseEvents(scenePos)) {
|
||||
return;
|
||||
}
|
||||
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||
|
@ -237,9 +235,7 @@ void FramelessWidgetsHelper::mouseReleaseEventHandler(QMouseEvent *event)
|
|||
#else
|
||||
const QPoint scenePos = event->windowPos();
|
||||
#endif
|
||||
if ((scenePos.x() < kDefaultResizeBorderThickness)
|
||||
|| (scenePos.x() >= (q->width() - kDefaultResizeBorderThickness))
|
||||
|| (scenePos.y() < kDefaultResizeBorderThickness)) {
|
||||
if (shouldIgnoreMouseEvents(scenePos)) {
|
||||
return;
|
||||
}
|
||||
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||
|
@ -270,9 +266,7 @@ void FramelessWidgetsHelper::mouseDoubleClickEventHandler(QMouseEvent *event)
|
|||
#else
|
||||
const QPoint scenePos = event->windowPos();
|
||||
#endif
|
||||
if ((scenePos.x() < kDefaultResizeBorderThickness)
|
||||
|| (scenePos.x() >= (q->width() - kDefaultResizeBorderThickness))
|
||||
|| (scenePos.y() < kDefaultResizeBorderThickness)) {
|
||||
if (shouldIgnoreMouseEvents(scenePos)) {
|
||||
return;
|
||||
}
|
||||
if (!isInTitleBarDraggableArea(scenePos)) {
|
||||
|
@ -439,6 +433,13 @@ bool FramelessWidgetsHelper::isCustomLayout() const
|
|||
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()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
Q_NODISCARD bool shouldDrawFrameBorder() const;
|
||||
Q_NODISCARD bool isStandardLayout() const;
|
||||
Q_NODISCARD bool isCustomLayout() const;
|
||||
Q_NODISCARD bool shouldIgnoreMouseEvents(const QPoint &pos) const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateContentsMargins();
|
||||
|
|
Loading…
Reference in New Issue