| | |
| | | + 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 |
| | | |
| | |
| | | |
| | | MyWidget::MyWidget(QWidget *parent) { |
| | | // ... |
| | | auto agent = new WidgetWindowAgent(w); |
| | | auto agent = new QWK::WidgetWindowAgent(w); |
| | | agent->setup(w); |
| | | // ... |
| | | } |
| | |
| | | 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. |
| | |
| | | } |
| | | } |
| | | |
| | | 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) { |
| | |
| | | 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); |
| | | |
| | |
| | | |
| | | enum WindowContextHook { |
| | | CentralizeHook = 1, |
| | | RaiseWindowHook, |
| | | ShowSystemMenuHook, |
| | | DefaultColorsHook, |
| | | WindowAttributeChangedHook, |
| | | DrawWindows10BorderHook, // Only works on Windows 10 |
| | | SystemButtonAreaChangedHook, // Only works on Mac |
| | | }; |
| | |
| | | |
| | | QObject *m_titleBar{}; |
| | | std::array<QObject *, WindowAgentBase::NumSystemButton> m_systemButtons{}; |
| | | |
| | | QVariantHash m_windowAttributes; |
| | | }; |
| | | |
| | | inline QObject *AbstractWindowContext::host() const { |
| | |
| | | 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); |
| | | } |
| | |
| | | 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); |
| | |
| | | |
| | | 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); |
| | |
| | | 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(); |
| | |
| | | |
| | | 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) |
| | |
| | | }; |
| | | 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(); |
| | | |