Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,16 @@ final class KeyboardStageMTKView: MTKView {
private var retryTask: Task<Void, Never>?
private var reportedWindowX = SIMD2<Float>(0, 1)

/// The renderer is visual output only; the native semantic overlay stacked
/// above it owns pointer interaction and accessibility. As a real `NSView`
/// this would otherwise return itself for every point inside the keyboard
/// and swallow clicks before those hit targets could see them, so pointer
/// presses worked in the SwiftUI fallback and silently failed whenever
/// Metal was active.
override func hitTest(_: NSPoint) -> NSView? {
nil
}

override func viewDidMoveToWindow() {
super.viewDidMoveToWindow()
stopObservingWindow()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
import AppKit
@testable import KeyPathAppKit
import XCTest

final class KeyboardStageInteractionTests: XCTestCase {
/// The Metal view must stay transparent to the mouse. It is a real NSView,
/// so without this it returns itself for every point inside the keyboard
/// and swallows clicks before the semantic overlay's per-key hit targets
/// receive them — pointer presses then work only in the SwiftUI fallback.
@MainActor
func testMetalStageViewPassesPointerEventsToTheOverlayAbove() {
let view = KeyboardStageMTKView(
frame: NSRect(x: 0, y: 0, width: 400, height: 300)
)

XCTAssertNil(view.hitTest(NSPoint(x: 200, y: 150)))
XCTAssertNil(view.hitTest(NSPoint(x: 1, y: 1)))
}

func testKeyDownFeedbackIsImmediate() {
var presentation = KeyboardStageInteractionPresentation()
let pressed = KeyboardStageInteractionState(
Expand Down
Loading