From 72d6afbd194275fb75e536948ad59a0b8c73a9a9 Mon Sep 17 00:00:00 2001 From: yeshanshan Date: Wed, 18 Mar 2026 15:14:03 +0800 Subject: [PATCH] fix: fix touchscreen long press and drag issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Changed visibility handling to opacity for dragged items to maintain layout stability 2. Replaced DragHandler with MouseArea for better touchscreen compatibility 3. Fixed drag state condition to use mouseArea.drag.active instead of dragHandler.active 4. Added proper touchscreen long press support via onPressAndHold handler 5. Implemented deferred drag start to prevent crashes during page/folder transitions 6. Restored click and right-click functionality within the MouseArea Log: Fixed touchscreen long press not triggering context menu and improved drag-and-drop reliability Influence: 1. Test long press on touchscreen to verify context menu appears 2. Test drag-and-drop operations on both mouse and touchscreen 3. Verify items disappear properly during drag (opacity becomes 0) 4. Test folder opening/closing during drag operations 5. Test right-click functionality still works correctly 6. Verify no crashes occur when switching pages during drag 7. Test drag threshold and hot spot positioning fix: 修复触摸屏长按和拖拽问题 1. 将拖拽项的可见性处理改为透明度控制,以保持布局稳定性 2. 用 MouseArea 替换 DragHandler 以获得更好的触摸屏兼容性 3. 修复拖拽状态条件,使用 mouseArea.drag.active 替代 dragHandler.active 4. 通过 onPressAndHold 处理器添加正确的触摸屏长按支持 5. 实现延迟拖拽启动,防止在页面/文件夹切换期间崩溃 6. 恢复 MouseArea 内的点击和右键点击功能 Log: 修复触摸屏长按无法触发上下文菜单的问题,并提高拖拽操作的可靠性 Influence: 1. 测试触摸屏长按,验证上下文菜单是否正常显示 2. 测试鼠标和触摸屏上的拖拽操作 3. 验证拖拽期间项目是否正确消失(透明度变为0) 4. 测试拖拽操作期间的文件夹打开/关闭 5. 测试右键点击功能是否仍然正常工作 6. 验证在拖拽期间切换页面不会导致崩溃 7. 测试拖拽阈值和热点定位 --- qml/FolderGridViewPopup.qml | 2 +- qml/FullscreenFrame.qml | 2 +- qml/IconItemDelegate.qml | 71 ++++++++++++++++++++++++------------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/qml/FolderGridViewPopup.qml b/qml/FolderGridViewPopup.qml index 47976501..f9b8b2b1 100644 --- a/qml/FolderGridViewPopup.qml +++ b/qml/FolderGridViewPopup.qml @@ -647,7 +647,7 @@ Popup { isDragHover: false displayFont: isWindowedMode ? DTK.fontManager.t9 : DTK.fontManager.t6 Drag.mimeData: Helper.generateDragMimeData(model.desktopId) - visible: dndItem.currentlyDraggedId !== model.desktopId + opacity: dndItem.currentlyDraggedId !== model.desktopId ? 1 : 0 iconSource: iconName padding: isWindowedMode ? 0 : 5 diff --git a/qml/FullscreenFrame.qml b/qml/FullscreenFrame.qml index c8b8cfdb..432532b8 100644 --- a/qml/FullscreenFrame.qml +++ b/qml/FullscreenFrame.qml @@ -639,7 +639,7 @@ InputEventItem { dndEnabled: !folderGridViewPopup.opened isDragHover: parent.isDragHover Drag.mimeData: Helper.generateDragMimeData(model.desktopId) - visible: dndItem.currentlyDraggedId !== model.desktopId + opacity: dndItem.currentlyDraggedId !== model.desktopId ? 1 : 0 iconSource: (iconName && iconName !== "") ? iconName : "application-x-desktop" icons: folderIcons iconScaleFactor: baseLayer.iconScaleFactor diff --git a/qml/IconItemDelegate.qml b/qml/IconItemDelegate.qml index cb86e971..3c02c706 100644 --- a/qml/IconItemDelegate.qml +++ b/qml/IconItemDelegate.qml @@ -44,11 +44,11 @@ Control { states: State { name: "dragged"; - when: dragHandler.active + when: mouseArea.drag.active // FIXME: When dragging finished, the position of the item is changed for unknown reason, // so we use the state to reset the x and y here. PropertyChanges { - target: dragHandler.target + target: mouseArea.drag.target x: x y: y } @@ -111,34 +111,57 @@ Control { anchors.fill: parent asynchronous: true sourceComponent: root.icons !== undefined ? folderComponent : imageComponent - DragHandler { - id: dragHandler - target: root - acceptedButtons: Qt.LeftButton - enabled: root.dndEnabled - dragThreshold: 1 - onActiveChanged: { - if (active) { - // We switch to use the `dndItem` to handle Drag event since that one will always exists. - // If we use the current item, then if the item that provides the drag attached property - // get destoryed (e.g. switch page or folder close caused destory), dropping at that moment - // will cause a crash. - - // Item will be hidden by checking the dndItem.currentlyDraggedId property. We assign the value - // to that property here - dndItem.currentlyDraggedId = target.Drag.mimeData["text/x-dde-launcher-dnd-desktopId"] - dndItem.currentlyDraggedIconName = root.iconSource - dndItem.Drag.hotSpot = target.Drag.hotSpot - dndItem.Drag.mimeData = target.Drag.mimeData - dndItem.mergeSize = Math.min(iconLoader.width, iconLoader.height) + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: false + drag.target: root.dndEnabled ? root : null + drag.threshold: 1 + onPressed: function (mouse) { + if (mouse.button === Qt.LeftButton && root.dndEnabled) { + root.Drag.hotSpot = mapToItem(iconLoader, Qt.point(mouse.x, mouse.y)) iconLoader.grabToImage(function(result) { - dndItem.Drag.imageSource = result.url; + root.Drag.imageSource = result.url; + }) + } + } + drag.onActiveChanged: function() { + if (drag.active) { + dndItem.currentlyDraggedId = root.Drag.mimeData["text/x-dde-launcher-dnd-desktopId"] + dndItem.currentlyDraggedIconName = root.iconSource + dndItem.Drag.hotSpot = root.Drag.hotSpot + dndItem.Drag.mimeData = root.Drag.mimeData + dndItem.mergeSize = Math.min(iconLoader.width, iconLoader.height) + dndItem.Drag.imageSource = root.Drag.imageSource + dndItem.Drag.dragType = root.Drag.Automatic + // Defer the drag start to avoid running a nested event loop + // (QDrag::exec) inside this signal handler. If the delegate + // gets destroyed during the drag (page switch / folder close), + // Qt would otherwise abort because the MouseArea's handler is + // still on the call stack. + Qt.callLater(function() { dndItem.Drag.active = true - dndItem.Drag.startDrag() }) } } + onClicked: function(mouse) { + if (mouse.button === Qt.LeftButton) { + if (model.itemType === ItemArrangementProxyModel.FolderItemType) { + root.folderClicked() + } else { + root.itemClicked() + } + } else if (mouse.button === Qt.RightButton) { + root.menuTriggered() + } + } + // touchscreen long press. + onPressAndHold: function (mouse) { + if (mouse.button === Qt.NoButton) { + root.menuTriggered() + } + } } }