已合并
fix拖拽时选中阔选不了手柄 #77917
jiangjiacheng创建于 2025年12月17日
fix拖拽时选中阔选不了手柄 #77917
已合并
jiangjiacheng创建于 2025年12月17日
共 2 个文件变更+34-6
@@ -710,7 +710,7 @@ void WebSelectOverlay::CheckHandles(SelectHandleInfo& handleInfo,
710 auto paintRect = handleInfo.paintRect;710 auto paintRect = handleInfo.paintRect;
711 PointF bottomPoint = { paintRect.Left(), paintRect.Bottom() };711 PointF bottomPoint = { paintRect.Left(), paintRect.Bottom() };
712 PointF topPoint = { paintRect.Left(), paintRect.Top() };712 PointF topPoint = { paintRect.Left(), paintRect.Top() };
713- handleInfo.isShow = (visibleInnerRect.IsInRegion(bottomPoint) && visibleInnerRect.IsInRegion(topPoint));713+ handleInfo.isShow = (visibleInnerRect.IsInnerRegion(bottomPoint) && visibleInnerRect.IsInnerRegion(topPoint));
arkui-feature-manager
arkui-feature-managerarkui-feature-manager2025年12月17日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🟡 区域检查函数变更需要语义验证

位置: L713 | 严重程度: Medium

❓ 问题描述

将IsInRegion改为IsInnerRegion,这两个函数的语义可能不同。IsInRegion可能包含边界检查,而IsInnerRegion可能是严格内部检查。这种改变可能会影响手柄在边界情况下的显示行为。

💡 修复建议

建议在代码注释中明确说明这两个函数的区别,并添加相应的单元测试来验证边界行为。示例:

// 使用IsInnerRegion确保手柄完全在可见区域内,避免部分遮挡
handleInfo.isShow = (visibleInnerRect.IsInnerRegion(bottomPoint) && visibleInnerRect.IsInnerRegion(topPoint));

likedislike
714}714}
715 715 
716RectF WebSelectOverlay::ComputeTouchHandleRect(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> touchHandle)716RectF WebSelectOverlay::ComputeTouchHandleRect(std::shared_ptr<OHOS::NWeb::NWebTouchHandleState> touchHandle)
@@ -1021,11 +1021,6 @@ void WebSelectOverlay::OnHandleMove(const RectF& handleRect, bool isFirst)
1021 CHECK_NULL_VOID(pattern);1021 CHECK_NULL_VOID(pattern);
1022 auto pipeline = PipelineContext::GetCurrentContext();1022 auto pipeline = PipelineContext::GetCurrentContext();
1023 CHECK_NULL_VOID(pipeline);1023 CHECK_NULL_VOID(pipeline);
1024- auto manager = pipeline->GetDragDropManager();
1025- CHECK_NULL_VOID(manager);
1026- if (pattern->isDragging_ || manager->IsDragged()) {
1027- return;
1028- }
1029 TouchInfo touchPoint;1024 TouchInfo touchPoint;
arkui-feature-manager
arkui-feature-managerarkui-feature-manager2025年12月17日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🟠 删除拖拽状态检查可能导致竞争条件

位置: L1024-L1028 | 严重程度: High

❓ 问题描述

代码移除了对DragDropManager的检查,这可能导致OnHandleMove与拖拽操作同时执行时产生竞争条件。特别是在多线程环境下,如果pattern->isDragging_或manager->IsDragged()状态在OnHandleMove执行过程中发生变化,可能导致不一致的UI状态或未定义行为。

💡 修复建议

建议保留拖拽检查逻辑,但使用适当的同步机制。如果确实需要移除,请确保:1)所有相关的共享状态访问都是原子的;2)添加适当的锁保护;3)或者重构为无锁算法。示例改进代码:

std::atomic<bool> isHandleMoving{false};
void WebSelectOverlay::OnHandleMove(const RectF& handleRect, bool isFirst) {
    // 使用原子操作检查和设置状态
    bool expected = false;
    if (!isHandleMoving.compare_exchange_strong(expected, true)) {
        return; // 已有操作在进行
    }
    // ... 原有逻辑 ...
    isHandleMoving = false;
}

likedislike
1030 touchPoint.id = 0;1025 touchPoint.id = 0;
1031 touchPoint.x = handleRect.GetX() - pattern->webOffset_.GetX();1026 touchPoint.x = handleRect.GetX() - pattern->webOffset_.GetX();
@@ -5708,6 +5708,39 @@ HWTEST_F(WebSelectOverlayTest, OnHandleMove, TestSize.Level1)
5708#endif5708#endif
5709}5709}
5710 5710 
5711+/**
5712+ * @tc.name: OnHandleMove_002
5713+ * @tc.desc: OnHandleMove.
5714+ * @tc.type: FUNC
5715+ */
5716+HWTEST_F(WebSelectOverlayTest, OnHandleMove_002, TestSize.Level1)
arkui-feature-manager
arkui-feature-managerarkui-feature-manager2025年12月17日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🟡 单元测试缺乏并发场景验证

位置: L5716-L5743 | 严重程度: Medium

❓ 问题描述

新增的测试用例OnHandleMove_002只验证了基本流程,没有测试拖拽与手柄移动的并发场景,无法充分验证移除拖拽检查后的安全性。

💡 修复建议

建议添加并发测试用例,模拟拖拽和手柄移动同时发生的情况:

HWTEST_F(WebSelectOverlayTest, OnHandleMove_Concurrent, TestSize.Level1) {
    // 使用多线程测试并发场景
    std::thread dragThread([&]() {
        // 模拟拖拽操作
    });
    std::thread handleThread([&]() {
        // 模拟手柄移动
        overlay.OnHandleMove(handleRect, true);
    });
    dragThread.join();
    handleThread.join();
    // 验证状态一致性
}

likedislike
5717+{
5718+#ifdef OHOS_STANDARD_SYSTEM
5719+ auto* stack = ViewStackProcessor::GetInstance();
5720+ ASSERT_NE(stack, nullptr);
5721+ auto nodeId = stack->ClaimNodeId();
5722+ auto frameNode =
5723+ FrameNode::GetOrCreateFrameNode(V2::WEB_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<WebPattern>(); });
5724+ stack->Push(frameNode);
5725+ auto webPattern = frameNode->GetPattern<WebPattern>();
5726+ ASSERT_NE(webPattern, nullptr);
5727+ webPattern->OnModifyDone();
5728+ WebSelectOverlay overlay(webPattern);
5729+ MockPipelineContext::SetUp();
5730+ auto pipeline = MockPipelineContext::GetCurrentContext();
5731+ RectF handleRect;
5732+ webPattern->SetOverlayCreating(false);
5733+ overlay.OnHandleMove(handleRect, true);
5734+ EXPECT_EQ(overlay.isCurrentStartHandleDragging_, false);
5735+ webPattern->SetOverlayCreating(true);
5736+ GestureEvent event;
5737+ overlay.OnHandleMoveStart(event, true);
5738+ overlay.OnHandleMove(handleRect, true);
5739+ EXPECT_EQ(overlay.isCurrentStartHandleDragging_, true);
5740+ MockPipelineContext::TearDown();
5741+#endif
5742+}
5743+ 
5711/**5744/**
5712 * @tc.name: OnHandleMoveStart_0015745 * @tc.name: OnHandleMoveStart_001
5713 * @tc.desc: OnHandleMoveStart.5746 * @tc.desc: OnHandleMoveStart.