From 650adb9a7e6f0d9a518e90ffcea743e1da706c3b Mon Sep 17 00:00:00 2001 From: Zhao Yuhang <2546789017@qq.com> Date: Sat, 21 Mar 2026 14:16:03 +0800 Subject: [PATCH] minor tweaks --- examples/qml/fpscounter.cpp | 45 ++++++++ examples/qml/fpscounter.h | 26 +++++ examples/qml/main.cpp | 20 +++- examples/qml/main.qml | 23 ++++ src/core/contexts/abstractwindowcontext.cpp | 20 +++- src/core/contexts/abstractwindowcontext_p.h | 58 ++++++---- src/core/contexts/cocoawindowcontext_p.h | 2 +- src/core/contexts/linuxwaylandcontext.cpp | 3 +- src/core/contexts/linuxwaylandcontext_p.h | 2 +- src/core/contexts/linuxx11context.cpp | 3 +- src/core/contexts/linuxx11context_p.h | 2 +- src/core/contexts/qtwindowcontext.cpp | 17 +-- src/core/contexts/qtwindowcontext_p.h | 10 +- src/core/contexts/win32windowcontext.cpp | 111 +++++++++++++++----- src/core/contexts/win32windowcontext_p.h | 2 +- src/core/kernel/nativeeventfilter.cpp | 16 ++- src/core/kernel/nativeeventfilter_p.h | 2 +- src/core/kernel/sharedeventfilter.cpp | 9 +- src/core/kernel/sharedeventfilter_p.h | 2 +- src/core/kernel/winidchangeeventfilter.cpp | 8 +- src/core/kernel/winidchangeeventfilter_p.h | 18 ++-- src/core/qwindowkit_windows.cpp | 13 ++- src/core/qwindowkit_windows.h | 10 +- src/core/qwkglobal.cpp | 3 + src/core/qwkglobal_p.h | 2 + src/core/shared/qwkwindowsextra_p.h | 13 ++- src/core/shared/systemwindow_p.h | 37 ++++--- src/core/shared/windows10borderhandler_p.h | 8 +- src/core/style/styleagent.cpp | 6 +- src/core/style/styleagent.h | 2 +- src/core/style/styleagent_p.h | 8 +- src/core/style/styleagent_win.cpp | 14 +-- src/core/windowagentbase.cpp | 10 +- src/core/windowagentbase.h | 4 +- src/core/windowagentbase_p.h | 4 +- src/core/windowitemdelegate.cpp | 2 + src/quick/quickitemdelegate.cpp | 19 +++- src/quick/quickitemdelegate_p.h | 2 +- src/quick/quickwindowagent_mac.cpp | 9 +- src/quick/quickwindowagent_p.h | 6 +- src/quick/quickwindowagent_win.cpp | 4 +- src/widgets/widgetitemdelegate.cpp | 27 ++++- src/widgets/widgetitemdelegate_p.h | 2 +- src/widgets/widgetwindowagent.cpp | 5 + src/widgets/widgetwindowagent.h | 2 +- src/widgets/widgetwindowagent_mac.cpp | 11 +- src/widgets/widgetwindowagent_p.h | 6 +- src/widgets/widgetwindowagent_win.cpp | 16 ++- 48 files changed, 469 insertions(+), 175 deletions(-) create mode 100644 examples/qml/fpscounter.cpp create mode 100644 examples/qml/fpscounter.h diff --git a/examples/qml/fpscounter.cpp b/examples/qml/fpscounter.cpp new file mode 100644 index 0000000..99a98c6 --- /dev/null +++ b/examples/qml/fpscounter.cpp @@ -0,0 +1,45 @@ +#include "fpscounter.h" +#include +#include + +class FPSCounterPrivate final { + Q_DISABLE_COPY(FPSCounterPrivate) + Q_DECLARE_PUBLIC(FPSCounter) + +public: + FPSCounterPrivate(FPSCounter* qq); + ~FPSCounterPrivate(); + + FPSCounter* q_ptr{ nullptr }; + int frameCount{ 0 }; + QMetaObject::Connection connection{}; +}; + +FPSCounterPrivate::FPSCounterPrivate(FPSCounter* qq) : q_ptr{ qq } { + QObject::connect(q_ptr, &FPSCounter::windowChanged, q_ptr, [this](QQuickWindow* window){ + if (connection) { + QObject::disconnect(std::exchange(connection, {})); + } + if (window) { + connection = QObject::connect(window, &QQuickWindow::frameSwapped, q_ptr, [this](){ ++frameCount; }); + } + }); + auto timer = new QTimer(q_ptr); + timer->setTimerType(Qt::PreciseTimer); + QObject::connect(timer, &QTimer::timeout, q_ptr, [this](){ + Q_EMIT q_ptr->valueChanged(); + frameCount = 0; + }); + timer->start(1000); +} + +FPSCounterPrivate::~FPSCounterPrivate() = default; + +FPSCounter::FPSCounter(QQuickItem* parent) : QQuickItem{ parent }, d_ptr{ std::make_unique(this) } {} + +FPSCounter::~FPSCounter() = default; + +int FPSCounter::value() const { + Q_D(const FPSCounter); + return d->frameCount; +} diff --git a/examples/qml/fpscounter.h b/examples/qml/fpscounter.h new file mode 100644 index 0000000..c73812d --- /dev/null +++ b/examples/qml/fpscounter.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class FPSCounterPrivate; +class FPSCounter : public QQuickItem { + Q_OBJECT + Q_DECLARE_PRIVATE(FPSCounter) + Q_PROPERTY(int value READ value NOTIFY valueChanged FINAL) +#ifdef QML_ELEMENT + QML_ELEMENT +#endif + +public: + explicit FPSCounter(QQuickItem* parent = nullptr); + ~FPSCounter() override; + + int value() const; + +Q_SIGNALS: + void valueChanged(); + +private: + const std::unique_ptr d_ptr; +}; diff --git a/examples/qml/main.cpp b/examples/qml/main.cpp index c81e550..16b3af8 100644 --- a/examples/qml/main.cpp +++ b/examples/qml/main.cpp @@ -2,6 +2,8 @@ // Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao) // SPDX-License-Identifier: Apache-2.0 +#include "fpscounter.h" +#include #include #include #include @@ -20,7 +22,10 @@ extern "C" { int main(int argc, char *argv[]) { qputenv("QT_WIN_DEBUG_CONSOLE", "attach"); // or "new": create a separate console window qputenv("QSG_INFO", "1"); + qputenv("QT_NO_OPENGL_BUGLIST", "1"); qputenv("QSG_NO_VSYNC", "1"); + qputenv("QT_D3D_NO_VBLANK_THREAD", "1"); + qputenv("QT_QPA_UPDATE_IDLE_TIME", "0"); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) qputenv("QT_QUICK_CONTROLS_STYLE", "Basic"); @@ -29,7 +34,7 @@ int main(int argc, char *argv[]) { #endif #ifdef Q_OS_WINDOWS - qputenv("QSG_RHI_BACKEND", "d3d11"); // options: d3d11, d3d12, opengl, vulkan + qputenv("QSG_RHI_BACKEND", "d3d11"); // options: d3d11, d3d12, opengl, vulkan qputenv("QT_QPA_DISABLE_REDIRECTION_SURFACE", "1"); #endif //qputenv("QSG_RHI_HDR", "scrgb"); // other options: hdr10, p3 @@ -38,17 +43,24 @@ int main(int argc, char *argv[]) { QGuiApplication::setHighDpiScaleFactorRoundingPolicy( Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif + QGuiApplication application(argc, argv); + + QLoggingCategory::setFilterRules(QStringLiteral("qt.qpa.screen.updates=true")); + // Make sure alpha channel is requested, our special effects on Windows depends on it. QQuickWindow::setDefaultAlphaBuffer(true); - QQmlApplicationEngine engine; + + QQmlApplicationEngine engine{}; #if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) - const bool curveRenderingAvailable = true; + constexpr bool curveRenderingAvailable = true; #else - const bool curveRenderingAvailable = false; + constexpr bool curveRenderingAvailable = false; #endif engine.rootContext()->setContextProperty(QStringLiteral("$curveRenderingAvailable"), QVariant(curveRenderingAvailable)); QWK::registerTypes(&engine); + qmlRegisterType("QWK.Demo", 1, 0, "FPSCounter"); engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); + return application.exec(); } \ No newline at end of file diff --git a/examples/qml/main.qml b/examples/qml/main.qml index 41871fc..81d5371 100644 --- a/examples/qml/main.qml +++ b/examples/qml/main.qml @@ -1,12 +1,34 @@ import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 +import QWK.Demo 1.0 FramelessWindow { property FramelessWindow childWindow: FramelessWindow { showWhenReady: false } + FPSCounter { + property int maxVal: 0 + + id: fps + onValueChanged: fps.maxVal = Math.max(fps.value, fps.maxVal) + } + + Text { + anchors { + bottom: buttonsRow.top + bottomMargin: 10 + horizontalCenter: parent.horizontalCenter + } + font { + pixelSize: 25 + bold: true + } + color: "green" + text: qsTr("FPS: ") + fps.value + qsTr(", Max: ") + fps.maxVal + } + Drawer { id: drawer width: 0.66 * parent.width @@ -22,6 +44,7 @@ FramelessWindow { } Row { + id: buttonsRow anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp index 086edf4..35d7c52 100644 --- a/src/core/contexts/abstractwindowcontext.cpp +++ b/src/core/contexts/abstractwindowcontext.cpp @@ -16,12 +16,16 @@ namespace QWK { AbstractWindowContext::~AbstractWindowContext() = default; - void AbstractWindowContext::setup(QObject *host, WindowItemDelegate *delegate) { - if (m_host || !host || !delegate) { + void AbstractWindowContext::setup(QObject *host, WindowItemDelegate *delegate, WindowAgentBase* agent) { + Q_ASSERT(host); + Q_ASSERT(delegate); + Q_ASSERT(agent); + if (m_host || !host || !delegate || !agent) { return; } m_host = host; m_delegate.reset(delegate); + m_agent = agent; m_winIdChangeEventFilter.reset(delegate->createWinIdEventFilter(host, this)); notifyWinIdChange(); } @@ -49,7 +53,8 @@ namespace QWK { bool AbstractWindowContext::setSystemButton(WindowAgentBase::SystemButton button, QObject *obj) { Q_ASSERT(button != WindowAgentBase::Unknown); - if (button == WindowAgentBase::Unknown) { + Q_ASSERT(obj); + if (button == WindowAgentBase::Unknown || !obj) { return false; } @@ -63,6 +68,10 @@ namespace QWK { bool AbstractWindowContext::setTitleBar(QObject *item) { Q_ASSERT(item); + if (!item) { + return false; + } + auto org = m_titleBar; if (org == item) { return false; @@ -85,6 +94,7 @@ namespace QWK { bool AbstractWindowContext::isInSystemButtons(const QPoint &pos, WindowAgentBase::SystemButton *button) const { + Q_ASSERT(button); *button = WindowAgentBase::Unknown; for (int i = WindowAgentBase::WindowIcon; i <= WindowAgentBase::Close; ++i) { auto currentButton = m_systemButtons[i]; @@ -144,7 +154,7 @@ namespace QWK { const quint32 activeDark = MAKE_RGBA_COLOR(177, 205, 190, 240); const quint32 inactiveLight = MAKE_RGBA_COLOR(193, 195, 211, 203); const quint32 inactiveDark = MAKE_RGBA_COLOR(240, 240, 250, 255); - } kSampleColorSet; + } kSampleColorSet{}; void AbstractWindowContext::virtual_hook(int id, void *data) { switch (id) { @@ -273,7 +283,7 @@ namespace QWK { } bool AbstractWindowContext::eventFilter(QObject *obj, QEvent *event) { - if (obj == m_windowHandle && sharedDispatch(obj, event)) { + if (obj && event && obj == m_windowHandle && sharedDispatch(obj, event)) { return true; } return QObject::eventFilter(obj, event); diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h index 057b16b..d248a06 100644 --- a/src/core/contexts/abstractwindowcontext_p.h +++ b/src/core/contexts/abstractwindowcontext_p.h @@ -41,12 +41,13 @@ namespace QWK { ~AbstractWindowContext() override; public: - void setup(QObject *host, WindowItemDelegate *delegate); + void setup(QObject *host, WindowItemDelegate *delegate, WindowAgentBase* agent); inline QObject *host() const; inline QWindow *window() const; inline WId windowId() const; inline WindowItemDelegate *delegate() const; + inline WindowAgentBase* agent() const; inline bool isHitTestVisible(const QObject *obj) const; bool setHitTestVisible(QObject *obj, bool visible); @@ -65,23 +66,9 @@ namespace QWK { bool isInSystemButtons(const QPoint &pos, WindowAgentBase::SystemButton *button) const; bool isInTitleBarDraggableArea(const QPoint &pos) const; - inline bool isHostWidthFixed() const { - return m_windowHandle - ? ((m_windowHandle->flags() & Qt::MSWindowsFixedSizeDialogHint) || - m_windowHandle->minimumWidth() == m_windowHandle->maximumWidth()) - : false; - } - inline bool isHostHeightFixed() const { - return m_windowHandle - ? ((m_windowHandle->flags() & Qt::MSWindowsFixedSizeDialogHint) || - m_windowHandle->minimumHeight() == m_windowHandle->maximumHeight()) - : false; - } - inline bool isHostSizeFixed() const { - return m_windowHandle ? ((m_windowHandle->flags() & Qt::MSWindowsFixedSizeDialogHint) || - m_windowHandle->minimumSize() == m_windowHandle->maximumSize()) - : false; - } + inline bool isHostWidthFixed() const; + inline bool isHostHeightFixed() const; + inline bool isHostSizeFixed() const; virtual QString key() const; @@ -111,18 +98,19 @@ namespace QWK { const QVariant &oldAttribute); protected: - QObject *m_host{}; + QObject *m_host{ nullptr }; std::unique_ptr m_delegate; + WindowAgentBase* m_agent{ nullptr }; QPointer m_windowHandle; - WId m_windowId{}; + WId m_windowId{ 0 }; QVector> m_hitTestVisibleItems; #ifdef Q_OS_MAC - ScreenRectCallback m_systemButtonAreaCallback; + ScreenRectCallback m_systemButtonAreaCallback{}; #endif - QPointer m_titleBar{}; - std::array, WindowAgentBase::Close + 1> m_systemButtons{}; + QPointer m_titleBar; + std::array, WindowAgentBase::Close + 1> m_systemButtons; std::list> m_windowAttributesOrder; QHash m_windowAttributes; @@ -148,6 +136,10 @@ namespace QWK { return m_delegate.get(); } + inline WindowAgentBase* AbstractWindowContext::agent() const { + return m_agent; + } + inline bool AbstractWindowContext::isHitTestVisible(const QObject *obj) const { return m_hitTestVisibleItems.contains(const_cast(obj)); } @@ -167,6 +159,26 @@ namespace QWK { } #endif + inline bool AbstractWindowContext::isHostWidthFixed() const { + return m_windowHandle + ? ((m_windowHandle->flags() & Qt::MSWindowsFixedSizeDialogHint) || + m_windowHandle->minimumWidth() == m_windowHandle->maximumWidth()) + : false; + } + + inline bool AbstractWindowContext::isHostHeightFixed() const { + return m_windowHandle + ? ((m_windowHandle->flags() & Qt::MSWindowsFixedSizeDialogHint) || + m_windowHandle->minimumHeight() == m_windowHandle->maximumHeight()) + : false; + } + + inline bool AbstractWindowContext::isHostSizeFixed() const { + return m_windowHandle ? ((m_windowHandle->flags() & Qt::MSWindowsFixedSizeDialogHint) || + m_windowHandle->minimumSize() == m_windowHandle->maximumSize()) + : false; + } + } #endif // ABSTRACTWINDOWCONTEXT_P_H diff --git a/src/core/contexts/cocoawindowcontext_p.h b/src/core/contexts/cocoawindowcontext_p.h index e35c686..b530739 100644 --- a/src/core/contexts/cocoawindowcontext_p.h +++ b/src/core/contexts/cocoawindowcontext_p.h @@ -18,7 +18,7 @@ namespace QWK { - class CocoaWindowContext : public AbstractWindowContext { + class QWK_CORE_EXPORT CocoaWindowContext final : public AbstractWindowContext { Q_OBJECT public: CocoaWindowContext(); diff --git a/src/core/contexts/linuxwaylandcontext.cpp b/src/core/contexts/linuxwaylandcontext.cpp index 9991dc5..bff6a0c 100644 --- a/src/core/contexts/linuxwaylandcontext.cpp +++ b/src/core/contexts/linuxwaylandcontext.cpp @@ -23,8 +23,7 @@ namespace QWK { seat, serial, x, y); } - LinuxWaylandContext::LinuxWaylandContext() : QtWindowContext() { - } + LinuxWaylandContext::LinuxWaylandContext() = default; LinuxWaylandContext::~LinuxWaylandContext() = default; diff --git a/src/core/contexts/linuxwaylandcontext_p.h b/src/core/contexts/linuxwaylandcontext_p.h index d2fea6f..97fcefc 100644 --- a/src/core/contexts/linuxwaylandcontext_p.h +++ b/src/core/contexts/linuxwaylandcontext_p.h @@ -22,7 +22,7 @@ #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) namespace QWK { - class LinuxWaylandContext : public QtWindowContext { + class QWK_CORE_EXPORT LinuxWaylandContext final : public QtWindowContext { Q_OBJECT public: LinuxWaylandContext(); diff --git a/src/core/contexts/linuxx11context.cpp b/src/core/contexts/linuxx11context.cpp index 9aa512b..91b939b 100644 --- a/src/core/contexts/linuxx11context.cpp +++ b/src/core/contexts/linuxx11context.cpp @@ -125,8 +125,7 @@ union _XEvent { namespace QWK { - LinuxX11Context::LinuxX11Context() : QtWindowContext() { - } + LinuxX11Context::LinuxX11Context() = default; LinuxX11Context::~LinuxX11Context() = default; diff --git a/src/core/contexts/linuxx11context_p.h b/src/core/contexts/linuxx11context_p.h index 932d326..dabe156 100644 --- a/src/core/contexts/linuxx11context_p.h +++ b/src/core/contexts/linuxx11context_p.h @@ -20,7 +20,7 @@ #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) namespace QWK { - class LinuxX11Context : public QtWindowContext { + class QWK_CORE_EXPORT LinuxX11Context final : public QtWindowContext { Q_OBJECT public: LinuxX11Context(); diff --git a/src/core/contexts/qtwindowcontext.cpp b/src/core/contexts/qtwindowcontext.cpp index ff362b7..1b1b90c 100644 --- a/src/core/contexts/qtwindowcontext.cpp +++ b/src/core/contexts/qtwindowcontext.cpp @@ -13,7 +13,7 @@ namespace QWK { static constexpr const quint8 kDefaultResizeBorderThickness = 8; - static Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos) { + static inline Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos) { #ifdef Q_OS_MACOS Q_UNUSED(window); Q_UNUSED(pos); @@ -81,9 +81,9 @@ namespace QWK { #endif } - class QtWindowEventFilter : public SharedEventFilter { + class QtWindowEventFilter final : public SharedEventFilter { public: - explicit QtWindowEventFilter(AbstractWindowContext *context); + QtWindowEventFilter(AbstractWindowContext *context); ~QtWindowEventFilter() override; enum WindowStatus { @@ -98,19 +98,22 @@ namespace QWK { bool sharedEventFilter(QObject *object, QEvent *event) override; private: - AbstractWindowContext *m_context; - bool m_cursorShapeChanged; - WindowStatus m_windowStatus; + AbstractWindowContext *m_context = nullptr; + bool m_cursorShapeChanged = false; + WindowStatus m_windowStatus = Idle; }; QtWindowEventFilter::QtWindowEventFilter(AbstractWindowContext *context) - : m_context(context), m_cursorShapeChanged(false), m_windowStatus(Idle) { + : m_context(context) { m_context->installSharedEventFilter(this); } QtWindowEventFilter::~QtWindowEventFilter() = default; bool QtWindowEventFilter::sharedEventFilter(QObject *obj, QEvent *event) { + Q_ASSERT(obj); + Q_ASSERT(event); + Q_UNUSED(obj) auto type = event->type(); diff --git a/src/core/contexts/qtwindowcontext_p.h b/src/core/contexts/qtwindowcontext_p.h index 9d315d5..001d3dc 100644 --- a/src/core/contexts/qtwindowcontext_p.h +++ b/src/core/contexts/qtwindowcontext_p.h @@ -16,9 +16,15 @@ #include +#ifdef Q_OS_WIN +# define QWK_FINAL final +#else +# define QWK_FINAL +#endif + namespace QWK { - class QtWindowContext : public AbstractWindowContext { + class QWK_CORE_EXPORT QtWindowContext QWK_FINAL : public AbstractWindowContext { Q_OBJECT public: QtWindowContext(); @@ -36,4 +42,6 @@ namespace QWK { } +#undef QWK_FINAL + #endif // QTWINDOWCONTEXT_P_H diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index e52a541..2db69b9 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -50,9 +50,9 @@ namespace QWK { enum IconButtonClickLevelFlag { - IconButtonClicked = 1, - IconButtonDoubleClicked = 2, - IconButtonTriggersClose = 4, + IconButtonClicked = 1 << 0, + IconButtonDoubleClicked = 1 << 1, + IconButtonTriggersClose = 1 << 2, }; // The thickness of an auto-hide taskbar in pixels. @@ -63,7 +63,7 @@ namespace QWK { const uint32_t activeDark = MAKE_RGBA_COLOR(51, 51, 51, 255); // #333333 const uint32_t inactiveLight = MAKE_RGBA_COLOR(167, 167, 167, 255); // #A7A7A7 const uint32_t inactiveDark = MAKE_RGBA_COLOR(61, 61, 62, 255); // #3D3D3E - } kWindowsColorSet; + } kWindowsColorSet{}; // hWnd -> context using WndProcHash = QHash; @@ -88,12 +88,14 @@ namespace QWK { } static inline void triggerFrameChange(HWND hwnd) { + Q_ASSERT(hwnd); ::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } - static void setInternalWindowFrameMargins(QWindow *window, const QMargins &margins) { + static inline void setInternalWindowFrameMargins(QWindow *window, const QMargins &margins) { + Q_ASSERT(window); #if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) Q_UNUSED(window); Q_UNUSED(margins); @@ -127,6 +129,7 @@ namespace QWK { } static inline MONITORINFOEXW getMonitorForWindow(HWND hwnd) { + Q_ASSERT(hwnd); // Use "MONITOR_DEFAULTTONEAREST" here so that we can still get the correct // monitor even if the window is minimized. HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); @@ -137,6 +140,7 @@ namespace QWK { } static inline void moveWindowToMonitor(HWND hwnd, const MONITORINFOEXW &activeMonitor) { + Q_ASSERT(hwnd); RECT currentMonitorRect = getMonitorForWindow(hwnd).rcMonitor; RECT activeMonitorRect = activeMonitor.rcMonitor; // We are in the same monitor, nothing to adjust here. @@ -154,6 +158,7 @@ namespace QWK { } static inline bool isFullScreen(HWND hwnd) { + Q_ASSERT(hwnd); RECT windowRect{}; ::GetWindowRect(hwnd, &windowRect); // Compare to the full area of the screen, not the work area. @@ -161,14 +166,17 @@ namespace QWK { } static inline bool isMaximized(HWND hwnd) { + Q_ASSERT(hwnd); return ::IsZoomed(hwnd); } static inline bool isMinimized(HWND hwnd) { + Q_ASSERT(hwnd); return ::IsIconic(hwnd); } static inline bool isWindowNoState(HWND hwnd) { + Q_ASSERT(hwnd); #if 0 WINDOWPLACEMENT wp{}; wp.length = sizeof(wp); @@ -184,6 +192,7 @@ namespace QWK { } static inline void bringWindowToFront(HWND hwnd) { + Q_ASSERT(hwnd); HWND oldForegroundWindow = ::GetForegroundWindow(); if (!oldForegroundWindow) { // The foreground window can be NULL, it's not an API error. @@ -232,8 +241,9 @@ namespace QWK { } // Returns false if the menu is canceled - static bool showSystemMenu_sys(HWND hWnd, const POINT &pos, const bool selectFirstEntry, + static inline bool showSystemMenu_sys(HWND hWnd, const POINT &pos, const bool selectFirstEntry, const bool fixedSize) { + Q_ASSERT(hWnd); HMENU hMenu = ::GetSystemMenu(hWnd, FALSE); if (!hMenu) { // The corresponding window doesn't have a system menu, most likely due to the @@ -310,7 +320,7 @@ namespace QWK { return true; } - static inline Win32WindowContext::WindowPart getHitWindowPart(int hitTestResult) { + static inline constexpr Win32WindowContext::WindowPart getHitWindowPart(int hitTestResult) { switch (hitTestResult) { case HTCLIENT: return Win32WindowContext::ClientArea; @@ -339,7 +349,8 @@ namespace QWK { return Win32WindowContext::Outside; } - static bool isValidWindow(HWND hWnd, bool checkVisible, bool checkTopLevel) { + static inline bool isValidWindow(HWND hWnd, bool checkVisible, bool checkTopLevel) { + Q_ASSERT(hWnd); if (!::IsWindow(hWnd)) { return false; } @@ -385,8 +396,10 @@ namespace QWK { } } - static MSG createMessageBlock(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - MSG msg; + static inline MSG createMessageBlock(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + Q_ASSERT(hWnd); + + MSG msg{}; msg.hwnd = hWnd; msg.message = message; msg.wParam = wParam; @@ -434,7 +447,9 @@ namespace QWK { } // Send to QAbstractEventDispatcher - static bool filterNativeEvent(MSG *msg, LRESULT *result) { + static inline bool filterNativeEvent(MSG *msg, LRESULT *result) { + Q_ASSERT(msg); + Q_ASSERT(result); auto dispatcher = QAbstractEventDispatcher::instance(); QT_NATIVE_EVENT_RESULT_TYPE filterResult = *result; if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) { @@ -445,7 +460,10 @@ namespace QWK { } // Send to QWindowSystemInterface - static bool filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result) { + static inline bool filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result) { + Q_ASSERT(window); + Q_ASSERT(msg); + Q_ASSERT(result); QT_NATIVE_EVENT_RESULT_TYPE filterResult = *result; if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), msg, &filterResult)) { @@ -457,6 +475,10 @@ namespace QWK { static inline bool forwardFilteredEvent(QWindow *window, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) { + Q_ASSERT(window); + Q_ASSERT(hWnd); + Q_ASSERT(result); + MSG msg = createMessageBlock(hWnd, message, wParam, lParam); // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/plugins/platforms/windows/qwindowscontext.cpp#L1025 @@ -481,11 +503,13 @@ namespace QWK { // DefWindowProc(). Consequently, we have to add a global native filter that forwards the result // of the hook function, telling Qt whether we have filtered the events before. Since Qt only // handles Windows window messages in the main thread, it is safe to do so. - class WindowsNativeEventFilter : public AppNativeEventFilter { + class WindowsNativeEventFilter final : public AppNativeEventFilter { public: bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override { Q_UNUSED(eventType) + Q_ASSERT(message); + Q_ASSERT(result); // It has been observed that the pointer that Qt gives us is sometimes null on some // machines. We need to guard against it in such scenarios. @@ -500,7 +524,7 @@ namespace QWK { // Qt needs to refer to the WM_NCCALCSIZE message data that hasn't been // processed, so we have to process it after Qt acquires the initial data. if (lastMessageContext) { - LRESULT res; + LRESULT res{ 0 }; if (lastMessageContext->nonClientCalcSizeHandler( msg->hwnd, msg->message, msg->wParam, msg->lParam, &res)) { *result = decltype(*result)(res); @@ -511,8 +535,7 @@ namespace QWK { } // case WM_NCHITTEST: { - // // The child window must return HTTRANSPARENT when processing - // WM_NCHITTEST for + // // The child window must return HTTRANSPARENT when processing WM_NCHITTEST for // // the parent window to receive WM_NCHITTEST. // if (!lastMessageContext) { // auto rootHWnd = ::GetAncestor(msg->hwnd, GA_ROOT); @@ -543,8 +566,7 @@ namespace QWK { if (!instance) { return; } - delete instance; - instance = nullptr; + delete std::exchange(instance, nullptr); } }; @@ -625,7 +647,7 @@ namespace QWK { } // Try hooked procedure and save result - LRESULT result; + LRESULT result{ 0 }; if (ctx->windowProc(hWnd, message, wParam, lParam, &result)) { // https://github.com/stdware/qwindowkit/issues/45 // Forward the event to user-defined native event filters, there may be some messages @@ -640,6 +662,10 @@ namespace QWK { } static inline void addManagedWindow(QWindow *window, HWND hWnd, Win32WindowContext *ctx) { + Q_ASSERT(window); + Q_ASSERT(hWnd); + Q_ASSERT(ctx); + if (isSystemBorderEnabled()) { // Inform Qt we want and have set custom margins setInternalWindowFrameMargins(window, QMargins(0, -int(getTitleBarHeight(hWnd)), 0, 0)); @@ -666,6 +692,8 @@ namespace QWK { } static inline void removeManagedWindow(HWND hWnd) { + Q_ASSERT(hWnd); + // Remove window handle mapping if (!g_wndProcHash->remove(hWnd)) return; @@ -676,8 +704,7 @@ namespace QWK { } } - Win32WindowContext::Win32WindowContext() : AbstractWindowContext() { - } + Win32WindowContext::Win32WindowContext() = default; Win32WindowContext::~Win32WindowContext() { if (m_windowId) { @@ -889,6 +916,9 @@ namespace QWK { bool Win32WindowContext::windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) { + Q_ASSERT(hWnd); + Q_ASSERT(result); + *result = FALSE; // We should skip these messages otherwise we will get crashes. @@ -1171,7 +1201,7 @@ namespace QWK { QWK_USED static constexpr const struct { const WPARAM wParam = MAKEWPARAM(44500, 61897); const LPARAM lParam = MAKELPARAM(62662, 44982); // Not used. Reserve for future use. - } kMessageTag; + } kMessageTag{}; static inline quint64 getKeyState() { quint64 result = 0; @@ -1203,8 +1233,9 @@ namespace QWK { return result; } - static void emulateClientAreaMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, + static inline void emulateClientAreaMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, const std::optional &overrideMessage = std::nullopt) { + Q_ASSERT(hWnd); const int myMsg = overrideMessage.value_or(message); const auto wParamNew = [myMsg, wParam]() -> WPARAM { if (myMsg == WM_NCMOUSELEAVE) { @@ -1303,6 +1334,7 @@ namespace QWK { } static inline void requestForMouseLeaveMessage(HWND hWnd, bool nonClient) { + Q_ASSERT(hWnd); TRACKMOUSEEVENT tme{}; tme.cbSize = sizeof(tme); tme.dwFlags = TME_LEAVE; @@ -1316,6 +1348,8 @@ namespace QWK { bool Win32WindowContext::snapLayoutHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) { + Q_ASSERT(hWnd); + Q_ASSERT(result); switch (message) { case WM_MOUSELEAVE: { if (wParam != kMessageTag.wParam) { @@ -1533,6 +1567,8 @@ namespace QWK { bool Win32WindowContext::customWindowHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) { + Q_ASSERT(hWnd); + Q_ASSERT(result); switch (message) { case WM_NCHITTEST: { // 原生Win32窗口只有顶边是在窗口内部resize的,其余三边都是在窗口 @@ -1616,7 +1652,7 @@ namespace QWK { // color, our homemade top border can almost have exactly the same // appearance with the system's one. [[maybe_unused]] const auto &hitTestRecorder = qScopeGuard([this, result]() { - lastHitTestResultRaw = int(*result); + lastHitTestResultRaw = static_cast(*result); lastHitTestResult = getHitWindowPart(lastHitTestResultRaw); }); @@ -1943,6 +1979,15 @@ namespace QWK { if (!wParam || !isWindowNoState(hWnd) || isFullScreen(hWnd)) { break; } + // The following code is totally a workaround. We should remove it as soon as possible. + // For windows painted by D3D (such as QtQuick windows), when it is first shown, there + // will always be a strange white line on the top, and it will always disappear when we + // resize the window. It seems to be some kind of leftover of the original window frame. + // So here we manually resize the window and restore it immediately to workaround this + // issue. Due to we only enlarge the window for 1x1 and restore it immediately, the user + // won't see this change in reality, but the strange white line is indeed gone. + // Anyway, this is still a non-sense workaround, no one can guarantee it will always work + // and won't break anything. RECT windowRect{}; ::GetWindowRect(hWnd, &windowRect); static constexpr const auto swpFlags = SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | @@ -2019,6 +2064,9 @@ namespace QWK { bool Win32WindowContext::nonClientCalcSizeHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) { + Q_ASSERT(hWnd); + Q_ASSERT(result); + Q_UNUSED(message) Q_UNUSED(this) @@ -2110,7 +2158,20 @@ namespace QWK { const auto clientRect = wParam ? &(reinterpret_cast(lParam))->rgrc[0] : reinterpret_cast(lParam); + // This is a workaround for the resize flicker when the window is painting by D3D or Vulkan. + // (OpenGL doesn't flicker at all so we skip it to avoid strange things from happening) + // According to my local experiments, it can greatly reduce the resize flicker if you disable + // QtQuick's V-Sync. I tested the same binary on 60Hz/120Hz/144Hz/240Hz monitors, and the + // conclusion is: for monitors whose refresh rate is greater than 60Hz, the flicker can be + // greatly reduced but cannot be totally gone, for monitors whose refresh rate is equal to + // or less than 60Hz, the flicker is totally gone. + // NOTE: The application's V-Sync MUST be DISABLED to let this trick work! [[maybe_unused]] const auto &flickerReducer = qScopeGuard([this]() { + // The user might doesn't want this, allow disable it. + static const bool disableThis = qEnvironmentVariableIntValue("QWK_DISABLE_FLICKER_WORKAROUND"); + if (disableThis) { + return; + } // When we receive this message, it means the window size has changed // already, and it seems this message always come before any client // area size notifications (eg. WM_WINDOWPOSCHANGED and WM_SIZE). Let @@ -2265,6 +2326,8 @@ namespace QWK { bool Win32WindowContext::systemMenuHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) { + Q_ASSERT(hWnd); + Q_ASSERT(result); const auto getNativePosFromMouse = [lParam]() -> POINT { return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; }; diff --git a/src/core/contexts/win32windowcontext_p.h b/src/core/contexts/win32windowcontext_p.h index c41fd77..44fffd7 100644 --- a/src/core/contexts/win32windowcontext_p.h +++ b/src/core/contexts/win32windowcontext_p.h @@ -19,7 +19,7 @@ namespace QWK { - class Win32WindowContext : public AbstractWindowContext { + class QWK_CORE_EXPORT Win32WindowContext final : public AbstractWindowContext { Q_OBJECT public: Win32WindowContext(); diff --git a/src/core/kernel/nativeeventfilter.cpp b/src/core/kernel/nativeeventfilter.cpp index 27c29d9..8fd7977 100644 --- a/src/core/kernel/nativeeventfilter.cpp +++ b/src/core/kernel/nativeeventfilter.cpp @@ -9,8 +9,7 @@ namespace QWK { - NativeEventFilter::NativeEventFilter() : m_nativeDispatcher(nullptr) { - } + NativeEventFilter::NativeEventFilter() = default; NativeEventFilter::~NativeEventFilter() { if (m_nativeDispatcher) @@ -21,13 +20,17 @@ namespace QWK { NativeEventDispatcher::~NativeEventDispatcher() { for (const auto &observer : std::as_const(m_nativeEventFilters)) { + Q_ASSERT(observer); observer->m_nativeDispatcher = nullptr; } } bool NativeEventDispatcher::nativeDispatch(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) { + Q_ASSERT(message); + Q_ASSERT(result); for (const auto &ef : std::as_const(m_nativeEventFilters)) { + Q_ASSERT(ef); if (ef->nativeEventFilter(eventType, message, result)) return true; } @@ -35,6 +38,7 @@ namespace QWK { } void NativeEventDispatcher::installNativeEventFilter(NativeEventFilter *filter) { + Q_ASSERT(filter); if (!filter || filter->m_nativeDispatcher) return; @@ -43,6 +47,7 @@ namespace QWK { } void NativeEventDispatcher::removeNativeEventFilter(NativeEventFilter *filter) { + Q_ASSERT(filter); if (!m_nativeEventFilters.removeOne(filter)) { return; } @@ -52,7 +57,7 @@ namespace QWK { // Avoid adding multiple global native event filters to QGuiApplication // in this library. - class AppMasterNativeEventFilter : public QAbstractNativeEventFilter, + class AppMasterNativeEventFilter final : public QAbstractNativeEventFilter, public NativeEventDispatcher { public: AppMasterNativeEventFilter() { @@ -64,6 +69,8 @@ namespace QWK { bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override { + Q_ASSERT(message); + Q_ASSERT(result); return nativeDispatch(eventType, message, result); } @@ -82,8 +89,7 @@ namespace QWK { AppNativeEventFilter::~AppNativeEventFilter() { AppMasterNativeEventFilter::instance->removeNativeEventFilter(this); if (AppMasterNativeEventFilter::instance->m_nativeEventFilters.isEmpty()) { - delete AppMasterNativeEventFilter::instance; - AppMasterNativeEventFilter::instance = nullptr; + delete std::exchange(AppMasterNativeEventFilter::instance, nullptr); } } diff --git a/src/core/kernel/nativeeventfilter_p.h b/src/core/kernel/nativeeventfilter_p.h index d7d3e3f..9aa705c 100644 --- a/src/core/kernel/nativeeventfilter_p.h +++ b/src/core/kernel/nativeeventfilter_p.h @@ -51,7 +51,7 @@ namespace QWK { QT_NATIVE_EVENT_RESULT_TYPE *result) = 0; protected: - NativeEventDispatcher *m_nativeDispatcher; + NativeEventDispatcher *m_nativeDispatcher = nullptr; friend class NativeEventDispatcher; diff --git a/src/core/kernel/sharedeventfilter.cpp b/src/core/kernel/sharedeventfilter.cpp index f57a626..c99298a 100644 --- a/src/core/kernel/sharedeventfilter.cpp +++ b/src/core/kernel/sharedeventfilter.cpp @@ -6,8 +6,7 @@ namespace QWK { - SharedEventFilter::SharedEventFilter() : m_sharedDispatcher(nullptr) { - } + SharedEventFilter::SharedEventFilter() = default; SharedEventFilter::~SharedEventFilter() { if (m_sharedDispatcher) @@ -18,12 +17,16 @@ namespace QWK { SharedEventDispatcher::~SharedEventDispatcher() { for (const auto &observer : std::as_const(m_sharedEventFilters)) { + Q_ASSERT(observer); observer->m_sharedDispatcher = nullptr; } } bool SharedEventDispatcher::sharedDispatch(QObject *obj, QEvent *event) { + Q_ASSERT(obj); + Q_ASSERT(event); for (const auto &ef : std::as_const(m_sharedEventFilters)) { + Q_ASSERT(ef); if (ef->sharedEventFilter(obj, event)) return true; } @@ -31,6 +34,7 @@ namespace QWK { } void SharedEventDispatcher::installSharedEventFilter(SharedEventFilter *filter) { + Q_ASSERT(filter); if (!filter || filter->m_sharedDispatcher) return; @@ -39,6 +43,7 @@ namespace QWK { } void SharedEventDispatcher::removeSharedEventFilter(SharedEventFilter *filter) { + Q_ASSERT(filter); if (!m_sharedEventFilters.removeOne(filter)) { return; } diff --git a/src/core/kernel/sharedeventfilter_p.h b/src/core/kernel/sharedeventfilter_p.h index 5c1935b..7348c5c 100644 --- a/src/core/kernel/sharedeventfilter_p.h +++ b/src/core/kernel/sharedeventfilter_p.h @@ -49,7 +49,7 @@ namespace QWK { virtual bool sharedEventFilter(QObject *obj, QEvent *event) = 0; protected: - SharedEventDispatcher *m_sharedDispatcher; + SharedEventDispatcher *m_sharedDispatcher = nullptr; friend class SharedEventDispatcher; diff --git a/src/core/kernel/winidchangeeventfilter.cpp b/src/core/kernel/winidchangeeventfilter.cpp index 4d60d74..583f732 100644 --- a/src/core/kernel/winidchangeeventfilter.cpp +++ b/src/core/kernel/winidchangeeventfilter.cpp @@ -12,20 +12,24 @@ namespace QWK { WindowWinIdChangeEventFilter::WindowWinIdChangeEventFilter(QWindow *host, AbstractWindowContext *context) - : WinIdChangeEventFilter(host, context), win(host), isAboutToBeDestroyed(false) { + : WinIdChangeEventFilter(host, context), win(host) { + Q_ASSERT(host); + Q_ASSERT(context); host->installEventFilter(this); } WId WindowWinIdChangeEventFilter::winId() const { - auto win = static_cast(host); if (isAboutToBeDestroyed) return 0; + auto win = static_cast(host); if (auto platformWindow = win->handle()) return platformWindow->winId(); return 0; } bool WindowWinIdChangeEventFilter::eventFilter(QObject *obj, QEvent *event) { + Q_ASSERT(obj); + Q_ASSERT(event); Q_UNUSED(obj) if (event->type() == QEvent::PlatformSurface) { auto e = static_cast(event); diff --git a/src/core/kernel/winidchangeeventfilter_p.h b/src/core/kernel/winidchangeeventfilter_p.h index fc1b732..3c40ac7 100644 --- a/src/core/kernel/winidchangeeventfilter_p.h +++ b/src/core/kernel/winidchangeeventfilter_p.h @@ -22,28 +22,32 @@ namespace QWK { class AbstractWindowContext; - class WinIdChangeEventFilter : public QObject { + class QWK_CORE_EXPORT WinIdChangeEventFilter : public QObject { + Q_OBJECT public: - WinIdChangeEventFilter(QObject *host, AbstractWindowContext *context) + inline WinIdChangeEventFilter(QObject *host, AbstractWindowContext *context) : host(host), context(context) { + Q_ASSERT(host); + Q_ASSERT(context); } virtual WId winId() const = 0; protected: - QObject *host; - AbstractWindowContext *context; + QObject *host = nullptr; + AbstractWindowContext *context = nullptr; }; - class QWK_CORE_EXPORT WindowWinIdChangeEventFilter : public WinIdChangeEventFilter { + class QWK_CORE_EXPORT WindowWinIdChangeEventFilter final : public WinIdChangeEventFilter { + Q_OBJECT public: WindowWinIdChangeEventFilter(QWindow *host, AbstractWindowContext *context); WId winId() const override; protected: - QWindow *win; - bool isAboutToBeDestroyed; + QWindow *win = nullptr; + bool isAboutToBeDestroyed = false; bool eventFilter(QObject *obj, QEvent *event) override; }; diff --git a/src/core/qwindowkit_windows.cpp b/src/core/qwindowkit_windows.cpp index 41b3500..6cabb5f 100644 --- a/src/core/qwindowkit_windows.cpp +++ b/src/core/qwindowkit_windows.cpp @@ -8,7 +8,7 @@ using QWK_NTSTATUS = long; namespace QWK { - static QWK_OSVERSIONINFOW GetRealOSVersionImpl() { + static inline QWK_OSVERSIONINFOW GetRealOSVersionImpl() { HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll"); Q_ASSERT(hMod); using RtlGetVersionPtr = QWK_NTSTATUS(WINAPI *)(QWK_OSVERSIONINFOW*); @@ -45,17 +45,16 @@ namespace QWK { void WindowsRegistryKey::close() { if (isValid()) { - ::RegCloseKey(m_key); - m_key = nullptr; + ::RegCloseKey(std::exchange(m_key, nullptr)); } } QString WindowsRegistryKey::stringValue(QStringView subKey) const { - QString result; + QString result{}; if (!isValid()) return result; - DWORD type; - DWORD size; + DWORD type{ 0 }; + DWORD size{ 0 }; auto subKeyC = reinterpret_cast(subKey.utf16()); if (::RegQueryValueExW(m_key, subKeyC, nullptr, &type, nullptr, &size) != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ) || size <= 2) { @@ -76,7 +75,7 @@ namespace QWK { std::pair WindowsRegistryKey::dwordValue(QStringView subKey) const { if (!isValid()) return std::make_pair(0, false); - DWORD type; + DWORD type{ 0 }; auto subKeyC = reinterpret_cast(subKey.utf16()); if (::RegQueryValueExW(m_key, subKeyC, nullptr, &type, nullptr, nullptr) != ERROR_SUCCESS || type != REG_DWORD) { diff --git a/src/core/qwindowkit_windows.h b/src/core/qwindowkit_windows.h index e20a035..ec53aff 100644 --- a/src/core/qwindowkit_windows.h +++ b/src/core/qwindowkit_windows.h @@ -151,21 +151,21 @@ namespace QWK { // #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) - class QWK_CORE_EXPORT WindowsRegistryKey { + class QWK_CORE_EXPORT WindowsRegistryKey final { public: WindowsRegistryKey(HKEY parentHandle, QStringView subKey, REGSAM permissions = KEY_READ, REGSAM access = 0); ~WindowsRegistryKey(); - bool isValid() const; + inline bool isValid() const; void close(); QString stringValue(QStringView subKey) const; std::pair dwordValue(QStringView subKey) const; private: - HKEY m_key; + HKEY m_key = nullptr; Q_DISABLE_COPY(WindowsRegistryKey) }; @@ -176,14 +176,14 @@ namespace QWK { #elif QT_VERSION < QT_VERSION_CHECK(6, 8, 1) using WindowsRegistryKey = QWinRegistryKey; #else - class WindowsRegistryKey : public QWinRegistryKey { + class QWK_CORE_EXPORT WindowsRegistryKey final : public QWinRegistryKey { #if QT_VERSION >= QT_VERSION_CHECK(6, 10, 1) using SubKeyType = const wchar_t*; #else using SubKeyType = QStringView; #endif public: - WindowsRegistryKey(HKEY parentHandle, SubKeyType subKey, + inline WindowsRegistryKey(HKEY parentHandle, SubKeyType subKey, REGSAM permissions = KEY_READ, REGSAM access = 0) : QWinRegistryKey(parentHandle, subKey, permissions, access) { } diff --git a/src/core/qwkglobal.cpp b/src/core/qwkglobal.cpp index 8a8df40..43cfb68 100644 --- a/src/core/qwkglobal.cpp +++ b/src/core/qwkglobal.cpp @@ -11,6 +11,9 @@ namespace QWK { bool forwardObjectEventFilters(QObject *currentFilter, QObject *receiver, QEvent *event) { + Q_ASSERT(currentFilter); + Q_ASSERT(receiver); + Q_ASSERT(event); // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/corelib/kernel/qcoreapplication.cpp#L1244 // Send the event through the rest event filters auto d = QObjectPrivate::get(receiver); diff --git a/src/core/qwkglobal_p.h b/src/core/qwkglobal_p.h index 57b499f..d5cfe53 100644 --- a/src/core/qwkglobal_p.h +++ b/src/core/qwkglobal_p.h @@ -48,6 +48,7 @@ QWK_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(qWindowKitLog) namespace QWK { inline QPoint getMouseEventScenePos(const QMouseEvent *event) { + Q_ASSERT(event); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) return event->scenePosition().toPoint(); #else @@ -56,6 +57,7 @@ namespace QWK { } inline QPoint getMouseEventGlobalPos(const QMouseEvent *event) { + Q_ASSERT(event); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) return event->globalPosition().toPoint(); #else diff --git a/src/core/shared/qwkwindowsextra_p.h b/src/core/shared/qwkwindowsextra_p.h index a173be9..f791a1e 100644 --- a/src/core/shared/qwkwindowsextra_p.h +++ b/src/core/shared/qwkwindowsextra_p.h @@ -193,7 +193,7 @@ namespace QWK { struct DynamicApis { static inline const DynamicApis &instance() { - static const DynamicApis inst; + static const DynamicApis inst{}; return inst; } @@ -342,8 +342,10 @@ namespace QWK { } inline /*constexpr*/ QString hwnd2str(const WId windowId) { - // NULL handle is allowed here. - return QLatin1String("0x") + + if (!windowId) { + return QStringLiteral("0x00000000"); + } + return QStringLiteral("0x") + QString::number(windowId, 16).toUpper().rightJustified(8, u'0'); } @@ -404,6 +406,7 @@ namespace QWK { } inline bool isDarkWindowFrameEnabled(HWND hwnd) { + Q_ASSERT(hwnd); if (!isWin101809OrGreater()) { return false; } @@ -438,6 +441,7 @@ namespace QWK { } inline quint32 getDpiForWindow(HWND hwnd) { + Q_ASSERT(hwnd); const DynamicApis &apis = DynamicApis::instance(); if (apis.pGetDpiForWindow) { // Win10 return apis.pGetDpiForWindow(hwnd); @@ -472,6 +476,7 @@ namespace QWK { } inline quint32 getWindowFrameBorderThickness(HWND hwnd) { + Q_ASSERT(hwnd); const DynamicApis &apis = DynamicApis::instance(); if (isWin11OrGreater()) { UINT result = 0; @@ -490,6 +495,7 @@ namespace QWK { } inline quint32 getResizeBorderThickness(HWND hwnd) { + Q_ASSERT(hwnd); const quint32 dpi = getDpiForWindow(hwnd); // When DPI is 96, SM_CXSIZEFRAME is 4px, SM_CXPADDEDBORDER is also 4px, // so the result should be 8px. This result won't be affected by OS version, @@ -499,6 +505,7 @@ namespace QWK { } inline quint32 getTitleBarHeight(HWND hwnd) { + Q_ASSERT(hwnd); const quint32 dpi = getDpiForWindow(hwnd); // When DPI is 96, SM_CYCAPTION is 23px, so the result should be 31px. // However, according to latest MS design manual, the title bar height diff --git a/src/core/shared/systemwindow_p.h b/src/core/shared/systemwindow_p.h index d7daf58..c6abc55 100644 --- a/src/core/shared/systemwindow_p.h +++ b/src/core/shared/systemwindow_p.h @@ -21,10 +21,12 @@ namespace QWK { - class WindowMoveManipulator : public QObject { + class QWK_CORE_EXPORT WindowMoveManipulator final : public QObject { + Q_OBJECT public: - explicit WindowMoveManipulator(QWindow *targetWindow) - : QObject(targetWindow), target(targetWindow), operationComplete(false), + WindowMoveManipulator(QWindow *targetWindow) + : QObject(targetWindow), + target(targetWindow), initialMousePosition(QCursor::pos()), initialWindowPosition(targetWindow->position()) { target->installEventFilter(this); @@ -59,17 +61,20 @@ namespace QWK { } private: - QWindow *target; - bool operationComplete; - QPoint initialMousePosition; - QPoint initialWindowPosition; + QWindow *target = nullptr; + bool operationComplete = false; + QPoint initialMousePosition{}; + QPoint initialWindowPosition{}; }; - class WindowResizeManipulator : public QObject { + class QWK_CORE_EXPORT WindowResizeManipulator final : public QObject { + Q_OBJECT public: WindowResizeManipulator(QWindow *targetWindow, Qt::Edges edges) - : QObject(targetWindow), target(targetWindow), operationComplete(false), - initialMousePosition(QCursor::pos()), initialWindowRect(target->geometry()), + : QObject(targetWindow), + target(targetWindow), + initialMousePosition(QCursor::pos()), + initialWindowRect(target->geometry()), resizeEdges(edges) { target->installEventFilter(this); } @@ -119,11 +124,11 @@ namespace QWK { } private: - QWindow *target; - bool operationComplete; - QPoint initialMousePosition; - QRect initialWindowRect; - Qt::Edges resizeEdges; + QWindow *target = nullptr; + bool operationComplete = false; + QPoint initialMousePosition{}; + QRect initialWindowRect{}; + Qt::Edges resizeEdges{}; }; // QWindow::startSystemMove() and QWindow::startSystemResize() is first supported at Qt 5.15 @@ -133,6 +138,7 @@ namespace QWK { // When the new API fails, we emulate the window actions using the classical API. inline void startSystemMove(QWindow *window) { + Q_ASSERT(window); #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) std::ignore = new WindowMoveManipulator(window); #elif defined(Q_OS_LINUX) @@ -146,6 +152,7 @@ namespace QWK { } inline void startSystemResize(QWindow *window, Qt::Edges edges) { + Q_ASSERT(window); #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) std::ignore = new WindowResizeManipulator(window, edges); #elif defined(Q_OS_MAC) || defined(Q_OS_LINUX) diff --git a/src/core/shared/windows10borderhandler_p.h b/src/core/shared/windows10borderhandler_p.h index 8f728f4..84f4451 100644 --- a/src/core/shared/windows10borderhandler_p.h +++ b/src/core/shared/windows10borderhandler_p.h @@ -89,12 +89,12 @@ namespace QWK { virtual void updateGeometry() = 0; - virtual bool isWindowActive() const { + inline virtual bool isWindowActive() const { return ctx->window()->isActive(); } protected: - bool nativeEventFilter(const QByteArray &eventType, void *message, + inline bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override { Q_UNUSED(eventType) @@ -131,7 +131,7 @@ namespace QWK { return false; } - bool sharedEventFilter(QObject *obj, QEvent *event) override { + inline bool sharedEventFilter(QObject *obj, QEvent *event) override { Q_UNUSED(obj) if (event->type() == QEvent::WinIdChange) { @@ -144,7 +144,7 @@ namespace QWK { } protected: - AbstractWindowContext *ctx; + AbstractWindowContext *ctx = nullptr; }; } diff --git a/src/core/style/styleagent.cpp b/src/core/style/styleagent.cpp index 78d3886..8f07c3e 100644 --- a/src/core/style/styleagent.cpp +++ b/src/core/style/styleagent.cpp @@ -16,8 +16,7 @@ namespace QWK { you don't include this class in your build system. */ - StyleAgentPrivate::StyleAgentPrivate() { - } + StyleAgentPrivate::StyleAgentPrivate() = default; StyleAgentPrivate::~StyleAgentPrivate() { removeSystemThemeHook(); @@ -56,8 +55,7 @@ namespace QWK { /*! Destructor. */ - StyleAgent::~StyleAgent() { - } + StyleAgent::~StyleAgent() = default; /*! Returns the system theme. diff --git a/src/core/style/styleagent.h b/src/core/style/styleagent.h index 49b298e..5c4be10 100644 --- a/src/core/style/styleagent.h +++ b/src/core/style/styleagent.h @@ -16,7 +16,7 @@ namespace QWK { class StyleAgentPrivate; - class QWK_CORE_EXPORT StyleAgent : public QObject { + class QWK_CORE_EXPORT StyleAgent final : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(StyleAgent) public: diff --git a/src/core/style/styleagent_p.h b/src/core/style/styleagent_p.h index 40e903f..efcbe31 100644 --- a/src/core/style/styleagent_p.h +++ b/src/core/style/styleagent_p.h @@ -18,18 +18,18 @@ namespace QWK { - class StyleAgentPrivate : public QObject { + class QWK_CORE_EXPORT StyleAgentPrivate final { Q_DECLARE_PUBLIC(StyleAgent) public: StyleAgentPrivate(); - ~StyleAgentPrivate() override; + ~StyleAgentPrivate(); void init(); - StyleAgent *q_ptr; + StyleAgent *q_ptr{ nullptr }; StyleAgent::SystemTheme systemTheme = StyleAgent::Unknown; - QColor systemAccentColor; + QColor systemAccentColor{}; void setupSystemThemeHook(); void removeSystemThemeHook(); diff --git a/src/core/style/styleagent_win.cpp b/src/core/style/styleagent_win.cpp index ab290dc..d1f99d4 100644 --- a/src/core/style/styleagent_win.cpp +++ b/src/core/style/styleagent_win.cpp @@ -14,7 +14,7 @@ namespace QWK { using StyleAgentSet = QSet; Q_GLOBAL_STATIC(StyleAgentSet, g_styleAgentSet) - static StyleAgent::SystemTheme getSystemTheme() { + static inline StyleAgent::SystemTheme getSystemTheme() { if (isHighContrastModeEnabled()) { return StyleAgent::HighContrast; } else if (isDarkThemeActive()) { @@ -24,21 +24,24 @@ namespace QWK { } } - static void notifyAllStyleAgents() { + static inline void notifyAllStyleAgents() { auto theme = getSystemTheme(); auto color = getAccentColor(); for (auto &&ap : std::as_const(*g_styleAgentSet())) { + Q_ASSERT(ap); ap->notifyThemeChanged(theme); ap->notifyAccentColorChanged(color); } } - class SystemSettingEventFilter : public AppNativeEventFilter { + class SystemSettingEventFilter final : public AppNativeEventFilter { public: bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override { Q_UNUSED(eventType) - if (!result) { + Q_ASSERT(message); + Q_ASSERT(result); + if (!message || !result) { return false; } @@ -77,8 +80,7 @@ namespace QWK { if (!instance) { return; } - delete instance; - instance = nullptr; + delete std::exchange(instance, nullptr); } }; diff --git a/src/core/windowagentbase.cpp b/src/core/windowagentbase.cpp index 4db16a3..6044d1a 100644 --- a/src/core/windowagentbase.cpp +++ b/src/core/windowagentbase.cpp @@ -38,11 +38,7 @@ namespace QWK { shared methods for derived classes to call. */ - WindowAgentBasePrivate::WindowContextFactoryMethod - WindowAgentBasePrivate::windowContextFactoryMethod = nullptr; - - WindowAgentBasePrivate::WindowAgentBasePrivate() : q_ptr(nullptr), context(nullptr) { - } + WindowAgentBasePrivate::WindowAgentBasePrivate() = default; WindowAgentBasePrivate::~WindowAgentBasePrivate() = default; @@ -74,8 +70,10 @@ namespace QWK { } void WindowAgentBasePrivate::setup(QObject *host, WindowItemDelegate *delegate) { + Q_ASSERT(host); + Q_ASSERT(delegate); auto ctx = createContext(); - ctx->setup(host, delegate); + ctx->setup(host, delegate, q_ptr); context.reset(ctx); } diff --git a/src/core/windowagentbase.h b/src/core/windowagentbase.h index 5b25528..faba57e 100644 --- a/src/core/windowagentbase.h +++ b/src/core/windowagentbase.h @@ -35,12 +35,12 @@ namespace QWK { Q_INVOKABLE bool setWindowAttribute(const QString &key, const QVariant &attribute); public Q_SLOTS: - void showSystemMenu(const QPoint &pos); // Only available on Windows now + void showSystemMenu(const QPoint &pos); // Not available on macOS. void centralize(); void raise(); protected: - explicit WindowAgentBase(WindowAgentBasePrivate &d, QObject *parent = nullptr); + WindowAgentBase(WindowAgentBasePrivate &d, QObject *parent = nullptr); const std::unique_ptr d_ptr; }; diff --git a/src/core/windowagentbase_p.h b/src/core/windowagentbase_p.h index e7b67ec..7c94c37 100644 --- a/src/core/windowagentbase_p.h +++ b/src/core/windowagentbase_p.h @@ -27,7 +27,7 @@ namespace QWK { void init(); - WindowAgentBase *q_ptr; // no need to initialize + WindowAgentBase *q_ptr{ nullptr }; virtual AbstractWindowContext *createContext() const; @@ -38,7 +38,7 @@ namespace QWK { public: using WindowContextFactoryMethod = AbstractWindowContext *(*) (); - static WindowContextFactoryMethod windowContextFactoryMethod; + static inline WindowContextFactoryMethod windowContextFactoryMethod = nullptr; private: Q_DISABLE_COPY(WindowAgentBasePrivate) diff --git a/src/core/windowitemdelegate.cpp b/src/core/windowitemdelegate.cpp index fd8a88e..fd84450 100644 --- a/src/core/windowitemdelegate.cpp +++ b/src/core/windowitemdelegate.cpp @@ -17,6 +17,8 @@ namespace QWK { WinIdChangeEventFilter * WindowItemDelegate::createWinIdEventFilter(QObject *host, AbstractWindowContext *context) const { + Q_ASSERT(host); + Q_ASSERT(context); return new WindowWinIdChangeEventFilter(static_cast(host), context); } diff --git a/src/quick/quickitemdelegate.cpp b/src/quick/quickitemdelegate.cpp index b63345e..484df5c 100644 --- a/src/quick/quickitemdelegate.cpp +++ b/src/quick/quickitemdelegate.cpp @@ -9,24 +9,27 @@ namespace QWK { - QuickItemDelegate::QuickItemDelegate() : WindowItemDelegate() { - } + QuickItemDelegate::QuickItemDelegate() = default; QuickItemDelegate::~QuickItemDelegate() = default; QWindow *QuickItemDelegate::window(const QObject *obj) const { + Q_ASSERT(obj); return static_cast(obj)->window(); } bool QuickItemDelegate::isEnabled(const QObject *obj) const { + Q_ASSERT(obj); return static_cast(obj)->isEnabled(); } bool QuickItemDelegate::isVisible(const QObject *obj) const { + Q_ASSERT(obj); return static_cast(obj)->isVisible(); } QRect QuickItemDelegate::mapGeometryToScene(const QObject *obj) const { + Q_ASSERT(obj); auto item = static_cast(obj); const QPointF originPoint = item->mapToScene(QPointF(0.0, 0.0)); const QSizeF size = item->size(); @@ -34,50 +37,62 @@ namespace QWK { } QWindow *QuickItemDelegate::hostWindow(const QObject *host) const { + Q_ASSERT(host); return static_cast(const_cast(host)); } bool QuickItemDelegate::isWindowActive(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->isActive(); } Qt::WindowStates QuickItemDelegate::getWindowState(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->windowStates(); } void QuickItemDelegate::setWindowState(QObject *host, Qt::WindowStates state) const { + Q_ASSERT(host); static_cast(host)->setWindowStates(state); } void QuickItemDelegate::setCursorShape(QObject *host, const Qt::CursorShape shape) const { + Q_ASSERT(host); static_cast(host)->setCursor(QCursor(shape)); } void QuickItemDelegate::restoreCursorShape(QObject *host) const { + Q_ASSERT(host); static_cast(host)->unsetCursor(); } Qt::WindowFlags QuickItemDelegate::getWindowFlags(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->flags(); } QRect QuickItemDelegate::getGeometry(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->geometry(); } void QuickItemDelegate::setWindowFlags(QObject *host, Qt::WindowFlags flags) const { + Q_ASSERT(host); static_cast(host)->setFlags(flags); } void QuickItemDelegate::setWindowVisible(QObject *host, bool visible) const { + Q_ASSERT(host); static_cast(host)->setVisible(visible); } void QuickItemDelegate::setGeometry(QObject *host, const QRect &rect) { + Q_ASSERT(host); static_cast(host)->setGeometry(rect); } void QuickItemDelegate::bringWindowToTop(QObject *host) const { + Q_ASSERT(host); static_cast(host)->raise(); } diff --git a/src/quick/quickitemdelegate_p.h b/src/quick/quickitemdelegate_p.h index c3666b5..57a6e33 100644 --- a/src/quick/quickitemdelegate_p.h +++ b/src/quick/quickitemdelegate_p.h @@ -22,7 +22,7 @@ namespace QWK { - class QWK_QUICK_EXPORT QuickItemDelegate : public WindowItemDelegate { + class QWK_QUICK_EXPORT QuickItemDelegate final : public WindowItemDelegate { public: QuickItemDelegate(); ~QuickItemDelegate() override; diff --git a/src/quick/quickwindowagent_mac.cpp b/src/quick/quickwindowagent_mac.cpp index c7a822e..a55bfc3 100644 --- a/src/quick/quickwindowagent_mac.cpp +++ b/src/quick/quickwindowagent_mac.cpp @@ -6,7 +6,8 @@ namespace QWK { - class SystemButtonAreaItemHandler : public QObject { + class SystemButtonAreaItemHandler final : public QObject { + Q_OBJECT public: SystemButtonAreaItemHandler(QQuickItem *item, AbstractWindowContext *ctx, QObject *parent = nullptr); @@ -15,8 +16,8 @@ namespace QWK { void updateSystemButtonArea(); protected: - QQuickItem *item; - AbstractWindowContext *ctx; + QQuickItem *item = nullptr; + AbstractWindowContext *ctx = nullptr; }; SystemButtonAreaItemHandler::SystemButtonAreaItemHandler(QQuickItem *item, @@ -73,3 +74,5 @@ namespace QWK { } } + +#include "quickwindowagent_mac.moc" diff --git a/src/quick/quickwindowagent_p.h b/src/quick/quickwindowagent_p.h index ec0042d..d5d1462 100644 --- a/src/quick/quickwindowagent_p.h +++ b/src/quick/quickwindowagent_p.h @@ -20,7 +20,7 @@ namespace QWK { - class QuickWindowAgentPrivate : public WindowAgentBasePrivate { + class QWK_QUICK_EXPORT QuickWindowAgentPrivate final : public WindowAgentBasePrivate { Q_DECLARE_PUBLIC(QuickWindowAgent) public: QuickWindowAgentPrivate(); @@ -29,10 +29,10 @@ namespace QWK { void init(); // Host - QQuickWindow *hostWindow{}; + QQuickWindow *hostWindow{ nullptr }; #ifdef Q_OS_MAC - QQuickItem *systemButtonAreaItem{}; + QQuickItem *systemButtonAreaItem{ nullptr }; std::unique_ptr systemButtonAreaItemHandler; #endif diff --git a/src/quick/quickwindowagent_win.cpp b/src/quick/quickwindowagent_win.cpp index e098bac..ba4c3f2 100644 --- a/src/quick/quickwindowagent_win.cpp +++ b/src/quick/quickwindowagent_win.cpp @@ -21,9 +21,9 @@ namespace QWK { #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDERS) - class BorderItem : public QQuickPaintedItem, public Windows10BorderHandler { + class BorderItem final : public QQuickPaintedItem, public Windows10BorderHandler { public: - explicit BorderItem(QQuickItem *parent, AbstractWindowContext *context); + BorderItem(QQuickItem *parent, AbstractWindowContext *context); ~BorderItem() override; bool shouldEnableEmulatedPainter() const; diff --git a/src/widgets/widgetitemdelegate.cpp b/src/widgets/widgetitemdelegate.cpp index 19d103b..1f3de15 100644 --- a/src/widgets/widgetitemdelegate.cpp +++ b/src/widgets/widgetitemdelegate.cpp @@ -14,9 +14,9 @@ extern Q_DECL_IMPORT QWidget *qt_button_down; namespace QWK { - class WidgetWinIdChangeEventFilter : public WinIdChangeEventFilter { + class WidgetWinIdChangeEventFilter final : public WinIdChangeEventFilter { public: - explicit WidgetWinIdChangeEventFilter(QObject *host, AbstractWindowContext *ctx) + WidgetWinIdChangeEventFilter(QObject *host, AbstractWindowContext *ctx) : WinIdChangeEventFilter(host, ctx), widget(static_cast(host)) { widget->installEventFilter(this); } @@ -27,6 +27,8 @@ namespace QWK { protected: bool eventFilter(QObject *obj, QEvent *event) override { + Q_ASSERT(obj); + Q_ASSERT(event); Q_UNUSED(obj) if (event->type() == QEvent::WinIdChange) { context->notifyWinIdChange(); @@ -34,7 +36,7 @@ namespace QWK { return false; } - QWidget *widget; + QWidget *widget = nullptr; }; WidgetItemDelegate::WidgetItemDelegate() = default; @@ -42,18 +44,22 @@ namespace QWK { WidgetItemDelegate::~WidgetItemDelegate() = default; QWindow *WidgetItemDelegate::window(const QObject *obj) const { + Q_ASSERT(obj); return static_cast(obj)->windowHandle(); } bool WidgetItemDelegate::isEnabled(const QObject *obj) const { + Q_ASSERT(obj); return static_cast(obj)->isEnabled(); } bool WidgetItemDelegate::isVisible(const QObject *obj) const { + Q_ASSERT(obj); return static_cast(obj)->isVisible(); } QRect WidgetItemDelegate::mapGeometryToScene(const QObject *obj) const { + Q_ASSERT(obj); auto widget = static_cast(obj); const QPoint originPoint = widget->mapTo(widget->window(), QPoint(0, 0)); const QSize size = widget->size(); @@ -61,14 +67,17 @@ namespace QWK { } QWindow *WidgetItemDelegate::hostWindow(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->windowHandle(); } bool WidgetItemDelegate::isWindowActive(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->isActiveWindow(); } void WidgetItemDelegate::resetQtGrabbedControl(QObject *host) const { + Q_ASSERT(host); Q_UNUSED(host); if (!qt_button_down) { return; @@ -83,48 +92,60 @@ namespace QWK { } Qt::WindowStates WidgetItemDelegate::getWindowState(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->windowState(); } void WidgetItemDelegate::setWindowState(QObject *host, Qt::WindowStates state) const { + Q_ASSERT(host); static_cast(host)->setWindowState(state); } void WidgetItemDelegate::setCursorShape(QObject *host, Qt::CursorShape shape) const { + Q_ASSERT(host); static_cast(host)->setCursor(QCursor(shape)); } void WidgetItemDelegate::restoreCursorShape(QObject *host) const { + Q_ASSERT(host); static_cast(host)->unsetCursor(); } Qt::WindowFlags WidgetItemDelegate::getWindowFlags(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->windowFlags(); } QRect WidgetItemDelegate::getGeometry(const QObject *host) const { + Q_ASSERT(host); return static_cast(host)->geometry(); } void WidgetItemDelegate::setWindowFlags(QObject *host, Qt::WindowFlags flags) const { + Q_ASSERT(host); static_cast(host)->setWindowFlags(flags); } void WidgetItemDelegate::setWindowVisible(QObject *host, bool visible) const { + Q_ASSERT(host); static_cast(host)->setVisible(visible); } void WidgetItemDelegate::setGeometry(QObject *host, const QRect &rect) { + Q_ASSERT(host); static_cast(host)->setGeometry(rect); } void WidgetItemDelegate::bringWindowToTop(QObject *host) const { + Q_ASSERT(host); static_cast(host)->raise(); } WinIdChangeEventFilter * WidgetItemDelegate::createWinIdEventFilter(QObject *host, AbstractWindowContext *context) const { + Q_ASSERT(host); + Q_ASSERT(context); return new WidgetWinIdChangeEventFilter(host, context); } diff --git a/src/widgets/widgetitemdelegate_p.h b/src/widgets/widgetitemdelegate_p.h index fcd4d31..16a3085 100644 --- a/src/widgets/widgetitemdelegate_p.h +++ b/src/widgets/widgetitemdelegate_p.h @@ -22,7 +22,7 @@ namespace QWK { - class QWK_WIDGETS_EXPORT WidgetItemDelegate : public WindowItemDelegate { + class QWK_WIDGETS_EXPORT WidgetItemDelegate final : public WindowItemDelegate { public: WidgetItemDelegate(); ~WidgetItemDelegate() override; diff --git a/src/widgets/widgetwindowagent.cpp b/src/widgets/widgetwindowagent.cpp index 2792128..50140b5 100644 --- a/src/widgets/widgetwindowagent.cpp +++ b/src/widgets/widgetwindowagent.cpp @@ -92,6 +92,7 @@ namespace QWK { have been set will be removed. */ void WidgetWindowAgent::setTitleBar(QWidget *w) { + Q_ASSERT(w); Q_D(WidgetWindowAgent); if (!d->context->setTitleBar(w)) { return; @@ -115,6 +116,7 @@ namespace QWK { you don't need to call \c setHitTestVisible for them. */ void WidgetWindowAgent::setSystemButton(SystemButton button, QWidget *w) { + Q_ASSERT(w); Q_D(WidgetWindowAgent); if (!d->context->setSystemButton(button, w)) { return; @@ -126,6 +128,7 @@ namespace QWK { Returns \a true if the widget can receive mouse events on title bar. */ bool WidgetWindowAgent::isHitTestVisible(const QWidget *w) const { + Q_ASSERT(w); Q_D(const WidgetWindowAgent); return d->context->isHitTestVisible(w); } @@ -136,6 +139,7 @@ namespace QWK { of the title bar widget. */ void WidgetWindowAgent::setHitTestVisible(QWidget *w, bool visible) { + Q_ASSERT(w); Q_D(WidgetWindowAgent); d->context->setHitTestVisible(w, visible); } @@ -145,6 +149,7 @@ namespace QWK { */ WidgetWindowAgent::WidgetWindowAgent(WidgetWindowAgentPrivate &d, QObject *parent) : WindowAgentBase(d, parent) { + d.q_ptr = this; d.init(); } diff --git a/src/widgets/widgetwindowagent.h b/src/widgets/widgetwindowagent.h index 4a0f9c8..352285d 100644 --- a/src/widgets/widgetwindowagent.h +++ b/src/widgets/widgetwindowagent.h @@ -14,7 +14,7 @@ namespace QWK { class WidgetWindowAgentPrivate; - class QWK_WIDGETS_EXPORT WidgetWindowAgent : public WindowAgentBase { + class QWK_WIDGETS_EXPORT WidgetWindowAgent final : public WindowAgentBase { Q_OBJECT Q_DECLARE_PRIVATE(WidgetWindowAgent) public: diff --git a/src/widgets/widgetwindowagent_mac.cpp b/src/widgets/widgetwindowagent_mac.cpp index 17156e4..5370129 100644 --- a/src/widgets/widgetwindowagent_mac.cpp +++ b/src/widgets/widgetwindowagent_mac.cpp @@ -12,7 +12,8 @@ namespace QWK { return {widget->mapTo(widget->window(), QPoint()), widget->size()}; } - class SystemButtonAreaWidgetEventFilter : public QObject { + class SystemButtonAreaWidgetEventFilter final : public QObject { + Q_OBJECT public: SystemButtonAreaWidgetEventFilter(QWidget *widget, AbstractWindowContext *ctx, QObject *parent = nullptr) @@ -41,8 +42,8 @@ namespace QWK { } protected: - QWidget *widget; - AbstractWindowContext *ctx; + QWidget *widget = nullptr; + AbstractWindowContext *ctx = nullptr; }; /*! @@ -95,4 +96,6 @@ namespace QWK { d->context->setSystemButtonAreaCallback(callback); } -} \ No newline at end of file +} + +#include "widgetwindowagent_mac.moc" diff --git a/src/widgets/widgetwindowagent_p.h b/src/widgets/widgetwindowagent_p.h index 1382dd5..cc05bdb 100644 --- a/src/widgets/widgetwindowagent_p.h +++ b/src/widgets/widgetwindowagent_p.h @@ -20,7 +20,7 @@ namespace QWK { - class WidgetWindowAgentPrivate : public WindowAgentBasePrivate { + class QWK_WIDGETS_EXPORT WidgetWindowAgentPrivate final : public WindowAgentBasePrivate { Q_DECLARE_PUBLIC(WidgetWindowAgent) public: WidgetWindowAgentPrivate(); @@ -29,10 +29,10 @@ namespace QWK { void init(); // Host - QWidget *hostWidget{}; + QWidget *hostWidget{ nullptr }; #ifdef Q_OS_MAC - QWidget *systemButtonAreaWidget{}; + QWidget *systemButtonAreaWidget{ nullptr }; std::unique_ptr systemButtonAreaWidgetEventFilter; #endif diff --git a/src/widgets/widgetwindowagent_win.cpp b/src/widgets/widgetwindowagent_win.cpp index f7501e0..9e2f9a3 100644 --- a/src/widgets/widgetwindowagent_win.cpp +++ b/src/widgets/widgetwindowagent_win.cpp @@ -40,11 +40,15 @@ namespace QWK { // returns, because Qt calls BeginPaint() and EndPaint() itself. We should make sure that we // draw the top border between these two calls, otherwise some display exceptions may arise. - class WidgetBorderHandler : public QObject, public Windows10BorderHandler { + class WidgetBorderHandler final : public QObject, public Windows10BorderHandler { + Q_OBJECT public: - explicit WidgetBorderHandler(QWidget *widget, AbstractWindowContext *ctx, + WidgetBorderHandler(QWidget *widget, AbstractWindowContext *ctx, QObject *parent = nullptr) : QObject(parent), Windows10BorderHandler(ctx), widget(widget) { + Q_ASSERT(widget); + Q_ASSERT(ctx); + widget->installEventFilter(this); // First update @@ -102,6 +106,8 @@ namespace QWK { protected: bool sharedEventFilter(QObject *obj, QEvent *event) override { + Q_ASSERT(obj); + Q_ASSERT(event); Q_UNUSED(obj) switch (event->type()) { @@ -137,6 +143,8 @@ namespace QWK { } bool eventFilter(QObject *obj, QEvent *event) override { + Q_ASSERT(obj); + Q_ASSERT(event); Q_UNUSED(obj) switch (event->type()) { @@ -164,7 +172,7 @@ namespace QWK { return false; } - QWidget *widget; + QWidget *widget = nullptr; }; void WidgetWindowAgentPrivate::setupWindows10BorderWorkaround() { @@ -177,3 +185,5 @@ namespace QWK { #endif } + +#include "widgetwindowagent_win.moc"