Internal refactor

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2021-06-25 14:17:32 +08:00
parent 28144b1e74
commit 5938fcb475
13 changed files with 129 additions and 243 deletions

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.5)
project(FramelessHelper LANGUAGES CXX) project(FramelessHelper LANGUAGES CXX)

View File

@ -26,6 +26,7 @@
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
#include "utilities.h" #include "utilities.h"
#include "framelesswindowsmanager.h"
#include <QtCore/qdebug.h> #include <QtCore/qdebug.h>
#include <QtCore/qcoreevent.h> #include <QtCore/qcoreevent.h>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
@ -33,65 +34,26 @@
FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {} FramelessHelper::FramelessHelper(QObject *parent) : QObject(parent) {}
int FramelessHelper::getBorderWidth() const
{
return m_borderWidth;
}
void FramelessHelper::setBorderWidth(const int val)
{
m_borderWidth = val;
}
int FramelessHelper::getBorderHeight() const
{
return m_borderHeight;
}
void FramelessHelper::setBorderHeight(const int val)
{
m_borderHeight = val;
}
int FramelessHelper::getTitleBarHeight() const
{
return m_titleBarHeight;
}
void FramelessHelper::setTitleBarHeight(const int val)
{
m_titleBarHeight = val;
}
bool FramelessHelper::getResizable(const QWindow *window) const
{
Q_ASSERT(window);
if (!window) {
return false;
}
return !m_fixedSize.value(window);
}
void FramelessHelper::setResizable(const QWindow *window, const bool val)
{
Q_ASSERT(window);
if (!window) {
return;
}
m_fixedSize.insert(window, !val);
}
void FramelessHelper::removeWindowFrame(QWindow *window) void FramelessHelper::removeWindowFrame(QWindow *window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
return; return;
} }
// TODO: check whether these flags are correct for Linux and macOS. window->setFlags(window->flags() | Qt::FramelessWindowHint);
window->setFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint
| Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
// MouseTracking is always enabled for QWindow.
window->installEventFilter(this); window->installEventFilter(this);
window->setProperty(_flh_global::_flh_framelessEnabled_flag, true);
}
void FramelessHelper::bringBackWindowFrame(QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return;
}
window->removeEventFilter(this);
window->setFlags(window->flags() & ~Qt::FramelessWindowHint);
window->setProperty(_flh_global::_flh_framelessEnabled_flag, false);
} }
bool FramelessHelper::eventFilter(QObject *object, QEvent *event) bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
@ -104,11 +66,13 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
if (!object->isWindowType()) { if (!object->isWindowType()) {
return false; return false;
} }
// QWindow will always be a top level window. It can't
// be anyone's child window.
const auto currentWindow = qobject_cast<QWindow *>(object); const auto currentWindow = qobject_cast<QWindow *>(object);
const int m_borderWidth = FramelessWindowsManager::getBorderWidth(currentWindow);
const int m_borderHeight = FramelessWindowsManager::getBorderHeight(currentWindow);
const int m_titleBarHeight = FramelessWindowsManager::getTitleBarHeight(currentWindow);
const bool m_resizable = FramelessWindowsManager::getResizable(currentWindow);
const auto getWindowEdges = const auto getWindowEdges =
[this](const QPointF &point, const int ww, const int wh) -> Qt::Edges { [m_borderWidth, m_borderHeight](const QPointF &point, const int ww, const int wh) -> Qt::Edges {
if (point.y() <= m_borderHeight) { if (point.y() <= m_borderHeight) {
if (point.x() <= m_borderWidth) { if (point.x() <= m_borderWidth) {
return Qt::Edge::TopEdge | Qt::Edge::LeftEdge; return Qt::Edge::TopEdge | Qt::Edge::LeftEdge;
@ -152,7 +116,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
} }
return Qt::CursorShape::ArrowCursor; return Qt::CursorShape::ArrowCursor;
}; };
const auto isInTitlebarArea = [this](const QPointF &point, const QWindow *window) -> bool { const auto isInTitlebarArea = [m_titleBarHeight](const QPointF &point, const QWindow *window) -> bool {
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
return false; return false;
@ -160,7 +124,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
return (point.y() <= m_titleBarHeight) && !Utilities::isHitTestVisibleInChrome(window); return (point.y() <= m_titleBarHeight) && !Utilities::isHitTestVisibleInChrome(window);
}; };
const auto moveOrResize = const auto moveOrResize =
[this, &getWindowEdges, &isInTitlebarArea](const QPointF &point, QWindow *window) { [m_resizable, &getWindowEdges, &isInTitlebarArea](const QPointF &point, QWindow *window) {
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
return; return;
@ -175,7 +139,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
} }
} else { } else {
if ((window->windowState() == Qt::WindowState::WindowNoState) if ((window->windowState() == Qt::WindowState::WindowNoState)
&& !Utilities::isHitTestVisibleInChrome(window) && getResizable(window)) { && !Utilities::isHitTestVisibleInChrome(window) && m_resizable) {
if (!window->startSystemResize(edges)) { if (!window->startSystemResize(edges)) {
// ### FIXME: TO BE IMPLEMENTED! // ### FIXME: TO BE IMPLEMENTED!
qWarning() << "Current OS doesn't support QWindow::startSystemResize()."; qWarning() << "Current OS doesn't support QWindow::startSystemResize().";
@ -221,8 +185,7 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
} break; } break;
case QEvent::MouseMove: { case QEvent::MouseMove: {
const auto mouseEvent = static_cast<QMouseEvent *>(event); const auto mouseEvent = static_cast<QMouseEvent *>(event);
if ((currentWindow->windowState() == Qt::WindowState::WindowNoState) if ((currentWindow->windowState() == Qt::WindowState::WindowNoState) && m_resizable) {
&& getResizable(currentWindow)) {
currentWindow->setCursor( currentWindow->setCursor(
getCursorShape(getWindowEdges(getMousePos(mouseEvent, false), getCursorShape(getWindowEdges(getMousePos(mouseEvent, false),
currentWindow->width(), currentWindow->width(),

View File

@ -27,8 +27,7 @@
#include "framelesshelper_global.h" #include "framelesshelper_global.h"
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
#include <QHash> #include <QtCore/qobject.h>
#include <QObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QT_FORWARD_DECLARE_CLASS(QWindow) QT_FORWARD_DECLARE_CLASS(QWindow)
@ -44,27 +43,9 @@ public:
~FramelessHelper() override = default; ~FramelessHelper() override = default;
void removeWindowFrame(QWindow *window); void removeWindowFrame(QWindow *window);
void bringBackWindowFrame(QWindow *window);
int getBorderWidth() const;
void setBorderWidth(const int val);
int getBorderHeight() const;
void setBorderHeight(const int val);
int getTitleBarHeight() const;
void setTitleBarHeight(const int val);
bool getResizable(const QWindow *window) const;
void setResizable(const QWindow *window, const bool val);
protected: protected:
bool eventFilter(QObject *object, QEvent *event) override; bool eventFilter(QObject *object, QEvent *event) override;
private:
// ### FIXME: The default border width and height on Windows is 8 pixels if
// the scale factor is 1.0. Don't know how to acquire these values on UNIX
// platforms through native API.
int m_borderWidth = 8, m_borderHeight = 8, m_titleBarHeight = 30;
QHash<const QWindow *, bool> m_fixedSize = {};
}; };
#endif #endif

View File

@ -67,6 +67,6 @@ namespace _flh_global {
[[maybe_unused]] const char _flh_useNativeTitleBar_flag[] = "_FRAMELESSHELPER_USE_NATIVE_TITLE_BAR"; [[maybe_unused]] const char _flh_useNativeTitleBar_flag[] = "_FRAMELESSHELPER_USE_NATIVE_TITLE_BAR";
[[maybe_unused]] const char _flh_preserveNativeFrame_flag[] = "_FRAMELESSHELPER_PRESERVE_NATIVE_WINDOW_FRAME"; [[maybe_unused]] const char _flh_preserveNativeFrame_flag[] = "_FRAMELESSHELPER_PRESERVE_NATIVE_WINDOW_FRAME";
[[maybe_unused]] const char _flh_forcePreserveNativeFrame_flag[] = "_FRAMELESSHELPER_FORCE_PRESERVE_NATIVE_WINDOW_FRAME"; [[maybe_unused]] const char _flh_forcePreserveNativeFrame_flag[] = "_FRAMELESSHELPER_FORCE_PRESERVE_NATIVE_WINDOW_FRAME";
[[maybe_unused]] const char _flh_nativeParent_flag[] = "_FRAMELESSHELPER_NATIVE_PARENT"; [[maybe_unused]] const char _flh_windowFixedSize_flag[] = "_FRAMELESSHELPER_WINDOW_FIXED_SIZE";
} }

View File

@ -116,10 +116,10 @@ static inline void installHelper(QWindow *window, const bool enable)
if (!window) { if (!window) {
return; return;
} }
window->setProperty(_flh_global::_flh_framelessEnabled_flag, enable);
Utilities::updateQtFrameMargins(window, enable); Utilities::updateQtFrameMargins(window, enable);
Utilities::updateFrameMargins(window, !enable); Utilities::updateFrameMargins(window, !enable);
Utilities::triggerFrameChange(window); Utilities::triggerFrameChange(window);
window->setProperty(_flh_global::_flh_framelessEnabled_flag, enable);
} }
FramelessHelperWin::FramelessHelperWin() = default; FramelessHelperWin::FramelessHelperWin() = default;
@ -134,19 +134,13 @@ FramelessHelperWin::~FramelessHelperWin()
void FramelessHelperWin::addFramelessWindow(QWindow *window) void FramelessHelperWin::addFramelessWindow(QWindow *window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
if (!window) {
return;
}
setup(); setup();
installHelper(window, true); installHelper(window, true);
} }
bool FramelessHelperWin::isWindowFrameless(const QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return false;
}
return window->property(_flh_global::_flh_framelessEnabled_flag).toBool();
}
void FramelessHelperWin::removeFramelessWindow(QWindow *window) void FramelessHelperWin::removeFramelessWindow(QWindow *window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
@ -639,30 +633,3 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
} }
return false; return false;
} }
void FramelessHelperWin::setBorderWidth(QWindow *window, const int bw)
{
Q_ASSERT(window);
if (!window) {
return;
}
window->setProperty(_flh_global::_flh_borderWidth_flag, bw);
}
void FramelessHelperWin::setBorderHeight(QWindow *window, const int bh)
{
Q_ASSERT(window);
if (!window) {
return;
}
window->setProperty(_flh_global::_flh_borderHeight_flag, bh);
}
void FramelessHelperWin::setTitleBarHeight(QWindow *window, const int tbh)
{
Q_ASSERT(window);
if (!window) {
return;
}
window->setProperty(_flh_global::_flh_titleBarHeight_flag, tbh);
}

View File

@ -41,13 +41,8 @@ public:
~FramelessHelperWin() override; ~FramelessHelperWin() override;
static void addFramelessWindow(QWindow *window); static void addFramelessWindow(QWindow *window);
static bool isWindowFrameless(const QWindow *window);
static void removeFramelessWindow(QWindow *window); static void removeFramelessWindow(QWindow *window);
static void setBorderWidth(QWindow *window, const int bw);
static void setBorderHeight(QWindow *window, const int bh);
static void setTitleBarHeight(QWindow *window, const int tbh);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override; bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
#else #else

View File

@ -97,6 +97,16 @@ void FramelessQuickHelper::removeWindowFrame()
FramelessWindowsManager::addWindow(window()); FramelessWindowsManager::addWindow(window());
} }
void FramelessQuickHelper::bringBackWindowFrame()
{
FramelessWindowsManager::removeWindow(window());
}
bool FramelessQuickHelper::isWindowFrameless() const
{
return FramelessWindowsManager::isWindowFrameless(window());
}
void FramelessQuickHelper::setHitTestVisibleInChrome(QQuickItem *item, const bool visible) void FramelessQuickHelper::setHitTestVisibleInChrome(QQuickItem *item, const bool visible)
{ {
Q_ASSERT(item); Q_ASSERT(item);

View File

@ -60,6 +60,8 @@ public:
public Q_SLOTS: public Q_SLOTS:
void removeWindowFrame(); void removeWindowFrame();
void bringBackWindowFrame();
bool isWindowFrameless() const;
void setHitTestVisibleInChrome(QQuickItem *item, const bool visible); void setHitTestVisibleInChrome(QQuickItem *item, const bool visible);
Q_SIGNALS: Q_SIGNALS:

View File

@ -35,13 +35,11 @@
#endif #endif
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION #ifdef FRAMELESSHELPER_USE_UNIX_VERSION
Q_GLOBAL_STATIC(FramelessHelper, framelessHelper) Q_GLOBAL_STATIC(FramelessHelper, framelessHelperUnix)
#endif #endif
Q_DECLARE_METATYPE(const QObject *) Q_DECLARE_METATYPE(const QObject *)
FramelessWindowsManager::FramelessWindowsManager() = default;
void FramelessWindowsManager::addWindow(QWindow *window) void FramelessWindowsManager::addWindow(QWindow *window)
{ {
Q_ASSERT(window); Q_ASSERT(window);
@ -49,7 +47,7 @@ void FramelessWindowsManager::addWindow(QWindow *window)
return; return;
} }
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION #ifdef FRAMELESSHELPER_USE_UNIX_VERSION
framelessHelper()->removeWindowFrame(window); framelessHelperUnix()->removeWindowFrame(window);
#else #else
FramelessHelperWin::addFramelessWindow(window); FramelessHelperWin::addFramelessWindow(window);
// Work-around a Win32 multi-monitor bug. // Work-around a Win32 multi-monitor bug.
@ -60,7 +58,7 @@ void FramelessWindowsManager::addWindow(QWindow *window)
#endif #endif
} }
void FramelessWindowsManager::setHitTestVisibleInChrome(QWindow *window, QObject *object, const bool value) void FramelessWindowsManager::setHitTestVisibleInChrome(QWindow *window, const QObject *object, const bool value)
{ {
Q_ASSERT(window); Q_ASSERT(window);
Q_ASSERT(object); Q_ASSERT(object);
@ -71,97 +69,86 @@ void FramelessWindowsManager::setHitTestVisibleInChrome(QWindow *window, QObject
qWarning() << object << "is not a QWidget or QQuickItem."; qWarning() << object << "is not a QWidget or QQuickItem.";
return; return;
} }
const QObject *nativeParent = Utilities::getNativeParent(object); auto objList = qvariant_cast<QObjectList>(window->property(_flh_global::_flh_hitTestVisibleInChrome_flag));
Q_ASSERT(nativeParent); if (value) {
if (!nativeParent) { if (objList.isEmpty() || !objList.contains(object)) {
return; objList.append(const_cast<QObject *>(object));
}
} else {
if (!objList.isEmpty() && objList.contains(object)) {
objList.removeAll(object);
}
} }
window->setProperty(_flh_global::_flh_nativeParent_flag, QVariant::fromValue(nativeParent)); window->setProperty(_flh_global::_flh_hitTestVisibleInChrome_flag, QVariant::fromValue(objList));
object->setProperty(_flh_global::_flh_hitTestVisibleInChrome_flag, value);
} }
int FramelessWindowsManager::getBorderWidth(const QWindow *window) int FramelessWindowsManager::getBorderWidth(const QWindow *window)
{ {
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
Q_UNUSED(window);
return framelessHelper()->getBorderWidth();
#else
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
return 0; return 8;
} }
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
const int value = window->property(_flh_global::_flh_borderWidth_flag).toInt();
return value <= 0 ? 8 : value;
#else
return Utilities::getSystemMetric(window, Utilities::SystemMetric::BorderWidth, false); return Utilities::getSystemMetric(window, Utilities::SystemMetric::BorderWidth, false);
#endif #endif
} }
void FramelessWindowsManager::setBorderWidth(QWindow *window, const int value) void FramelessWindowsManager::setBorderWidth(QWindow *window, const int value)
{ {
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
Q_UNUSED(window);
framelessHelper()->setBorderWidth(value);
#else
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window || (value <= 0)) {
return; return;
} }
FramelessHelperWin::setBorderWidth(window, value); window->setProperty(_flh_global::_flh_borderWidth_flag, value);
#endif
} }
int FramelessWindowsManager::getBorderHeight(const QWindow *window) int FramelessWindowsManager::getBorderHeight(const QWindow *window)
{ {
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
Q_UNUSED(window);
return framelessHelper()->getBorderHeight();
#else
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
return 0; return 8;
} }
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
const int value = window->property(_flh_global::_flh_borderHeight_flag).toInt();
return value <= 0 ? 8 : value;
#else
return Utilities::getSystemMetric(window, Utilities::SystemMetric::BorderHeight, false); return Utilities::getSystemMetric(window, Utilities::SystemMetric::BorderHeight, false);
#endif #endif
} }
void FramelessWindowsManager::setBorderHeight(QWindow *window, const int value) void FramelessWindowsManager::setBorderHeight(QWindow *window, const int value)
{ {
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
Q_UNUSED(window);
framelessHelper()->setBorderHeight(value);
#else
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window || (value <= 0)) {
return; return;
} }
FramelessHelperWin::setBorderHeight(window, value); window->setProperty(_flh_global::_flh_borderHeight_flag, value);
#endif
} }
int FramelessWindowsManager::getTitleBarHeight(const QWindow *window) int FramelessWindowsManager::getTitleBarHeight(const QWindow *window)
{ {
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
Q_UNUSED(window);
return framelessHelper()->getTitleBarHeight();
#else
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
return 0; return 30;
} }
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
const int value = window->property(_flh_global::_flh_titleBarHeight_flag).toInt();
return value <= 0 ? 30 : value;
#else
return Utilities::getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, false); return Utilities::getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, false);
#endif #endif
} }
void FramelessWindowsManager::setTitleBarHeight(QWindow *window, const int value) void FramelessWindowsManager::setTitleBarHeight(QWindow *window, const int value)
{ {
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
Q_UNUSED(window);
framelessHelper()->setTitleBarHeight(value);
#else
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window || (value <= 0)) {
return; return;
} }
FramelessHelperWin::setTitleBarHeight(window, value); window->setProperty(_flh_global::_flh_titleBarHeight_flag, value);
#endif
} }
bool FramelessWindowsManager::getResizable(const QWindow *window) bool FramelessWindowsManager::getResizable(const QWindow *window)
@ -171,7 +158,7 @@ bool FramelessWindowsManager::getResizable(const QWindow *window)
return false; return false;
} }
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION #ifdef FRAMELESSHELPER_USE_UNIX_VERSION
return framelessHelper()->getResizable(window); return !window->property(_flh_global::_flh_windowFixedSize_flag).toBool();
#else #else
return !Utilities::isWindowFixedSize(window); return !Utilities::isWindowFixedSize(window);
#endif #endif
@ -184,8 +171,30 @@ void FramelessWindowsManager::setResizable(QWindow *window, const bool value)
return; return;
} }
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION #ifdef FRAMELESSHELPER_USE_UNIX_VERSION
framelessHelper()->setResizable(window, value); window->setProperty(_flh_global::_flh_windowFixedSize_flag, !value);
#else #else
window->setFlag(Qt::MSWindowsFixedSizeDialogHint, !value); window->setFlag(Qt::MSWindowsFixedSizeDialogHint, !value);
#endif #endif
} }
void FramelessWindowsManager::removeWindow(QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return;
}
#ifdef FRAMELESSHELPER_USE_UNIX_VERSION
framelessHelperUnix()->bringBackWindowFrame(window);
#else
FramelessHelperWin::removeFramelessWindow(window);
#endif
}
bool FramelessWindowsManager::isWindowFrameless(const QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return false;
}
return window->property(_flh_global::_flh_framelessEnabled_flag).toBool();
}

