Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-03-15 13:02:59 +08:00
parent f68665298b
commit d46ec0c1b6
12 changed files with 163 additions and 99 deletions

View File

@ -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)

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>518</width>
<height>368</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">

View File

@ -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 = {};

View File

@ -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

View File

@ -23,12 +23,27 @@
*/
#include "framelesshelper.h"
#include <QtCore/qmutex.h>
#include <QtGui/qevent.h>
#include <QtGui/qwindow.h>
#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<QWindow *>(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;
}

View File

@ -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

View File

@ -30,37 +30,37 @@
#include <QtCore/qcoreapplication.h>
#include <QtGui/qwindow.h>
#include "framelesswindowsmanager.h"
#include "framelesswindowsmanager_p.h"
#include "utilities.h"
#include "framelesshelper_windows.h"
FRAMELESSHELPER_BEGIN_NAMESPACE
struct FramelessHelperWinData
struct Win32Helper
{
QMutex mutex = {};
QScopedPointer<FramelessHelperWin> instance;
QList<WId> acceptableWinIds = {};
QScopedPointer<FramelessHelperWin> nativeEventFilter;
QWindowList acceptableWindows = {};
QHash<WId, QWindow *> windowMapping = {};
QHash<HWND, WNDPROC> 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<WId>(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<HWND>(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<HWND>(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<WId>(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<BOOL>(msg->wParam) == FALSE)
? reinterpret_cast<LPRECT>(msg->lParam)
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(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: {

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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<LPWSTR>(&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<int>(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<QNativeInterface::Private::QWindowsWindow *>(
window->handle());
if (platformWindow) {
if (const auto platformWindow = dynamic_cast<QNativeInterface::Private::QWindowsWindow *>(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