Clicks can pass AppKit hit testing but fail to trigger onTapGesture when an NSHostingView has a nonzero offset within its window. This occurs in the Example macOS preview, where the hosting view is centered inside the preview window.
Reproduction
-
Use the following content in the Example app:
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.onTapGesture {
print("Tapped")
}
.padding()
}
}
-
Run the macOS preview with OpenSwiftUI and click the text. The same condition can be reproduced by placing an NSHostingView at a nonzero origin inside an AppKit container.
Expected: The tap handler runs once for each click. Hit testing stays correct when the hosting view or an ancestor moves.
Actual: The handler does not run. Event diagnostics show an empty BINDINGS section and root-phase ... failed, even though native hit testing finds the rendered text view.
Cause
MouseEvent.globalLocation uses window coordinates, but responder geometry remains relative to the hosting view. For example, the reported click is near (301.82, 199.96), while the text responder reports its global bounds at (16, 35) with size (76, 16).
NSHostingView does not conform to RootTransformProvider, and its as(...) method does not return that interface. RootTransform.value therefore falls back to an empty transform and omits the host-to-window mapping. Event binding fails before the gesture phase is evaluated.
Proposed fix
Add the root transform provider and delegate lookup, using the same window coordinate convention as mouse events. Observe changes to the hosting view's geometry in the window so that the transform is invalidated after host or ancestor movement.
Clicks can pass AppKit hit testing but fail to trigger
onTapGesturewhen anNSHostingViewhas a nonzero offset within its window. This occurs in the Example macOS preview, where the hosting view is centered inside the preview window.Reproduction
Use the following content in the Example app:
Run the macOS preview with OpenSwiftUI and click the text. The same condition can be reproduced by placing an
NSHostingViewat a nonzero origin inside an AppKit container.Expected: The tap handler runs once for each click. Hit testing stays correct when the hosting view or an ancestor moves.
Actual: The handler does not run. Event diagnostics show an empty
BINDINGSsection androot-phase ... failed, even though native hit testing finds the rendered text view.Cause
MouseEvent.globalLocationuses window coordinates, but responder geometry remains relative to the hosting view. For example, the reported click is near(301.82, 199.96), while the text responder reports its global bounds at(16, 35)with size(76, 16).NSHostingViewdoes not conform toRootTransformProvider, and itsas(...)method does not return that interface.RootTransform.valuetherefore falls back to an empty transform and omits the host-to-window mapping. Event binding fails before the gesture phase is evaluated.Proposed fix
Add the root transform provider and delegate lookup, using the same window coordinate convention as mouse events. Observe changes to the hosting view's geometry in the window so that the transform is invalidated after host or ancestor movement.