View File

@ -25,34 +25,25 @@
#pragma once #pragma once
#include "framelesshelper_global.h" #include "framelesshelper_global.h"
#include <QRect>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QT_FORWARD_DECLARE_CLASS(QObject) QT_FORWARD_DECLARE_CLASS(QObject)
QT_FORWARD_DECLARE_CLASS(QWindow) QT_FORWARD_DECLARE_CLASS(QWindow)
QT_END_NAMESPACE QT_END_NAMESPACE
class FRAMELESSHELPER_API FramelessWindowsManager namespace FramelessWindowsManager {
{
Q_DISABLE_COPY_MOVE(FramelessWindowsManager)
public: FRAMELESSHELPER_API void addWindow(QWindow *window);
explicit FramelessWindowsManager(); FRAMELESSHELPER_API void removeWindow(QWindow *window);
~FramelessWindowsManager() = default; FRAMELESSHELPER_API bool isWindowFrameless(const QWindow *window);
FRAMELESSHELPER_API void setHitTestVisibleInChrome(QWindow *window, const QObject *object, const bool value = true);
FRAMELESSHELPER_API int getBorderWidth(const QWindow *window);
FRAMELESSHELPER_API void setBorderWidth(QWindow *window, const int value);
FRAMELESSHELPER_API int getBorderHeight(const QWindow *window);
FRAMELESSHELPER_API void setBorderHeight(QWindow *window, const int value);
FRAMELESSHELPER_API int getTitleBarHeight(const QWindow *window);
FRAMELESSHELPER_API void setTitleBarHeight(QWindow *window, const int value);
FRAMELESSHELPER_API bool getResizable(const QWindow *window);
FRAMELESSHELPER_API void setResizable(QWindow *window, const bool value = true);
static void addWindow(QWindow *window); }
static void setHitTestVisibleInChrome(QWindow *window, QObject *object, const bool value = true);
static int getBorderWidth(const QWindow *window);
static void setBorderWidth(QWindow *window, const int value);
static int getBorderHeight(const QWindow *window);
static void setBorderHeight(QWindow *window, const int value);
static int getTitleBarHeight(const QWindow *window);
static void setTitleBarHeight(QWindow *window, const int value);
static bool getResizable(const QWindow *window);
static void setResizable(QWindow *window, const bool value = true);
};

