From 2f6c83c095724bbba0f43b2f2893ba73c17949a6 Mon Sep 17 00:00:00 2001 From: Zhao Yuhang <2546789017@qq.com> Date: 周一, 11 12月 2023 21:57:40 +0800 Subject: [PATCH] add quick border --- src/core/contexts/abstractwindowcontext.cpp | 13 +--- src/widgets/widgetwindowagent.cpp | 10 +- src/core/contexts/abstractwindowcontext_p.h | 1 src/quick/quickwindowagent_p.h | 4 + src/core/contexts/win32windowcontext.cpp | 25 ++++++-- src/quick/quickwindowagent.cpp | 78 +++++++++++++++++++++++++ 6 files changed, 110 insertions(+), 21 deletions(-) diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp index 18ed37f..49eb0c5 100644 --- a/src/core/contexts/abstractwindowcontext.cpp +++ b/src/core/contexts/abstractwindowcontext.cpp @@ -181,20 +181,15 @@ void AbstractWindowContext::virtual_hook(int id, void *data) { switch (id) { - case ShowSystemMenuHook: { - const auto &pos = *reinterpret_cast<const QPoint *>(data); - std::ignore = pos; - return; - } case NeedsDrawBordersHook: { - auto &result = *reinterpret_cast<bool *>(data); + auto &result = *static_cast<bool *>(data); result = false; return; } case DrawBordersHook: { - auto args = reinterpret_cast<void **>(data); - auto &painter = *reinterpret_cast<QPainter *>(args[0]); - auto &rect = *reinterpret_cast<const QRect *>(args[1]); + auto args = static_cast<void **>(data); + auto &painter = *static_cast<QPainter *>(args[0]); + const auto &rect = *static_cast<const QRect *>(args[1]); // Top painter.setPen(kSampleColorSet.grass); diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h index a7b6767..3c04073 100644 --- a/src/core/contexts/abstractwindowcontext_p.h +++ b/src/core/contexts/abstractwindowcontext_p.h @@ -48,6 +48,7 @@ ShowSystemMenuHook, NeedsDrawBordersHook, DrawBordersHook, + QueryBorderThicknessHook }; virtual void virtual_hook(int id, void *data); diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 603079c..78a54c5 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -781,22 +781,22 @@ return; } case ShowSystemMenuHook: { - const auto &pos = *reinterpret_cast<const QPoint *>(data); + const auto &pos = *static_cast<const QPoint *>(data); auto hWnd = reinterpret_cast<HWND>(m_windowHandle->winId()); showSystemMenu2(hWnd, qpoint2point(pos), false, m_delegate->isHostSizeFixed(m_host)); return; } case NeedsDrawBordersHook: { - auto &result = *reinterpret_cast<bool *>(data); + auto &result = *static_cast<bool *>(data); result = isWin10OrGreater() && !isWin11OrGreater(); return; } case DrawBordersHook: { - auto args = reinterpret_cast<void **>(data); - auto &painter = *reinterpret_cast<QPainter *>(args[0]); - auto &rect = *reinterpret_cast<const QRect *>(args[1]); - auto ®ion = *reinterpret_cast<const QRegion *>(args[2]); + auto args = static_cast<void **>(data); + auto &painter = *static_cast<QPainter *>(args[0]); + const auto &rect = *static_cast<const QRect *>(args[1]); + const auto ®ion = *static_cast<const QRegion *>(args[2]); const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); QPen pen{}; const auto borderThickness = int(QHighDpi::fromNativePixels(getWindowFrameBorderThickness(hwnd), m_windowHandle)); @@ -827,6 +827,19 @@ painter.restore(); return; } + case QueryBorderThicknessHook: { + auto args = static_cast<void **>(data); + const bool requireNative = *static_cast<const bool *>(args[0]); + quint32 &thickness = *static_cast<quint32 *>(args[1]); + const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); + const auto nativeThickness = getWindowFrameBorderThickness(hwnd); + if (requireNative) { + thickness = nativeThickness; + } else { + thickness = QHighDpi::fromNativePixels(nativeThickness, m_windowHandle); + } + return; + } default: { // unreachable break; diff --git a/src/quick/quickwindowagent.cpp b/src/quick/quickwindowagent.cpp index 2bc9bca..74a032b 100644 --- a/src/quick/quickwindowagent.cpp +++ b/src/quick/quickwindowagent.cpp @@ -3,8 +3,81 @@ #include "quickitemdelegate_p.h" #include <QtQuick/QQuickWindow> +#include <QtQuick/QQuickPaintedItem> +#include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquickanchors_p.h> namespace QWK { + + class BorderItem : public QQuickPaintedItem { + Q_OBJECT + + public: + explicit BorderItem(AbstractWindowContext *ctx, QQuickItem *parent = nullptr); + ~BorderItem() override; + + void updateHeight(); + + void paint(QPainter *painter) override; + + void itemChange(ItemChange change, const ItemChangeData &data) override; + + private: + AbstractWindowContext *context; + }; + + BorderItem::BorderItem(AbstractWindowContext *ctx, QQuickItem *parent) : QQuickPaintedItem(parent), context(ctx) { + setAntialiasing(true); // ### FIXME: do we need to enable or disable this? + setMipmap(true); // ### FIXME: do we need to enable or disable this? + setFillColor({}); // Will improve the performance a little bit. + setOpaquePainting(true); // Will also improve the performance, we don't draw semi-transparent borders of course. + + auto parentPri = QQuickItemPrivate::get(parent); + auto anchors = QQuickItemPrivate::get(this)->anchors(); + anchors->setTop(parentPri->top()); + anchors->setLeft(parentPri->left()); + anchors->setRight(parentPri->right()); + + setZ(std::numeric_limits<qreal>::max()); + } + + BorderItem::~BorderItem() = default; + + void BorderItem::updateHeight() { + bool native = false; + quint32 thickness = 0; + void *args[] = { &native, &thickness }; + context->virtual_hook(AbstractWindowContext::QueryBorderThicknessHook, &args); + setHeight(thickness); + } + + void BorderItem::paint(QPainter *painter) { + auto rect = QRect{ QPoint{ 0, 0}, size().toSize() }; + auto region = QRegion{ rect }; + void *args[] = { + painter, + &rect, + ®ion + }; + context->virtual_hook(AbstractWindowContext::DrawBordersHook, args); + } + + void BorderItem::itemChange(ItemChange change, const ItemChangeData &data) { + QQuickPaintedItem::itemChange(change, data); + switch (change) { + case ItemSceneChange: + if (data.window) { + connect(data.window, &QQuickWindow::activeChanged, this, [this](){ update(); }); + } + Q_FALLTHROUGH(); + case ItemVisibleHasChanged: + case ItemDevicePixelRatioHasChanged: + updateHeight(); + break; + default: + break; + } + } QuickWindowAgentPrivate::QuickWindowAgentPrivate() { } @@ -13,6 +86,7 @@ } void QuickWindowAgentPrivate::init() { + borderItem = std::make_unique<BorderItem>(context.get(), hostWindow->contentItem()); } QuickWindowAgent::QuickWindowAgent(QObject *parent) @@ -34,7 +108,7 @@ } if (!d->setup(window, new QuickItemDelegate())) { - return true; + return false; } d->hostWindow = window; return true; @@ -87,3 +161,5 @@ } } + +#include "quickwindowagent.moc" \ No newline at end of file diff --git a/src/quick/quickwindowagent_p.h b/src/quick/quickwindowagent_p.h index 243f534..d457690 100644 --- a/src/quick/quickwindowagent_p.h +++ b/src/quick/quickwindowagent_p.h @@ -6,6 +6,8 @@ namespace QWK { + class BorderItem; + class QuickWindowAgentPrivate : public WindowAgentBasePrivate { Q_DECLARE_PUBLIC(QuickWindowAgent) public: @@ -16,6 +18,8 @@ // Host QQuickWindow *hostWindow{}; + + std::unique_ptr<BorderItem> borderItem; }; } diff --git a/src/widgets/widgetwindowagent.cpp b/src/widgets/widgetwindowagent.cpp index 43528b5..e859fbd 100644 --- a/src/widgets/widgetwindowagent.cpp +++ b/src/widgets/widgetwindowagent.cpp @@ -18,16 +18,16 @@ bool eventFilter(QObject *obj, QEvent *event) override { switch (event->type()) { case QEvent::Paint: { - auto e = static_cast<QPaintEvent *>(event); + auto pe = static_cast<QPaintEvent *>(event); QPainter painter(widget); - QRect rect = e->rect(); - QRegion region = e->region(); - void *a[] = { + QRect rect = pe->rect(); + QRegion region = pe->region(); + void *args[] = { &painter, &rect, ®ion, }; - ctx->virtual_hook(AbstractWindowContext::DrawBordersHook, a); + ctx->virtual_hook(AbstractWindowContext::DrawBordersHook, args); return true; } default: -- Gitblit v1.9.1