Skip to content
Merged
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 @@ -131,11 +131,22 @@ enum DebugMouse {
) else { return nil }
guard [.otherMouseDown, .otherMouseUp, .otherMouseDragged].contains(type) else { return event }
// NSEvent.mouseEvent leaves buttonNumber 0 on otherMouse events; the
// middle button is 2, which the views that handle it check. The
// copy keeps the window and the window-local point (on a Mac with a
// display; DebugMouseButtonTests).
// middle button is 2, which the views that handle it check. AppKit
// maps the copy back through the window server's frame for the window,
// which for a window not on screen is not the window's own frame, so the
// copy is moved by what that mapping got wrong (DebugMouseButtonTests).
guard let cg = event.cgEvent?.copy() else { return nil }
cg.setIntegerValueField(.mouseEventButtonNumber, value: 2)
return keepingWindowPoint(cg, event.locationInWindow)
}

/// `cg` as an NSEvent at window-local `base`: built once, then moved by the
/// difference between `base` and the point AppKit mapped (global y grows down).
static func keepingWindowPoint(_ cg: CGEvent, _ base: NSPoint) -> NSEvent? {
guard let first = NSEvent(cgEvent: cg) else { return nil }
let miss = NSPoint(x: base.x - first.locationInWindow.x, y: base.y - first.locationInWindow.y)
guard miss != .zero else { return first }
cg.location = CGPoint(x: cg.location.x + miss.x, y: cg.location.y - miss.y)
return NSEvent(cgEvent: cg)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,14 @@ import Testing
with: type, location: at, modifierFlags: [], timestamp: ProcessInfo.processInfo.systemUptime,
windowNumber: h.window.windowNumber, context: nil, eventNumber: 0, clickCount: 1,
pressure: type == .otherMouseUp ? 0 : 1))
// As debug.mouse makes them: NSEvent.mouseEvent leaves buttonNumber 0, the middle button is 2.
// As debug.mouse makes them (DebugMouse.keepingWindowPoint): NSEvent.mouseEvent leaves
// buttonNumber 0, the middle button is 2, and the copy is moved by what AppKit's mapping
// through the window server's frame (not this unshown window's) got wrong.
let cg = try #require(made.cgEvent?.copy())
cg.setIntegerValueField(.mouseEventButtonNumber, value: 2)
let first = try #require(NSEvent(cgEvent: cg))
cg.location = CGPoint(x: cg.location.x + at.x - first.locationInWindow.x,
y: cg.location.y - (at.y - first.locationInWindow.y))
let event = try #require(NSEvent(cgEvent: cg))
#expect(event.buttonNumber == 2)
#expect(event.locationInWindow == at)
Expand Down
Loading