Add watchOS and macOS runners

Seto Elkahfi committed Jul 30, 2026 at 20:49 UTC 349e7c079f6105059b710ed7ca912773d538e727
26 files changed +1067 -17
README.md
+7 -4
@@ -49,17 +49,20 @@ Runners/
49 ├── Shared/ # transport + RPC server
50 ├── iOS/ # iOS / iPadOS host app
51 ├── tvOS/ # tvOS host app
52 -└── visionOS/ # visionOS host app
52 +├── visionOS/ # visionOS host app
53 +├── macOS/ # macOS host app
54 +└── watchOS/ # watchOS host app
55 ```
56
57 Each platform gets its own application and UI-test targets and a matching
56 -scheme (`ControlKit-iOS`, `ControlKit-tvOS`, `ControlKit-visionOS`) while
57 -importing `XCRSControlKit` and sharing the transport. See `Runners/README.md`.
58 +scheme (`ControlKit-iOS`, `ControlKit-tvOS`, `ControlKit-visionOS`,
59 +`ControlKit-macOS`, `ControlKit-watchOS`) while importing `XCRSControlKit` and
60 +sharing the transport. See `Runners/README.md`.
61
62 ## Status
63
64 The package provides the public cross-platform contract. Native ControlKit
62 -runners currently support iOS, iPadOS, tvOS, and visionOS.
65 +runners currently support iOS, iPadOS, tvOS, visionOS, macOS, and watchOS.
66
67 ## License
68
Runners/README.md
+5 -1
@@ -15,7 +15,9 @@ Runners/
15 │ └── ControlKitRunnerUITests.swift
16 ├── iOS/ # iOS / iPadOS host app + assets
17 ├── tvOS/ # tvOS host app + assets
18 -└── visionOS/ # visionOS host app + assets
18 +├── visionOS/ # visionOS host app + assets
19 +├── macOS/ # macOS host app + assets
20 +└── watchOS/ # watchOS host app + assets
21 ```
22
23 ## Targets and schemes
@@ -25,6 +27,8 @@ Runners/
27 | `ControlKit-iOS` | `ControlKit-iOS` | `ControlKit-iOS-UITests` | iOS / iPadOS |
28 | `ControlKit-tvOS` | `ControlKit-tvOS` | `ControlKit-tvOS-UITests` | tvOS |
29 | `ControlKit-visionOS` | `ControlKit-visionOS` | `ControlKit-visionOS-UITests` | visionOS |
30 +| `ControlKit-macOS` | `ControlKit-macOS` | `ControlKit-macOS-UITests` | macOS |
31 +| `ControlKit-watchOS` | `ControlKit-watchOS` | `ControlKit-watchOS-UITests` | watchOS |
32
33 Each UI-test target compiles the shared `Shared/` sources for its platform, so
34 platform behaviour is selected at compile time via `#if os(...)` in
Runners/Shared/ControlKitRPCServer.swift
+12 -1
@@ -78,6 +78,10 @@ final class ControlKitRPCServer {
78 return .tvOS
79 #elseif os(visionOS)
80 return .visionOS
81 + #elseif os(macOS)
82 + return .macOS
83 + #elseif os(watchOS)
84 + return .watchOS
85 #else
86 return .iOS
87 #endif
@@ -104,12 +108,19 @@ final class ControlKitRPCServer {
108 XCUIApplication(bundleIdentifier: bundleIdentifier).terminate()
109 return try response(result: ["success": true], id: request.id)
110 case "device.io.tap":
107 - #if os(tvOS) || os(visionOS)
111 + #if os(tvOS) || os(visionOS) || os(macOS)
112 throw RunnerError.unsupportedInteraction("touch")
113 #else
114 try tap(request.params)
115 return try response(result: ["success": true], id: request.id)
116 #endif
117 + case "device.io.click":
118 + #if os(macOS)
119 + try tap(request.params)
120 + return try response(result: ["success": true], id: request.id)
121 + #else
122 + throw RunnerError.unsupportedInteraction("pointer click")
123 + #endif
124 case "device.io.spatial.tap":
125 #if os(visionOS)
126 try tap(request.params)
Runners/XCRSControlKitRunner.xcodeproj/project.pbxproj
+449 -11
@@ -11,21 +11,33 @@
11 0DFC449880A304B5154D7F6D /* XCRSControlKit in Frameworks */ = {isa = PBXBuildFile; productRef = BE99FEAB3F75651FC71BB9B5 /* XCRSControlKit */; };
12 100DCE12F169B8A38E219931 /* ControlKitRPCServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976BFE251DB7DC2248C8D0E7 /* ControlKitRPCServer.swift */; };
13 25622E0215D89F31880E6356 /* ControlKitRunnerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D582F818EB333BD812EBDAC7 /* ControlKitRunnerUITests.swift */; };
14 + 2CE41182704301ED3E17F12A /* NIOCore in Frameworks */ = {isa = PBXBuildFile; productRef = 611C969D93EC290726A7395E /* NIOCore */; };
15 3CAE36F48F2BB14EC17B1A49 /* NIOHTTP1 in Frameworks */ = {isa = PBXBuildFile; productRef = 39DF23C6EF63909919D192E1 /* NIOHTTP1 */; };
16 + 42F868C46B85D81A82D325F0 /* ControlKitRPCServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976BFE251DB7DC2248C8D0E7 /* ControlKitRPCServer.swift */; };
17 + 49C565818AD8C7C3D85C498E /* ControlKitRunnerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D582F818EB333BD812EBDAC7 /* ControlKitRunnerUITests.swift */; };
18 4D29102252109822A895B881 /* NIOPosix in Frameworks */ = {isa = PBXBuildFile; productRef = C9A26D0E7AB404E7BE27C778 /* NIOPosix */; };
19 + 560FDA8EB7B9DE368869D155 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FD4E3603A115950345EC4C96 /* Assets.xcassets */; };
20 + 561834A353CBD37B8354A58E /* NIOCore in Frameworks */ = {isa = PBXBuildFile; productRef = 786AF91DEFF9CFAF6733FE5D /* NIOCore */; };
21 57C6D92B45E7092A5C2AD7D2 /* ControlKitRunnerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FB5CFB03469D6F6B4B90338 /* ControlKitRunnerApp.swift */; };
22 57E28C91935955E0FCA55C21 /* NIOCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1EEBDB1A27DC2D28A6BB1B95 /* NIOCore */; };
23 5C1F1D551479D29CA351EEF1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E395E1A9D0B3259F9C816109 /* Assets.xcassets */; };
24 + 607F9363076F0FE76CA24A73 /* ControlKitRunnerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5591C7FEF7205CCA88C10507 /* ControlKitRunnerApp.swift */; };
25 673EB3CCA913F73C710B72B0 /* NIOCore in Frameworks */ = {isa = PBXBuildFile; productRef = 58494EA2BBD98AE84158250F /* NIOCore */; };
26 6D60E555ABB299495F608B27 /* NIOPosix in Frameworks */ = {isa = PBXBuildFile; productRef = 2B7D7F431DC211BEDBFC374A /* NIOPosix */; };
27 6F0CF3B6D51AEB5C4F3E1827 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 06ABEBF2BC26029BF199977C /* README.md */; };
28 7CAF0B42FF68BF36CAC8C8CD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A09FB52496A952CB13C163B /* Assets.xcassets */; };
29 7D3C77F9ABF4E0CD672DCEF5 /* NIOHTTP1 in Frameworks */ = {isa = PBXBuildFile; productRef = 84A03CA7B1A8BF405AD3F3C4 /* NIOHTTP1 */; };
30 + 82D074F9A9D0F5FD6F00CA7B /* ControlKitRPCServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976BFE251DB7DC2248C8D0E7 /* ControlKitRPCServer.swift */; };
31 8F79A6E8A60191E7A095D2F2 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 3DFF0D230E8E7D8DF4E8AF86 /* README.md */; };
32 93235E8B38222B9CC779ED84 /* XCRSControlKit in Frameworks */ = {isa = PBXBuildFile; productRef = 50AB05BF2C324210174A3476 /* XCRSControlKit */; };
33 9540EFD6CC87D6DEF2FBFC0F /* ControlKitRPCServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 976BFE251DB7DC2248C8D0E7 /* ControlKitRPCServer.swift */; };
34 986705883AA98C348CFE6E72 /* XCRSControlKit in Frameworks */ = {isa = PBXBuildFile; productRef = 17A1603CDD0A79E07FAC7D43 /* XCRSControlKit */; };
35 + 9CC0F626565F3ADFBCAEFE1C /* XCRSControlKit in Frameworks */ = {isa = PBXBuildFile; productRef = F1634B11C3B52F3F9511DF74 /* XCRSControlKit */; };
36 + 9DF1151412A41AC8D2EDE2D5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 40A16F9F72DA073E165B0149 /* Assets.xcassets */; };
37 9DFD228E556F05433F75A568 /* NIOHTTP1 in Frameworks */ = {isa = PBXBuildFile; productRef = EE8C054B1BC0620402AEA51B /* NIOHTTP1 */; };
38 + A5BD016357891BCC301E3E4E /* ControlKitRunnerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6FBC92946E0D2F913F6A1E /* ControlKitRunnerApp.swift */; };
39 + AABA08D219C9E167F666E012 /* NIOHTTP1 in Frameworks */ = {isa = PBXBuildFile; productRef = 9CEC91988487EAD9E87B6D83 /* NIOHTTP1 */; };
40 + AAED42787D0BEB5F637C9163 /* NIOPosix in Frameworks */ = {isa = PBXBuildFile; productRef = 3253817A08FC0D668A552FA6 /* NIOPosix */; };
41 B2A57E383F93751851FE880C /* NIOCore in Frameworks */ = {isa = PBXBuildFile; productRef = F83D3AB07112BE3B5C5CEEB0 /* NIOCore */; };
42 B986DCE75E07965CA4C1E7F8 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = D11F41B613A58B56653C16C6 /* README.md */; };
43 BEFE1733DCB97BE06F428AD2 /* ControlKitRunnerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898E84DC2CE45F3463AA7E5D /* ControlKitRunnerApp.swift */; };
@@ -33,7 +45,11 @@
45 C552103B6652E1005DB6B8C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1D9522A60419FFC7F405FE88 /* Assets.xcassets */; };
46 C8B2C54C0B06115DE7F14ACE /* ControlKitRunnerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A32F608A3A429B81416D59FC /* ControlKitRunnerApp.swift */; };
47 D96F5E268D3AFF7DC328622A /* ControlKitRunnerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D582F818EB333BD812EBDAC7 /* ControlKitRunnerUITests.swift */; };
48 + E0EA8983AA28CBEFEBDFE501 /* ControlKitRunnerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D582F818EB333BD812EBDAC7 /* ControlKitRunnerUITests.swift */; };
49 + E2BD398ADA1021C423A4B263 /* XCRSControlKit in Frameworks */ = {isa = PBXBuildFile; productRef = A71D21E23B0941B7D7C03762 /* XCRSControlKit */; };
50 + E73C698597C5E140B7FC84A2 /* NIOPosix in Frameworks */ = {isa = PBXBuildFile; productRef = 4DB5F4B1F3592AA72060C1FB /* NIOPosix */; };
51 E7D00D2B9B79391ABB28574C /* NIOPosix in Frameworks */ = {isa = PBXBuildFile; productRef = FFAF906BB53F58598BDAE35B /* NIOPosix */; };
52 + EB7069C674DA185740685F87 /* NIOHTTP1 in Frameworks */ = {isa = PBXBuildFile; productRef = 3E030B34C4FDF41205C694F8 /* NIOHTTP1 */; };
53 /* End PBXBuildFile section */
54
55 /* Begin PBXContainerItemProxy section */
@@ -51,6 +67,20 @@
67 remoteGlobalIDString = 720F3EC917A0116B593FBBBB;
68 remoteInfo = "ControlKit-visionOS";
69 };
70 + 3975F74C863C2E47636D5DAE /* PBXContainerItemProxy */ = {
71 + isa = PBXContainerItemProxy;
72 + containerPortal = A886E2D8FDDF1B058227A931 /* Project object */;
73 + proxyType = 1;
74 + remoteGlobalIDString = 5B67E51B3C9E09531D57616F;
75 + remoteInfo = "ControlKit-macOS";
76 + };
77 + 5A71C8672C07A86ED68BC559 /* PBXContainerItemProxy */ = {
78 + isa = PBXContainerItemProxy;
79 + containerPortal = A886E2D8FDDF1B058227A931 /* Project object */;
80 + proxyType = 1;
81 + remoteGlobalIDString = E85C2DCD1888C5276C1F13E4;
82 + remoteInfo = "ControlKit-watchOS";
83 + };
84 AEE01B43669A92A0B635826C /* PBXContainerItemProxy */ = {
85 isa = PBXContainerItemProxy;
86 containerPortal = A886E2D8FDDF1B058227A931 /* Project object */;
@@ -62,26 +92,46 @@
92
93 /* Begin PBXFileReference section */
94 06ABEBF2BC26029BF199977C /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
65 - 08CFC4F37BB1C3444B435EC8 /* ControlKit-tvOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; name = "ControlKit-tvOS.app"; path = ControlKit.app; sourceTree = BUILT_PRODUCTS_DIR; };
66 - 0AF2C936A45BEF3E427051E8 /* ControlKit-iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; name = "ControlKit-iOS.app"; path = ControlKit.app; sourceTree = BUILT_PRODUCTS_DIR; };
95 + 08CFC4F37BB1C3444B435EC8 /* ControlKit-tvOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ControlKit-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
96 + 0AF2C936A45BEF3E427051E8 /* ControlKit-iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ControlKit-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
97 1D9522A60419FFC7F405FE88 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
68 - 2A9F28238A4519F25B302BD1 /* ControlKit-visionOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; name = "ControlKit-visionOS.app"; path = ControlKit.app; sourceTree = BUILT_PRODUCTS_DIR; };
98 + 2A9F28238A4519F25B302BD1 /* ControlKit-visionOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ControlKit-visionOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
99 + 3686EC34042E55BB49FCE937 /* ControlKit-macOS-UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ControlKit-macOS-UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
100 3DFF0D230E8E7D8DF4E8AF86 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
101 + 40A16F9F72DA073E165B0149 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
102 + 5591C7FEF7205CCA88C10507 /* ControlKitRunnerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlKitRunnerApp.swift; sourceTree = "<group>"; };
103 + 5A26B9285A83B3312F79B286 /* ControlKit-macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ControlKit-macOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
104 5A89F5048B0CAE4988FB1203 /* ControlKit-visionOS-UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "ControlKit-visionOS-UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
105 5FB5CFB03469D6F6B4B90338 /* ControlKitRunnerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlKitRunnerApp.swift; sourceTree = "<group>"; };
106 898E84DC2CE45F3463AA7E5D /* ControlKitRunnerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlKitRunnerApp.swift; sourceTree = "<group>"; };
107 8A09FB52496A952CB13C163B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
108 904DF2F8A56B8FA1C5EE1431 /* ControlKit-tvOS-UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "ControlKit-tvOS-UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
109 976BFE251DB7DC2248C8D0E7 /* ControlKitRPCServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlKitRPCServer.swift; sourceTree = "<group>"; };
110 + 9D200812648C48867D12D43D /* ControlKit-watchOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ControlKit-watchOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
111 A32F608A3A429B81416D59FC /* ControlKitRunnerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlKitRunnerApp.swift; sourceTree = "<group>"; };
112 + B4A7C1166461333A52056112 /* ControlKit-macOS-UITests.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "ControlKit-macOS-UITests.entitlements"; sourceTree = "<group>"; };
113 + CD648878AF85C1F1CC002EC1 /* ControlKit-watchOS-UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ControlKit-watchOS-UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
114 D11F41B613A58B56653C16C6 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
115 D1DCCDE3A93E1CF31802D658 /* xcrs-controlkit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "xcrs-controlkit"; path = ..; sourceTree = SOURCE_ROOT; };
116 D582F818EB333BD812EBDAC7 /* ControlKitRunnerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlKitRunnerUITests.swift; sourceTree = "<group>"; };
117 E395E1A9D0B3259F9C816109 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
118 + EC6FBC92946E0D2F913F6A1E /* ControlKitRunnerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlKitRunnerApp.swift; sourceTree = "<group>"; };
119 F93B11596E43814F825966AC /* ControlKit-iOS-UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "ControlKit-iOS-UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
120 + FD4E3603A115950345EC4C96 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
121 /* End PBXFileReference section */
122
123 /* Begin PBXFrameworksBuildPhase section */
124 + 1BD2A5EFA635301D4165CD27 /* Frameworks */ = {
125 + isa = PBXFrameworksBuildPhase;
126 + buildActionMask = 2147483647;
127 + files = (
128 + 9CC0F626565F3ADFBCAEFE1C /* XCRSControlKit in Frameworks */,
129 + 561834A353CBD37B8354A58E /* NIOCore in Frameworks */,
130 + EB7069C674DA185740685F87 /* NIOHTTP1 in Frameworks */,
131 + AAED42787D0BEB5F637C9163 /* NIOPosix in Frameworks */,
132 + );
133 + runOnlyForDeploymentPostprocessing = 0;
134 + };
135 2A75581ED579005C72375AAB /* Frameworks */ = {
136 isa = PBXFrameworksBuildPhase;
137 buildActionMask = 2147483647;
@@ -115,6 +165,17 @@
165 );
166 runOnlyForDeploymentPostprocessing = 0;
167 };
168 + F086B824B8DB8D48046D2A34 /* Frameworks */ = {
169 + isa = PBXFrameworksBuildPhase;
170 + buildActionMask = 2147483647;
171 + files = (
172 + E2BD398ADA1021C423A4B263 /* XCRSControlKit in Frameworks */,
173 + 2CE41182704301ED3E17F12A /* NIOCore in Frameworks */,
174 + AABA08D219C9E167F666E012 /* NIOHTTP1 in Frameworks */,
175 + E73C698597C5E140B7FC84A2 /* NIOPosix in Frameworks */,
176 + );
177 + runOnlyForDeploymentPostprocessing = 0;
178 + };
179 /* End PBXFrameworksBuildPhase section */
180
181 /* Begin PBXGroup section */
@@ -142,22 +203,47 @@
203 children = (
204 F93B11596E43814F825966AC /* ControlKit-iOS-UITests.xctest */,
205 0AF2C936A45BEF3E427051E8 /* ControlKit-iOS.app */,
206 + 3686EC34042E55BB49FCE937 /* ControlKit-macOS-UITests.xctest */,
207 + 5A26B9285A83B3312F79B286 /* ControlKit-macOS.app */,
208 904DF2F8A56B8FA1C5EE1431 /* ControlKit-tvOS-UITests.xctest */,
209 08CFC4F37BB1C3444B435EC8 /* ControlKit-tvOS.app */,
210 5A89F5048B0CAE4988FB1203 /* ControlKit-visionOS-UITests.xctest */,
211 2A9F28238A4519F25B302BD1 /* ControlKit-visionOS.app */,
212 + CD648878AF85C1F1CC002EC1 /* ControlKit-watchOS-UITests.xctest */,
213 + 9D200812648C48867D12D43D /* ControlKit-watchOS.app */,
214 );
215 name = Products;
216 sourceTree = "<group>";
217 };
218 + 72270F7916B04830BCC2AB34 /* watchOS */ = {
219 + isa = PBXGroup;
220 + children = (
221 + FD4E3603A115950345EC4C96 /* Assets.xcassets */,
222 + EC6FBC92946E0D2F913F6A1E /* ControlKitRunnerApp.swift */,
223 + );
224 + path = watchOS;
225 + sourceTree = "<group>";
226 + };
227 + 820ECEA915ACE527EF0CA19E /* macOS */ = {
228 + isa = PBXGroup;
229 + children = (
230 + 40A16F9F72DA073E165B0149 /* Assets.xcassets */,
231 + B4A7C1166461333A52056112 /* ControlKit-macOS-UITests.entitlements */,
232 + 5591C7FEF7205CCA88C10507 /* ControlKitRunnerApp.swift */,
233 + );
234 + path = macOS;
235 + sourceTree = "<group>";
236 + };
237 8BF319E1B3CB4CA319D804BA = {
238 isa = PBXGroup;
239 children = (
240 CEE9E165E43396ABDCF722E3 /* iOS */,
241 + 820ECEA915ACE527EF0CA19E /* macOS */,
242 AAF9A6C2C031D435E78F618D /* Packages */,
243 0AD16B636A496FC575FABB2F /* Shared */,
244 F3830AB6FA85799037B91E7D /* tvOS */,
245 18CD92B06EDA4B61503FE8DA /* visionOS */,
246 + 72270F7916B04830BCC2AB34 /* watchOS */,
247 2D1B85549DE31AFEDF5D1159 /* Products */,
248 );
249 sourceTree = "<group>";
@@ -234,6 +320,24 @@
320 productReference = 5A89F5048B0CAE4988FB1203 /* ControlKit-visionOS-UITests.xctest */;
321 productType = "com.apple.product-type.bundle.ui-testing";
322 };
323 + 5B67E51B3C9E09531D57616F /* ControlKit-macOS */ = {
324 + isa = PBXNativeTarget;
325 + buildConfigurationList = D6C80CE473AEC1B232446EB2 /* Build configuration list for PBXNativeTarget "ControlKit-macOS" */;
326 + buildPhases = (
327 + 9A9604B1CA131DA035CE57B4 /* Sources */,
328 + F6FC78229E31A8705EA840DA /* Resources */,
329 + );
330 + buildRules = (
331 + );
332 + dependencies = (
333 + );
334 + name = "ControlKit-macOS";
335 + packageProductDependencies = (
336 + );
337 + productName = "ControlKit-macOS";
338 + productReference = 5A26B9285A83B3312F79B286 /* ControlKit-macOS.app */;
339 + productType = "com.apple.product-type.application";
340 + };
341 720F3EC917A0116B593FBBBB /* ControlKit-visionOS */ = {
342 isa = PBXNativeTarget;
343 buildConfigurationList = A3E875F2C0588D2AFB728EC8 /* Build configuration list for PBXNativeTarget "ControlKit-visionOS" */;
@@ -252,6 +356,29 @@
356 productReference = 2A9F28238A4519F25B302BD1 /* ControlKit-visionOS.app */;
357 productType = "com.apple.product-type.application";
358 };
359 + 8A89960127FE4F8007E66449 /* ControlKit-watchOS-UITests */ = {
360 + isa = PBXNativeTarget;
361 + buildConfigurationList = 708FB1855395DEDE0D00C5D9 /* Build configuration list for PBXNativeTarget "ControlKit-watchOS-UITests" */;
362 + buildPhases = (
363 + DBDE4573C281CF3AAC9BE22F /* Sources */,
364 + 1BD2A5EFA635301D4165CD27 /* Frameworks */,
365 + );
366 + buildRules = (
367 + );
368 + dependencies = (
369 + E84304E076EE747D380D070C /* PBXTargetDependency */,
370 + );
371 + name = "ControlKit-watchOS-UITests";
372 + packageProductDependencies = (
373 + F1634B11C3B52F3F9511DF74 /* XCRSControlKit */,
374 + 786AF91DEFF9CFAF6733FE5D /* NIOCore */,
375 + 3E030B34C4FDF41205C694F8 /* NIOHTTP1 */,
376 + 3253817A08FC0D668A552FA6 /* NIOPosix */,
377 + );
378 + productName = "ControlKit-watchOS-UITests";
379 + productReference = CD648878AF85C1F1CC002EC1 /* ControlKit-watchOS-UITests.xctest */;
380 + productType = "com.apple.product-type.bundle.ui-testing";
381 + };
382 8B29B60E49F265583C3FB987 /* ControlKit-tvOS-UITests */ = {
383 isa = PBXNativeTarget;
384 buildConfigurationList = DC1656DA116F4F1E1E7A9039 /* Build configuration list for PBXNativeTarget "ControlKit-tvOS-UITests" */;
@@ -293,6 +420,29 @@
420 productReference = 0AF2C936A45BEF3E427051E8 /* ControlKit-iOS.app */;
421 productType = "com.apple.product-type.application";
422 };
423 + BBEDFC1F8A411D980AF3432F /* ControlKit-macOS-UITests */ = {
424 + isa = PBXNativeTarget;
425 + buildConfigurationList = E61F070B23F4FAE658E19065 /* Build configuration list for PBXNativeTarget "ControlKit-macOS-UITests" */;
426 + buildPhases = (
427 + 0E5FA41A44AC2624E81E9974 /* Sources */,
428 + F086B824B8DB8D48046D2A34 /* Frameworks */,
429 + );
430 + buildRules = (
431 + );
432 + dependencies = (
433 + 071B3FE090CFAEFBE620914A /* PBXTargetDependency */,
434 + );
435 + name = "ControlKit-macOS-UITests";
436 + packageProductDependencies = (
437 + A71D21E23B0941B7D7C03762 /* XCRSControlKit */,
438 + 611C969D93EC290726A7395E /* NIOCore */,
439 + 9CEC91988487EAD9E87B6D83 /* NIOHTTP1 */,
440 + 4DB5F4B1F3592AA72060C1FB /* NIOPosix */,
441 + );
442 + productName = "ControlKit-macOS-UITests";
443 + productReference = 3686EC34042E55BB49FCE937 /* ControlKit-macOS-UITests.xctest */;
444 + productType = "com.apple.product-type.bundle.ui-testing";
445 + };
446 CD73A40CAB68D297974A7E90 /* ControlKit-iOS-UITests */ = {
447 isa = PBXNativeTarget;
448 buildConfigurationList = 83E3FC025793339356561648 /* Build configuration list for PBXNativeTarget "ControlKit-iOS-UITests" */;
@@ -316,6 +466,24 @@
466 productReference = F93B11596E43814F825966AC /* ControlKit-iOS-UITests.xctest */;
467 productType = "com.apple.product-type.bundle.ui-testing";
468 };
469 + E85C2DCD1888C5276C1F13E4 /* ControlKit-watchOS */ = {
470 + isa = PBXNativeTarget;
471 + buildConfigurationList = D28A8B9028C344107343F1FB /* Build configuration list for PBXNativeTarget "ControlKit-watchOS" */;
472 + buildPhases = (
473 + 08F2647A4EB5883ED31CD05C /* Sources */,
474 + 5DE56F756B7A75E80ACF62EB /* Resources */,
475 + );
476 + buildRules = (
477 + );
478 + dependencies = (
479 + );
480 + name = "ControlKit-watchOS";
481 + packageProductDependencies = (
482 + );
483 + productName = "ControlKit-watchOS";
484 + productReference = 9D200812648C48867D12D43D /* ControlKit-watchOS.app */;
485 + productType = "com.apple.product-type.application";
486 + };
487 /* End PBXNativeTarget section */
488
489 /* Begin PBXProject section */
@@ -328,9 +496,15 @@
496 09F6B446FD034D1BCF7FE56B = {
497 TestTargetID = 720F3EC917A0116B593FBBBB;
498 };
499 + 8A89960127FE4F8007E66449 = {
500 + TestTargetID = E85C2DCD1888C5276C1F13E4;
501 + };
502 8B29B60E49F265583C3FB987 = {
503 TestTargetID = 029C796A915A8119077A2F2D;
504 };
505 + BBEDFC1F8A411D980AF3432F = {
506 + TestTargetID = 5B67E51B3C9E09531D57616F;
507 + };
508 CD73A40CAB68D297974A7E90 = {
509 TestTargetID = 9F5E3C368E274D9C0BF1AC09;
510 };
@@ -360,6 +534,10 @@
534 8B29B60E49F265583C3FB987 /* ControlKit-tvOS-UITests */,
535 720F3EC917A0116B593FBBBB /* ControlKit-visionOS */,
536 09F6B446FD034D1BCF7FE56B /* ControlKit-visionOS-UITests */,
537 + 5B67E51B3C9E09531D57616F /* ControlKit-macOS */,
538 + BBEDFC1F8A411D980AF3432F /* ControlKit-macOS-UITests */,
539 + E85C2DCD1888C5276C1F13E4 /* ControlKit-watchOS */,
540 + 8A89960127FE4F8007E66449 /* ControlKit-watchOS-UITests */,
541 );
542 };
543 /* End PBXProject section */
@@ -374,6 +552,14 @@
552 );
553 runOnlyForDeploymentPostprocessing = 0;
554 };
555 + 5DE56F756B7A75E80ACF62EB /* Resources */ = {
556 + isa = PBXResourcesBuildPhase;
557 + buildActionMask = 2147483647;
558 + files = (
559 + 560FDA8EB7B9DE368869D155 /* Assets.xcassets in Resources */,
560 + );
561 + runOnlyForDeploymentPostprocessing = 0;
562 + };
563 A88C8E544C02C1D56E86A9C7 /* Resources */ = {
564 isa = PBXResourcesBuildPhase;
565 buildActionMask = 2147483647;
@@ -383,6 +569,14 @@
569 );
570 runOnlyForDeploymentPostprocessing = 0;
571 };
572 + F6FC78229E31A8705EA840DA /* Resources */ = {
573 + isa = PBXResourcesBuildPhase;
574 + buildActionMask = 2147483647;
575 + files = (
576 + 9DF1151412A41AC8D2EDE2D5 /* Assets.xcassets in Resources */,
577 + );
578 + runOnlyForDeploymentPostprocessing = 0;
579 + };
580 FE06AFC9AE7B730022308652 /* Resources */ = {
581 isa = PBXResourcesBuildPhase;
582 buildActionMask = 2147483647;
@@ -395,6 +589,23 @@
589 /* End PBXResourcesBuildPhase section */
590
591 /* Begin PBXSourcesBuildPhase section */
592 + 08F2647A4EB5883ED31CD05C /* Sources */ = {
593 + isa = PBXSourcesBuildPhase;
594 + buildActionMask = 2147483647;
595 + files = (
596 + A5BD016357891BCC301E3E4E /* ControlKitRunnerApp.swift in Sources */,
597 + );
598 + runOnlyForDeploymentPostprocessing = 0;
599 + };
600 + 0E5FA41A44AC2624E81E9974 /* Sources */ = {
601 + isa = PBXSourcesBuildPhase;
602 + buildActionMask = 2147483647;
603 + files = (
604 + 82D074F9A9D0F5FD6F00CA7B /* ControlKitRPCServer.swift in Sources */,
605 + E0EA8983AA28CBEFEBDFE501 /* ControlKitRunnerUITests.swift in Sources */,
606 + );
607 + runOnlyForDeploymentPostprocessing = 0;
608 + };
609 25A5679D9AB0D84C081D9343 /* Sources */ = {
610 isa = PBXSourcesBuildPhase;
611 buildActionMask = 2147483647;
@@ -446,9 +657,31 @@
657 );
658 runOnlyForDeploymentPostprocessing = 0;
659 };
660 + 9A9604B1CA131DA035CE57B4 /* Sources */ = {
661 + isa = PBXSourcesBuildPhase;
662 + buildActionMask = 2147483647;
663 + files = (
664 + 607F9363076F0FE76CA24A73 /* ControlKitRunnerApp.swift in Sources */,
665 + );
666 + runOnlyForDeploymentPostprocessing = 0;
667 + };
668 + DBDE4573C281CF3AAC9BE22F /* Sources */ = {
669 + isa = PBXSourcesBuildPhase;
670 + buildActionMask = 2147483647;
671 + files = (
672 + 42F868C46B85D81A82D325F0 /* ControlKitRPCServer.swift in Sources */,
673 + 49C565818AD8C7C3D85C498E /* ControlKitRunnerUITests.swift in Sources */,
674 + );
675 + runOnlyForDeploymentPostprocessing = 0;
676 + };
677 /* End PBXSourcesBuildPhase section */
678
679 /* Begin PBXTargetDependency section */
680 + 071B3FE090CFAEFBE620914A /* PBXTargetDependency */ = {
681 + isa = PBXTargetDependency;
682 + target = 5B67E51B3C9E09531D57616F /* ControlKit-macOS */;
683 + targetProxy = 3975F74C863C2E47636D5DAE /* PBXContainerItemProxy */;
684 + };
685 55C3178DB2606813467C97CC /* PBXTargetDependency */ = {
686 isa = PBXTargetDependency;
687 target = 720F3EC917A0116B593FBBBB /* ControlKit-visionOS */;
@@ -459,6 +692,11 @@
692 target = 9F5E3C368E274D9C0BF1AC09 /* ControlKit-iOS */;
693 targetProxy = 154A64286F9DFB5C95CF695E /* PBXContainerItemProxy */;
694 };
695 + E84304E076EE747D380D070C /* PBXTargetDependency */ = {
696 + isa = PBXTargetDependency;
697 + target = E85C2DCD1888C5276C1F13E4 /* ControlKit-watchOS */;
698 + targetProxy = 5A71C8672C07A86ED68BC559 /* PBXContainerItemProxy */;
699 + };
700 F37FD1FE4F9670C2C355615F /* PBXTargetDependency */ = {
701 isa = PBXTargetDependency;
702 target = 029C796A915A8119077A2F2D /* ControlKit-tvOS */;
@@ -485,6 +723,23 @@
723 };
724 name = Release;
725 };
726 + 0615B9D71FCA89F904AEAB2D /* Debug */ = {
727 + isa = XCBuildConfiguration;
728 + buildSettings = {
729 + BUNDLE_LOADER = "$(TEST_HOST)";
730 + LD_RUNPATH_SEARCH_PATHS = (
731 + "$(inherited)",
732 + "@executable_path/Frameworks",
733 + "@loader_path/Frameworks",
734 + );
735 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.watchos.runnerUITests";
736 + SDKROOT = watchos;
737 + SKIP_INSTALL = YES;
738 + TARGETED_DEVICE_FAMILY = 4;
739 + TEST_TARGET_NAME = "ControlKit-watchOS";
740 + };
741 + name = Debug;
742 + };
743 21F4165C7F57458C04C5805E /* Debug */ = {
744 isa = XCBuildConfiguration;
745 buildSettings = {
@@ -518,6 +773,41 @@
773 };
774 name = Debug;
775 };
776 + 337182B361D51F9D6F10F5DC /* Debug */ = {
777 + isa = XCBuildConfiguration;
778 + buildSettings = {
779 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
780 + CODE_SIGN_IDENTITY = "-";
781 + COMBINE_HIDPI_IMAGES = YES;
782 + ENABLE_HARDENED_RUNTIME = NO;
783 + LD_RUNPATH_SEARCH_PATHS = (
784 + "$(inherited)",
785 + "@executable_path/../Frameworks",
786 + );
787 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.macos.runner";
788 + PRODUCT_NAME = ControlKit;
789 + SDKROOT = macosx;
790 + };
791 + name = Debug;
792 + };
793 + 37B91A75D6E30BD6311172CE /* Release */ = {
794 + isa = XCBuildConfiguration;
795 + buildSettings = {
796 + BUNDLE_LOADER = "$(TEST_HOST)";
797 + CODE_SIGN_ENTITLEMENTS = "macOS/ControlKit-macOS-UITests.entitlements";
798 + CODE_SIGN_IDENTITY = "-";
799 + COMBINE_HIDPI_IMAGES = YES;
800 + LD_RUNPATH_SEARCH_PATHS = (
801 + "$(inherited)",
802 + "@executable_path/Frameworks",
803 + "@loader_path/Frameworks",
804 + );
805 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.macos.runnerUITests";
806 + SDKROOT = macosx;
807 + TEST_TARGET_NAME = "ControlKit-macOS";
808 + };
809 + name = Release;
810 + };
811 41FF10163C9AB188CF4891AF /* Debug */ = {
812 isa = XCBuildConfiguration;
813 buildSettings = {
@@ -588,10 +878,8 @@
878 GENERATE_INFOPLIST_FILE = YES;
879 INFOPLIST_KEY_CFBundleDisplayName = ControlKit;
880 IPHONEOS_DEPLOYMENT_TARGET = 16.0;
591 - LD_RUNPATH_SEARCH_PATHS = (
592 - "$(inherited)",
593 - "@executable_path/Frameworks",
594 - );
881 + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
882 + MACOSX_DEPLOYMENT_TARGET = 13.0;
883 MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
884 MTL_FAST_MATH = YES;
885 ONLY_ACTIVE_ARCH = YES;
@@ -600,6 +888,7 @@
888 SWIFT_OPTIMIZATION_LEVEL = "-Onone";
889 SWIFT_VERSION = 5.9;
890 TVOS_DEPLOYMENT_TARGET = 16.0;
891 + WATCHOS_DEPLOYMENT_TARGET = 9.0;
892 XROS_DEPLOYMENT_TARGET = 1.0;
893 };
894 name = Debug;
@@ -715,6 +1004,30 @@
1004 };
1005 name = Release;
1006 };
1007 + A15E58D90454C1314DF91A79 /* Debug */ = {
1008 + isa = XCBuildConfiguration;
1009 + buildSettings = {
1010 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1011 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.watchos.runner";
1012 + PRODUCT_NAME = ControlKit;
1013 + SDKROOT = watchos;
1014 + SKIP_INSTALL = YES;
1015 + TARGETED_DEVICE_FAMILY = 4;
1016 + };
1017 + name = Debug;
1018 + };
1019 + A24720312170C6FC3A02C248 /* Release */ = {
1020 + isa = XCBuildConfiguration;
1021 + buildSettings = {
1022 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1023 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.watchos.runner";
1024 + PRODUCT_NAME = ControlKit;
1025 + SDKROOT = watchos;
1026 + SKIP_INSTALL = YES;
1027 + TARGETED_DEVICE_FAMILY = 4;
1028 + };
1029 + name = Release;
1030 + };
1031 AE247B8CB1FB1A6E8E8B8696 /* Release */ = {
1032 isa = XCBuildConfiguration;
1033 buildSettings = {
@@ -731,6 +1044,41 @@
1044 };
1045 name = Release;
1046 };
1047 + B656C0A63029764B760E4397 /* Debug */ = {
1048 + isa = XCBuildConfiguration;
1049 + buildSettings = {
1050 + BUNDLE_LOADER = "$(TEST_HOST)";
1051 + CODE_SIGN_ENTITLEMENTS = "macOS/ControlKit-macOS-UITests.entitlements";
1052 + CODE_SIGN_IDENTITY = "-";
1053 + COMBINE_HIDPI_IMAGES = YES;
1054 + LD_RUNPATH_SEARCH_PATHS = (
1055 + "$(inherited)",
1056 + "@executable_path/Frameworks",
1057 + "@loader_path/Frameworks",
1058 + );
1059 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.macos.runnerUITests";
1060 + SDKROOT = macosx;
1061 + TEST_TARGET_NAME = "ControlKit-macOS";
1062 + };
1063 + name = Debug;
1064 + };
1065 + D749370E86B8B19A96D7BC0E /* Release */ = {
1066 + isa = XCBuildConfiguration;
1067 + buildSettings = {
1068 + BUNDLE_LOADER = "$(TEST_HOST)";
1069 + LD_RUNPATH_SEARCH_PATHS = (
1070 + "$(inherited)",
1071 + "@executable_path/Frameworks",
1072 + "@loader_path/Frameworks",
1073 + );
1074 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.watchos.runnerUITests";
1075 + SDKROOT = watchos;
1076 + SKIP_INSTALL = YES;
1077 + TARGETED_DEVICE_FAMILY = 4;
1078 + TEST_TARGET_NAME = "ControlKit-watchOS";
1079 + };
1080 + name = Release;
1081 + };
1082 E4C3287EEC34289D60AD8369 /* Release */ = {
1083 isa = XCBuildConfiguration;
1084 buildSettings = {
@@ -779,10 +1127,8 @@
1127 GENERATE_INFOPLIST_FILE = YES;
1128 INFOPLIST_KEY_CFBundleDisplayName = ControlKit;
1129 IPHONEOS_DEPLOYMENT_TARGET = 16.0;
782 - LD_RUNPATH_SEARCH_PATHS = (
783 - "$(inherited)",
784 - "@executable_path/Frameworks",
785 - );
1130 + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1131 + MACOSX_DEPLOYMENT_TARGET = 13.0;
1132 MTL_ENABLE_DEBUG_INFO = NO;
1133 MTL_FAST_MATH = YES;
1134 PRODUCT_NAME = "$(TARGET_NAME)";
@@ -790,10 +1136,28 @@
1136 SWIFT_OPTIMIZATION_LEVEL = "-O";
1137 SWIFT_VERSION = 5.9;
1138 TVOS_DEPLOYMENT_TARGET = 16.0;
1139 + WATCHOS_DEPLOYMENT_TARGET = 9.0;
1140 XROS_DEPLOYMENT_TARGET = 1.0;
1141 };
1142 name = Release;
1143 };
1144 + F39E0821F2FA6F20D59DF041 /* Release */ = {
1145 + isa = XCBuildConfiguration;
1146 + buildSettings = {
1147 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1148 + CODE_SIGN_IDENTITY = "-";
1149 + COMBINE_HIDPI_IMAGES = YES;
1150 + ENABLE_HARDENED_RUNTIME = NO;
1151 + LD_RUNPATH_SEARCH_PATHS = (
1152 + "$(inherited)",
1153 + "@executable_path/../Frameworks",
1154 + );
1155 + PRODUCT_BUNDLE_IDENTIFIER = "com.smbcloud.xcrs-controlkit.macos.runner";
1156 + PRODUCT_NAME = ControlKit;
1157 + SDKROOT = macosx;
1158 + };
1159 + name = Release;
1160 + };
1161 /* End XCBuildConfiguration section */
1162
1163 /* Begin XCConfigurationList section */
@@ -815,6 +1179,15 @@
1179 defaultConfigurationIsVisible = 0;
1180 defaultConfigurationName = Debug;
1181 };
1182 + 708FB1855395DEDE0D00C5D9 /* Build configuration list for PBXNativeTarget "ControlKit-watchOS-UITests" */ = {
1183 + isa = XCConfigurationList;
1184 + buildConfigurations = (
1185 + 0615B9D71FCA89F904AEAB2D /* Debug */,
1186 + D749370E86B8B19A96D7BC0E /* Release */,
1187 + );
1188 + defaultConfigurationIsVisible = 0;
1189 + defaultConfigurationName = Debug;
1190 + };
1191 83E3FC025793339356561648 /* Build configuration list for PBXNativeTarget "ControlKit-iOS-UITests" */ = {
1192 isa = XCConfigurationList;
1193 buildConfigurations = (
@@ -842,6 +1215,24 @@
1215 defaultConfigurationIsVisible = 0;
1216 defaultConfigurationName = Debug;
1217 };
1218 + D28A8B9028C344107343F1FB /* Build configuration list for PBXNativeTarget "ControlKit-watchOS" */ = {
1219 + isa = XCConfigurationList;
1220 + buildConfigurations = (
1221 + A15E58D90454C1314DF91A79 /* Debug */,
1222 + A24720312170C6FC3A02C248 /* Release */,
1223 + );
1224 + defaultConfigurationIsVisible = 0;
1225 + defaultConfigurationName = Debug;
1226 + };
1227 + D6C80CE473AEC1B232446EB2 /* Build configuration list for PBXNativeTarget "ControlKit-macOS" */ = {
1228 + isa = XCConfigurationList;
1229 + buildConfigurations = (
1230 + 337182B361D51F9D6F10F5DC /* Debug */,
1231 + F39E0821F2FA6F20D59DF041 /* Release */,
1232 + );
1233 + defaultConfigurationIsVisible = 0;
1234 + defaultConfigurationName = Debug;
1235 + };
1236 DC1656DA116F4F1E1E7A9039 /* Build configuration list for PBXNativeTarget "ControlKit-tvOS-UITests" */ = {
1237 isa = XCConfigurationList;
1238 buildConfigurations = (
@@ -851,6 +1242,15 @@
1242 defaultConfigurationIsVisible = 0;
1243 defaultConfigurationName = Debug;
1244 };
1245 + E61F070B23F4FAE658E19065 /* Build configuration list for PBXNativeTarget "ControlKit-macOS-UITests" */ = {
1246 + isa = XCConfigurationList;
1247 + buildConfigurations = (
1248 + B656C0A63029764B760E4397 /* Debug */,
1249 + 37B91A75D6E30BD6311172CE /* Release */,
1250 + );
1251 + defaultConfigurationIsVisible = 0;
1252 + defaultConfigurationName = Debug;
1253 + };
1254 F90CA1FF8DF178C6B4D2D56F /* Build configuration list for PBXNativeTarget "ControlKit-tvOS" */ = {
1255 isa = XCConfigurationList;
1256 buildConfigurations = (
@@ -895,11 +1295,26 @@
1295 package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1296 productName = NIOPosix;
1297 };
1298 + 3253817A08FC0D668A552FA6 /* NIOPosix */ = {
1299 + isa = XCSwiftPackageProductDependency;
1300 + package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1301 + productName = NIOPosix;
1302 + };
1303 39DF23C6EF63909919D192E1 /* NIOHTTP1 */ = {
1304 isa = XCSwiftPackageProductDependency;
1305 package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1306 productName = NIOHTTP1;
1307 };
1308 + 3E030B34C4FDF41205C694F8 /* NIOHTTP1 */ = {
1309 + isa = XCSwiftPackageProductDependency;
1310 + package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1311 + productName = NIOHTTP1;
1312 + };
1313 + 4DB5F4B1F3592AA72060C1FB /* NIOPosix */ = {
1314 + isa = XCSwiftPackageProductDependency;
1315 + package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1316 + productName = NIOPosix;
1317 + };
1318 50AB05BF2C324210174A3476 /* XCRSControlKit */ = {
1319 isa = XCSwiftPackageProductDependency;
1320 productName = XCRSControlKit;
@@ -909,11 +1324,30 @@
1324 package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1325 productName = NIOCore;
1326 };
1327 + 611C969D93EC290726A7395E /* NIOCore */ = {
1328 + isa = XCSwiftPackageProductDependency;
1329 + package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1330 + productName = NIOCore;
1331 + };
1332 + 786AF91DEFF9CFAF6733FE5D /* NIOCore */ = {
1333 + isa = XCSwiftPackageProductDependency;
1334 + package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1335 + productName = NIOCore;
1336 + };
1337 84A03CA7B1A8BF405AD3F3C4 /* NIOHTTP1 */ = {
1338 isa = XCSwiftPackageProductDependency;
1339 package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1340 productName = NIOHTTP1;
1341 };
1342 + 9CEC91988487EAD9E87B6D83 /* NIOHTTP1 */ = {
1343 + isa = XCSwiftPackageProductDependency;
1344 + package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1345 + productName = NIOHTTP1;
1346 + };
1347 + A71D21E23B0941B7D7C03762 /* XCRSControlKit */ = {
1348 + isa = XCSwiftPackageProductDependency;
1349 + productName = XCRSControlKit;
1350 + };
1351 BE99FEAB3F75651FC71BB9B5 /* XCRSControlKit */ = {
1352 isa = XCSwiftPackageProductDependency;
1353 productName = XCRSControlKit;
@@ -928,6 +1362,10 @@
1362 package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
1363 productName = NIOHTTP1;
1364 };
1365 + F1634B11C3B52F3F9511DF74 /* XCRSControlKit */ = {
1366 + isa = XCSwiftPackageProductDependency;
1367 + productName = XCRSControlKit;
1368 + };
1369 F83D3AB07112BE3B5C5CEEB0 /* NIOCore */ = {
1370 isa = XCSwiftPackageProductDependency;
1371 package = 097CD02F3C7519204C9CDC73 /* XCRemoteSwiftPackageReference "swift-nio" */;
Runners/XCRSControlKitRunner.xcodeproj/xcshareddata/xcschemes/ControlKit-macOS.xcscheme new
+111
@@ -0,0 +1,111 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<Scheme
3 + LastUpgradeVersion = "1430"
4 + version = "1.3">
5 + <BuildAction
6 + parallelizeBuildables = "YES"
7 + buildImplicitDependencies = "YES">
8 + <BuildActionEntries>
9 + <BuildActionEntry
10 + buildForTesting = "YES"
11 + buildForRunning = "YES"
12 + buildForProfiling = "YES"
13 + buildForArchiving = "YES"
14 + buildForAnalyzing = "YES">
15 + <BuildableReference
16 + BuildableIdentifier = "primary"
17 + BlueprintIdentifier = "5B67E51B3C9E09531D57616F"
18 + BuildableName = "ControlKit.app"
19 + BlueprintName = "ControlKit-macOS"
20 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
21 + </BuildableReference>
22 + </BuildActionEntry>
23 + <BuildActionEntry
24 + buildForTesting = "YES"
25 + buildForRunning = "NO"
26 + buildForProfiling = "NO"
27 + buildForArchiving = "NO"
28 + buildForAnalyzing = "NO">
29 + <BuildableReference
30 + BuildableIdentifier = "primary"
31 + BlueprintIdentifier = "BBEDFC1F8A411D980AF3432F"
32 + BuildableName = "ControlKit-macOS-UITests.xctest"
33 + BlueprintName = "ControlKit-macOS-UITests"
34 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
35 + </BuildableReference>
36 + </BuildActionEntry>
37 + </BuildActionEntries>
38 + </BuildAction>
39 + <TestAction
40 + buildConfiguration = "Debug"
41 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
42 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43 + shouldUseLaunchSchemeArgsEnv = "YES">
44 + <MacroExpansion>
45 + <BuildableReference
46 + BuildableIdentifier = "primary"
47 + BlueprintIdentifier = "5B67E51B3C9E09531D57616F"
48 + BuildableName = "ControlKit.app"
49 + BlueprintName = "ControlKit-macOS"
50 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
51 + </BuildableReference>
52 + </MacroExpansion>
53 + <Testables>
54 + <TestableReference
55 + skipped = "NO">
56 + <BuildableReference
57 + BuildableIdentifier = "primary"
58 + BlueprintIdentifier = "BBEDFC1F8A411D980AF3432F"
59 + BuildableName = "ControlKit-macOS-UITests.xctest"
60 + BlueprintName = "ControlKit-macOS-UITests"
61 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
62 + </BuildableReference>
63 + </TestableReference>
64 + </Testables>
65 + </TestAction>
66 + <LaunchAction
67 + buildConfiguration = "Debug"
68 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
69 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
70 + launchStyle = "0"
71 + useCustomWorkingDirectory = "NO"
72 + ignoresPersistentStateOnLaunch = "NO"
73 + debugDocumentVersioning = "YES"
74 + debugServiceExtension = "internal"
75 + allowLocationSimulation = "YES">
76 + <BuildableProductRunnable
77 + runnableDebuggingMode = "0">
78 + <BuildableReference
79 + BuildableIdentifier = "primary"
80 + BlueprintIdentifier = "5B67E51B3C9E09531D57616F"
81 + BuildableName = "ControlKit.app"
82 + BlueprintName = "ControlKit-macOS"
83 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
84 + </BuildableReference>
85 + </BuildableProductRunnable>
86 + </LaunchAction>
87 + <ProfileAction
88 + buildConfiguration = "Release"
89 + shouldUseLaunchSchemeArgsEnv = "YES"
90 + savedToolIdentifier = ""
91 + useCustomWorkingDirectory = "NO"
92 + debugDocumentVersioning = "YES">
93 + <BuildableProductRunnable
94 + runnableDebuggingMode = "0">
95 + <BuildableReference
96 + BuildableIdentifier = "primary"
97 + BlueprintIdentifier = "5B67E51B3C9E09531D57616F"
98 + BuildableName = "ControlKit.app"
99 + BlueprintName = "ControlKit-macOS"
100 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
101 + </BuildableReference>
102 + </BuildableProductRunnable>
103 + </ProfileAction>
104 + <AnalyzeAction
105 + buildConfiguration = "Debug">
106 + </AnalyzeAction>
107 + <ArchiveAction
108 + buildConfiguration = "Release"
109 + revealArchiveInOrganizer = "YES">
110 + </ArchiveAction>
111 +</Scheme>
Runners/XCRSControlKitRunner.xcodeproj/xcshareddata/xcschemes/ControlKit-watchOS.xcscheme new
+111
@@ -0,0 +1,111 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<Scheme
3 + LastUpgradeVersion = "1430"
4 + version = "1.3">
5 + <BuildAction
6 + parallelizeBuildables = "YES"
7 + buildImplicitDependencies = "YES">
8 + <BuildActionEntries>
9 + <BuildActionEntry
10 + buildForTesting = "YES"
11 + buildForRunning = "YES"
12 + buildForProfiling = "YES"
13 + buildForArchiving = "YES"
14 + buildForAnalyzing = "YES">
15 + <BuildableReference
16 + BuildableIdentifier = "primary"
17 + BlueprintIdentifier = "E85C2DCD1888C5276C1F13E4"
18 + BuildableName = "ControlKit.app"
19 + BlueprintName = "ControlKit-watchOS"
20 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
21 + </BuildableReference>
22 + </BuildActionEntry>
23 + <BuildActionEntry
24 + buildForTesting = "YES"
25 + buildForRunning = "NO"
26 + buildForProfiling = "NO"
27 + buildForArchiving = "NO"
28 + buildForAnalyzing = "NO">
29 + <BuildableReference
30 + BuildableIdentifier = "primary"
31 + BlueprintIdentifier = "8A89960127FE4F8007E66449"
32 + BuildableName = "ControlKit-watchOS-UITests.xctest"
33 + BlueprintName = "ControlKit-watchOS-UITests"
34 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
35 + </BuildableReference>
36 + </BuildActionEntry>
37 + </BuildActionEntries>
38 + </BuildAction>
39 + <TestAction
40 + buildConfiguration = "Debug"
41 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
42 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43 + shouldUseLaunchSchemeArgsEnv = "YES">
44 + <MacroExpansion>
45 + <BuildableReference
46 + BuildableIdentifier = "primary"
47 + BlueprintIdentifier = "E85C2DCD1888C5276C1F13E4"
48 + BuildableName = "ControlKit.app"
49 + BlueprintName = "ControlKit-watchOS"
50 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
51 + </BuildableReference>
52 + </MacroExpansion>
53 + <Testables>
54 + <TestableReference
55 + skipped = "NO">
56 + <BuildableReference
57 + BuildableIdentifier = "primary"
58 + BlueprintIdentifier = "8A89960127FE4F8007E66449"
59 + BuildableName = "ControlKit-watchOS-UITests.xctest"
60 + BlueprintName = "ControlKit-watchOS-UITests"
61 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
62 + </BuildableReference>
63 + </TestableReference>
64 + </Testables>
65 + </TestAction>
66 + <LaunchAction
67 + buildConfiguration = "Debug"
68 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
69 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
70 + launchStyle = "0"
71 + useCustomWorkingDirectory = "NO"
72 + ignoresPersistentStateOnLaunch = "NO"
73 + debugDocumentVersioning = "YES"
74 + debugServiceExtension = "internal"
75 + allowLocationSimulation = "YES">
76 + <BuildableProductRunnable
77 + runnableDebuggingMode = "0">
78 + <BuildableReference
79 + BuildableIdentifier = "primary"
80 + BlueprintIdentifier = "E85C2DCD1888C5276C1F13E4"
81 + BuildableName = "ControlKit.app"
82 + BlueprintName = "ControlKit-watchOS"
83 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
84 + </BuildableReference>
85 + </BuildableProductRunnable>
86 + </LaunchAction>
87 + <ProfileAction
88 + buildConfiguration = "Release"
89 + shouldUseLaunchSchemeArgsEnv = "YES"
90 + savedToolIdentifier = ""
91 + useCustomWorkingDirectory = "NO"
92 + debugDocumentVersioning = "YES">
93 + <BuildableProductRunnable
94 + runnableDebuggingMode = "0">
95 + <BuildableReference
96 + BuildableIdentifier = "primary"
97 + BlueprintIdentifier = "E85C2DCD1888C5276C1F13E4"
98 + BuildableName = "ControlKit.app"
99 + BlueprintName = "ControlKit-watchOS"
100 + ReferencedContainer = "container:XCRSControlKitRunner.xcodeproj">
101 + </BuildableReference>
102 + </BuildableProductRunnable>
103 + </ProfileAction>
104 + <AnalyzeAction
105 + buildConfiguration = "Debug">
106 + </AnalyzeAction>
107 + <ArchiveAction
108 + buildConfiguration = "Release"
109 + revealArchiveInOrganizer = "YES">
110 + </ArchiveAction>
111 +</Scheme>
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128x128.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128x128.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128x128@2x.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-128x128@2x.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16x16.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16x16.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16x16@2x.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-16x16@2x.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256x256.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256x256.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256x256@2x.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256x256@2x.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32x32.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32x32.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32x32@2x.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32x32@2x.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512x512.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512x512.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512x512@2x.png
Binary files /dev/null and b/Runners/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512x512@2x.png differ
Runners/macOS/Assets.xcassets/AppIcon.appiconset/Contents.json new
+68
@@ -0,0 +1,68 @@
1 +{
2 + "images": [
3 + {
4 + "size": "16x16",
5 + "idiom": "mac",
6 + "filename": "AppIcon-16x16.png",
7 + "scale": "1x"
8 + },
9 + {
10 + "size": "16x16",
11 + "idiom": "mac",
12 + "filename": "AppIcon-16x16@2x.png",
13 + "scale": "2x"
14 + },
15 + {
16 + "size": "32x32",
17 + "idiom": "mac",
18 + "filename": "AppIcon-32x32.png",
19 + "scale": "1x"
20 + },
21 + {
22 + "size": "32x32",
23 + "idiom": "mac",
24 + "filename": "AppIcon-32x32@2x.png",
25 + "scale": "2x"
26 + },
27 + {
28 + "size": "128x128",
29 + "idiom": "mac",
30 + "filename": "AppIcon-128x128.png",
31 + "scale": "1x"
32 + },
33 + {
34 + "size": "128x128",
35 + "idiom": "mac",
36 + "filename": "AppIcon-128x128@2x.png",
37 + "scale": "2x"
38 + },
39 + {
40 + "size": "256x256",
41 + "idiom": "mac",
42 + "filename": "AppIcon-256x256.png",
43 + "scale": "1x"
44 + },
45 + {
46 + "size": "256x256",
47 + "idiom": "mac",
48 + "filename": "AppIcon-256x256@2x.png",
49 + "scale": "2x"
50 + },
51 + {
52 + "size": "512x512",
53 + "idiom": "mac",
54 + "filename": "AppIcon-512x512.png",
55 + "scale": "1x"
56 + },
57 + {
58 + "size": "512x512",
59 + "idiom": "mac",
60 + "filename": "AppIcon-512x512@2x.png",
61 + "scale": "2x"
62 + }
63 + ],
64 + "info": {
65 + "author": "xcode",
66 + "version": 1
67 + }
68 +}
\ No newline at end of file
Runners/macOS/ControlKit-macOS-UITests.entitlements new
+12
@@ -0,0 +1,12 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 +<plist version="1.0">
4 +<dict>
5 + <key>com.apple.security.app-sandbox</key>
6 + <true/>
7 + <key>com.apple.security.network.server</key>
8 + <true/>
9 + <key>com.apple.security.network.client</key>
10 + <true/>
11 +</dict>
12 +</plist>
Runners/macOS/ControlKitRunnerApp.swift new
+99
@@ -0,0 +1,99 @@
1 +import SwiftUI
2 +
3 +@main
4 +struct ControlKitRunnerApp: App {
5 + var body: some Scene {
6 + WindowGroup {
7 + ControlKitShowcaseView()
8 + }
9 + .defaultSize(width: 820, height: 620)
10 + }
11 +}
12 +
13 +private struct ControlKitShowcaseView: View {
14 + private let repositoryURL = URL(string: "https://github.com/ondeinference/xcrs-controlkit")!
15 +
16 + var body: some View {
17 + ScrollView {
18 + VStack(alignment: .leading, spacing: 28) {
19 + HStack(spacing: 18) {
20 + logo
21 + VStack(alignment: .leading, spacing: 4) {
22 + Text("ControlKit")
23 + .font(.system(size: 40, weight: .bold, design: .rounded))
24 + Text("Apple platform automation")
25 + .font(.title3)
26 + .foregroundStyle(.secondary)
27 + }
28 + }
29 +
30 + Text("A clean-room runner for reliable black-box testing across Apple platforms.")
31 + .font(.title2.weight(.medium))
32 + .fixedSize(horizontal: false, vertical: true)
33 +
34 + statusCard
35 + informationCard
36 +
37 + Link(destination: repositoryURL) {
38 + Label("View project on GitHub", systemImage: "arrow.up.right")
39 + .font(.headline)
40 + .frame(maxWidth: .infinity)
41 + }
42 + .buttonStyle(.borderedProminent)
43 + }
44 + .padding(40)
45 + .frame(maxWidth: 760, alignment: .leading)
46 + }
47 + .frame(minWidth: 640, minHeight: 480)
48 + }
49 +
50 + private var logo: some View {
51 + Text("XC\nRS")
52 + .font(.system(size: 30, weight: .black, design: .rounded))
53 + .multilineTextAlignment(.center)
54 + .lineSpacing(-8)
55 + .foregroundStyle(Color.controlKitGreen)
56 + .frame(width: 96, height: 96)
57 + .background(Color.controlKitCream, in: RoundedRectangle(cornerRadius: 24))
58 + }
59 +
60 + private var statusCard: some View {
61 + VStack(alignment: .leading, spacing: 14) {
62 + Label("Runner online", systemImage: "checkmark.circle.fill")
63 + .font(.headline)
64 + .foregroundStyle(.green)
65 + Text("The XCTest host is ready to receive ControlKit automation requests.")
66 + .foregroundStyle(.secondary)
67 + }
68 + .padding(22)
69 + .frame(maxWidth: .infinity, alignment: .leading)
70 + .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 20))
71 + }
72 +
73 + private var informationCard: some View {
74 + VStack(alignment: .leading, spacing: 16) {
75 + infoRow(title: "Project", value: "XCRSControlKit")
76 + infoRow(title: "Creator", value: "smbCloud")
77 + infoRow(title: "Platform", value: "macOS")
78 + infoRow(title: "Purpose", value: "Native pointer and keyboard automation runner")
79 + }
80 + .padding(22)
81 + .frame(maxWidth: .infinity, alignment: .leading)
82 + .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 20))
83 + }
84 +
85 + private func infoRow(title: String, value: String) -> some View {
86 + HStack {
87 + Text(title)
88 + .foregroundStyle(.secondary)
89 + Spacer()
90 + Text(value)
91 + .fontWeight(.semibold)
92 + }
93 + }
94 +}
95 +
96 +private extension Color {
97 + static let controlKitGreen = Color(red: 0.106, green: 0.263, blue: 0.196)
98 + static let controlKitCream = Color(red: 0.961, green: 0.953, blue: 0.925)
99 +}
Runners/macOS/README.md new
+17
@@ -0,0 +1,17 @@
1 +# ControlKit macOS host app
2 +
3 +This folder holds the macOS host application (`ControlKitRunnerApp.swift` and
4 +`Assets.xcassets`) for the `ControlKit-macOS` target in the shared
5 +`XCRSControlKitRunner.xcodeproj`.
6 +
7 +macOS is pointer-driven: `device.io.click` performs an `XCUICoordinate` click and
8 +`device.io.text` types through the keyboard, while raw `device.io.tap` (touch),
9 +`home`, and orientation controls are intentionally unsupported. The JSON-RPC
10 +transport and server live in `../Shared` and are compiled into the
11 +`ControlKit-macOS-UITests` target.
12 +
13 +The generated XCUITest runner ships sandboxed with only the network *client*
14 +entitlement, so `ControlKit-macOS-UITests.entitlements` additionally grants
15 +`com.apple.security.network.server`, allowing the runner to bind its local RPC
16 +port. The targets sign locally (`CODE_SIGN_IDENTITY = "-"`), so no team or
17 +provisioning profile is required to build and test.
Runners/project.yml
+57
@@ -6,6 +6,8 @@ options:
6 iOS: "16.0"
7 tvOS: "16.0"
8 visionOS: "1.0"
9 + macOS: "13.0"
10 + watchOS: "9.0"
11
12 settings:
13 base:
@@ -103,6 +105,45 @@ targets:
105 platformName: visionOS
106 platformId: visionos
107
108 + ControlKit-macOS:
109 + templates: [Runner]
110 + platform: macOS
111 + templateAttributes:
112 + platformDir: macOS
113 + platformId: macos
114 + settings:
115 + base:
116 + ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
117 + CODE_SIGN_IDENTITY: "-"
118 + ENABLE_HARDENED_RUNTIME: NO
119 + ControlKit-macOS-UITests:
120 + templates: [UITests]
121 + platform: macOS
122 + templateAttributes:
123 + platformName: macOS
124 + platformId: macos
125 + settings:
126 + base:
127 + CODE_SIGN_IDENTITY: "-"
128 + CODE_SIGN_ENTITLEMENTS: macOS/ControlKit-macOS-UITests.entitlements
129 +
130 + ControlKit-watchOS:
131 + templates: [Runner]
132 + platform: watchOS
133 + templateAttributes:
134 + platformDir: watchOS
135 + platformId: watchos
136 + settings:
137 + base:
138 + TARGETED_DEVICE_FAMILY: "4"
139 + ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
140 + ControlKit-watchOS-UITests:
141 + templates: [UITests]
142 + platform: watchOS
143 + templateAttributes:
144 + platformName: watchOS
145 + platformId: watchos
146 +
147 schemes:
148 ControlKit-iOS:
149 build:
@@ -128,3 +169,19 @@ schemes:
169 test:
170 targets:
171 - ControlKit-visionOS-UITests
172 + ControlKit-macOS:
173 + build:
174 + targets:
175 + ControlKit-macOS: all
176 + ControlKit-macOS-UITests: [test]
177 + test:
178 + targets:
179 + - ControlKit-macOS-UITests
180 + ControlKit-watchOS:
181 + build:
182 + targets:
183 + ControlKit-watchOS: all
184 + ControlKit-watchOS-UITests: [test]
185 + test:
186 + targets:
187 + - ControlKit-watchOS-UITests
Runners/watchOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png
Binary files /dev/null and b/Runners/watchOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png differ
Runners/watchOS/Assets.xcassets/AppIcon.appiconset/Contents.json new
+14
@@ -0,0 +1,14 @@
1 +{
2 + "images": [
3 + {
4 + "filename": "AppIcon-1024.png",
5 + "idiom": "universal",
6 + "platform": "watchos",
7 + "size": "1024x1024"
8 + }
9 + ],
10 + "info": {
11 + "author": "xcode",
12 + "version": 1
13 + }
14 +}
\ No newline at end of file
Runners/watchOS/Assets.xcassets/Contents.json new
+6
@@ -0,0 +1,6 @@
1 +{
2 + "info": {
3 + "author": "xcode",
4 + "version": 1
5 + }
6 +}
\ No newline at end of file
Runners/watchOS/ControlKitRunnerApp.swift new
+86
@@ -0,0 +1,86 @@
1 +import SwiftUI
2 +
3 +@main
4 +struct ControlKitRunnerApp: App {
5 + var body: some Scene {
6 + WindowGroup {
7 + ControlKitShowcaseView()
8 + }
9 + }
10 +}
11 +
12 +private struct ControlKitShowcaseView: View {
13 + var body: some View {
14 + ScrollView {
15 + VStack(alignment: .leading, spacing: 12) {
16 + HStack(spacing: 10) {
17 + logo
18 + VStack(alignment: .leading, spacing: 2) {
19 + Text("ControlKit")
20 + .font(.headline)
21 + Text("watchOS")
22 + .font(.caption2)
23 + .foregroundStyle(.secondary)
24 + }
25 + }
26 +
27 + statusCard
28 + informationCard
29 + }
30 + .padding(12)
31 + }
32 + .background(Color.controlKitGreen.ignoresSafeArea())
33 + .foregroundStyle(Color.controlKitCream)
34 + }
35 +
36 + private var logo: some View {
37 + Text("XC\nRS")
38 + .font(.system(size: 14, weight: .black, design: .rounded))
39 + .multilineTextAlignment(.center)
40 + .lineSpacing(-3)
41 + .foregroundStyle(Color.controlKitGreen)
42 + .frame(width: 40, height: 40)
43 + .background(Color.controlKitCream, in: RoundedRectangle(cornerRadius: 10))
44 + }
45 +
46 + private var statusCard: some View {
47 + VStack(alignment: .leading, spacing: 6) {
48 + Label("Runner online", systemImage: "checkmark.circle.fill")
49 + .font(.footnote)
50 + .foregroundStyle(.green)
51 + Text("Ready for ControlKit automation requests.")
52 + .font(.caption2)
53 + .foregroundStyle(Color.controlKitCream.opacity(0.78))
54 + }
55 + .padding(12)
56 + .frame(maxWidth: .infinity, alignment: .leading)
57 + .background(.white.opacity(0.1), in: RoundedRectangle(cornerRadius: 14))
58 + }
59 +
60 + private var informationCard: some View {
61 + VStack(alignment: .leading, spacing: 8) {
62 + infoRow(title: "Project", value: "XCRSControlKit")
63 + infoRow(title: "Creator", value: "smbCloud")
64 + infoRow(title: "Purpose", value: "Companion automation runner")
65 + }
66 + .padding(12)
67 + .frame(maxWidth: .infinity, alignment: .leading)
68 + .background(.white.opacity(0.08), in: RoundedRectangle(cornerRadius: 14))
69 + }
70 +
71 + private func infoRow(title: String, value: String) -> some View {
72 + VStack(alignment: .leading, spacing: 1) {
73 + Text(title)
74 + .font(.caption2)
75 + .foregroundStyle(Color.controlKitCream.opacity(0.62))
76 + Text(value)
77 + .font(.caption)
78 + .fontWeight(.semibold)
79 + }
80 + }
81 +}
82 +
83 +private extension Color {
84 + static let controlKitGreen = Color(red: 0.106, green: 0.263, blue: 0.196)
85 + static let controlKitCream = Color(red: 0.961, green: 0.953, blue: 0.925)
86 +}
Runners/watchOS/README.md new
+13
@@ -0,0 +1,13 @@
1 +# ControlKit watchOS host app
2 +
3 +This folder holds the watchOS host application (`ControlKitRunnerApp.swift` and
4 +`Assets.xcassets`) for the `ControlKit-watchOS` target in the shared
5 +`XCRSControlKitRunner.xcodeproj`.
6 +
7 +watchOS UI testing is supported from Xcode 26 onward (the platform ships
8 +`XCUIAutomation.framework`). Touch input is delivered through `XCUICoordinate`
9 +taps; `device.capabilities` reports the paired-device profile
10 +(`accessibility`, `appLifecycle`, `pairedDevice`, `screenshot`), and pointer,
11 +spatial, `home`, and remote-button interactions are intentionally unsupported.
12 +The JSON-RPC transport and server live in `../Shared` and are compiled into the
13 +`ControlKit-watchOS-UITests` target.