From dfc6499d12bc92c99367fca461dfd0a39f739120 Mon Sep 17 00:00:00 2001 From: Ivy233 Date: Mon, 31 Aug 2026 16:05:37 +0800 Subject: [PATCH] fix: address build and QML runtime warnings across shell and dock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a set of compiler and QML runtime warnings: - Enable -Werror for C/C++ and guard the clang-format targets so the build fails on warnings instead of silently ignoring them; only set up the format/commit hooks when clang-format is available. - Register the D_APPLET_CLASS macro as an AUTOMOC macro name for the notification server test to silence its moc warning. - AppletDockItem: coerce Applet.visible/supported to bool with !! operators to avoid assigning undefined to a bool property. - ShellSurfaceItemProxy: connect the cursorShapeRequested signal dynamically and only when the surface exposes it (PluginPopup), since a static Connections handler warned that no matching signal exists. - TaskManager: drop the implicitWidth/implicitHeight binding loop by returning the fixed dock size in the layout direction that does not depend on appContainer, and give the onAdd animation an id so the deprecated object-to-signal-handler assignment is avoided. - AppItem: resolve the Drag.active binding loop by setting Drag.active imperatively from the MouseArea's drag handler instead of binding it to the driving property. - TrayItemPositionManager: register the DropIndex value type under the lowercase name dropIndex via QML_NAMED_ELEMENT, so qmltyperegistrar stops warning about its value-type name while keeping the C++ struct name unchanged; also use Qt::QueuedConnection for the dockHeightChanged -> updateVisualSize connection to break the synchronous signal/slot cascade that causes the "Binding loop detected for dockItemMaxSize" warning. - OverlapNotify: guard the panelShown lookup so an undefined ListView.view no longer assigns undefined to a bool property. - Resolve dpkg -Wall -Werror build failures: reorder the member initializer list in AMAppItemModel to match the declaration order, drop the unused windowCount/initResult variables, and initialize the previously uninitialized needHide/needShow/anchor variables. 修复 dde-shell 及任务栏的编译与 QML 运行时告警: - 对 C/C++ 启用 -Werror,并将 clang-format 相关目标用条件包裹,让构建 在出现告警时报错而非静默跳过;仅在检测到 clang-format 时才构建 格式化与提交钩子目标。 - 为通知服务测试注册额外 moc 宏 D_APPLET_CLASS,消除其必要的 moc 告警。 - AppletDockItem:对 Applet.visible/Applet.supported 使用 !! 强制转换为 bool,避免将 undefined 赋给 bool 属性。 - ShellSurfaceItemProxy:将 cursorShapeRequested 改为仅在 surface 暴露该 信号时(PluginPopup)动态连接,原静态 Connections 处理器会因没有匹配 信号而告警。 - 通过在被布局方向直接返回固定的 dock 尺寸、不再依赖 appContainer, 消除 TaskManager 的 implicitWidth/implicitHeight 绑定循环;并为委托的 入场动画补充 id,规避已废弃的"将对象赋给信号处理器"写法。 - AppItem:改为在 mouseArea 的拖拽处理器中命令式设置 Drag.active, 而非绑定到驱动它的属性,消除 Drag.active 绑定循环告警。 - TrayItemPositionManager:通过 QML_NAMED_ELEMENT 将 DropIndex 值类型 注册为小写 dropIndex,在保留 C++ 结构体名的同时消除 qmltyperegistrar 对值类型名的告警;并将 dockHeightChanged 到 updateVisualSize 的连接 改为 Qt::QueuedConnection,打断同步 C++ 信号/槽级联,消除 "Binding loop detected for dockItemMaxSize" 告警。 - OverlapNotify:为 panelShown 查询加空值守卫,避免未定义的 ListView.view 将 undefined 赋给 bool 属性。 - 解决 dpkg -Wall -Werror 编译失败:调整 AMAppItemModel 的成员初始化 列表顺序使其与声明顺序一致,移除未使用的 windowCount/initResult 变量,并初始化先前未初始化的 needHide/needShow/anchor 变量。 PMS: TASK-394335 --- CMakeLists.txt | 7 ++-- applets/dde-apps/amappitemmodel.cpp | 2 +- panels/dock/AppletDockItem.qml | 2 +- panels/dock/ShellSurfaceItemProxy.qml | 35 +++++++++++++------ panels/dock/dockhelper.cpp | 4 +-- panels/dock/taskmanager/dockgroupmodel.cpp | 1 - panels/dock/taskmanager/package/AppItem.qml | 6 +++- .../dock/taskmanager/package/TaskManager.qml | 25 +++++++++---- panels/dock/tray/trayitempositionmanager.cpp | 9 ++++- panels/dock/tray/trayitempositionmanager.h | 2 +- panels/dock/waylanddockhelper.cpp | 2 +- panels/notification/center/OverlapNotify.qml | 2 +- .../panels/notification/server/CMakeLists.txt | 4 ++- .../server/notifyserverapplet_test.cpp | 2 +- 14 files changed, 72 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f48d57954..f43150880 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ endif () set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +add_compile_options($<$:-Werror>) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -119,5 +120,7 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/DDEShellConfigVersion.cmake" DESTINAT # add clang-format target for all our real source files file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h) -kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) -kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) +if(KDE_CLANG_FORMAT_EXECUTABLE) + kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) + kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) +endif() diff --git a/applets/dde-apps/amappitemmodel.cpp b/applets/dde-apps/amappitemmodel.cpp index 5801dea82..967f3cc5d 100644 --- a/applets/dde-apps/amappitemmodel.cpp +++ b/applets/dde-apps/amappitemmodel.cpp @@ -15,8 +15,8 @@ namespace apps { AMAppItemModel::AMAppItemModel(QObject *parent) : AppItemModel(parent) - , m_manager(new ObjectManager("org.desktopspec.ApplicationManager1", "/org/desktopspec/ApplicationManager1", QDBusConnection::sessionBus(), this)) , m_ready(false) + , m_manager(new ObjectManager("org.desktopspec.ApplicationManager1", "/org/desktopspec/ApplicationManager1", QDBusConnection::sessionBus(), this)) { qRegisterMetaType(); qDBusRegisterMetaType(); diff --git a/panels/dock/AppletDockItem.qml b/panels/dock/AppletDockItem.qml index 547f347bf..c990b2651 100644 --- a/panels/dock/AppletDockItem.qml +++ b/panels/dock/AppletDockItem.qml @@ -9,7 +9,7 @@ AppletItem { id: appletDockItem property int dockOrder: 0 - property bool shouldVisible: Applet.visible && Applet.supported + property bool shouldVisible: !!Applet.visible && !!Applet.supported property bool useColumnLayout: Panel.position % 2 implicitWidth: useColumnLayout ? Panel.rootObject.dockSize : Panel.rootObject.dockItemMaxSize * 0.8 implicitHeight: useColumnLayout ? Panel.rootObject.dockItemMaxSize * 0.8 : Panel.rootObject.dockSize diff --git a/panels/dock/ShellSurfaceItemProxy.qml b/panels/dock/ShellSurfaceItemProxy.qml index e55eaea63..e0c2caa9c 100644 --- a/panels/dock/ShellSurfaceItemProxy.qml +++ b/panels/dock/ShellSurfaceItemProxy.qml @@ -111,6 +111,7 @@ Item { } Component.onCompleted: function () { impl.surfaceDestroyed.connect(root.surfaceDestroyed) + updateCursorShapeConnection() } Connections { @@ -125,17 +126,31 @@ Item { }) }) } + } - function onCursorShapeRequested(cursorShape) - { - console.log("onCursorShapeRequested:", cursorShape) - // Qt::CursorShape range is 0-21, plus 24 (BitmapCursor) and 25 (CustomCursor). - // We set a default if the value is out of logical bounds. - if (cursorShape < 0 || cursorShape > 25) { - root.cursorShape = Qt.ArrowCursor - } else { - root.cursorShape = cursorShape - } + property var cursorShapeConnection: null + + onShellSurfaceChanged: updateCursorShapeConnection() + + function updateCursorShapeConnection() { + if (cursorShapeConnection) { + cursorShapeConnection.disconnect() + cursorShapeConnection = null + } + // cursorShapeRequested only exists on PluginPopup, not on PluginSurface, + // so connect dynamically to avoid a QML warning for surfaces lacking it. + if (shellSurface && shellSurface.cursorShapeRequested) { + cursorShapeConnection = shellSurface.cursorShapeRequested.connect(onCursorShapeRequested) + } + } + + function onCursorShapeRequested(cursorShape) { + // Qt::CursorShape range is 0-21, plus 24 (BitmapCursor) and 25 (CustomCursor). + // We set a default if the value is out of logical bounds. + if (cursorShape < 0 || cursorShape > 25) { + root.cursorShape = Qt.ArrowCursor + } else { + root.cursorShape = cursorShape } } } diff --git a/panels/dock/dockhelper.cpp b/panels/dock/dockhelper.cpp index 9e31c2aee..e3767bcb1 100644 --- a/panels/dock/dockhelper.cpp +++ b/panels/dock/dockhelper.cpp @@ -198,7 +198,7 @@ void DockHelper::updateAllDockWakeArea() void DockHelper::checkNeedHideOrNot() { - bool needHide; + bool needHide = false; switch (parent()->hideMode()) { case KeepShowing: { // KeepShow. current activeWindow is fullscreend. @@ -238,7 +238,7 @@ void DockHelper::checkNeedHideOrNot() void DockHelper::checkNeedShowOrNot() { - bool needShow; + bool needShow = false; switch (parent()->hideMode()) { case KeepShowing: { // KeepShow. currentWindow is not fullscreened. diff --git a/panels/dock/taskmanager/dockgroupmodel.cpp b/panels/dock/taskmanager/dockgroupmodel.cpp index 432453357..9adc8e7d0 100644 --- a/panels/dock/taskmanager/dockgroupmodel.cpp +++ b/panels/dock/taskmanager/dockgroupmodel.cpp @@ -42,7 +42,6 @@ DockGroupModel::DockGroupModel(QAbstractItemModel *sourceModel, int role, QObjec int parentRow = parent.row(); if (m_currentActiveWindow.contains(parentRow)) { int currentActive = m_currentActiveWindow.value(parentRow); - int windowCount = RoleGroupModel::rowCount(parent); // Check if the current active window was removed if (currentActive >= first && currentActive <= last) { diff --git a/panels/dock/taskmanager/package/AppItem.qml b/panels/dock/taskmanager/package/AppItem.qml index f4233a7fb..0af21e8be 100644 --- a/panels/dock/taskmanager/package/AppItem.qml +++ b/panels/dock/taskmanager/package/AppItem.qml @@ -30,7 +30,10 @@ Item { signal dropFilesOnItem(itemId: string, files: list) signal dragFinished() - Drag.active: mouseArea.drag.active + // Binding Drag.active to mouseArea.drag.active would make Drag.active read + // back the very property it drives (see visible/fixPosition below), + // causing a QML binding loop. Set it imperatively from the MouseArea instead. + Drag.active: false Drag.source: root Drag.hotSpot.x: icon.width / 2 Drag.hotSpot.y: icon.height / 2 @@ -494,6 +497,7 @@ Item { acceptedButtons: Qt.LeftButton | Qt.RightButton drag.target: root drag.onActiveChanged: { + root.Drag.active = drag.active if (!drag.active) { Panel.contextDragging = false root.dragFinished() diff --git a/panels/dock/taskmanager/package/TaskManager.qml b/panels/dock/taskmanager/package/TaskManager.qml index 1177a52d9..aa348544e 100644 --- a/panels/dock/taskmanager/package/TaskManager.qml +++ b/panels/dock/taskmanager/package/TaskManager.qml @@ -40,16 +40,24 @@ ContainmentItem { readonly property real startPadding: Math.max(0, appTitleSpacing - (Panel.rootObject.dockItemMaxSize * (multitaskViewIconRatio - iconWidthToMaxSizeRatio) / 2)) implicitWidth: { - let extra = useColumnLayout ? 0 : startPadding + // In column layout the width is fixed to the dock size, so do not + // depend on appContainer.implicitWidth (the delegates read this + // implicitWidth back, which would cause a binding loop). + if (useColumnLayout) + return Panel.rootObject.dockSize + let extra = startPadding let w = appContainer.implicitWidth + extra - let maxW = Panel.itemAlignment === Dock.LeftAlignment ? Math.max(remainingSpacesForTaskManager, w) : Math.min(remainingSpacesForTaskManager, w) - return useColumnLayout ? Panel.rootObject.dockSize : maxW + return Panel.itemAlignment === Dock.LeftAlignment ? Math.max(remainingSpacesForTaskManager, w) : Math.min(remainingSpacesForTaskManager, w) } implicitHeight: { - let extra = useColumnLayout ? startPadding : 0 + // In row layout the height is fixed to the dock size, so do not + // depend on appContainer.implicitHeight (the delegates read this + // implicitHeight back, which would cause a binding loop). + if (!useColumnLayout) + return Panel.rootObject.dockSize + let extra = startPadding let h = appContainer.implicitHeight + extra - let maxH = Panel.itemAlignment === Dock.LeftAlignment ? Math.max(remainingSpacesForTaskManager, h) : Math.min(remainingSpacesForTaskManager, h) - return useColumnLayout ? maxH : Panel.rootObject.dockSize + return Panel.itemAlignment === Dock.LeftAlignment ? Math.max(remainingSpacesForTaskManager, h) : Math.min(remainingSpacesForTaskManager, h) } // Helper function to find the current index of an app by its appId in the visualModel function findAppIndex(appId) { @@ -140,7 +148,10 @@ ContainmentItem { return windows.length > 0 && launcherDndDropArea.launcherDndWinId !== windows[0] } - ListView.onAdd: NumberAnimation { + ListView.onAdd: addAnimation.restart() + + NumberAnimation { + id: addAnimation target: delegateRoot properties: "scale,opacity" from: 0 diff --git a/panels/dock/tray/trayitempositionmanager.cpp b/panels/dock/tray/trayitempositionmanager.cpp index 346f8b1ad..c68cb5d34 100644 --- a/panels/dock/tray/trayitempositionmanager.cpp +++ b/panels/dock/tray/trayitempositionmanager.cpp @@ -139,8 +139,15 @@ TrayItemPositionManager::TrayItemPositionManager(QObject *parent) connect(this, &TrayItemPositionManager::visualItemCountChanged, this, &TrayItemPositionManager::updateVisualSize); + // Use QueuedConnection for dockHeightChanged to break a synchronous + // signal/slot cascade that causes "Binding loop for dockItemMaxSize". + // When dockSize changes (e.g. during drag), dockHeightChanged fires + // synchronously, calling updateVisualSize -> visualSizeChanged, which + // marks dockItemMaxSize dirty (it transitively reads visualSize via + // dockRawCenterSpace -> dockRightPart -> tray). Queuing the slot lets + // the current binding evaluation finish before visualSize updates. connect(this, &TrayItemPositionManager::dockHeightChanged, - this, &TrayItemPositionManager::updateVisualSize); + this, &TrayItemPositionManager::updateVisualSize, Qt::QueuedConnection); connect(this, &TrayItemPositionManager::orientationChanged, this, &TrayItemPositionManager::updateVisualSize); connect(this, &TrayItemPositionManager::visualItemSizeChanged, diff --git a/panels/dock/tray/trayitempositionmanager.h b/panels/dock/tray/trayitempositionmanager.h index da1c89cd0..dfc436dcb 100644 --- a/panels/dock/tray/trayitempositionmanager.h +++ b/panels/dock/tray/trayitempositionmanager.h @@ -15,7 +15,7 @@ struct DropIndex { Q_PROPERTY(int index MEMBER index) Q_PROPERTY(bool isOnItem MEMBER isOnItem) Q_PROPERTY(bool isBefore MEMBER isBefore) - QML_ELEMENT + QML_NAMED_ELEMENT(dropIndex) public: int index; bool isOnItem = true; diff --git a/panels/dock/waylanddockhelper.cpp b/panels/dock/waylanddockhelper.cpp index 5b23bcf08..584483c73 100644 --- a/panels/dock/waylanddockhelper.cpp +++ b/panels/dock/waylanddockhelper.cpp @@ -73,7 +73,7 @@ void WaylandDockHelper::updateOverlapCheckerPos() if (!waylandScreen) return; - uint32_t anchor; + uint32_t anchor = 0; switch (m_panel->position()) { case Top: anchor = QtWayland::treeland_window_overlap_checker::anchor_top; diff --git a/panels/notification/center/OverlapNotify.qml b/panels/notification/center/OverlapNotify.qml index ba674931b..3c20a5f81 100644 --- a/panels/notification/center/OverlapNotify.qml +++ b/panels/notification/center/OverlapNotify.qml @@ -143,7 +143,7 @@ NotifyItem { OverlapIndicator { id: indicator - enableAnimation: root.ListView.view.panelShown + enableAnimation: (root.ListView.view && root.ListView.view.panelShown) ?? false clipItems: true anchors { bottom: parent.bottom diff --git a/tests/panels/notification/server/CMakeLists.txt b/tests/panels/notification/server/CMakeLists.txt index 3a4d4f48a..4c08e02a0 100644 --- a/tests/panels/notification/server/CMakeLists.txt +++ b/tests/panels/notification/server/CMakeLists.txt @@ -33,6 +33,8 @@ add_executable(notifyserverapplet_tests notifyserverapplet_test.cpp ) +set_property(TARGET notifyserverapplet_tests APPEND PROPERTY AUTOMOC_MACRO_NAMES "D_APPLET_CLASS") + target_compile_options(notifyserverapplet_tests PRIVATE -fvisibility=hidden -fvisibility-inlines-hidden @@ -64,4 +66,4 @@ add_test( COMMAND ${CMAKE_COMMAND} -E env LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/frame:${CMAKE_BINARY_DIR}/panels/notification $ -) \ No newline at end of file +) diff --git a/tests/panels/notification/server/notifyserverapplet_test.cpp b/tests/panels/notification/server/notifyserverapplet_test.cpp index 9a0463167..6ee764adb 100644 --- a/tests/panels/notification/server/notifyserverapplet_test.cpp +++ b/tests/panels/notification/server/notifyserverapplet_test.cpp @@ -80,7 +80,7 @@ TEST_F(NotifyServerAppletTest, DestructorMemoryLeakTest) { auto *testApplet = new NotifyServerApplet(); // Initialize the applet (creates m_manager, m_worker, and DbusAdaptors) - bool initResult = testApplet->init(); + testApplet->init(); // Even if init fails (e.g., D-Bus not available), we should clean up properly // Record the state before deletion