Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-10-11 11:52:49 +08:00
parent 1e43ba2e81
commit fcf51d6d73
13 changed files with 192 additions and 163 deletions

View File

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

View File

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

View File

@ -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<FramelessQuickHelper> q_ptr = nullptr;

View File

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

View File

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

View File

@ -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<MicaMaterial *>()) {
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

View File

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

View File

@ -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<QuickMicaMaterial *>()) {
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<QuickWindowBorder *>()) {
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<QuickMicaMaterial *>()) {
return item;
}
if (const auto item = window->findChild<QuickMicaMaterial *>()) {
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<QuickWindowBorder *>()) {
return item;
}
if (const auto item = window->findChild<QuickWindowBorder *>()) {
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<QQuickWindow *>(object)) {
if (QQuickItem * const item = window->contentItem()) {
parent = item;
parentItem = item;
} else {
parent = window;
}
} else if (const auto item = qobject_cast<QQuickItem *>(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<FramelessQuickHelper *>();
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<QQuickWindow *>(object)) {
if (QQuickItem * const item = window->contentItem()) {
parent = item;
parentItem = item;
} else {
parent = window;
}
} else if (const auto item = qobject_cast<QQuickItem *>(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<FramelessQuickHelper *>();
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();
}
}

View File

@ -27,7 +27,6 @@
#include "framelessquickhelper.h"
#include "quickwindowborder.h"
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickanchors_p.h>
FRAMELESSHELPER_BEGIN_NAMESPACE

View File

@ -29,6 +29,7 @@
#include <QtGui/qscreen.h>
#include <QtGui/qpainter.h>
#include <QtGui/qguiapplication.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuick/qsgsimpletexturenode.h>
@ -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);

View File

@ -25,6 +25,7 @@
#include "quickwindowborder.h"
#include "quickwindowborder_p.h"
#include <windowborderpainter.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/qquickwindow.h>
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);

View File

@ -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<FramelessWidget *>(window)) {
if (const auto widgetPriv = FramelessWidgetPrivate::get(widget)) {
return widgetPriv->widgetsSharedHelper();
}
}
if (const auto mainWindow = qobject_cast<FramelessMainWindow *>(window)) {
if (const auto mainWindowPriv = FramelessMainWindowPrivate::get(mainWindow)) {
return mainWindowPriv->widgetsSharedHelper();
}
}
if (const auto dialog = qobject_cast<FramelessDialog *>(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<FramelessWidget *>(window)) {
if (const auto widgetPriv = FramelessWidgetPrivate::get(widget)) {
return widgetPriv->widgetsSharedHelper();
}
}
if (const auto mainWindow = qobject_cast<FramelessMainWindow *>(window)) {
if (const auto mainWindowPriv = FramelessMainWindowPrivate::get(mainWindow)) {
return mainWindowPriv->widgetsSharedHelper();
}
}
if (const auto dialog = qobject_cast<FramelessDialog *>(window)) {
if (const auto dialogPriv = FramelessDialogPrivate::get(dialog)) {
return dialogPriv->widgetsSharedHelper();
}
}
QWidget * const topLevelWindow = (window->nativeParentWidget()
? window->nativeParentWidget() : window->window());
WidgetsSharedHelper *helper = topLevelWindow->findChild<WidgetsSharedHelper *>();
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<QWidget *>(object)) {
if (QWidget * const nativeParent = widget->nativeParentWidget()) {
parent = nativeParent;
} else {
parent = widget->window();
}
} else {
parent = object;
}
FramelessWidgetsHelper *instance = parent->findChild<FramelessWidgetsHelper *>();
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<QWidget *>(object)) {
if (QWidget * const nativeParent = widget->nativeParentWidget()) {
parent = nativeParent;
} else {
parent = widget->window();
}
} else {
parent = object;
}
FramelessWidgetsHelper *instance = parent->findChild<FramelessWidgetsHelper *>();
if (!instance) {
instance = new FramelessWidgetsHelper(parent);
instance->extendsContentIntoTitleBar();
}
return instance;
return FramelessWidgetsHelperPrivate::findOrCreateFramelessHelper(object);
}
QWidget *FramelessWidgetsHelper::titleBarWidget() const

View File

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