| | |
| | | import CoreGraphics |
| | | import Foundation |
| | | import AlignerCore |
| | | |
| | |
| | | case layout |
| | | case candidateFiltering |
| | | case activation |
| | | case spaceFilter |
| | | case splitView |
| | | } |
| | | |
| | | final class LiveQuickSwitchSnapshotLoader: QuickSwitchSnapshotLoading { |
| | |
| | | private let appCount: Int |
| | | private let windowsPerApp: Int |
| | | private let mode: FixtureQuickSwitchMode |
| | | private let usesMultipleDisplays: Bool |
| | | |
| | | init(appCount: Int, windowsPerApp: Int = 1, mode: FixtureQuickSwitchMode = .layout) { |
| | | init( |
| | | appCount: Int, |
| | | windowsPerApp: Int = 1, |
| | | mode: FixtureQuickSwitchMode = .layout, |
| | | usesMultipleDisplays: Bool = false |
| | | ) { |
| | | self.appCount = max(1, appCount) |
| | | self.windowsPerApp = max(1, windowsPerApp) |
| | | self.mode = mode |
| | | self.usesMultipleDisplays = usesMultipleDisplays |
| | | } |
| | | |
| | | func snapshot() throws -> QuickSwitchSnapshotLoad { |
| | |
| | | if mode == .activation { |
| | | return activationSnapshot() |
| | | } |
| | | if mode == .spaceFilter { |
| | | return spaceFilterSnapshot() |
| | | } |
| | | if mode == .splitView { |
| | | return splitViewSnapshot() |
| | | } |
| | | |
| | | return layoutSnapshot() |
| | | } |
| | | |
| | | private func layoutSnapshot() -> QuickSwitchSnapshotLoad { |
| | | let displayUUID = "fixture-display-a" |
| | | let displays = [ |
| | | AlignerDisplay( |
| | | uuid: displayUUID, |
| | | physical: true, |
| | | spaces: [ |
| | | AlignerSpace(id: 1, type: .user, displayUUID: displayUUID, index: 1), |
| | | AlignerSpace(id: 2, type: .fullscreen, displayUUID: displayUUID, index: 2), |
| | | AlignerSpace(id: 3, type: .user, displayUUID: displayUUID, index: 3) |
| | | ] |
| | | ) |
| | | ] |
| | | let displays = layoutDisplays() |
| | | let spaceIDs: [UInt64] = usesMultipleDisplays ? [1, 2, 3, 4, 5] : [1, 2, 3] |
| | | let windows = (0..<appCount).flatMap { index in |
| | | let app = AlignerApp( |
| | | bundleIdentifier: "com.example.fixture.\(String(format: "%03d", index))", |
| | |
| | | |
| | | return (0..<windowsPerApp).map { windowIndex in |
| | | let spaceSeed = index + windowIndex |
| | | let spaceID = spaceSeed % 5 == 0 ? UInt64(2) : UInt64(spaceSeed % 2 == 0 ? 1 : 3) |
| | | let spaceID = usesMultipleDisplays |
| | | ? spaceIDs[spaceSeed % spaceIDs.count] |
| | | : UInt64(spaceSeed % 5 == 0 ? 2 : spaceSeed % 2 == 0 ? 1 : 3) |
| | | return AlignerWindow( |
| | | id: UInt32(10_000 + index * 100 + windowIndex), |
| | | app: app, |
| | |
| | | |
| | | return QuickSwitchSnapshotLoad( |
| | | snapshot: QuickSwitchSnapshotBuilder.snapshot(displays: displays, windows: windows), |
| | | currentSpaceIDs: [2] |
| | | currentSpaceIDs: usesMultipleDisplays ? [2, 4] : [2] |
| | | ) |
| | | } |
| | | |
| | | private func layoutDisplays() -> [AlignerDisplay] { |
| | | let displayAUUID = "fixture-display-a" |
| | | guard usesMultipleDisplays else { |
| | | return [ |
| | | AlignerDisplay( |
| | | uuid: displayAUUID, |
| | | physical: true, |
| | | spaces: [ |
| | | AlignerSpace(id: 1, type: .user, displayUUID: displayAUUID, index: 1), |
| | | AlignerSpace(id: 2, type: .fullscreen, displayUUID: displayAUUID, index: 2), |
| | | AlignerSpace(id: 3, type: .user, displayUUID: displayAUUID, index: 3) |
| | | ] |
| | | ) |
| | | ] |
| | | } |
| | | |
| | | let displayBUUID = "fixture-display-b" |
| | | return [ |
| | | AlignerDisplay( |
| | | uuid: displayAUUID, |
| | | physical: true, |
| | | spaces: [ |
| | | AlignerSpace(id: 1, type: .user, displayUUID: displayAUUID, index: 1), |
| | | AlignerSpace(id: 2, type: .fullscreen, displayUUID: displayAUUID, index: 2), |
| | | AlignerSpace(id: 3, type: .user, displayUUID: displayAUUID, index: 3) |
| | | ] |
| | | ), |
| | | AlignerDisplay( |
| | | uuid: displayBUUID, |
| | | physical: true, |
| | | spaces: [ |
| | | AlignerSpace(id: 4, type: .user, displayUUID: displayBUUID, index: 1), |
| | | AlignerSpace(id: 5, type: .user, displayUUID: displayBUUID, index: 2) |
| | | ] |
| | | ) |
| | | ] |
| | | } |
| | | |
| | | private func candidateFilteringSnapshot() -> QuickSwitchSnapshotLoad { |
| | |
| | | WindowEnumerationRecord( |
| | | id: 20_015, |
| | | app: app, |
| | | title: "CG-only Offscreen Rejected", |
| | | title: "CG-only Space-backed Candidate", |
| | | size: CGSize(width: 900, height: 600), |
| | | subrole: .standard, |
| | | hasAXBacking: false, |
| | |
| | | currentSpaceIDs: [1] |
| | | ) |
| | | } |
| | | |
| | | private func spaceFilterSnapshot() -> QuickSwitchSnapshotLoad { |
| | | let displayAUUID = "fixture-display-a" |
| | | let displayBUUID = "fixture-display-b" |
| | | let displays = [ |
| | | AlignerDisplay( |
| | | uuid: displayAUUID, |
| | | physical: true, |
| | | spaces: [ |
| | | AlignerSpace(id: 1, type: .user, displayUUID: displayAUUID, index: 1), |
| | | AlignerSpace(id: 2, type: .user, displayUUID: displayAUUID, index: 2), |
| | | AlignerSpace(id: 3, type: .user, displayUUID: displayAUUID, index: 3) |
| | | ] |
| | | ), |
| | | AlignerDisplay( |
| | | uuid: displayBUUID, |
| | | physical: true, |
| | | spaces: [ |
| | | AlignerSpace(id: 4, type: .user, displayUUID: displayBUUID, index: 1), |
| | | AlignerSpace(id: 5, type: .fullscreen, displayUUID: displayBUUID, index: 2) |
| | | ] |
| | | ) |
| | | ] |
| | | |
| | | let alphaApp = AlignerApp( |
| | | bundleIdentifier: "com.example.spacefilter.alpha", |
| | | name: "Alpha Space App", |
| | | category: .finder, |
| | | processIdentifier: 50_001 |
| | | ) |
| | | let betaApp = AlignerApp( |
| | | bundleIdentifier: "com.example.spacefilter.beta", |
| | | name: "Beta Space App", |
| | | category: .documentNotes, |
| | | processIdentifier: 50_002 |
| | | ) |
| | | let fullscreenApp = AlignerApp( |
| | | bundleIdentifier: "com.example.spacefilter.fullscreen", |
| | | name: "Fullscreen Solo App", |
| | | category: .generic, |
| | | processIdentifier: 50_003 |
| | | ) |
| | | let noSpaceApp = AlignerApp( |
| | | bundleIdentifier: "com.example.spacefilter.nospace", |
| | | name: "No Space App", |
| | | category: .generic, |
| | | processIdentifier: 50_004 |
| | | ) |
| | | |
| | | let windows = [ |
| | | AlignerWindow( |
| | | id: 50_101, |
| | | app: alphaApp, |
| | | title: "Alpha A1 Primary", |
| | | spaceIDs: [1] |
| | | ), |
| | | AlignerWindow( |
| | | id: 50_102, |
| | | app: alphaApp, |
| | | title: "Alpha A1 Secondary", |
| | | isMinimized: true, |
| | | spaceIDs: [1] |
| | | ), |
| | | AlignerWindow( |
| | | id: 50_201, |
| | | app: betaApp, |
| | | title: "Beta A1 Shared", |
| | | spaceIDs: [1] |
| | | ), |
| | | AlignerWindow( |
| | | id: 50_202, |
| | | app: betaApp, |
| | | title: "Beta A2 Only", |
| | | spaceIDs: [2] |
| | | ), |
| | | AlignerWindow( |
| | | id: 50_501, |
| | | app: fullscreenApp, |
| | | title: "Fullscreen B2 Solo", |
| | | isFullscreen: true, |
| | | spaceIDs: [5] |
| | | ), |
| | | AlignerWindow( |
| | | id: 50_901, |
| | | app: noSpaceApp, |
| | | title: "No Space Diagnostic", |
| | | spaceIDs: [] |
| | | ) |
| | | ] |
| | | |
| | | return QuickSwitchSnapshotLoad( |
| | | snapshot: QuickSwitchSnapshotBuilder.snapshot(displays: displays, windows: windows), |
| | | currentSpaceIDs: [1, 4] |
| | | ) |
| | | } |
| | | |
| | | private func splitViewSnapshot() -> QuickSwitchSnapshotLoad { |
| | | let displayUUID = "fixture-display-a" |
| | | let displays = [ |
| | | AlignerDisplay( |
| | | uuid: displayUUID, |
| | | physical: true, |
| | | spaces: [ |
| | | AlignerSpace(id: 1, type: .user, displayUUID: displayUUID, index: 1), |
| | | AlignerSpace(id: 2, type: .fullscreen, displayUUID: displayUUID, index: 2), |
| | | AlignerSpace(id: 3, type: .fullscreen, displayUUID: displayUUID, index: 3) |
| | | ] |
| | | ) |
| | | ] |
| | | |
| | | let normalApp = AlignerApp( |
| | | bundleIdentifier: "com.example.split.normal", |
| | | name: "普通窗口", |
| | | category: .generic, |
| | | processIdentifier: 60_001 |
| | | ) |
| | | let leftApp = AlignerApp( |
| | | bundleIdentifier: "com.example.split.left", |
| | | name: "左侧应用", |
| | | category: .finder, |
| | | processIdentifier: 60_002 |
| | | ) |
| | | let rightApp = AlignerApp( |
| | | bundleIdentifier: "com.example.split.right", |
| | | name: "右侧应用", |
| | | category: .documentNotes, |
| | | processIdentifier: 60_003 |
| | | ) |
| | | let singleFullscreenApp = AlignerApp( |
| | | bundleIdentifier: "com.example.split.single", |
| | | name: "单全屏", |
| | | category: .generic, |
| | | processIdentifier: 60_004 |
| | | ) |
| | | |
| | | let windows = [ |
| | | AlignerWindow( |
| | | id: 60_101, |
| | | app: normalApp, |
| | | title: "普通窗口", |
| | | frame: CGRect(x: 80, y: 120, width: 900, height: 620), |
| | | spaceIDs: [1] |
| | | ), |
| | | AlignerWindow( |
| | | id: 60_202, |
| | | app: rightApp, |
| | | title: "右侧 Split View", |
| | | isFullscreen: true, |
| | | frame: CGRect(x: 960, y: 0, width: 960, height: 1080), |
| | | spaceIDs: [2] |
| | | ), |
| | | AlignerWindow( |
| | | id: 60_201, |
| | | app: leftApp, |
| | | title: "左侧 Split View", |
| | | isFullscreen: true, |
| | | frame: CGRect(x: 0, y: 0, width: 960, height: 1080), |
| | | spaceIDs: [2] |
| | | ), |
| | | AlignerWindow( |
| | | id: 60_301, |
| | | app: singleFullscreenApp, |
| | | title: "单全屏", |
| | | isFullscreen: true, |
| | | frame: CGRect(x: 0, y: 0, width: 1920, height: 1080), |
| | | spaceIDs: [3] |
| | | ) |
| | | ] |
| | | |
| | | return QuickSwitchSnapshotLoad( |
| | | snapshot: QuickSwitchSnapshotBuilder.snapshot(displays: displays, windows: windows), |
| | | currentSpaceIDs: [1] |
| | | ) |
| | | } |
| | | } |