classifyDesktopHit function

MyDesktopHitKind classifyDesktopHit(
  1. Offset globalPosition
)

通过 hit test 分类 globalPosition 的交互属性。

检测顺序:

  1. RenderEditable → 输入框
  2. RenderMyDoubleClickConsumeZone → 显式标记
  3. RenderSemanticsGestureHandler.onTap 非空 → InkWell / 带 onTap 或 onTapDown 的 GestureDetector

Scrollable 等只有 scroll/drag 语义的 handler(onTap == null)不算交互, 这样列表空白处仍能双击最大化。

Flutter 只要存在 TapGestureRecognizer(包括仅 onSecondaryTapDown) 就会填上非空 onTap。整页右键请用 showRightMenu(内部是 Listener), 不要自行用 GestureDetector(onSecondaryTapDown) 包一整页。整页 GestureDetector(onTap: unfocus) 同样会关掉空白处最大化。

Implementation

MyDesktopHitKind classifyDesktopHit(Offset globalPosition) {
  final viewId =
      WidgetsBinding.instance.platformDispatcher.implicitView?.viewId;
  if (viewId == null) return MyDesktopHitKind.background;

  final result = HitTestResult();
  WidgetsBinding.instance.hitTestInView(result, globalPosition, viewId);

  var hasEditable = false;
  var hasConsumeZone = false;
  var hasTapInteractive = false;

  for (final entry in result.path) {
    final target = entry.target;
    if (target is RenderEditable) hasEditable = true;
    if (target is RenderMyDoubleClickConsumeZone) hasConsumeZone = true;
    if (target is RenderSemanticsGestureHandler && target.onTap != null) {
      hasTapInteractive = true;
    }
  }

  if (hasEditable) return MyDesktopHitKind.editable;
  if (hasConsumeZone || hasTapInteractive) {
    return MyDesktopHitKind.interactive;
  }
  return MyDesktopHitKind.background;
}