View File

@ -73,10 +73,9 @@ bool Utilities::isWindowFixedSize(const QWindow *window)
QPointF Utilities::getGlobalMousePosition(const QWindow *window) QPointF Utilities::getGlobalMousePosition(const QWindow *window)
{ {
if (window) { if (window) {
return (QCursor::pos(window->screen()) * window->devicePixelRatio()); return QPointF(QCursor::pos(window->screen()) * window->devicePixelRatio());
} else { } else {
const qreal dpr = 1.0; // TODO return QPointF(QCursor::pos() * qGuiApp->devicePixelRatio());
return (QCursor::pos() * dpr);
} }
} }
@ -86,8 +85,7 @@ bool Utilities::isHitTestVisibleInChrome(const QWindow *window)
if (!window) { if (!window) {
return false; return false;
} }
const auto target = qvariant_cast<const QObject *>(window->property(_flh_global::_flh_nativeParent_flag)); const auto objs = qvariant_cast<QObjectList>(window->property(_flh_global::_flh_hitTestVisibleInChrome_flag));
const QObjectList objs = target ? target->findChildren<QObject *>() : window->findChildren<QObject *>();
if (objs.isEmpty()) { if (objs.isEmpty()) {
return false; return false;
} }
@ -95,7 +93,7 @@ bool Utilities::isHitTestVisibleInChrome(const QWindow *window)
if (!obj || !(obj->isWidgetType() || obj->inherits("QQuickItem"))) { if (!obj || !(obj->isWidgetType() || obj->inherits("QQuickItem"))) {
continue; continue;
} }
if (!obj->property(_flh_global::_flh_hitTestVisibleInChrome_flag).toBool() || !obj->property("visible").toBool()) { if (!obj->property("visible").toBool()) {
continue; continue;
} }
const QPointF originPoint = mapOriginPointToWindow(obj); const QPointF originPoint = mapOriginPointToWindow(obj);
@ -110,27 +108,6 @@ bool Utilities::isHitTestVisibleInChrome(const QWindow *window)
return false; return false;
} }
QObject *Utilities::getNativeParent(const QObject *object)
{
Q_ASSERT(object);
if (!object) {
return nullptr;
}
if (!object->isWidgetType() && !object->inherits("QQuickItem")) {
qWarning() << object << "is not a QWidget or a QQuickItem.";
return nullptr;
}
QObject *parent = object->parent();
while (parent) {
QObject *p = parent->parent();
if (!p || p->isWindowType()) {
return parent;
}
parent = p;
}
return parent;
}
QPointF Utilities::mapOriginPointToWindow(const QObject *object) QPointF Utilities::mapOriginPointToWindow(const QObject *object)
{ {
Q_ASSERT(object); Q_ASSERT(object);

View File

@ -39,24 +39,14 @@ enum class SystemMetric
// Common // Common
FRAMELESSHELPER_API int getSystemMetric(const QWindow *window, const SystemMetric metric, const bool dpiAware, const bool forceSystemValue = false); FRAMELESSHELPER_API int getSystemMetric(const QWindow *window, const SystemMetric metric, const bool dpiAware, const bool forceSystemValue = false);
FRAMELESSHELPER_API bool isLightThemeEnabled(); FRAMELESSHELPER_API bool isLightThemeEnabled();
FRAMELESSHELPER_API bool isDarkThemeEnabled(); FRAMELESSHELPER_API bool isDarkThemeEnabled();
FRAMELESSHELPER_API QWindow *findWindow(const WId winId); FRAMELESSHELPER_API QWindow *findWindow(const WId winId);
FRAMELESSHELPER_API bool shouldUseNativeTitleBar(); FRAMELESSHELPER_API bool shouldUseNativeTitleBar();
FRAMELESSHELPER_API bool isWindowFixedSize(const QWindow *window); FRAMELESSHELPER_API bool isWindowFixedSize(const QWindow *window);
FRAMELESSHELPER_API QPointF getGlobalMousePosition(const QWindow *window); FRAMELESSHELPER_API QPointF getGlobalMousePosition(const QWindow *window);
FRAMELESSHELPER_API bool isHitTestVisibleInChrome(const QWindow *window); FRAMELESSHELPER_API bool isHitTestVisibleInChrome(const QWindow *window);
FRAMELESSHELPER_API QColor getNativeWindowFrameColor(const bool isActive = true); FRAMELESSHELPER_API QColor getNativeWindowFrameColor(const bool isActive = true);
FRAMELESSHELPER_API QObject *getNativeParent(const QObject *object);
FRAMELESSHELPER_API QPointF mapOriginPointToWindow(const QObject *object); FRAMELESSHELPER_API QPointF mapOriginPointToWindow(const QObject *object);
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
@ -66,20 +56,15 @@ FRAMELESSHELPER_API bool isWin8OrGreater();
FRAMELESSHELPER_API bool isWin8Point1OrGreater(); FRAMELESSHELPER_API bool isWin8Point1OrGreater();
FRAMELESSHELPER_API bool isWin10OrGreater(); FRAMELESSHELPER_API bool isWin10OrGreater();
FRAMELESSHELPER_API bool isWin10OrGreater(const int subVer); FRAMELESSHELPER_API bool isWin10OrGreater(const int subVer);
FRAMELESSHELPER_API bool isDwmBlurAvailable(); FRAMELESSHELPER_API bool isDwmBlurAvailable();
FRAMELESSHELPER_API bool isColorizationEnabled(); FRAMELESSHELPER_API bool isColorizationEnabled();
FRAMELESSHELPER_API QColor getColorizationColor(); FRAMELESSHELPER_API QColor getColorizationColor();
FRAMELESSHELPER_API void triggerFrameChange(const QWindow *window); FRAMELESSHELPER_API void triggerFrameChange(const QWindow *window);
FRAMELESSHELPER_API void updateFrameMargins(const QWindow *window, const bool reset); FRAMELESSHELPER_API void updateFrameMargins(const QWindow *window, const bool reset);
FRAMELESSHELPER_API void updateQtFrameMargins(QWindow *window, const bool enable); FRAMELESSHELPER_API void updateQtFrameMargins(QWindow *window, const bool enable);
FRAMELESSHELPER_API quint32 getWindowDpi(const QWindow *window); FRAMELESSHELPER_API quint32 getWindowDpi(const QWindow *window);
FRAMELESSHELPER_API QMargins getWindowNativeFrameMargins(const QWindow *window); FRAMELESSHELPER_API QMargins getWindowNativeFrameMargins(const QWindow *window);
FRAMELESSHELPER_API void displaySystemMenu(const QWindow *window, const QPointF &pos = {});
FRAMELESSHELPER_API void displaySystemMenu(const QWindow *window, const QPoint &pos = {});
#endif #endif
} }

