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_p.h b/src/core/contexts/abstractwindowcontext_p.h index 057b16b..aeb73a3 100644 --- a/src/core/contexts/abstractwindowcontext_p.h +++ b/src/core/contexts/abstractwindowcontext_p.h @@ -65,23 +65,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; @@ -167,6 +153,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/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/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/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index e52a541..3802f8d 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. @@ -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) { + 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. @@ -234,6 +243,7 @@ namespace QWK { // Returns false if the menu is canceled static 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; @@ -340,6 +350,7 @@ namespace QWK { } static bool isValidWindow(HWND hWnd, bool checkVisible, bool checkTopLevel) { + Q_ASSERT(hWnd); if (!::IsWindow(hWnd)) { return false; } @@ -386,7 +397,9 @@ namespace QWK { } static MSG createMessageBlock(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - MSG msg; + Q_ASSERT(hWnd); + + MSG msg{}; msg.hwnd = hWnd; msg.message = message; msg.wParam = wParam; @@ -435,6 +448,8 @@ namespace QWK { // Send to QAbstractEventDispatcher static 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)) { @@ -446,6 +461,9 @@ namespace QWK { // Send to QWindowSystemInterface static 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 @@ -486,6 +508,8 @@ namespace QWK { 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. @@ -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); } }; @@ -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. @@ -1205,6 +1235,7 @@ namespace QWK { static 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的,其余三边都是在窗口 @@ -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/kernel/nativeeventfilter.cpp b/src/core/kernel/nativeeventfilter.cpp index 27c29d9..6bd9f14 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) @@ -82,8 +81,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..3234315 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) 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..8746e55 100644 --- a/src/core/kernel/winidchangeeventfilter.cpp +++ b/src/core/kernel/winidchangeeventfilter.cpp @@ -17,9 +17,9 @@ namespace QWK { } 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; diff --git a/src/core/qwindowkit_windows.cpp b/src/core/qwindowkit_windows.cpp index 41b3500..e8449ea 100644 --- a/src/core/qwindowkit_windows.cpp +++ b/src/core/qwindowkit_windows.cpp @@ -45,8 +45,7 @@ namespace QWK { void WindowsRegistryKey::close() { if (isValid()) { - ::RegCloseKey(m_key); - m_key = nullptr; + ::RegCloseKey(std::exchange(m_key, nullptr)); } } diff --git a/src/core/qwindowkit_windows.h b/src/core/qwindowkit_windows.h index e20a035..20d875c 100644 --- a/src/core/qwindowkit_windows.h +++ b/src/core/qwindowkit_windows.h @@ -158,7 +158,7 @@ namespace QWK { ~WindowsRegistryKey(); - bool isValid() const; + inline bool isValid() const; void close(); QString stringValue(QStringView subKey) const; 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..6a5ebdd 100644 --- a/src/core/shared/qwkwindowsextra_p.h +++ b/src/core/shared/qwkwindowsextra_p.h @@ -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..7a10872 100644 --- a/src/core/shared/systemwindow_p.h +++ b/src/core/shared/systemwindow_p.h @@ -133,6 +133,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 +147,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/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_p.h b/src/core/style/styleagent_p.h index 40e903f..e84f629 100644 --- a/src/core/style/styleagent_p.h +++ b/src/core/style/styleagent_p.h @@ -18,11 +18,11 @@ namespace QWK { - class StyleAgentPrivate : public QObject { + class StyleAgentPrivate { Q_DECLARE_PUBLIC(StyleAgent) public: StyleAgentPrivate(); - ~StyleAgentPrivate() override; + ~StyleAgentPrivate(); void init(); diff --git a/src/core/style/styleagent_win.cpp b/src/core/style/styleagent_win.cpp index ab290dc..3b371c4 100644 --- a/src/core/style/styleagent_win.cpp +++ b/src/core/style/styleagent_win.cpp @@ -77,8 +77,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..5687f03 100644 --- a/src/core/windowagentbase.cpp +++ b/src/core/windowagentbase.cpp @@ -41,8 +41,7 @@ namespace QWK { WindowAgentBasePrivate::WindowContextFactoryMethod WindowAgentBasePrivate::windowContextFactoryMethod = nullptr; - WindowAgentBasePrivate::WindowAgentBasePrivate() : q_ptr(nullptr), context(nullptr) { - } + WindowAgentBasePrivate::WindowAgentBasePrivate() = default; WindowAgentBasePrivate::~WindowAgentBasePrivate() = default; diff --git a/src/core/windowagentbase.h b/src/core/windowagentbase.h index 5b25528..5413f84 100644 --- a/src/core/windowagentbase.h +++ b/src/core/windowagentbase.h @@ -35,7 +35,7 @@ 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(); diff --git a/src/quick/quickitemdelegate.cpp b/src/quick/quickitemdelegate.cpp index b63345e..2812be3 100644 --- a/src/quick/quickitemdelegate.cpp +++ b/src/quick/quickitemdelegate.cpp @@ -9,8 +9,7 @@ namespace QWK { - QuickItemDelegate::QuickItemDelegate() : WindowItemDelegate() { - } + QuickItemDelegate::QuickItemDelegate() = default; QuickItemDelegate::~QuickItemDelegate() = default;