diff --git a/include/FramelessHelper/Core/micamaterial.h b/include/FramelessHelper/Core/micamaterial.h index 92550d7..26fd9ec 100644 --- a/include/FramelessHelper/Core/micamaterial.h +++ b/include/FramelessHelper/Core/micamaterial.h @@ -57,7 +57,7 @@ public: public Q_SLOTS: void paint(QPainter *painter, const QSize &size, const QPoint &pos); - Q_NODISCARD static MicaMaterial *attach(QObject *target); + Q_NODISCARD static MicaMaterial *findOrCreateMicaMaterial(QObject *target); Q_SIGNALS: void tintColorChanged(); diff --git a/include/FramelessHelper/Core/private/micamaterial_p.h b/include/FramelessHelper/Core/private/micamaterial_p.h index 9a7613c..0467ced 100644 --- a/include/FramelessHelper/Core/private/micamaterial_p.h +++ b/include/FramelessHelper/Core/private/micamaterial_p.h @@ -47,7 +47,7 @@ public Q_SLOTS: void maybeGenerateBlurredWallpaper(const bool force = false); void updateMaterialBrush(); void paint(QPainter *painter, const QSize &size, const QPoint &pos); - Q_NODISCARD static MicaMaterial *attach(QObject *target); + Q_NODISCARD static MicaMaterial *findOrCreateMicaMaterial(QObject *target); private: void initialize(); diff --git a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h index 5304672..0ce8dbc 100644 --- a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h @@ -80,6 +80,8 @@ public: Q_NODISCARD QuickMicaMaterial *findOrCreateMicaMaterial() const; Q_NODISCARD QuickWindowBorder *findOrCreateWindowBorder() const; + Q_NODISCARD static FramelessQuickHelper *findOrCreateFramelessHelper(QObject *object); + protected: Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override; @@ -91,6 +93,7 @@ private: void setSystemButtonState(const QuickGlobal::SystemButtonType button, const QuickGlobal::ButtonState state); Q_NODISCARD QuickHelperData getWindowData() const; Q_NODISCARD QuickHelperData *getWindowDataMutable() const; + void rebindWindow(); private: QPointer q_ptr = nullptr; diff --git a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h index 9f9158b..660ce07 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h @@ -30,6 +30,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE struct WidgetsHelperData; +class WidgetsSharedHelper; class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelperPrivate : public QObject { @@ -78,6 +79,9 @@ public: Q_NODISCARD MicaMaterial *getMicaMaterialIfAny() const; Q_NODISCARD WindowBorderPainter *getWindowBorderIfAny() const; + Q_NODISCARD static WidgetsSharedHelper *findOrCreateSharedHelper(QWidget *window); + Q_NODISCARD static FramelessWidgetsHelper *findOrCreateFramelessHelper(QObject *object); + private: Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const; Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const; diff --git a/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h b/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h index 5432fae..1584277 100644 --- a/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h +++ b/include/FramelessHelper/Widgets/private/widgetssharedhelper_p.h @@ -64,7 +64,6 @@ private Q_SLOTS: private: void changeEventHandler(QEvent *event); void paintEventHandler(QPaintEvent *event); - Q_NODISCARD bool shouldDrawFrameBorder() const; Q_SIGNALS: void micaEnabledChanged(); diff --git a/src/core/micamaterial.cpp b/src/core/micamaterial.cpp index fe7b53b..295161d 100644 --- a/src/core/micamaterial.cpp +++ b/src/core/micamaterial.cpp @@ -593,7 +593,7 @@ void MicaMaterialPrivate::paint(QPainter *painter, const QSize &size, const QPoi painter->restore(); } -MicaMaterial *MicaMaterialPrivate::attach(QObject *target) +MicaMaterial *MicaMaterialPrivate::findOrCreateMicaMaterial(QObject *target) { Q_ASSERT(target); if (!target) { @@ -602,8 +602,7 @@ MicaMaterial *MicaMaterialPrivate::attach(QObject *target) if (const auto instance = target->findChild()) { return instance; } - const auto instance = new MicaMaterial(target); - return instance; + return new MicaMaterial(target); } void MicaMaterialPrivate::initialize() @@ -708,9 +707,9 @@ void MicaMaterial::paint(QPainter *painter, const QSize &size, const QPoint &pos d->paint(painter, size, pos); } -MicaMaterial *MicaMaterial::attach(QObject *target) +MicaMaterial *MicaMaterial::findOrCreateMicaMaterial(QObject *target) { - return MicaMaterialPrivate::attach(target); + return MicaMaterialPrivate::findOrCreateMicaMaterial(target); } FRAMELESSHELPER_END_NAMESPACE diff --git a/src/core/windowborderpainter.cpp b/src/core/windowborderpainter.cpp index b42e335..76167f0 100644 --- a/src/core/windowborderpainter.cpp +++ b/src/core/windowborderpainter.cpp @@ -88,20 +88,18 @@ QColor WindowBorderPainterPrivate::getNativeBorderColor(const bool active) WindowEdges WindowBorderPainterPrivate::getNativeBorderEdges() { #ifdef Q_OS_WINDOWS - if (WindowsVersionHelper::isWin10OrGreater() - && !WindowsVersionHelper::isWin11OrGreater()) { + if (Utils::isWindowFrameBorderVisible() && !WindowsVersionHelper::isWin11OrGreater()) { return {WindowEdge::Top}; } - return {}; -#else - return {}; #endif + return {}; } void WindowBorderPainterPrivate::paint(QPainter *painter, const QSize &size, const bool active) const { Q_ASSERT(painter); - if (!painter) { + Q_ASSERT(!size.isEmpty()); + if (!painter || size.isEmpty()) { return; } #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index 53913c4..760d215 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -75,42 +75,6 @@ struct QuickHelper Q_GLOBAL_STATIC(QuickHelper, g_quickHelper) -[[nodiscard]] static inline QuickMicaMaterial *findOrCreateMicaMaterial(const QQuickWindow * const window) -{ - Q_ASSERT(window); - if (!window) { - return nullptr; - } - QQuickItem * const rootItem = window->contentItem(); - if (const auto item = rootItem->findChild()) { - return item; - } - const auto item = new QuickMicaMaterial; - item->setParent(rootItem); - item->setParentItem(rootItem); - item->setZ(-999); // Make sure it always stays on the bottom. - QQuickItemPrivate::get(item)->anchors()->setFill(rootItem); - return item; -} - -[[nodiscard]] static inline QuickWindowBorder *findOrCreateWindowBorder(const QQuickWindow * const window) -{ - Q_ASSERT(window); - if (!window) { - return nullptr; - } - QQuickItem * const rootItem = window->contentItem(); - if (const auto item = rootItem->findChild()) { - return item; - } - const auto item = new QuickWindowBorder; - item->setParent(rootItem); - item->setParentItem(rootItem); - item->setZ(999); // Make sure it always stays on the top. - QQuickItemPrivate::get(item)->anchors()->setFill(rootItem); - return item; -} - FramelessQuickHelperPrivate::FramelessQuickHelperPrivate(FramelessQuickHelper *q) : QObject(q) { Q_ASSERT(q); @@ -577,7 +541,19 @@ QuickMicaMaterial *FramelessQuickHelperPrivate::findOrCreateMicaMaterial() const if (!window) { return nullptr; } - return FRAMELESSHELPER_PREPEND_NAMESPACE(findOrCreateMicaMaterial)(window); + QQuickItem * const rootItem = window->contentItem(); + if (const auto item = rootItem->findChild()) { + return item; + } + if (const auto item = window->findChild()) { + return item; + } + const auto item = new QuickMicaMaterial; + item->setParent(rootItem); + item->setParentItem(rootItem); + item->setZ(-999); // Make sure it always stays on the bottom. + QQuickItemPrivate::get(item)->anchors()->setFill(rootItem); + return item; } QuickWindowBorder *FramelessQuickHelperPrivate::findOrCreateWindowBorder() const @@ -587,7 +563,61 @@ QuickWindowBorder *FramelessQuickHelperPrivate::findOrCreateWindowBorder() const if (!window) { return nullptr; } - return FRAMELESSHELPER_PREPEND_NAMESPACE(findOrCreateWindowBorder)(window); + QQuickItem * const rootItem = window->contentItem(); + if (const auto item = rootItem->findChild()) { + return item; + } + if (const auto item = window->findChild()) { + return item; + } + const auto item = new QuickWindowBorder; + item->setParent(rootItem); + item->setParentItem(rootItem); + item->setZ(999); // Make sure it always stays on the top. + QQuickItemPrivate::get(item)->anchors()->setFill(rootItem); + return item; +} + +FramelessQuickHelper *FramelessQuickHelperPrivate::findOrCreateFramelessHelper(QObject *object) +{ + Q_ASSERT(object); + if (!object) { + return nullptr; + } + QObject *parent = nullptr; + QQuickItem *parentItem = nullptr; + if (const auto window = qobject_cast(object)) { + if (QQuickItem * const item = window->contentItem()) { + parent = item; + parentItem = item; + } else { + parent = window; + } + } else if (const auto item = qobject_cast(object)) { + if (QQuickWindow * const window = item->window()) { + if (QQuickItem * const contentItem = window->contentItem()) { + parent = contentItem; + parentItem = contentItem; + } else { + parent = window; + parentItem = item; + } + } else { + parent = item; + parentItem = item; + } + } else { + parent = object; + } + FramelessQuickHelper *instance = parent->findChild(); + if (!instance) { + instance = new FramelessQuickHelper; + instance->setParentItem(parentItem); + instance->setParent(parent); + // No need to do this here, we'll do it once the item has been assigned to a specific window. + //instance->extendsContentIntoTitleBar(); + } + return instance; } bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event) @@ -865,6 +895,34 @@ QuickHelperData *FramelessQuickHelperPrivate::getWindowDataMutable() const return &g_quickHelper()->data[windowId]; } +void FramelessQuickHelperPrivate::rebindWindow() +{ + Q_Q(FramelessQuickHelper); + QQuickWindow * const window = q->window(); + if (!window) { + return; + } + QQuickItem * const rootItem = window->contentItem(); + const QObject * const p = q->parent(); + const QQuickItem * const pItem = q->parentItem(); + if (rootItem) { + if ((pItem != rootItem) || (p != rootItem)) { + q->setParentItem(rootItem); + q->setParent(rootItem); + } + } else { + if (pItem != nullptr) { + q->setParentItem(nullptr); + } + if (p != window) { + q->setParent(window); + } + } + if (m_extendIntoTitleBar.value_or(true)) { + extendsContentIntoTitleBar(true); + } +} + FramelessQuickHelper::FramelessQuickHelper(QQuickItem *parent) : QQuickItem(parent), d_ptr(new FramelessQuickHelperPrivate(this)) { @@ -878,40 +936,7 @@ FramelessQuickHelper *FramelessQuickHelper::get(QObject *object) if (!object) { return nullptr; } - QObject *parent = nullptr; - QQuickItem *parentItem = nullptr; - if (const auto window = qobject_cast(object)) { - if (QQuickItem * const item = window->contentItem()) { - parent = item; - parentItem = item; - } else { - parent = window; - } - } else if (const auto item = qobject_cast(object)) { - if (QQuickWindow * const window = item->window()) { - if (QQuickItem * const contentItem = window->contentItem()) { - parent = contentItem; - parentItem = contentItem; - } else { - parent = window; - parentItem = item; - } - } else { - parent = item; - parentItem = item; - } - } else { - parent = object; - } - FramelessQuickHelper *instance = parent->findChild(); - if (!instance) { - instance = new FramelessQuickHelper; - instance->setParentItem(parentItem); - instance->setParent(parent); - // No need to do this here, we'll do it once the item has been assigned to a specific window. - //instance->extendsContentIntoTitleBar(); - } - return instance; + return FramelessQuickHelperPrivate::findOrCreateFramelessHelper(object); } FramelessQuickHelper *FramelessQuickHelper::qmlAttachedProperties(QObject *parentObject) @@ -1055,26 +1080,8 @@ void FramelessQuickHelper::itemChange(const ItemChange change, const ItemChangeD { QQuickItem::itemChange(change, value); if ((change == ItemSceneChange) && value.window) { - const QObject * const p = parent(); - const QQuickItem * const pItem = parentItem(); - QQuickItem * const rootItem = value.window->contentItem(); - if (rootItem) { - if ((pItem != rootItem) || (p != rootItem)) { - setParentItem(rootItem); - setParent(rootItem); - } - } else { - if (pItem != nullptr) { - setParentItem(nullptr); - } - if (p != value.window) { - setParent(value.window); - } - } Q_D(FramelessQuickHelper); - if (d->m_extendIntoTitleBar.value_or(true)) { - extendsContentIntoTitleBar(); - } + d->rebindWindow(); } } diff --git a/src/quick/framelessquickwindow.cpp b/src/quick/framelessquickwindow.cpp index c41ea20..d3c4deb 100644 --- a/src/quick/framelessquickwindow.cpp +++ b/src/quick/framelessquickwindow.cpp @@ -27,7 +27,6 @@ #include "framelessquickhelper.h" #include "quickwindowborder.h" #include -#include FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/src/quick/quickmicamaterial.cpp b/src/quick/quickmicamaterial.cpp index 252c07e..1be10f9 100644 --- a/src/quick/quickmicamaterial.cpp +++ b/src/quick/quickmicamaterial.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -90,7 +91,7 @@ void WallpaperImageNode::initialize() g_data()->mutex.lock(); QQuickWindow * const window = m_item->window(); - m_micaMaterial = MicaMaterial::attach(window); + m_micaMaterial = MicaMaterial::findOrCreateMicaMaterial(window); m_node = new QSGSimpleTextureNode; m_node->setFiltering(QSGTexture::Linear); @@ -185,6 +186,10 @@ void QuickMicaMaterialPrivate::rebindWindow() if (!window) { return; } + QQuickItem * const rootItem = window->contentItem(); + q->setParent(rootItem); + q->setParentItem(rootItem); + QQuickItemPrivate::get(q)->anchors()->setFill(rootItem); q->setZ(-999); // Make sure we always stays on the bottom most place. if (m_rootWindowXChangedConnection) { disconnect(m_rootWindowXChangedConnection); diff --git a/src/quick/quickwindowborder.cpp b/src/quick/quickwindowborder.cpp index 1a784fe..9a9f22a 100644 --- a/src/quick/quickwindowborder.cpp +++ b/src/quick/quickwindowborder.cpp @@ -25,6 +25,7 @@ #include "quickwindowborder.h" #include "quickwindowborder_p.h" #include +#include #include FRAMELESSHELPER_BEGIN_NAMESPACE @@ -159,6 +160,10 @@ void QuickWindowBorderPrivate::rebindWindow() if (!window) { return; } + QQuickItem * const rootItem = window->contentItem(); + q->setParent(rootItem); + q->setParentItem(rootItem); + QQuickItemPrivate::get(q)->anchors()->setFill(rootItem); q->setZ(999); // Make sure we always stays on the top most place. if (m_activeChangeConnection) { disconnect(m_activeChangeConnection); diff --git a/src/widgets/framelesswidgetshelper.cpp b/src/widgets/framelesswidgetshelper.cpp index cdb1890..950f90b 100644 --- a/src/widgets/framelesswidgetshelper.cpp +++ b/src/widgets/framelesswidgetshelper.cpp @@ -73,30 +73,6 @@ struct WidgetsHelper Q_GLOBAL_STATIC(WidgetsHelper, g_widgetsHelper) -[[nodiscard]] static inline WidgetsSharedHelper *findWidgetsSharedHelper(QWidget *window) -{ - Q_ASSERT(window); - if (!window) { - return nullptr; - } - if (const auto widget = qobject_cast(window)) { - if (const auto widgetPriv = FramelessWidgetPrivate::get(widget)) { - return widgetPriv->widgetsSharedHelper(); - } - } - if (const auto mainWindow = qobject_cast(window)) { - if (const auto mainWindowPriv = FramelessMainWindowPrivate::get(mainWindow)) { - return mainWindowPriv->widgetsSharedHelper(); - } - } - if (const auto dialog = qobject_cast(window)) { - if (const auto dialogPriv = FramelessDialogPrivate::get(dialog)) { - return dialogPriv->widgetsSharedHelper(); - } - } - return nullptr; -} - FramelessWidgetsHelperPrivate::FramelessWidgetsHelperPrivate(FramelessWidgetsHelper *q) : QObject(q) { Q_ASSERT(q); @@ -224,7 +200,7 @@ void FramelessWidgetsHelperPrivate::setBlurBehindWindowEnabled(const bool enable WARNING << "Failed to enable/disable blur behind window."; } } else { - if (WidgetsSharedHelper * const helper = findWidgetsSharedHelper(m_window)) { + if (WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) { m_blurBehindWindowEnabled = enable; helper->setMicaEnabled(m_blurBehindWindowEnabled); emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("blurBehindWindowEnabledChanged")); @@ -272,7 +248,7 @@ MicaMaterial *FramelessWidgetsHelperPrivate::getMicaMaterialIfAny() const if (!m_window) { return nullptr; } - if (const WidgetsSharedHelper * const helper = findWidgetsSharedHelper(m_window)) { + if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) { return helper->rawMicaMaterial(); } return nullptr; @@ -283,12 +259,68 @@ WindowBorderPainter *FramelessWidgetsHelperPrivate::getWindowBorderIfAny() const if (!m_window) { return nullptr; } - if (const WidgetsSharedHelper * const helper = findWidgetsSharedHelper(m_window)) { + if (const WidgetsSharedHelper * const helper = findOrCreateSharedHelper(m_window)) { return helper->rawWindowBorder(); } return nullptr; } +WidgetsSharedHelper *FramelessWidgetsHelperPrivate::findOrCreateSharedHelper(QWidget *window) +{ + Q_ASSERT(window); + if (!window) { + return nullptr; + } + if (const auto widget = qobject_cast(window)) { + if (const auto widgetPriv = FramelessWidgetPrivate::get(widget)) { + return widgetPriv->widgetsSharedHelper(); + } + } + if (const auto mainWindow = qobject_cast(window)) { + if (const auto mainWindowPriv = FramelessMainWindowPrivate::get(mainWindow)) { + return mainWindowPriv->widgetsSharedHelper(); + } + } + if (const auto dialog = qobject_cast(window)) { + if (const auto dialogPriv = FramelessDialogPrivate::get(dialog)) { + return dialogPriv->widgetsSharedHelper(); + } + } + QWidget * const topLevelWindow = (window->nativeParentWidget() + ? window->nativeParentWidget() : window->window()); + WidgetsSharedHelper *helper = topLevelWindow->findChild(); + if (!helper) { + helper = new WidgetsSharedHelper; + helper->setParent(topLevelWindow); + helper->setup(topLevelWindow); + } + return helper; +} + +FramelessWidgetsHelper *FramelessWidgetsHelperPrivate::findOrCreateFramelessHelper(QObject *object) +{ + Q_ASSERT(object); + if (!object) { + return nullptr; + } + QObject *parent = nullptr; + if (const auto widget = qobject_cast(object)) { + if (QWidget * const nativeParent = widget->nativeParentWidget()) { + parent = nativeParent; + } else { + parent = widget->window(); + } + } else { + parent = object; + } + FramelessWidgetsHelper *instance = parent->findChild(); + if (!instance) { + instance = new FramelessWidgetsHelper(parent); + instance->extendsContentIntoTitleBar(); + } + return instance; +} + bool FramelessWidgetsHelperPrivate::isContentExtendedIntoTitleBar() const { return getWindowData().ready; @@ -832,22 +864,7 @@ FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *object) if (!object) { return nullptr; } - QObject *parent = nullptr; - if (const auto widget = qobject_cast(object)) { - if (QWidget * const nativeParent = widget->nativeParentWidget()) { - parent = nativeParent; - } else { - parent = widget->window(); - } - } else { - parent = object; - } - FramelessWidgetsHelper *instance = parent->findChild(); - if (!instance) { - instance = new FramelessWidgetsHelper(parent); - instance->extendsContentIntoTitleBar(); - } - return instance; + return FramelessWidgetsHelperPrivate::findOrCreateFramelessHelper(object); } QWidget *FramelessWidgetsHelper::titleBarWidget() const diff --git a/src/widgets/widgetssharedhelper.cpp b/src/widgets/widgetssharedhelper.cpp index 5994226..6944404 100644 --- a/src/widgets/widgetssharedhelper.cpp +++ b/src/widgets/widgetssharedhelper.cpp @@ -74,7 +74,7 @@ void WidgetsSharedHelper::setup(QWidget *widget) m_targetWidget->update(); } }); - m_micaMaterial = MicaMaterial::attach(m_targetWidget); + m_micaMaterial = MicaMaterial::findOrCreateMicaMaterial(m_targetWidget); if (m_micaRedrawConnection) { disconnect(m_micaRedrawConnection); m_micaRedrawConnection = {}; @@ -217,7 +217,8 @@ void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event) m_micaMaterial->paint(&painter, m_targetWidget->size(), m_targetWidget->mapToGlobal(QPoint(0, 0))); } - if (shouldDrawFrameBorder() && !m_borderPainter.isNull()) { + if ((Utils::windowStatesToWindowState(m_targetWidget->windowState()) == Qt::WindowNoState) + && !m_borderPainter.isNull()) { QPainter painter(m_targetWidget); m_borderPainter->paint(&painter, m_targetWidget->size(), m_targetWidget->isActiveWindow()); } @@ -225,16 +226,6 @@ void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event) // otherwise the widget won't paint anything else from the user side. } -bool WidgetsSharedHelper::shouldDrawFrameBorder() const -{ -#ifdef Q_OS_WINDOWS - return (Utils::isWindowFrameBorderVisible() && !WindowsVersionHelper::isWin11OrGreater() - && (Utils::windowStatesToWindowState(m_targetWidget->windowState()) == Qt::WindowNoState)); -#else - return false; -#endif -} - void WidgetsSharedHelper::handleScreenChanged(QScreen *screen) { Q_ASSERT(m_targetWidget); @@ -271,7 +262,9 @@ void WidgetsSharedHelper::handleScreenChanged(QScreen *screen) void WidgetsSharedHelper::updateContentsMargins() { #ifdef Q_OS_WINDOWS - m_targetWidget->setContentsMargins(0, (shouldDrawFrameBorder() ? kDefaultWindowFrameBorderThickness : 0), 0, 0); + m_targetWidget->setContentsMargins(0, + ((Utils::windowStatesToWindowState(m_targetWidget->windowState()) == Qt::WindowNoState) + ? kDefaultWindowFrameBorderThickness : 0), 0, 0); #endif }