From d46ec0c1b618d96b2f6b0e0d3f23a434bef1f57f Mon Sep 17 00:00:00 2001
From: Yuhang Zhao <2546789017@qq.com>
Date: Tue, 15 Mar 2022 13:02:59 +0800
Subject: [PATCH] wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
---
CMakeLists.txt | 8 +++
examples/mainwindow/MainWindow.ui | 4 +-
examples/mainwindow/mainwindow.cpp | 6 +-
examples/widget/widget.cpp | 6 +-
framelesshelper.cpp | 35 ++++++++++
framelesshelper_global.h | 12 +---
framelesshelper_win32.cpp | 104 ++++++++++++++---------------
framelessquickhelper.cpp | 2 +-
framelessquickhelper.h | 6 ++
utilities.cpp | 22 +++---
utilities.h | 12 ++++
utilities_win32.cpp | 45 +++++++++----
12 files changed, 163 insertions(+), 99 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0006ece..4d0a4fc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,14 @@ if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug") AND NOT DEFINED CMAKE_INTERPROCEDURAL
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
endif()
+if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
+ if(WIN32)
+ set(CMAKE_DEBUG_POSTFIX d)
+ else()
+ set(CMAKE_DEBUG_POSTFIX _debug)
+ endif()
+endif()
+
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
diff --git a/examples/mainwindow/MainWindow.ui b/examples/mainwindow/MainWindow.ui
index 4e54cdb..0dc3e7e 100644
--- a/examples/mainwindow/MainWindow.ui
+++ b/examples/mainwindow/MainWindow.ui
@@ -6,8 +6,8 @@
0
0
- 518
- 368
+ 800
+ 600
diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp
index 3727086..c55dd65 100644
--- a/examples/mainwindow/mainwindow.cpp
+++ b/examples/mainwindow/mainwindow.cpp
@@ -61,7 +61,7 @@ void MainWindow::changeEvent(QEvent *event)
bool shouldUpdate = false;
if (event->type() == QEvent::WindowStateChange) {
#ifdef Q_OS_WINDOWS
- if (Utilities::isWin10OrGreater()) {
+ if (Utilities::isWindowFrameBorderVisible()) {
if (isMaximized() || isFullScreen()) {
setContentsMargins(0, 0, 0, 0);
} else if (!isMinimized()) {
@@ -91,7 +91,7 @@ void MainWindow::initFramelessHelperOnce()
void MainWindow::resetContentsMargins()
{
#ifdef Q_OS_WINDOWS
- if (Utilities::isWin10OrGreater()) {
+ if (Utilities::isWindowFrameBorderVisible()) {
setContentsMargins(0, 1, 0, 0);
}
#endif
@@ -101,7 +101,7 @@ void MainWindow::paintEvent(QPaintEvent *event)
{
QMainWindow::paintEvent(event);
#ifdef Q_OS_WINDOWS
- if ((windowState() == Qt::WindowNoState) && Utilities::isWin10OrGreater() && !Utilities::isWin11OrGreater()) {
+ if ((windowState() == Qt::WindowNoState) && Utilities::isWindowFrameBorderVisible() && !Utilities::isWin11OrGreater()) {
QPainter painter(this);
painter.save();
QPen pen = {};
diff --git a/examples/widget/widget.cpp b/examples/widget/widget.cpp
index ff5462b..bc114a5 100644
--- a/examples/widget/widget.cpp
+++ b/examples/widget/widget.cpp
@@ -111,7 +111,7 @@ void Widget::changeEvent(QEvent *event)
bool shouldUpdate = false;
if (event->type() == QEvent::WindowStateChange) {
#ifdef Q_OS_WINDOWS
- if (Utilities::isWin10OrGreater()) {
+ if (Utilities::isWindowFrameBorderVisible()) {
if (isMaximized() || isFullScreen()) {
setContentsMargins(0, 0, 0, 0);
} else if (!isMinimized()) {
@@ -133,7 +133,7 @@ void Widget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
#ifdef Q_OS_WINDOWS
- if ((windowState() == Qt::WindowNoState) && Utilities::isWin10OrGreater() && !Utilities::isWin11OrGreater()) {
+ if ((windowState() == Qt::WindowNoState) && Utilities::isWindowFrameBorderVisible() && !Utilities::isWin11OrGreater()) {
QPainter painter(this);
painter.save();
QPen pen = {};
@@ -333,7 +333,7 @@ void Widget::updateSystemButtonIcons()
void Widget::resetContentsMargins()
{
#ifdef Q_OS_WINDOWS
- if (Utilities::isWin10OrGreater()) {
+ if (Utilities::isWindowFrameBorderVisible()) {
setContentsMargins(0, 1, 0, 0);
}
#endif
diff --git a/framelesshelper.cpp b/framelesshelper.cpp
index 687049c..d023d89 100644
--- a/framelesshelper.cpp
+++ b/framelesshelper.cpp
@@ -23,12 +23,27 @@
*/
#include "framelesshelper.h"
+#include
#include
#include
#include "utilities.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
+struct UnixHelper
+{
+ QMutex mutex = {};
+ QWindowList acceptableWindows = {};
+
+ explicit UnixHelper() = default;
+ ~UnixHelper() = default;
+
+private:
+ Q_DISABLE_COPY_MOVE(UnixHelper)
+};
+
+Q_GLOBAL_STATIC(UnixHelper, g_unixHelper)
+
FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {}
FramelessHelper::~FramelessHelper() = default;
@@ -39,6 +54,13 @@ void FramelessHelper::addWindow(QWindow *window)
if (!window) {
return;
}
+ g_unixHelper()->mutex.lock();
+ if (g_unixHelper()->acceptableWindows.contains(window)) {
+ g_unixHelper()->mutex.unlock();
+ return;
+ }
+ g_unixHelper()->acceptableWindows.append(window);
+ g_unixHelper()->mutex.unlock();
window->setFlags(window->flags() | Qt::FramelessWindowHint);
window->installEventFilter(this);
}
@@ -49,6 +71,13 @@ void FramelessHelper::removeWindow(QWindow *window)
if (!window) {
return;
}
+ g_unixHelper()->mutex.lock();
+ if (!g_unixHelper()->acceptableWindows.contains(window)) {
+ g_unixHelper()->mutex.unlock();
+ return;
+ }
+ g_unixHelper()->acceptableWindows.removeAll(window);
+ g_unixHelper()->mutex.unlock();
window->removeEventFilter(this);
window->setFlags(window->flags() & ~Qt::FramelessWindowHint);
}
@@ -70,6 +99,12 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
return false;
}
const auto window = qobject_cast(object);
+ g_unixHelper()->mutex.lock();
+ if (!g_unixHelper()->acceptableWindows.contains(window)) {
+ g_unixHelper()->mutex.unlock();
+ return false;
+ }
+ g_unixHelper()->mutex.unlock();
if (Utilities::isWindowFixedSize(window)) {
return false;
}
diff --git a/framelesshelper_global.h b/framelesshelper_global.h
index 91ddd99..8e41e7a 100644
--- a/framelesshelper_global.h
+++ b/framelesshelper_global.h
@@ -95,19 +95,9 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
Q_NAMESPACE_EXPORT(FRAMELESSHELPER_API)
-[[maybe_unused]] static constexpr const int kDefaultResizeBorderThicknessClassic = 4;
-[[maybe_unused]] static constexpr const int kDefaultResizeBorderThicknessAero = 8;
+[[maybe_unused]] static constexpr const int kDefaultResizeBorderThickness = 8;
[[maybe_unused]] static constexpr const int kDefaultCaptionHeight = 23;
[[maybe_unused]] static constexpr const int kDefaultTitleBarHeight = 30;
[[maybe_unused]] static constexpr const int kDefaultWindowFrameBorderThickness = 1;
-enum class DwmColorizationArea : int
-{
- None = 0,
- StartMenu_TaskBar_ActionCenter = 1,
- TitleBar_WindowBorder = 2,
- All = 3
-};
-Q_ENUM_NS(DwmColorizationArea)
-
FRAMELESSHELPER_END_NAMESPACE
diff --git a/framelesshelper_win32.cpp b/framelesshelper_win32.cpp
index b47bea3..1fc1717 100644
--- a/framelesshelper_win32.cpp
+++ b/framelesshelper_win32.cpp
@@ -30,37 +30,37 @@
#include
#include
#include "framelesswindowsmanager.h"
-#include "framelesswindowsmanager_p.h"
#include "utilities.h"
#include "framelesshelper_windows.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
-struct FramelessHelperWinData
+struct Win32Helper
{
QMutex mutex = {};
- QScopedPointer instance;
- QList acceptableWinIds = {};
+ QScopedPointer nativeEventFilter;
+ QWindowList acceptableWindows = {};
+ QHash windowMapping = {};
QHash qtWindowProcs = {};
- explicit FramelessHelperWinData() = default;
- ~FramelessHelperWinData() = default;
+ explicit Win32Helper() = default;
+ ~Win32Helper() = default;
private:
- Q_DISABLE_COPY_MOVE(FramelessHelperWinData)
+ Q_DISABLE_COPY_MOVE(Win32Helper)
};
-Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
+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_helper()->mutex.lock();
- if (!g_helper()->qtWindowProcs.contains(hWnd)) {
- g_helper()->mutex.unlock();
+ g_win32Helper()->mutex.lock();
+ if (!g_win32Helper()->qtWindowProcs.contains(hWnd)) {
+ g_win32Helper()->mutex.unlock();
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
- g_helper()->mutex.unlock();
+ g_win32Helper()->mutex.unlock();
const auto winId = reinterpret_cast(hWnd);
const auto getGlobalPosFromMouse = [lParam]() -> QPointF {
return {qreal(GET_X_LPARAM(lParam)), qreal(GET_Y_LPARAM(lParam))};
@@ -75,7 +75,7 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
const int frameSizeX = Utilities::getResizeBorderThickness(winId, true, true);
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
const int titleBarHeight = Utilities::getTitleBarHeight(winId, true);
- const int horizontalOffset = ((maxOrFull || !Utilities::isWin10OrGreater()) ? 0 : frameSizeX);
+ const int horizontalOffset = ((maxOrFull || !Utilities::isWindowFrameBorderVisible()) ? 0 : frameSizeX);
const int verticalOffset = (maxOrFull ? titleBarHeight : (titleBarHeight - frameSizeY));
return {qreal(rect.left + horizontalOffset), qreal(rect.top + verticalOffset)};
};
@@ -108,9 +108,9 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
// entering Qt's own handling logic.
return 0; // Return 0 means we have handled this event.
}
- g_helper()->mutex.lock();
- const WNDPROC originalWindowProc = g_helper()->qtWindowProcs.value(hWnd);
- g_helper()->mutex.unlock();
+ 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
@@ -128,8 +128,8 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
return false;
}
const auto hwnd = reinterpret_cast(winId);
- QMutexLocker locker(&g_helper()->mutex);
- if (g_helper()->qtWindowProcs.contains(hwnd)) {
+ QMutexLocker locker(&g_win32Helper()->mutex);
+ if (g_win32Helper()->qtWindowProcs.contains(hwnd)) {
return false;
}
SetLastError(ERROR_SUCCESS);
@@ -144,7 +144,7 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return false;
}
- g_helper()->qtWindowProcs.insert(hwnd, originalWindowProc);
+ g_win32Helper()->qtWindowProcs.insert(hwnd, originalWindowProc);
return true;
}
@@ -155,11 +155,11 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
return false;
}
const auto hwnd = reinterpret_cast(winId);
- QMutexLocker locker(&g_helper()->mutex);
- if (!g_helper()->qtWindowProcs.contains(hwnd)) {
+ QMutexLocker locker(&g_win32Helper()->mutex);
+ if (!g_win32Helper()->qtWindowProcs.contains(hwnd)) {
return false;
}
- const WNDPROC originalWindowProc = g_helper()->qtWindowProcs.value(hwnd);
+ const WNDPROC originalWindowProc = g_win32Helper()->qtWindowProcs.value(hwnd);
Q_ASSERT(originalWindowProc);
if (!originalWindowProc) {
return false;
@@ -169,7 +169,7 @@ Q_GLOBAL_STATIC(FramelessHelperWinData, g_helper)
qWarning() << Utilities::getSystemErrorMessage(QStringLiteral("SetWindowLongPtrW"));
return false;
}
- g_helper()->qtWindowProcs.remove(hwnd);
+ g_win32Helper()->qtWindowProcs.remove(hwnd);
return true;
}
@@ -186,18 +186,19 @@ void FramelessHelperWin::addWindow(QWindow *window)
if (!window) {
return;
}
- const WId winId = window->winId();
- g_helper()->mutex.lock();
- if (g_helper()->acceptableWinIds.contains(winId)) {
- g_helper()->mutex.unlock();
+ g_win32Helper()->mutex.lock();
+ if (g_win32Helper()->acceptableWindows.contains(window)) {
+ g_win32Helper()->mutex.unlock();
return;
}
- g_helper()->acceptableWinIds.append(winId);
- if (g_helper()->instance.isNull()) {
- g_helper()->instance.reset(new FramelessHelperWin);
- qApp->installNativeEventFilter(g_helper()->instance.data());
+ g_win32Helper()->acceptableWindows.append(window);
+ const WId winId = window->winId();
+ g_win32Helper()->windowMapping.insert(winId, window);
+ if (g_win32Helper()->nativeEventFilter.isNull()) {
+ g_win32Helper()->nativeEventFilter.reset(new FramelessHelperWin);
+ qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
}
- g_helper()->mutex.unlock();
+ g_win32Helper()->mutex.unlock();
Utilities::fixupQtInternals(winId);
Utilities::updateInternalWindowFrameMargins(window, true);
Utilities::updateWindowFrameMargins(winId, false);
@@ -214,14 +215,15 @@ void FramelessHelperWin::removeWindow(QWindow *window)
if (!window) {
return;
}
- const WId winId = window->winId();
- g_helper()->mutex.lock();
- if (!g_helper()->acceptableWinIds.contains(winId)) {
- g_helper()->mutex.unlock();
+ g_win32Helper()->mutex.lock();
+ if (!g_win32Helper()->acceptableWindows.contains(window)) {
+ g_win32Helper()->mutex.unlock();
return;
}
- g_helper()->acceptableWinIds.removeAll(winId);
- g_helper()->mutex.unlock();
+ g_win32Helper()->acceptableWindows.removeAll(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.";
}
@@ -250,19 +252,13 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return false;
}
const WId winId = reinterpret_cast(msg->hwnd);
- g_helper()->mutex.lock();
- if (!g_helper()->acceptableWinIds.contains(winId)) {
- g_helper()->mutex.unlock();
+ g_win32Helper()->mutex.lock();
+ if (!g_win32Helper()->windowMapping.contains(winId)) {
+ g_win32Helper()->mutex.unlock();
return false;
}
- g_helper()->mutex.unlock();
- const FramelessManagerPrivate * const manager = FramelessManagerPrivate::instance();
- const QUuid id = manager->findIdByWinId(winId);
- Q_ASSERT(!id.isNull());
- if (id.isNull()) {
- return false;
- }
- QWindow * const window = manager->findWindowById(id);
+ QWindow * const window = g_win32Helper()->windowMapping.value(winId);
+ g_win32Helper()->mutex.unlock();
Q_ASSERT(window);
if (!window) {
return false;
@@ -359,7 +355,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
const auto clientRect = ((static_cast(msg->wParam) == FALSE)
? reinterpret_cast(msg->lParam)
: &(reinterpret_cast(msg->lParam))->rgrc[0]);
- if (Utilities::isWin10OrGreater()) {
+ if (Utilities::isWindowFrameBorderVisible()) {
// Store the original top before the default window proc applies the default frame.
const LONG originalTop = clientRect->top;
// Apply the default frame.
@@ -385,7 +381,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
// a window when it's maximized unless you restore it).
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
clientRect->top += frameSizeY;
- if (!Utilities::isWin10OrGreater()) {
+ if (!Utilities::isWindowFrameBorderVisible()) {
clientRect->bottom -= frameSizeY;
const int frameSizeX = Utilities::getResizeBorderThickness(winId, true, true);
clientRect->left += frameSizeX;
@@ -598,8 +594,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
const bool full = Utilities::isFullScreen(winId);
const int frameSizeY = Utilities::getResizeBorderThickness(winId, false, true);
const bool isTop = (localPos.y < frameSizeY);
- const bool isTitleBar = false; // ### TODO
- if (Utilities::isWin10OrGreater()) {
+ static constexpr const bool isTitleBar = false;
+ if (Utilities::isWindowFrameBorderVisible()) {
// This will handle the left, right and bottom parts of the frame
// because we didn't change them.
const LRESULT originalRet = DefWindowProcW(msg->hwnd, WM_NCHITTEST, 0, msg->lParam);
@@ -712,7 +708,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
default:
break;
}
- if (!Utilities::isWin10OrGreater()) {
+ if (!Utilities::isWindowFrameBorderVisible()) {
switch (msg->message) {
case WM_NCUAHDRAWCAPTION:
case WM_NCUAHDRAWFRAME: {
diff --git a/framelessquickhelper.cpp b/framelessquickhelper.cpp
index 48d4443..a28e2ae 100644
--- a/framelessquickhelper.cpp
+++ b/framelessquickhelper.cpp
@@ -78,7 +78,7 @@ qreal FramelessQuickUtils::titleBarHeight()
bool FramelessQuickUtils::frameBorderVisible()
{
#ifdef Q_OS_WINDOWS
- return (Utilities::isWin10OrGreater() && !Utilities::isWin11OrGreater());
+ return (Utilities::isWindowFrameBorderVisible() && !Utilities::isWin11OrGreater());
#else
return false;
#endif
diff --git a/framelessquickhelper.h b/framelessquickhelper.h
index 0f35076..eef8c6e 100644
--- a/framelessquickhelper.h
+++ b/framelessquickhelper.h
@@ -41,6 +41,9 @@ class FRAMELESSHELPER_API FramelessQuickHelper : public QObject
#ifdef QML_NAMED_ELEMENT
QML_NAMED_ELEMENT(FramelessHelper)
#endif
+#ifdef QML_SINGLETON
+ QML_SINGLETON
+#endif
public:
explicit FramelessQuickHelper(QObject *parent = nullptr);
@@ -56,6 +59,9 @@ class FRAMELESSHELPER_API FramelessQuickUtils : public QObject
Q_DISABLE_COPY_MOVE(FramelessQuickUtils)
#ifdef QML_NAMED_ELEMENT
QML_NAMED_ELEMENT(FramelessUtils)
+#endif
+#ifdef QML_SINGLETON
+ QML_SINGLETON
#endif
Q_PROPERTY(qreal titleBarHeight READ titleBarHeight CONSTANT FINAL)
Q_PROPERTY(bool frameBorderVisible READ frameBorderVisible CONSTANT FINAL)
diff --git a/utilities.cpp b/utilities.cpp
index 76ccace..02072e5 100644
--- a/utilities.cpp
+++ b/utilities.cpp
@@ -26,8 +26,6 @@
FRAMELESSHELPER_BEGIN_NAMESPACE
-static constexpr const int g_resizeBorderThickness = kDefaultResizeBorderThicknessAero;
-
Qt::CursorShape Utilities::calculateCursorShape(const QWindow *window, const QPointF &pos)
{
Q_ASSERT(window);
@@ -37,18 +35,18 @@ Qt::CursorShape Utilities::calculateCursorShape(const QWindow *window, const QPo
if (window->visibility() != QWindow::Windowed) {
return Qt::ArrowCursor;
}
- if (((pos.x() < g_resizeBorderThickness) && (pos.y() < g_resizeBorderThickness))
- || ((pos.x() >= (window->width() - g_resizeBorderThickness)) && (pos.y() >= (window->height() - g_resizeBorderThickness)))) {
+ if (((pos.x() < kDefaultResizeBorderThickness) && (pos.y() < kDefaultResizeBorderThickness))
+ || ((pos.x() >= (window->width() - kDefaultResizeBorderThickness)) && (pos.y() >= (window->height() - kDefaultResizeBorderThickness)))) {
return Qt::SizeFDiagCursor;
}
- if (((pos.x() >= (window->width() - g_resizeBorderThickness)) && (pos.y() < g_resizeBorderThickness))
- || ((pos.x() < g_resizeBorderThickness) && (pos.y() >= (window->height() - g_resizeBorderThickness)))) {
+ if (((pos.x() >= (window->width() - kDefaultResizeBorderThickness)) && (pos.y() < kDefaultResizeBorderThickness))
+ || ((pos.x() < kDefaultResizeBorderThickness) && (pos.y() >= (window->height() - kDefaultResizeBorderThickness)))) {
return Qt::SizeBDiagCursor;
}
- if ((pos.x() < g_resizeBorderThickness) || (pos.x() >= (window->width() - g_resizeBorderThickness))) {
+ if ((pos.x() < kDefaultResizeBorderThickness) || (pos.x() >= (window->width() - kDefaultResizeBorderThickness))) {
return Qt::SizeHorCursor;
}
- if ((pos.y() < g_resizeBorderThickness) || (pos.y() >= (window->height() - g_resizeBorderThickness))) {
+ if ((pos.y() < kDefaultResizeBorderThickness) || (pos.y() >= (window->height() - kDefaultResizeBorderThickness))) {
return Qt::SizeVerCursor;
}
return Qt::ArrowCursor;
@@ -64,16 +62,16 @@ Qt::Edges Utilities::calculateWindowEdges(const QWindow *window, const QPointF &
return {};
}
Qt::Edges edges = {};
- if (pos.x() < g_resizeBorderThickness) {
+ if (pos.x() < kDefaultResizeBorderThickness) {
edges |= Qt::LeftEdge;
}
- if (pos.x() >= (window->width() - g_resizeBorderThickness)) {
+ if (pos.x() >= (window->width() - kDefaultResizeBorderThickness)) {
edges |= Qt::RightEdge;
}
- if (pos.y() < g_resizeBorderThickness) {
+ if (pos.y() < kDefaultResizeBorderThickness) {
edges |= Qt::TopEdge;
}
- if (pos.y() >= (window->height() - g_resizeBorderThickness)) {
+ if (pos.y() >= (window->height() - kDefaultResizeBorderThickness)) {
edges |= Qt::BottomEdge;
}
return edges;
diff --git a/utilities.h b/utilities.h
index 86d3bda..4247554 100644
--- a/utilities.h
+++ b/utilities.h
@@ -29,6 +29,17 @@
FRAMELESSHELPER_BEGIN_NAMESPACE
+#ifdef Q_OS_WINDOWS
+enum class DwmColorizationArea : int
+{
+ None = 0,
+ StartMenu_TaskBar_ActionCenter = 1,
+ TitleBar_WindowBorder = 2,
+ All = 3
+};
+Q_ENUM_NS(DwmColorizationArea)
+#endif
+
namespace Utilities
{
@@ -66,6 +77,7 @@ FRAMELESSHELPER_API void showSystemMenu(const WId winId, const QPointF &pos);
[[nodiscard]] FRAMELESSHELPER_API QColor getFrameBorderColor(const bool active);
FRAMELESSHELPER_API void updateWindowFrameBorderColor(const WId winId, const bool dark);
FRAMELESSHELPER_API void fixupQtInternals(const WId winId);
+[[nodiscard]] FRAMELESSHELPER_API bool isWindowFrameBorderVisible();
#endif // Q_OS_WINDOWS
} // namespace Utilities
diff --git a/utilities_win32.cpp b/utilities_win32.cpp
index ce5b654..5e473e4 100644
--- a/utilities_win32.cpp
+++ b/utilities_win32.cpp
@@ -46,6 +46,8 @@ Q_DECLARE_METATYPE(QMargins)
FRAMELESSHELPER_BEGIN_NAMESPACE
+static const QString successErrorText = QStringLiteral("The operation completed successfully.");
+
#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
[[nodiscard]] static inline bool isWindowsVersionOrGreater(const DWORD dwMajor, const DWORD dwMinor, const DWORD dwBuild)
{
@@ -71,17 +73,21 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
return {};
}
if (code == ERROR_SUCCESS) {
- return {};
+ return successErrorText;
}
LPWSTR buf = nullptr;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&buf), 0, nullptr) == 0) {
- return {};
+ return QStringLiteral("FormatMessageW() returned empty string.");
}
- const QString message = QStringLiteral("Function %1() failed with error code %2: %3.")
- .arg(function, QString::number(code), QString::fromWCharArray(buf));
+ QString errorText = QString::fromWCharArray(buf);
LocalFree(buf);
- return message;
+ buf = nullptr;
+ errorText = errorText.trimmed();
+ errorText.remove(QStringLiteral("\\r"));
+ errorText.replace(QStringLiteral("\\n"), QStringLiteral("\n"));
+ return QStringLiteral("Function \"%1()\" failed with error code %2: %3.")
+ .arg(function, QString::number(code), errorText);
}
[[nodiscard]] static inline QString __getSystemErrorMessage(const QString &function, const HRESULT hr)
@@ -91,7 +97,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
return {};
}
if (SUCCEEDED(hr)) {
- return {};
+ return successErrorText;
}
const DWORD dwError = HRESULT_CODE(hr);
return __getSystemErrorMessage(function, dwError);
@@ -248,7 +254,7 @@ void Utilities::updateWindowFrameMargins(const WId winId, const bool reset)
if (reset) {
return {0, 0, 0, 0};
}
- if (isWin10OrGreater()) {
+ if (isWindowFrameBorderVisible()) {
return {0, static_cast(getTitleBarHeight(winId, true)), 0, 0};
} else {
return {1, 1, 1, 1};
@@ -275,7 +281,7 @@ void Utilities::updateInternalWindowFrameMargins(QWindow *window, const bool ena
return {};
}
const int titleBarHeight = getTitleBarHeight(winId, true);
- if (isWin10OrGreater()) {
+ if (isWindowFrameBorderVisible()) {
return {0, -titleBarHeight, 0, 0};
} else {
const int frameSizeX = getResizeBorderThickness(winId, true, true);
@@ -286,17 +292,14 @@ void Utilities::updateInternalWindowFrameMargins(QWindow *window, const bool ena
const QVariant marginsVar = QVariant::fromValue(margins);
window->setProperty("_q_windowsCustomMargins", marginsVar);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
- QPlatformWindow *platformWindow = window->handle();
- if (platformWindow) {
+ if (QPlatformWindow *platformWindow = window->handle()) {
QGuiApplication::platformNativeInterface()->setWindowProperty(platformWindow, QStringLiteral("WindowsCustomMargins"), marginsVar);
} else {
qWarning() << "Failed to retrieve the platform window.";
return;
}
#else
- auto *platformWindow = dynamic_cast(
- window->handle());
- if (platformWindow) {
+ if (const auto platformWindow = dynamic_cast(window->handle())) {
platformWindow->setCustomMargins(margins);
} else {
qWarning() << "Failed to retrieve the platform window.";
@@ -866,4 +869,20 @@ void Utilities::startSystemResize(QWindow *window, const Qt::Edges edges)
#endif
}
+bool Utilities::isWindowFrameBorderVisible()
+{
+ static const bool result = []() -> bool {
+ // If we preserve the window frame border on systems before Windows 10,
+ // the window will look rather ugly and I guess no one would like to see
+ // such weired windows. If you really want to know what the window look
+ // like in such situations, just comment out the following IF statement
+ // and run your application on Windows 7/8/8.1.
+ if (!isWin10OrGreater()) {
+ return false;
+ }
+ return !qEnvironmentVariableIsSet("FRAMELESSHELPER_HIDE_FRAME_BORDER");
+ }();
+ return result;
+}
+
FRAMELESSHELPER_END_NAMESPACE