View File

@ -284,6 +284,11 @@ void Utilities::triggerFrameChange(const QWindow *window)
void Utilities::updateFrameMargins(const QWindow *window, const bool reset) void Utilities::updateFrameMargins(const QWindow *window, const bool reset)
{ {
// DwmExtendFrameIntoClientArea() will always fail if DWM Composition is disabled.
// No need to try in this case.
if (!isDwmBlurAvailable()) {
return;
}
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
return; return;
@ -456,7 +461,7 @@ bool Utilities::isWin10OrGreater(const int subVer)
#endif #endif
} }
void Utilities::displaySystemMenu(const QWindow *window, const QPoint &pos) void Utilities::displaySystemMenu(const QWindow *window, const QPointF &pos)
{ {
Q_ASSERT(window); Q_ASSERT(window);
if (!window) { if (!window) {
@ -511,11 +516,12 @@ void Utilities::displaySystemMenu(const QWindow *window, const QPoint &pos)
SetMenuItemInfoW(hMenu, SC_MINIMIZE, FALSE, &mii); SetMenuItemInfoW(hMenu, SC_MINIMIZE, FALSE, &mii);
} }
const bool isRtl = QGuiApplication::isRightToLeft(); const bool isRtl = QGuiApplication::isRightToLeft();
const QPoint point = pos.isNull() ? QCursor::pos(window->screen()) : window->mapToGlobal(pos); const qreal dpr = window->devicePixelRatio();
const QPointF point = pos.isNull() ? QPointF(QCursor::pos(window->screen()) * dpr) : QPointF(window->mapToGlobal(pos) * dpr);
const LPARAM cmd = TrackPopupMenu(hMenu, const LPARAM cmd = TrackPopupMenu(hMenu,
(TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_TOPALIGN | (TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_TOPALIGN |
(isRtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), (isRtl ? TPM_RIGHTALIGN : TPM_LEFTALIGN)),
point.x(), point.y(), 0, hwnd, nullptr); qRound(point.x()), qRound(point.y()), 0, hwnd, nullptr);
if (cmd) { if (cmd) {
PostMessageW(hwnd, WM_SYSCOMMAND, cmd, 0); PostMessageW(hwnd, WM_SYSCOMMAND, cmd, 0);
} }