From ed5f9693b3cd7ddcdc746c4bb65dcd9cf7a8268b Mon Sep 17 00:00:00 2001 From: Sine Striker <trueful@163.com> Date: 周二, 19 12月 2023 15:09:49 +0800 Subject: [PATCH] Add window attributes --- src/core/contexts/abstractwindowcontext.cpp | 15 +++++++ src/core/contexts/abstractwindowcontext_p.h | 11 +++++ src/core/windowagentbase.h | 5 +- src/core/windowagentbase.cpp | 36 +++++++----------- README.md | 7 ++- src/core/contexts/win32windowcontext.cpp | 21 +++++++++- 6 files changed, 66 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 5b0f685..c8f6c14 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ + Fix window 10 top border color in dark background + Fix `isFixedSize` code + Support customized system button area on Mac -+ Make Linux system move/resize more robust ## Supported Platforms @@ -95,7 +94,7 @@ MyWidget::MyWidget(QWidget *parent) { // ... - auto agent = new WidgetWindowAgent(w); + auto agent = new QWK::WidgetWindowAgent(w); agent->setup(w); // ... } @@ -104,10 +103,12 @@ You can also initialize the agent after the window constructs. ```c++ auto w = new MyWidget(); -auto agent = new WidgetWindowAgent(w); +auto agent = new QWK::WidgetWindowAgent(w); agent->setup(w); ``` + + Then, construct your title bar widget, without which the window lacks the basic interaction feature, and it's better to put it into the window's layout. You can use the [`WindowBar`](examples/shared/widgetframe/windowbar.h) provided by `WidgetFrame` in the examples as the container of your title bar components. diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp index d34a1f9..a62d037 100644 --- a/src/core/contexts/abstractwindowcontext.cpp +++ b/src/core/contexts/abstractwindowcontext.cpp @@ -23,6 +23,21 @@ } } + void AbstractWindowContext::setWindowAttribute(const QString &key, const QVariant &var) { + auto it = m_windowAttributes.find(key); + if (it.value() == var) + return; + + auto newVar = var; + auto oldVar = it.value(); + void *a[] = { + &const_cast<QString &>(key), + &newVar, + &oldVar, + }; + virtual_hook(WindowAttributeChangedHook, a); + } + bool AbstractWindowContext::setHitTestVisible(const QObject *obj, bool visible) { Q_ASSERT(obj); if (!obj) { diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h index 3938d75..3115141 100644 --- a/src/core/contexts/abstractwindowcontext_p.h +++ b/src/core/contexts/abstractwindowcontext_p.h @@ -28,6 +28,9 @@ inline QWindow *window() const; inline WindowItemDelegate *delegate() const; + inline QVariant windowAttribute(const QString &key) const; + void setWindowAttribute(const QString &key, const QVariant &var); + inline bool isHitTestVisible(const QObject *obj) const; bool setHitTestVisible(const QObject *obj, bool visible); @@ -49,8 +52,10 @@ enum WindowContextHook { CentralizeHook = 1, + RaiseWindowHook, ShowSystemMenuHook, DefaultColorsHook, + WindowAttributeChangedHook, DrawWindows10BorderHook, // Only works on Windows 10 SystemButtonAreaChangedHook, // Only works on Mac }; @@ -74,6 +79,8 @@ QObject *m_titleBar{}; std::array<QObject *, WindowAgentBase::NumSystemButton> m_systemButtons{}; + + QVariantHash m_windowAttributes; }; inline QObject *AbstractWindowContext::host() const { @@ -88,6 +95,10 @@ return m_delegate.get(); } + inline QVariant AbstractWindowContext::windowAttribute(const QString &key) const { + return m_windowAttributes.value(key); + } + inline bool AbstractWindowContext::isHitTestVisible(const QObject *obj) const { return m_hitTestVisibleItems.contains(obj); } diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 2a6ee76..8af6a3f 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -117,7 +117,7 @@ private: DynamicApis() { #define DYNAMIC_API_RESOLVE(DLL, NAME) \ - p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME)) + p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME)) QSystemLibrary user32(QStringLiteral("user32")); DYNAMIC_API_RESOLVE(user32, GetDpiForWindow); @@ -332,7 +332,7 @@ static inline quint32 getDpiForWindow(HWND hwnd) { const DynamicApis &apis = DynamicApis::instance(); - if (apis.pGetDpiForWindow) { // Win10 + if (apis.pGetDpiForWindow) { // Win10 return apis.pGetDpiForWindow(hwnd); } else if (apis.pGetDpiForMonitor) { // Win8.1 HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); @@ -826,6 +826,23 @@ return; } + case WindowAttributeChangedHook: { + auto args = static_cast<void **>(data); + const auto &key = *static_cast<const QString *>(args[0]); + const auto &newVar = *static_cast<const QVariant *>(args[1]); + const auto &oldVar = *static_cast<const QVariant *>(args[2]); + + if (key == QStringLiteral("no-frame-shadow")) { + if (newVar.toBool()) { + // TODO: set off + } else { + // TODO: set on + } + } + + break; + } + case DefaultColorsHook: { auto &map = *static_cast<QMap<QString, QColor> *>(data); map.clear(); diff --git a/src/core/windowagentbase.cpp b/src/core/windowagentbase.cpp index d2b9e1e..c043838 100644 --- a/src/core/windowagentbase.cpp +++ b/src/core/windowagentbase.cpp @@ -50,37 +50,29 @@ WindowAgentBase::~WindowAgentBase() = default; + QVariant WindowAgentBase::windowAttribute(const QString &key) const { + Q_D(const WindowAgentBase); + return d->context->windowAttribute(key); + } + + void WindowAgentBase::setWindowAttribute(const QString &key, const QVariant &var) { + Q_D(WindowAgentBase); + d->context->setWindowAttribute(key, var); + } + void WindowAgentBase::showSystemMenu(const QPoint &pos) { Q_D(WindowAgentBase); d->context->showSystemMenu(pos); } - void WindowAgentBase::startSystemMove(const QPoint &pos) { - Q_D(WindowAgentBase); - auto win = d->context->window(); - if (!win) { - return; - } - - Q_UNUSED(pos) - win->startSystemMove(); - } - - void WindowAgentBase::startSystemResize(Qt::Edges edges, const QPoint &pos) { - Q_D(WindowAgentBase); - auto win = d->context->window(); - if (!win) { - return; - } - - Q_UNUSED(pos) - win->startSystemResize(edges); - } - void WindowAgentBase::centralize() { + Q_D(WindowAgentBase); + d->context->virtual_hook(AbstractWindowContext::CentralizeHook, nullptr); } void WindowAgentBase::raise() { + Q_D(WindowAgentBase); + d->context->virtual_hook(AbstractWindowContext::RaiseWindowHook, nullptr); } WindowAgentBase::WindowAgentBase(WindowAgentBasePrivate &d, QObject *parent) diff --git a/src/core/windowagentbase.h b/src/core/windowagentbase.h index b0b884b..d5b02fa 100644 --- a/src/core/windowagentbase.h +++ b/src/core/windowagentbase.h @@ -28,10 +28,11 @@ }; Q_ENUM(SystemButton) + QVariant windowAttribute(const QString &key) const; + void setWindowAttribute(const QString &key, const QVariant &var); + public Q_SLOTS: void showSystemMenu(const QPoint &pos); - void startSystemMove(const QPoint &pos); - void startSystemResize(Qt::Edges edges, const QPoint &pos); void centralize(); void raise(); -- Gitblit v1.9.1