#if os(macOS) import AppKit import SwiftUI /// The mini window pressed as a person presses it, for CallsInterop's /// --mini-clicks (2026-10-05, Paul: "Sometimes I can't click the mini /// window"). A real panel, on screen, in an app that is not active (the /// harness never activates), with a call behind it; presses made as /// NSEvents and sent through the window, so AppKit's hit-testing, first /// mouse, the surface's tracking loop and SwiftUI's buttons all take /// part. What each press did is read from the actions it called and /// from the window's frame. This Mac refuses screen capture and event /// posting to this process, so these presses do not pass through the /// window server; everything after it they do. @_spi(Fixtures) @MainActor public enum MiniWindowProbe { public struct Result: Sendable { public let name: String public let passed: Bool public let detail: String } public static func run(call: Call) async -> [Result] { var results: [Result] = [] for width in [MiniWindowRules.minimumWidth, MiniWindowRules.size.width, 480] { results += await pressWindow(call: call, width: width) } results += await pressTab(call: call) return results } static func trace(_ line: String) { FileHandle.standardError.write(Data(("mini-clicks: " + line + "\n").utf8)) } private final class Recorder { var calls: [String] = [] } private static func panel(call: Call, recorder: Recorder) -> MiniWindowPanel { MiniWindowPanel( call: call, actions: MiniWindowActions( leave: { recorder.calls.append("leave") }, open: { recorder.calls.append("open") }, moved: { option in recorder.calls.append(option ? "moved-option" : "moved") }, resized: { recorder.calls.append("resized") }, collapse: { recorder.calls.append("collapse") }, expand: { recorder.calls.append("expand") }, tabReleased: { recorder.calls.append("tabReleased") })) } private static func pressWindow(call: Call, width: CGFloat) async -> [Result] { let recorder = Recorder() let size = CGSize(width: width, height: width / MiniWindowRules.aspect) let panel = panel(call: call, recorder: recorder) let visible = NSScreen.main?.visibleFrame ?? CGRect(x: 0, y: 0, width: 1440, height: 900) let home = CGRect(x: visible.midX - size.width / 2, y: visible.midY - size.height / 2, width: size.width, height: size.height) panel.expand(to: home, animated: false) panel.reassert(because: "probe") try? await Task.sleep(for: .milliseconds(300)) var results: [Result] = [] let tag = "\(Int(width))" trace("window \(tag) up at \(panel.frame)") func check(_ name: String, _ expected: String, _ act: () async -> Void, frame: ((CGRect) -> Bool)? = nil) async { panel.expand(to: home, animated: false) recorder.calls = [] trace("\(tag) \(name)") await act() try? await Task.sleep(for: .milliseconds(80)) let got = recorder.calls.joined(separator: ",") let frameOK = frame?(panel.frame) ?? true results.append( Result( name: "\(tag) \(name)", passed: got == expected && frameOK, detail: "expected \(expected), got [\(got)], frame \(panel.frame)")) } let w = size.width, h = size.height // Hover off: the picture alone. panel.content.hovering = false try? await Task.sleep(for: .milliseconds(100)) await check("click in the middle brings the call forward", "open") { await click(panel, at: CGPoint(x: w / 2, y: h / 2)) } await check("click on the name brings the call forward", "open") { await click(panel, at: CGPoint(x: 24, y: 16)) } await check("click near the top left brings the call forward", "open") { await click(panel, at: CGPoint(x: 20, y: h - 20)) } await check("a shaky click is still a click", "open") { await press(panel, from: CGPoint(x: w / 2, y: h / 2), by: CGSize(width: 3, height: -2)) } await check("a drag from the middle moves it", "moved", { await press(panel, from: CGPoint(x: w / 2, y: h / 2), by: CGSize(width: 60, height: -40)) }, frame: { abs($0.minX - (home.minX + 60)) < 1 && abs($0.minY - (home.minY - 40)) < 1 }) await check("a drag from the right edge resizes it", "resized", { await press(panel, from: CGPoint(x: w - 3, y: h / 2), by: CGSize(width: 40, height: 0)) }, frame: { $0.width > w + 20 || w >= MiniWindowRules.size(width: 10_000, in: visible).width }) await check("a drag from the bottom left corner resizes it", "resized", { await press(panel, from: CGPoint(x: 3, y: 3), by: CGSize(width: -30, height: -20)) }, frame: { $0.width > w + 10 || w >= MiniWindowRules.size(width: 10_000, in: visible).width }) // Marks over the picture are not controls: muted, and someone // still connecting (the ear), a press on them is the window's. call.showFixtureSelf(muted: true, cameraOff: false, sharingScreen: false) call.showFixtureConnecting(["li"]) try? await Task.sleep(for: .milliseconds(200)) await check("click on the Muted mark brings the call forward", "open") { await click(panel, at: CGPoint(x: 10 + 16, y: h - 10 - 16)) } await check("click on the connecting ear brings the call forward", "open") { await click(panel, at: CGPoint(x: w - 10 - 16, y: h - 10 - 16)) } await check("a drag from the Muted mark moves it", "moved") { await press(panel, from: CGPoint(x: 10 + 16, y: h - 10 - 16), by: CGSize(width: -50, height: -30)) } call.showFixtureSelf(muted: false, cameraOff: false, sharingScreen: false) call.showFixtureConnecting([]) // Hover on: the controls (44 pt, 8 apart, 10 in from the top right: // Collapse, Mute, Leave) answer the first click. panel.content.hovering = true try? await Task.sleep(for: .milliseconds(200)) let row = h - 10 - 22 await check("first click on Leave", "leave") { await click(panel, at: CGPoint(x: w - 10 - 22, y: row), control: true) } await check("first click on Collapse", "collapse") { await click(panel, at: CGPoint(x: w - 10 - 44 - 8 - 44 - 8 - 22, y: row), control: true) } let before = call.muted await click(panel, at: CGPoint(x: w - 10 - 44 - 8 - 22, y: row), control: true) try? await Task.sleep(for: .milliseconds(80)) results.append(Result(name: "\(tag) first click on Mute", passed: call.muted != before, detail: "muted \(before) -> \(call.muted)")) if call.muted != before { call.showFixtureSelf(muted: before, cameraOff: false, sharingScreen: false) } await check("click in the middle with the controls up", "open") { await click(panel, at: CGPoint(x: w / 2, y: h / 2)) } panel.dismiss() return results } private static func pressTab(call: Call) async -> [Result] { let recorder = Recorder() let panel = panel(call: call, recorder: recorder) let visible = NSScreen.main?.visibleFrame ?? CGRect(x: 0, y: 0, width: 1440, height: 900) let expanded = CGRect(origin: CGPoint(x: visible.maxX - 340, y: visible.minY + 20), size: MiniWindowRules.size) let tab = MiniWindowTab.dock(expanded, in: visible).1 var results: [Result] = [] func reset() { panel.collapse(to: tab, expanded: expanded) recorder.calls = [] } reset() panel.reassert(because: "probe") try? await Task.sleep(for: .milliseconds(300)) let middle = CGPoint(x: tab.width / 2, y: tab.height / 2) await click(panel, at: middle) try? await Task.sleep(for: .milliseconds(80)) results.append(Result(name: "tab click opens the window", passed: recorder.calls == ["expand"], detail: "\(recorder.calls)")) reset() await click(panel, at: middle, count: 2) try? await Task.sleep(for: .milliseconds(80)) results.append(Result(name: "tab double click opens the call", passed: recorder.calls.last == "open", detail: "\(recorder.calls)")) reset() await press(panel, from: CGPoint(x: 3, y: middle.y), by: CGSize(width: -120, height: 30)) try? await Task.sleep(for: .milliseconds(80)) results.append(Result(name: "tab drag, even from its edge, is a drag", passed: recorder.calls == ["tabReleased"], detail: "\(recorder.calls)")) panel.dismiss() return results } private static func click(_ panel: NSWindow, at point: CGPoint, count: Int = 1, control: Bool = false) async { for n in 1...count { await press(panel, from: point, by: .zero, clickCount: n, control: control) } } /// A press at `point` in the window, moved by `by` in steps, released: /// the down sent through the window as AppKit would, the drags and /// the up queued for the surface's tracking loop, in screen points. /// A control's up goes to the window, where SwiftUI's button reads it; /// the surface's tracking loop reads screen points from window-less /// events (SurfaceView.screenLocation). private static func press( _ panel: NSWindow, from point: CGPoint, by: CGSize, clickCount: Int = 1, control: Bool = false ) async { let screenStart = panel.convertPoint(toScreen: point) let now = ProcessInfo.processInfo.systemUptime func event(_ type: NSEvent.EventType, at location: CGPoint, window: Bool) -> NSEvent? { NSEvent.mouseEvent( with: type, location: location, modifierFlags: [], timestamp: now, windowNumber: window ? panel.windowNumber : 0, context: nil, eventNumber: 0, clickCount: clickCount, pressure: type == .leftMouseUp ? 0 : 1) } let steps = by == .zero ? 0 : 5 for i in stride(from: 1, through: steps, by: 1) { let f = CGFloat(i) / CGFloat(steps) if let drag = event(.leftMouseDragged, at: CGPoint(x: screenStart.x + by.width * f, y: screenStart.y + by.height * f), window: false) { NSApp.postEvent(drag, atStart: false) } } if control, let up = event(.leftMouseUp, at: point, window: true) { NSApp.postEvent(up, atStart: false) } else if let up = event(.leftMouseUp, at: CGPoint(x: screenStart.x + by.width, y: screenStart.y + by.height), window: false) { NSApp.postEvent(up, atStart: false) } if let down = event(.leftMouseDown, at: point, window: true) { panel.sendEvent(down) } // A SwiftUI button acts on the up, which it reads from the queue // itself; let the run loop turn. try? await Task.sleep(for: .milliseconds(60)) } } #endif