@geastack/apple 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +54 -0
  3. package/dist/index.d.ts +127 -0
  4. package/dist/index.js +3076 -0
  5. package/generated/AVFoundation.d.ts +112 -0
  6. package/generated/ActivityKit.d.ts +7 -0
  7. package/generated/AppKit.d.ts +268 -0
  8. package/generated/CoreGraphics.d.ts +18 -0
  9. package/generated/CoreLocation.d.ts +28 -0
  10. package/generated/CoreMedia.d.ts +8 -0
  11. package/generated/Dispatch.d.ts +2 -0
  12. package/generated/Foundation.d.ts +13 -0
  13. package/generated/MapKit.d.ts +28 -0
  14. package/generated/Metal.d.ts +91 -0
  15. package/generated/MetalKit.d.ts +22 -0
  16. package/generated/Photos.d.ts +5 -0
  17. package/generated/QuartzCore.d.ts +12 -0
  18. package/generated/SwiftData.d.ts +11 -0
  19. package/generated/UIKit.d.ts +187 -0
  20. package/package.json +123 -0
  21. package/runtime/AVFoundation.js +136 -0
  22. package/runtime/ActivityKit.js +18 -0
  23. package/runtime/AppKit.js +313 -0
  24. package/runtime/CoreGraphics.js +15 -0
  25. package/runtime/CoreLocation.js +30 -0
  26. package/runtime/CoreMedia.js +7 -0
  27. package/runtime/Dispatch.js +11 -0
  28. package/runtime/Foundation.js +21 -0
  29. package/runtime/MapKit.js +22 -0
  30. package/runtime/Metal.js +126 -0
  31. package/runtime/MetalKit.js +15 -0
  32. package/runtime/Photos.js +9 -0
  33. package/runtime/QuartzCore.js +9 -0
  34. package/runtime/SwiftData.js +29 -0
  35. package/runtime/UIKit.js +242 -0
  36. package/runtime/empty.js +1 -0
  37. package/targets/ios/Info.plist.in +25 -0
  38. package/targets/ios/README.md +46 -0
  39. package/targets/ios/build-ios.sh +395 -0
  40. package/targets/ios/detect-development-team.mjs +109 -0
  41. package/targets/ios/generate-resident-entry.mjs +67 -0
  42. package/targets/ios/generate-resident-registry.mjs +162 -0
  43. package/targets/ios/generate-xcode-project.mjs +520 -0
  44. package/targets/ios/main/canvas_view.h +7 -0
  45. package/targets/ios/main/canvas_view.mm +94 -0
  46. package/targets/ios/main/font_registry.h +17 -0
  47. package/targets/ios/main/font_registry.mm +129 -0
  48. package/targets/ios/main/image_bridge.h +13 -0
  49. package/targets/ios/main/image_bridge.mm +53 -0
  50. package/targets/ios/main/ios_apps.c +28 -0
  51. package/targets/ios/main/ios_camera.mm +446 -0
  52. package/targets/ios/main/ios_display.mm +344 -0
  53. package/targets/ios/main/ios_main.mm +811 -0
  54. package/targets/ios/main/ios_memory.cpp +55 -0
  55. package/targets/ios/main/ios_renderer.h +20 -0
  56. package/targets/ios/main/ios_renderer.mm +27 -0
  57. package/targets/ios/main/ios_root_background.cpp +20 -0
  58. package/targets/ios/main/ios_root_background.h +11 -0
  59. package/targets/ios/main/ios_sensors.mm +244 -0
  60. package/targets/ios/main/ios_timers.mm +53 -0
  61. package/targets/ios/main/renderer/ios_renderer_internal.h +65 -0
  62. package/targets/ios/main/renderer/ios_renderer_support.mm +111 -0
  63. package/targets/ios/main/renderer/native_button.mm +179 -0
  64. package/targets/ios/main/renderer/native_label.mm +161 -0
  65. package/targets/ios/main/renderer/native_scroll_container.mm +279 -0
  66. package/targets/ios/main/renderer/view_reconciler.mm +274 -0
  67. package/targets/macos/Info.plist.in +26 -0
  68. package/targets/macos/README.md +131 -0
  69. package/targets/macos/build-child-lifecycle.sh +119 -0
  70. package/targets/macos/build-macos.sh +2156 -0
  71. package/targets/macos/check-module-graph-freshness.mjs +82 -0
  72. package/targets/macos/compiler-input-fingerprint.mjs +32 -0
  73. package/targets/macos/finalize-apple-native-output.mjs +77 -0
  74. package/targets/macos/generate-resident-entry.mjs +80 -0
  75. package/targets/macos/generate-resident-registry.mjs +141 -0
  76. package/targets/macos/heavy-build-lock.sh +176 -0
  77. package/targets/macos/main/canvas_view.h +9 -0
  78. package/targets/macos/main/canvas_view.mm +176 -0
  79. package/targets/macos/main/color_convert.h +18 -0
  80. package/targets/macos/main/color_convert.mm +39 -0
  81. package/targets/macos/main/font_registry.h +35 -0
  82. package/targets/macos/main/font_registry.mm +350 -0
  83. package/targets/macos/main/image_bridge.h +16 -0
  84. package/targets/macos/main/image_bridge.mm +52 -0
  85. package/targets/macos/main/macos_app_platform.mm +95 -0
  86. package/targets/macos/main/macos_apps.c +31 -0
  87. package/targets/macos/main/macos_device_control.mm +56 -0
  88. package/targets/macos/main/macos_display.mm +484 -0
  89. package/targets/macos/main/macos_host_device_control.mm +95 -0
  90. package/targets/macos/main/macos_main.mm +839 -0
  91. package/targets/macos/main/macos_memory.cpp +31 -0
  92. package/targets/macos/main/macos_native_shell.h +31 -0
  93. package/targets/macos/main/macos_native_shell.mm +396 -0
  94. package/targets/macos/main/macos_network.mm +253 -0
  95. package/targets/macos/main/macos_renderer.h +39 -0
  96. package/targets/macos/main/macos_renderer.mm +1969 -0
  97. package/targets/macos/main/macos_sensors.cpp +148 -0
  98. package/targets/macos/main/macos_smoke_app.cpp +65 -0
  99. package/targets/macos/main/macos_timers.mm +52 -0
  100. package/targets/macos/main/press_bridge.h +21 -0
  101. package/targets/macos/main/press_bridge.mm +72 -0
  102. package/targets/macos/main/thermalright_hid_display.h +14 -0
  103. package/targets/macos/main/thermalright_hid_display.mm +995 -0
  104. package/targets/macos/native-artifact-provenance.mjs +421 -0
  105. package/targets/macos/order-compile-edges.mjs +64 -0
  106. package/targets/macos/preflight-hard-muted-artifact.mjs +93 -0
  107. package/targets/macos/prune-generated-modules.mjs +147 -0
  108. package/targets/macos/sync-resources.mjs +153 -0
  109. package/targets/shared/analyze-audio-capture.mjs +131 -0
  110. package/targets/shared/apple_audio.mm +1194 -0
  111. package/targets/shared/apple_audio_selftest.mm +602 -0
  112. package/targets/shared/apple_audio_testing.h +34 -0
  113. package/targets/shared/build-audio-selftest.sh +50 -0
package/dist/index.js ADDED
@@ -0,0 +1,3076 @@
1
+ const objcFrameworkImports = {
2
+ AVFoundation: 'AVFoundation/AVFoundation.h',
3
+ CoreMedia: 'CoreMedia/CoreMedia.h',
4
+ CoreLocation: 'CoreLocation/CoreLocation.h',
5
+ Dispatch: 'dispatch/dispatch.h',
6
+ Foundation: 'Foundation/Foundation.h',
7
+ MapKit: 'MapKit/MapKit.h',
8
+ Metal: 'Metal/Metal.h',
9
+ MetalKit: 'MetalKit/MetalKit.h',
10
+ Photos: 'Photos/Photos.h',
11
+ QuartzCore: 'QuartzCore/QuartzCore.h',
12
+ UIKit: 'UIKit/UIKit.h',
13
+ AppKit: 'AppKit/AppKit.h',
14
+ };
15
+ const voidType = { kind: 'primitive', name: 'void' };
16
+ const stringType = { kind: 'primitive', name: 'string' };
17
+ const numberType = { kind: 'primitive', name: 'number' };
18
+ const selectorType = { kind: 'primitive', name: 'selector' };
19
+ const controlEventsType = { kind: 'primitive', name: 'UIControlEvents' };
20
+ const textAlignmentType = { kind: 'primitive', name: 'NSTextAlignment' };
21
+ // NSLayoutConstraintOrientation is an NS_ENUM; model it as a named primitive (not
22
+ // `number`) so the apple-native lowering emits the explicit int->enum static_cast
23
+ // for method args (e.g. setContentHuggingPriority:forOrientation:). A bare `number`
24
+ // arg fails to compile ("cannot initialize NSLayoutConstraintOrientation from int").
25
+ const layoutConstraintOrientationType = { kind: 'primitive', name: 'NSLayoutConstraintOrientation' };
26
+ const viewContentModeType = { kind: 'primitive', name: 'UIViewContentMode' };
27
+ const layoutConstraintAxisType = { kind: 'primitive', name: 'UILayoutConstraintAxis' };
28
+ const stackViewAlignmentType = { kind: 'primitive', name: 'UIStackViewAlignment' };
29
+ const stackViewDistributionType = { kind: 'primitive', name: 'UIStackViewDistribution' };
30
+ const alertActionStyleType = { kind: 'primitive', name: 'UIAlertActionStyle' };
31
+ const alertControllerStyleType = { kind: 'primitive', name: 'UIAlertControllerStyle' };
32
+ const modalPresentationStyleType = { kind: 'primitive', name: 'UIModalPresentationStyle' };
33
+ const mapTypeType = { kind: 'primitive', name: 'MKMapType' };
34
+ const userTrackingModeType = { kind: 'primitive', name: 'MKUserTrackingMode' };
35
+ const captureFocusModeType = { kind: 'primitive', name: 'AVCaptureFocusMode' };
36
+ const captureExposureModeType = { kind: 'primitive', name: 'AVCaptureExposureMode' };
37
+ const captureDevicePositionType = { kind: 'primitive', name: 'AVCaptureDevicePosition' };
38
+ const captureFlashModeType = { kind: 'primitive', name: 'AVCaptureFlashMode' };
39
+ const capturePhotoQualityPrioritizationType = { kind: 'primitive', name: 'AVCapturePhotoQualityPrioritization' };
40
+ const captureWhiteBalanceModeType = { kind: 'primitive', name: 'AVCaptureWhiteBalanceMode' };
41
+ const metalPixelFormatType = numberType;
42
+ const metalPrimitiveType = numberType;
43
+ const metalResourceOptionsType = numberType;
44
+ const metalCompareFunctionType = numberType;
45
+ const numberArrayType = { kind: 'array', element: numberType };
46
+ const voidCallbackType = { kind: 'function', returns: voidType, parameters: [] };
47
+ const uiActionHandlerType = {
48
+ kind: 'function',
49
+ returns: voidType,
50
+ parameters: [{ name: 'action', type: { kind: 'class', name: 'UIKit.UIAction' } }],
51
+ };
52
+ const uiAlertActionHandlerType = {
53
+ kind: 'function',
54
+ returns: voidType,
55
+ parameters: [{ name: 'action', type: { kind: 'class', name: 'UIKit.UIAlertAction' } }],
56
+ };
57
+ const photoCaptureHandlerType = {
58
+ kind: 'function',
59
+ returns: voidType,
60
+ parameters: [
61
+ { name: 'data', type: { kind: 'class', name: 'Foundation.NSData' } },
62
+ { name: 'error', type: stringType },
63
+ ],
64
+ };
65
+ const photoLibrarySaveHandlerType = {
66
+ kind: 'function',
67
+ returns: voidType,
68
+ parameters: [
69
+ { name: 'success', type: { kind: 'primitive', name: 'boolean' } },
70
+ { name: 'error', type: stringType },
71
+ ],
72
+ };
73
+ const urlOpenCompletionHandlerType = {
74
+ kind: 'function',
75
+ returns: voidType,
76
+ parameters: [{ name: 'success', type: { kind: 'primitive', name: 'boolean' } }],
77
+ };
78
+ const cmtimeCallbackType = {
79
+ kind: 'function',
80
+ returns: voidType,
81
+ parameters: [{ name: 'syncTime', type: { kind: 'struct', name: 'CoreMedia.CMTime' } }],
82
+ };
83
+ const mtkViewDrawCallbackType = {
84
+ kind: 'function',
85
+ returns: voidType,
86
+ parameters: [],
87
+ };
88
+ const nativeStructFrameworks = new Set(['CoreGraphics', 'CoreLocation', 'CoreMedia', 'MapKit']);
89
+ export const appleSdkFixture = {
90
+ frameworks: [
91
+ {
92
+ name: 'Foundation',
93
+ classes: [
94
+ { name: 'NSObject' },
95
+ { name: 'NSData', extends: 'Foundation.NSObject' },
96
+ {
97
+ name: 'NSDictionary',
98
+ extends: 'Foundation.NSObject',
99
+ methods: [
100
+ {
101
+ name: 'dictionary',
102
+ selector: 'dictionary',
103
+ static: true,
104
+ returns: { kind: 'class', name: 'Foundation.NSDictionary' },
105
+ },
106
+ ],
107
+ },
108
+ {
109
+ name: 'NSURL',
110
+ extends: 'Foundation.NSObject',
111
+ methods: [
112
+ {
113
+ name: 'URLWithString',
114
+ selector: 'URLWithString:',
115
+ static: true,
116
+ returns: { kind: 'class', name: 'Foundation.NSURL', nullable: true },
117
+ parameters: [{ name: 'URLString', type: stringType }],
118
+ },
119
+ ],
120
+ },
121
+ ],
122
+ },
123
+ {
124
+ name: 'Dispatch',
125
+ functions: [
126
+ {
127
+ name: 'dispatchAsyncGlobal',
128
+ returns: voidType,
129
+ parameters: [{ name: 'execute', type: voidCallbackType }],
130
+ },
131
+ {
132
+ name: 'dispatchAsyncMain',
133
+ returns: voidType,
134
+ parameters: [{ name: 'execute', type: voidCallbackType }],
135
+ },
136
+ ],
137
+ },
138
+ {
139
+ name: 'CoreGraphics',
140
+ functions: [
141
+ {
142
+ name: 'CGRectMake',
143
+ returns: { kind: 'struct', name: 'CoreGraphics.CGRect' },
144
+ parameters: [
145
+ { name: 'x', type: numberType },
146
+ { name: 'y', type: numberType },
147
+ { name: 'width', type: numberType },
148
+ { name: 'height', type: numberType },
149
+ ],
150
+ },
151
+ {
152
+ name: 'CGPointMake',
153
+ returns: { kind: 'struct', name: 'CoreGraphics.CGPoint' },
154
+ parameters: [
155
+ { name: 'x', type: numberType },
156
+ { name: 'y', type: numberType },
157
+ ],
158
+ },
159
+ {
160
+ name: 'CGSizeMake',
161
+ returns: { kind: 'struct', name: 'CoreGraphics.CGSize' },
162
+ parameters: [
163
+ { name: 'width', type: numberType },
164
+ { name: 'height', type: numberType },
165
+ ],
166
+ },
167
+ ],
168
+ structs: [
169
+ {
170
+ name: 'CGPoint',
171
+ fields: [
172
+ { name: 'x', type: numberType },
173
+ { name: 'y', type: numberType },
174
+ ],
175
+ },
176
+ {
177
+ name: 'CGSize',
178
+ fields: [
179
+ { name: 'width', type: numberType },
180
+ { name: 'height', type: numberType },
181
+ ],
182
+ },
183
+ {
184
+ name: 'CGRect',
185
+ fields: [
186
+ { name: 'origin', type: { kind: 'struct', name: 'CoreGraphics.CGPoint' } },
187
+ { name: 'size', type: { kind: 'struct', name: 'CoreGraphics.CGSize' } },
188
+ ],
189
+ },
190
+ ],
191
+ },
192
+ {
193
+ name: 'QuartzCore',
194
+ imports: {
195
+ Foundation: ['NSObject'],
196
+ CoreGraphics: ['CGSize'],
197
+ },
198
+ classes: [
199
+ {
200
+ name: 'CALayer',
201
+ extends: 'Foundation.NSObject',
202
+ properties: [
203
+ { name: 'frame', type: { kind: 'struct', name: 'CoreGraphics.CGRect' } },
204
+ { name: 'cornerRadius', type: numberType },
205
+ { name: 'shadowOpacity', type: numberType },
206
+ { name: 'shadowRadius', type: numberType },
207
+ { name: 'shadowOffset', type: { kind: 'struct', name: 'CoreGraphics.CGSize' } },
208
+ { name: 'masksToBounds', type: { kind: 'primitive', name: 'boolean' } },
209
+ ],
210
+ methods: [
211
+ {
212
+ name: 'addSublayer',
213
+ selector: 'addSublayer:',
214
+ returns: voidType,
215
+ parameters: [{ name: 'layer', type: { kind: 'class', name: 'QuartzCore.CALayer' } }],
216
+ },
217
+ ],
218
+ },
219
+ ],
220
+ },
221
+ {
222
+ name: 'UIKit',
223
+ imports: {
224
+ Foundation: ['NSObject', 'NSURL'],
225
+ CoreGraphics: ['CGRect'],
226
+ QuartzCore: ['CALayer'],
227
+ },
228
+ constants: [
229
+ { name: 'UIAlertActionStyleDefault', type: alertActionStyleType, value: 0 },
230
+ { name: 'UIAlertActionStyleCancel', type: alertActionStyleType, value: 1 },
231
+ { name: 'UIAlertActionStyleDestructive', type: alertActionStyleType, value: 2 },
232
+ { name: 'UIAlertControllerStyleActionSheet', type: alertControllerStyleType, value: 0 },
233
+ { name: 'UIAlertControllerStyleAlert', type: alertControllerStyleType, value: 1 },
234
+ { name: 'UIModalPresentationFullScreen', type: modalPresentationStyleType, value: 0 },
235
+ { name: 'UIControlEventTouchDown', type: controlEventsType, value: 1 },
236
+ { name: 'UIControlEventTouchUpInside', type: controlEventsType, value: 64 },
237
+ { name: 'UIControlEventTouchUpOutside', type: controlEventsType, value: 128 },
238
+ { name: 'UIControlEventTouchCancel', type: controlEventsType, value: 256 },
239
+ { name: 'UIControlEventValueChanged', type: controlEventsType, value: 4096 },
240
+ { name: 'ObjCTargetAction', type: selectorType, value: 'invoke:' },
241
+ ],
242
+ classes: [
243
+ {
244
+ name: 'UIColor',
245
+ extends: 'Foundation.NSObject',
246
+ methods: [
247
+ {
248
+ name: 'systemBackgroundColor',
249
+ selector: 'systemBackgroundColor',
250
+ static: true,
251
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
252
+ },
253
+ {
254
+ name: 'systemGroupedBackgroundColor',
255
+ selector: 'systemGroupedBackgroundColor',
256
+ static: true,
257
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
258
+ },
259
+ {
260
+ name: 'secondarySystemGroupedBackgroundColor',
261
+ selector: 'secondarySystemGroupedBackgroundColor',
262
+ static: true,
263
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
264
+ },
265
+ {
266
+ name: 'labelColor',
267
+ selector: 'labelColor',
268
+ static: true,
269
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
270
+ },
271
+ {
272
+ name: 'secondaryLabelColor',
273
+ selector: 'secondaryLabelColor',
274
+ static: true,
275
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
276
+ },
277
+ {
278
+ name: 'systemBlueColor',
279
+ selector: 'systemBlueColor',
280
+ static: true,
281
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
282
+ },
283
+ {
284
+ name: 'systemIndigoColor',
285
+ selector: 'systemIndigoColor',
286
+ static: true,
287
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
288
+ },
289
+ {
290
+ name: 'systemPurpleColor',
291
+ selector: 'systemPurpleColor',
292
+ static: true,
293
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
294
+ },
295
+ {
296
+ name: 'systemTealColor',
297
+ selector: 'systemTealColor',
298
+ static: true,
299
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
300
+ },
301
+ {
302
+ name: 'systemGreenColor',
303
+ selector: 'systemGreenColor',
304
+ static: true,
305
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
306
+ },
307
+ {
308
+ name: 'systemOrangeColor',
309
+ selector: 'systemOrangeColor',
310
+ static: true,
311
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
312
+ },
313
+ {
314
+ name: 'systemGray5Color',
315
+ selector: 'systemGray5Color',
316
+ static: true,
317
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
318
+ },
319
+ {
320
+ name: 'whiteColor',
321
+ selector: 'whiteColor',
322
+ static: true,
323
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
324
+ },
325
+ {
326
+ name: 'blackColor',
327
+ selector: 'blackColor',
328
+ static: true,
329
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
330
+ },
331
+ {
332
+ name: 'colorWithRed',
333
+ selector: 'colorWithRed:green:blue:alpha:',
334
+ static: true,
335
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
336
+ parameters: [
337
+ { name: 'red', type: numberType },
338
+ { name: 'green', type: numberType },
339
+ { name: 'blue', type: numberType },
340
+ { name: 'alpha', type: numberType },
341
+ ],
342
+ },
343
+ {
344
+ name: 'colorWithRedGreenBlueAlpha',
345
+ selector: 'colorWithRed:green:blue:alpha:',
346
+ static: true,
347
+ returns: { kind: 'class', name: 'UIKit.UIColor' },
348
+ parameters: [
349
+ { name: 'red', type: numberType },
350
+ { name: 'green', type: numberType },
351
+ { name: 'blue', type: numberType },
352
+ { name: 'alpha', type: numberType },
353
+ ],
354
+ },
355
+ ],
356
+ },
357
+ {
358
+ name: 'UIFont',
359
+ extends: 'Foundation.NSObject',
360
+ methods: [
361
+ {
362
+ name: 'systemFontOfSize',
363
+ selector: 'systemFontOfSize:',
364
+ static: true,
365
+ returns: { kind: 'class', name: 'UIKit.UIFont' },
366
+ parameters: [{ name: 'fontSize', type: numberType }],
367
+ },
368
+ {
369
+ name: 'systemFontOfSizeWeight',
370
+ selector: 'systemFontOfSize:weight:',
371
+ static: true,
372
+ returns: { kind: 'class', name: 'UIKit.UIFont' },
373
+ parameters: [
374
+ { name: 'fontSize', type: numberType },
375
+ { name: 'weight', type: numberType },
376
+ ],
377
+ },
378
+ {
379
+ name: 'boldSystemFontOfSize',
380
+ selector: 'boldSystemFontOfSize:',
381
+ static: true,
382
+ returns: { kind: 'class', name: 'UIKit.UIFont' },
383
+ parameters: [{ name: 'fontSize', type: numberType }],
384
+ },
385
+ ],
386
+ },
387
+ {
388
+ name: 'UIScreen',
389
+ extends: 'Foundation.NSObject',
390
+ properties: [
391
+ { name: 'bounds', type: { kind: 'struct', name: 'CoreGraphics.CGRect' }, readonly: true },
392
+ { name: 'scale', type: numberType, readonly: true },
393
+ ],
394
+ methods: [
395
+ {
396
+ name: 'mainScreen',
397
+ selector: 'mainScreen',
398
+ static: true,
399
+ returns: { kind: 'class', name: 'UIKit.UIScreen' },
400
+ },
401
+ ],
402
+ },
403
+ {
404
+ name: 'UIApplication',
405
+ extends: 'Foundation.NSObject',
406
+ properties: [
407
+ { name: 'keyWindow', type: { kind: 'class', name: 'UIKit.UIWindow' }, readonly: true },
408
+ ],
409
+ methods: [
410
+ {
411
+ name: 'sharedApplication',
412
+ selector: 'sharedApplication',
413
+ static: true,
414
+ returns: { kind: 'class', name: 'UIKit.UIApplication' },
415
+ },
416
+ {
417
+ name: 'openURL',
418
+ selector: 'openURL:',
419
+ returns: { kind: 'primitive', name: 'boolean' },
420
+ parameters: [{ name: 'url', type: { kind: 'class', name: 'Foundation.NSURL' } }],
421
+ },
422
+ {
423
+ name: 'openURLOptionsCompletionHandler',
424
+ selector: 'openURL:options:completionHandler:',
425
+ returns: voidType,
426
+ parameters: [
427
+ { name: 'url', type: { kind: 'class', name: 'Foundation.NSURL' } },
428
+ { name: 'options', type: { kind: 'class', name: 'Foundation.NSDictionary' } },
429
+ { name: 'completionHandler', type: urlOpenCompletionHandlerType },
430
+ ],
431
+ },
432
+ ],
433
+ },
434
+ {
435
+ name: 'UIViewController',
436
+ extends: 'Foundation.NSObject',
437
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UIViewController' } }],
438
+ properties: [
439
+ { name: 'view', type: { kind: 'class', name: 'UIKit.UIView' } },
440
+ { name: 'title', type: stringType },
441
+ { name: 'modalPresentationStyle', type: modalPresentationStyleType },
442
+ ],
443
+ methods: [
444
+ {
445
+ name: 'presentViewControllerAnimatedCompletion',
446
+ selector: 'presentViewController:animated:completion:',
447
+ returns: voidType,
448
+ parameters: [
449
+ { name: 'viewControllerToPresent', type: { kind: 'class', name: 'UIKit.UIViewController' } },
450
+ { name: 'animated', type: { kind: 'primitive', name: 'boolean' } },
451
+ { name: 'completion', type: voidCallbackType },
452
+ ],
453
+ },
454
+ {
455
+ name: 'dismissViewControllerAnimatedCompletion',
456
+ selector: 'dismissViewControllerAnimated:completion:',
457
+ returns: voidType,
458
+ parameters: [
459
+ { name: 'animated', type: { kind: 'primitive', name: 'boolean' } },
460
+ { name: 'completion', type: voidCallbackType },
461
+ ],
462
+ },
463
+ ],
464
+ },
465
+ {
466
+ name: 'UINavigationController',
467
+ extends: 'UIKit.UIViewController',
468
+ constructors: [
469
+ {
470
+ name: 'initWithRootViewController',
471
+ selector: 'initWithRootViewController:',
472
+ returns: { kind: 'class', name: 'UIKit.UINavigationController' },
473
+ parameters: [{ name: 'rootViewController', type: { kind: 'class', name: 'UIKit.UIViewController' } }],
474
+ },
475
+ ],
476
+ },
477
+ {
478
+ name: 'UIAlertAction',
479
+ extends: 'Foundation.NSObject',
480
+ methods: [
481
+ {
482
+ name: 'actionWithTitleStyleHandler',
483
+ selector: 'actionWithTitle:style:handler:',
484
+ static: true,
485
+ returns: { kind: 'class', name: 'UIKit.UIAlertAction' },
486
+ parameters: [
487
+ { name: 'title', type: stringType },
488
+ { name: 'style', type: alertActionStyleType },
489
+ { name: 'handler', type: uiAlertActionHandlerType },
490
+ ],
491
+ },
492
+ ],
493
+ },
494
+ {
495
+ name: 'UIAlertController',
496
+ extends: 'UIKit.UIViewController',
497
+ methods: [
498
+ {
499
+ name: 'alertControllerWithTitleMessagePreferredStyle',
500
+ selector: 'alertControllerWithTitle:message:preferredStyle:',
501
+ static: true,
502
+ returns: { kind: 'class', name: 'UIKit.UIAlertController' },
503
+ parameters: [
504
+ { name: 'title', type: stringType },
505
+ { name: 'message', type: stringType },
506
+ { name: 'preferredStyle', type: alertControllerStyleType },
507
+ ],
508
+ },
509
+ {
510
+ name: 'addAction',
511
+ selector: 'addAction:',
512
+ returns: voidType,
513
+ parameters: [{ name: 'action', type: { kind: 'class', name: 'UIKit.UIAlertAction' } }],
514
+ },
515
+ ],
516
+ },
517
+ {
518
+ name: 'UIAction',
519
+ extends: 'Foundation.NSObject',
520
+ methods: [
521
+ {
522
+ name: 'actionWithHandler',
523
+ selector: 'actionWithHandler:',
524
+ static: true,
525
+ returns: { kind: 'class', name: 'UIKit.UIAction' },
526
+ parameters: [{ name: 'handler', type: uiActionHandlerType }],
527
+ },
528
+ ],
529
+ },
530
+ {
531
+ name: 'ObjCTarget',
532
+ methods: [
533
+ {
534
+ name: 'create',
535
+ selector: 'create:',
536
+ static: true,
537
+ returns: { kind: 'class', name: 'Foundation.NSObject' },
538
+ parameters: [{ name: 'callback', type: voidCallbackType }],
539
+ },
540
+ ],
541
+ },
542
+ {
543
+ name: 'UIView',
544
+ extends: 'Foundation.NSObject',
545
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UIView' } }],
546
+ properties: [
547
+ { name: 'frame', type: { kind: 'struct', name: 'CoreGraphics.CGRect' } },
548
+ { name: 'bounds', type: { kind: 'struct', name: 'CoreGraphics.CGRect' } },
549
+ { name: 'backgroundColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
550
+ { name: 'tintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
551
+ { name: 'layer', type: { kind: 'class', name: 'QuartzCore.CALayer' }, readonly: true },
552
+ { name: 'alpha', type: numberType },
553
+ { name: 'hidden', type: { kind: 'primitive', name: 'boolean' } },
554
+ { name: 'clipsToBounds', type: { kind: 'primitive', name: 'boolean' } },
555
+ { name: 'userInteractionEnabled', type: { kind: 'primitive', name: 'boolean' } },
556
+ { name: 'tag', type: numberType },
557
+ { name: 'isAccessibilityElement', type: { kind: 'primitive', name: 'boolean' } },
558
+ { name: 'accessibilityLabel', type: stringType },
559
+ ],
560
+ methods: [
561
+ {
562
+ name: 'addSubview',
563
+ selector: 'addSubview:',
564
+ returns: voidType,
565
+ parameters: [{ name: 'view', type: { kind: 'class', name: 'UIKit.UIView' } }],
566
+ },
567
+ {
568
+ name: 'layoutIfNeeded',
569
+ selector: 'layoutIfNeeded',
570
+ returns: voidType,
571
+ },
572
+ ],
573
+ },
574
+ {
575
+ name: 'UIWindow',
576
+ extends: 'UIKit.UIView',
577
+ properties: [
578
+ { name: 'rootViewController', type: { kind: 'class', name: 'UIKit.UIViewController' } },
579
+ ],
580
+ },
581
+ {
582
+ name: 'UIControl',
583
+ extends: 'UIKit.UIView',
584
+ methods: [
585
+ {
586
+ name: 'addTarget',
587
+ selector: 'addTarget:action:forControlEvents:',
588
+ returns: voidType,
589
+ parameters: [
590
+ { name: 'target', type: { kind: 'class', name: 'Foundation.NSObject', nullable: true } },
591
+ { name: 'action', type: selectorType },
592
+ { name: 'controlEvents', type: controlEventsType },
593
+ ],
594
+ },
595
+ {
596
+ name: 'addAction',
597
+ selector: 'addAction:forControlEvents:',
598
+ returns: voidType,
599
+ parameters: [
600
+ { name: 'action', type: { kind: 'class', name: 'UIKit.UIAction' } },
601
+ { name: 'controlEvents', type: controlEventsType },
602
+ ],
603
+ },
604
+ ],
605
+ },
606
+ {
607
+ name: 'UIButton',
608
+ extends: 'UIKit.UIControl',
609
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UIButton' } }],
610
+ methods: [
611
+ {
612
+ name: 'setTitle',
613
+ selector: 'setTitle:forState:',
614
+ returns: voidType,
615
+ parameters: [
616
+ { name: 'title', type: stringType },
617
+ { name: 'state', type: numberType },
618
+ ],
619
+ },
620
+ {
621
+ name: 'setTitleColor',
622
+ selector: 'setTitleColor:forState:',
623
+ returns: voidType,
624
+ parameters: [
625
+ { name: 'color', type: { kind: 'class', name: 'UIKit.UIColor' } },
626
+ { name: 'state', type: numberType },
627
+ ],
628
+ },
629
+ ],
630
+ properties: [{ name: 'titleLabel', type: { kind: 'class', name: 'UIKit.UILabel' }, readonly: true }],
631
+ },
632
+ {
633
+ name: 'UILabel',
634
+ extends: 'UIKit.UIView',
635
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UILabel' } }],
636
+ properties: [
637
+ { name: 'text', type: stringType },
638
+ { name: 'textColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
639
+ { name: 'font', type: { kind: 'class', name: 'UIKit.UIFont', nullable: true } },
640
+ { name: 'numberOfLines', type: numberType },
641
+ { name: 'textAlignment', type: textAlignmentType },
642
+ ],
643
+ },
644
+ {
645
+ name: 'UIImage',
646
+ extends: 'Foundation.NSObject',
647
+ methods: [
648
+ {
649
+ name: 'systemImageNamed',
650
+ selector: 'systemImageNamed:',
651
+ static: true,
652
+ returns: { kind: 'class', name: 'UIKit.UIImage', nullable: true },
653
+ parameters: [{ name: 'name', type: stringType }],
654
+ },
655
+ ],
656
+ },
657
+ {
658
+ name: 'UIImageView',
659
+ extends: 'UIKit.UIView',
660
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UIImageView' } }],
661
+ properties: [
662
+ { name: 'image', type: { kind: 'class', name: 'UIKit.UIImage', nullable: true } },
663
+ { name: 'tintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
664
+ { name: 'contentMode', type: viewContentModeType },
665
+ ],
666
+ },
667
+ {
668
+ name: 'UIStackView',
669
+ extends: 'UIKit.UIView',
670
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UIStackView' } }],
671
+ properties: [
672
+ { name: 'axis', type: layoutConstraintAxisType },
673
+ { name: 'alignment', type: stackViewAlignmentType },
674
+ { name: 'distribution', type: stackViewDistributionType },
675
+ { name: 'spacing', type: numberType },
676
+ ],
677
+ methods: [
678
+ {
679
+ name: 'addArrangedSubview',
680
+ selector: 'addArrangedSubview:',
681
+ returns: voidType,
682
+ parameters: [{ name: 'view', type: { kind: 'class', name: 'UIKit.UIView' } }],
683
+ },
684
+ ],
685
+ },
686
+ {
687
+ name: 'UIBlurEffect',
688
+ extends: 'Foundation.NSObject',
689
+ methods: [
690
+ {
691
+ name: 'effectWithStyle',
692
+ selector: 'effectWithStyle:',
693
+ static: true,
694
+ returns: { kind: 'class', name: 'UIKit.UIBlurEffect' },
695
+ parameters: [{ name: 'style', type: { kind: 'primitive', name: 'UIBlurEffectStyle' } }],
696
+ },
697
+ ],
698
+ },
699
+ {
700
+ name: 'UIVisualEffectView',
701
+ extends: 'UIKit.UIView',
702
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UIVisualEffectView' } }],
703
+ properties: [
704
+ { name: 'effect', type: { kind: 'class', name: 'UIKit.UIBlurEffect', nullable: true } },
705
+ { name: 'contentView', type: { kind: 'class', name: 'UIKit.UIView' }, readonly: true },
706
+ ],
707
+ },
708
+ {
709
+ name: 'UISwitch',
710
+ extends: 'UIKit.UIView',
711
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UISwitch' } }],
712
+ properties: [
713
+ { name: 'on', type: { kind: 'primitive', name: 'boolean' } },
714
+ { name: 'onTintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
715
+ { name: 'thumbTintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
716
+ ],
717
+ methods: [
718
+ {
719
+ name: 'setOn',
720
+ selector: 'setOn:animated:',
721
+ returns: voidType,
722
+ parameters: [
723
+ { name: 'on', type: { kind: 'primitive', name: 'boolean' } },
724
+ { name: 'animated', type: { kind: 'primitive', name: 'boolean' } },
725
+ ],
726
+ },
727
+ ],
728
+ },
729
+ {
730
+ name: 'UIProgressView',
731
+ extends: 'UIKit.UIView',
732
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UIProgressView' } }],
733
+ properties: [
734
+ { name: 'progress', type: numberType },
735
+ { name: 'progressTintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
736
+ { name: 'trackTintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
737
+ ],
738
+ },
739
+ {
740
+ name: 'UISlider',
741
+ extends: 'UIKit.UIControl',
742
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'UIKit.UISlider' } }],
743
+ properties: [
744
+ { name: 'value', type: numberType },
745
+ { name: 'minimumValue', type: numberType },
746
+ { name: 'maximumValue', type: numberType },
747
+ { name: 'continuous', type: { kind: 'primitive', name: 'boolean' } },
748
+ { name: 'minimumTrackTintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
749
+ { name: 'maximumTrackTintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
750
+ { name: 'thumbTintColor', type: { kind: 'class', name: 'UIKit.UIColor', nullable: true } },
751
+ ],
752
+ },
753
+ ],
754
+ functions: [
755
+ {
756
+ name: 'installRootView',
757
+ returns: voidType,
758
+ parameters: [{ name: 'view', type: { kind: 'class', name: 'UIKit.UIView' } }],
759
+ },
760
+ ],
761
+ },
762
+ {
763
+ name: 'CoreLocation',
764
+ imports: {
765
+ Foundation: ['NSObject'],
766
+ },
767
+ constants: [
768
+ { name: 'kCLLocationAccuracyBest', type: numberType, value: -1 },
769
+ { name: 'CLDistanceFilterNone', type: numberType, value: -1 },
770
+ { name: 'CLAuthorizationStatusNotDetermined', type: numberType, value: 0 },
771
+ { name: 'CLAuthorizationStatusAuthorizedWhenInUse', type: numberType, value: 4 },
772
+ ],
773
+ functions: [
774
+ {
775
+ name: 'CLLocationCoordinate2DMake',
776
+ returns: { kind: 'struct', name: 'CoreLocation.CLLocationCoordinate2D' },
777
+ parameters: [
778
+ { name: 'latitude', type: numberType },
779
+ { name: 'longitude', type: numberType },
780
+ ],
781
+ },
782
+ ],
783
+ structs: [
784
+ {
785
+ name: 'CLLocationCoordinate2D',
786
+ fields: [
787
+ { name: 'latitude', type: numberType },
788
+ { name: 'longitude', type: numberType },
789
+ ],
790
+ },
791
+ ],
792
+ classes: [
793
+ {
794
+ name: 'CLLocation',
795
+ extends: 'Foundation.NSObject',
796
+ properties: [
797
+ { name: 'coordinate', type: { kind: 'struct', name: 'CoreLocation.CLLocationCoordinate2D' }, readonly: true },
798
+ { name: 'horizontalAccuracy', type: numberType, readonly: true },
799
+ ],
800
+ },
801
+ {
802
+ name: 'CLLocationManager',
803
+ extends: 'Foundation.NSObject',
804
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'CoreLocation.CLLocationManager' } }],
805
+ properties: [
806
+ { name: 'desiredAccuracy', type: numberType },
807
+ { name: 'distanceFilter', type: numberType },
808
+ { name: 'location', type: { kind: 'class', name: 'CoreLocation.CLLocation', nullable: true }, readonly: true },
809
+ ],
810
+ methods: [
811
+ { name: 'requestWhenInUseAuthorization', selector: 'requestWhenInUseAuthorization', returns: voidType },
812
+ { name: 'startUpdatingLocation', selector: 'startUpdatingLocation', returns: voidType },
813
+ { name: 'stopUpdatingLocation', selector: 'stopUpdatingLocation', returns: voidType },
814
+ ],
815
+ },
816
+ ],
817
+ },
818
+ {
819
+ name: 'MapKit',
820
+ imports: {
821
+ CoreLocation: ['CLLocationCoordinate2D'],
822
+ UIKit: ['UIView'],
823
+ },
824
+ constants: [
825
+ { name: 'MKMapTypeStandard', type: mapTypeType, value: 0 },
826
+ { name: 'MKMapTypeMutedStandard', type: mapTypeType, value: 1 },
827
+ { name: 'MKMapTypeSatellite', type: mapTypeType, value: 2 },
828
+ { name: 'MKUserTrackingModeNone', type: userTrackingModeType, value: 0 },
829
+ { name: 'MKUserTrackingModeFollow', type: userTrackingModeType, value: 1 },
830
+ ],
831
+ functions: [
832
+ {
833
+ name: 'MKCoordinateRegionMakeWithDistance',
834
+ returns: { kind: 'struct', name: 'MapKit.MKCoordinateRegion' },
835
+ parameters: [
836
+ { name: 'centerCoordinate', type: { kind: 'struct', name: 'CoreLocation.CLLocationCoordinate2D' } },
837
+ { name: 'latitudinalMeters', type: numberType },
838
+ { name: 'longitudinalMeters', type: numberType },
839
+ ],
840
+ },
841
+ ],
842
+ structs: [
843
+ {
844
+ name: 'MKCoordinateSpan',
845
+ fields: [
846
+ { name: 'latitudeDelta', type: numberType },
847
+ { name: 'longitudeDelta', type: numberType },
848
+ ],
849
+ },
850
+ {
851
+ name: 'MKCoordinateRegion',
852
+ fields: [
853
+ { name: 'center', type: { kind: 'struct', name: 'CoreLocation.CLLocationCoordinate2D' } },
854
+ { name: 'span', type: { kind: 'struct', name: 'MapKit.MKCoordinateSpan' } },
855
+ ],
856
+ },
857
+ ],
858
+ classes: [
859
+ {
860
+ name: 'MKMapView',
861
+ extends: 'UIKit.UIView',
862
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'MapKit.MKMapView' } }],
863
+ properties: [
864
+ { name: 'mapType', type: mapTypeType },
865
+ { name: 'showsUserLocation', type: { kind: 'primitive', name: 'boolean' } },
866
+ { name: 'userTrackingMode', type: userTrackingModeType },
867
+ ],
868
+ methods: [
869
+ {
870
+ name: 'setRegionAnimated',
871
+ selector: 'setRegion:animated:',
872
+ returns: voidType,
873
+ parameters: [
874
+ { name: 'region', type: { kind: 'struct', name: 'MapKit.MKCoordinateRegion' } },
875
+ { name: 'animated', type: { kind: 'primitive', name: 'boolean' } },
876
+ ],
877
+ },
878
+ ],
879
+ },
880
+ ],
881
+ },
882
+ {
883
+ name: 'CoreMedia',
884
+ functions: [
885
+ {
886
+ name: 'CMTimeMakeWithSeconds',
887
+ returns: { kind: 'struct', name: 'CoreMedia.CMTime' },
888
+ parameters: [
889
+ { name: 'seconds', type: numberType },
890
+ { name: 'preferredTimescale', type: numberType },
891
+ ],
892
+ },
893
+ ],
894
+ structs: [
895
+ {
896
+ name: 'CMTime',
897
+ fields: [
898
+ { name: 'value', type: numberType },
899
+ { name: 'timescale', type: numberType },
900
+ { name: 'flags', type: numberType },
901
+ { name: 'epoch', type: numberType },
902
+ ],
903
+ },
904
+ ],
905
+ },
906
+ {
907
+ name: 'AVFoundation',
908
+ imports: {
909
+ CoreGraphics: ['CGRect', 'CGPoint'],
910
+ CoreMedia: ['CMTime'],
911
+ Foundation: ['NSData', 'NSObject'],
912
+ QuartzCore: ['CALayer'],
913
+ },
914
+ constants: [
915
+ { name: 'AVMediaTypeVideo', type: stringType, value: 'vide' },
916
+ { name: 'AVLayerVideoGravityResizeAspectFill', type: stringType, value: 'resizeAspectFill' },
917
+ { name: 'AVCaptureSessionPresetPhoto', type: stringType, value: 'Photo' },
918
+ { name: 'AVCaptureSessionPresetHigh', type: stringType, value: 'High' },
919
+ { name: 'AVCaptureSessionPresetMedium', type: stringType, value: 'Medium' },
920
+ { name: 'AVCaptureFocusModeLocked', type: captureFocusModeType, value: 0 },
921
+ { name: 'AVCaptureFocusModeAutoFocus', type: captureFocusModeType, value: 1 },
922
+ { name: 'AVCaptureFocusModeContinuousAutoFocus', type: captureFocusModeType, value: 2 },
923
+ { name: 'AVCaptureExposureModeLocked', type: captureExposureModeType, value: 0 },
924
+ { name: 'AVCaptureExposureModeAutoExpose', type: captureExposureModeType, value: 1 },
925
+ { name: 'AVCaptureExposureModeContinuousAutoExposure', type: captureExposureModeType, value: 2 },
926
+ { name: 'AVCaptureExposureModeCustom', type: captureExposureModeType, value: 3 },
927
+ { name: 'AVCaptureWhiteBalanceModeLocked', type: captureWhiteBalanceModeType, value: 0 },
928
+ { name: 'AVCaptureWhiteBalanceModeAutoWhiteBalance', type: captureWhiteBalanceModeType, value: 1 },
929
+ { name: 'AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance', type: captureWhiteBalanceModeType, value: 2 },
930
+ { name: 'AVCaptureFlashModeOff', type: captureFlashModeType, value: 0 },
931
+ { name: 'AVCaptureFlashModeOn', type: captureFlashModeType, value: 1 },
932
+ { name: 'AVCaptureFlashModeAuto', type: captureFlashModeType, value: 2 },
933
+ { name: 'AVCapturePhotoQualityPrioritizationSpeed', type: capturePhotoQualityPrioritizationType, value: 1 },
934
+ { name: 'AVCapturePhotoQualityPrioritizationBalanced', type: capturePhotoQualityPrioritizationType, value: 2 },
935
+ { name: 'AVCapturePhotoQualityPrioritizationQuality', type: capturePhotoQualityPrioritizationType, value: 3 },
936
+ { name: 'AVCaptureDevicePositionUnspecified', type: captureDevicePositionType, value: 0 },
937
+ { name: 'AVCaptureDevicePositionBack', type: captureDevicePositionType, value: 1 },
938
+ { name: 'AVCaptureDevicePositionFront', type: captureDevicePositionType, value: 2 },
939
+ { name: 'AVCaptureDeviceTypeBuiltInWideAngleCamera', type: stringType, value: 'AVCaptureDeviceTypeBuiltInWideAngleCamera' },
940
+ { name: 'AVCaptureDeviceTypeBuiltInUltraWideCamera', type: stringType, value: 'AVCaptureDeviceTypeBuiltInUltraWideCamera' },
941
+ { name: 'AVCaptureDeviceTypeBuiltInTelephotoCamera', type: stringType, value: 'AVCaptureDeviceTypeBuiltInTelephotoCamera' },
942
+ { name: 'AVCaptureDeviceTypeBuiltInDualCamera', type: stringType, value: 'AVCaptureDeviceTypeBuiltInDualCamera' },
943
+ { name: 'AVCaptureDeviceTypeBuiltInDualWideCamera', type: stringType, value: 'AVCaptureDeviceTypeBuiltInDualWideCamera' },
944
+ { name: 'AVCaptureDeviceTypeBuiltInTripleCamera', type: stringType, value: 'AVCaptureDeviceTypeBuiltInTripleCamera' },
945
+ ],
946
+ classes: [
947
+ {
948
+ name: 'AVCaptureInput',
949
+ extends: 'Foundation.NSObject',
950
+ },
951
+ {
952
+ name: 'AVCaptureOutput',
953
+ extends: 'Foundation.NSObject',
954
+ },
955
+ {
956
+ name: 'AVCaptureDeviceFormat',
957
+ extends: 'Foundation.NSObject',
958
+ properties: [
959
+ { name: 'minISO', type: numberType, readonly: true },
960
+ { name: 'maxISO', type: numberType, readonly: true },
961
+ { name: 'videoMaxZoomFactor', type: numberType, readonly: true },
962
+ ],
963
+ },
964
+ {
965
+ name: 'AVCaptureDevice',
966
+ extends: 'Foundation.NSObject',
967
+ properties: [
968
+ { name: 'activeFormat', type: { kind: 'class', name: 'AVFoundation.AVCaptureDeviceFormat' }, readonly: true },
969
+ { name: 'videoZoomFactor', type: numberType },
970
+ { name: 'minAvailableVideoZoomFactor', type: numberType, readonly: true },
971
+ { name: 'maxAvailableVideoZoomFactor', type: numberType, readonly: true },
972
+ { name: 'focusPointOfInterest', type: { kind: 'struct', name: 'CoreGraphics.CGPoint' } },
973
+ { name: 'focusMode', type: captureFocusModeType },
974
+ { name: 'isFocusPointOfInterestSupported', type: { kind: 'primitive', name: 'boolean' }, readonly: true },
975
+ { name: 'exposurePointOfInterest', type: { kind: 'struct', name: 'CoreGraphics.CGPoint' } },
976
+ { name: 'exposureMode', type: captureExposureModeType },
977
+ { name: 'isExposurePointOfInterestSupported', type: { kind: 'primitive', name: 'boolean' }, readonly: true },
978
+ { name: 'exposureTargetBias', type: numberType, readonly: true },
979
+ { name: 'minExposureTargetBias', type: numberType, readonly: true },
980
+ { name: 'maxExposureTargetBias', type: numberType, readonly: true },
981
+ { name: 'ISO', type: numberType, readonly: true },
982
+ { name: 'whiteBalanceMode', type: captureWhiteBalanceModeType },
983
+ { name: 'hasFlash', type: { kind: 'primitive', name: 'boolean' }, readonly: true },
984
+ { name: 'virtualDeviceSwitchOverVideoZoomFactors', type: numberArrayType, readonly: true },
985
+ ],
986
+ methods: [
987
+ {
988
+ name: 'defaultDeviceWithMediaType',
989
+ selector: 'defaultDeviceWithMediaType:',
990
+ static: true,
991
+ returns: { kind: 'class', name: 'AVFoundation.AVCaptureDevice', nullable: true },
992
+ parameters: [{ name: 'mediaType', type: stringType }],
993
+ },
994
+ {
995
+ name: 'defaultDeviceWithDeviceTypeMediaTypePosition',
996
+ selector: 'defaultDeviceWithDeviceType:mediaType:position:',
997
+ static: true,
998
+ returns: { kind: 'class', name: 'AVFoundation.AVCaptureDevice', nullable: true },
999
+ parameters: [
1000
+ { name: 'deviceType', type: stringType },
1001
+ { name: 'mediaType', type: stringType },
1002
+ { name: 'position', type: captureDevicePositionType },
1003
+ ],
1004
+ },
1005
+ {
1006
+ name: 'lockForConfiguration',
1007
+ selector: 'lockForConfiguration:',
1008
+ returns: { kind: 'primitive', name: 'boolean' },
1009
+ },
1010
+ { name: 'unlockForConfiguration', selector: 'unlockForConfiguration', returns: voidType },
1011
+ {
1012
+ name: 'isFocusModeSupported',
1013
+ selector: 'isFocusModeSupported:',
1014
+ returns: { kind: 'primitive', name: 'boolean' },
1015
+ parameters: [{ name: 'focusMode', type: captureFocusModeType }],
1016
+ },
1017
+ {
1018
+ name: 'isExposureModeSupported',
1019
+ selector: 'isExposureModeSupported:',
1020
+ returns: { kind: 'primitive', name: 'boolean' },
1021
+ parameters: [{ name: 'exposureMode', type: captureExposureModeType }],
1022
+ },
1023
+ {
1024
+ name: 'isWhiteBalanceModeSupported',
1025
+ selector: 'isWhiteBalanceModeSupported:',
1026
+ returns: { kind: 'primitive', name: 'boolean' },
1027
+ parameters: [{ name: 'whiteBalanceMode', type: captureWhiteBalanceModeType }],
1028
+ },
1029
+ {
1030
+ name: 'isFlashModeSupported',
1031
+ selector: 'isFlashModeSupported:',
1032
+ returns: { kind: 'primitive', name: 'boolean' },
1033
+ parameters: [{ name: 'flashMode', type: captureFlashModeType }],
1034
+ },
1035
+ {
1036
+ name: 'setExposureTargetBiasCompletionHandler',
1037
+ selector: 'setExposureTargetBias:completionHandler:',
1038
+ returns: voidType,
1039
+ parameters: [
1040
+ { name: 'bias', type: numberType },
1041
+ { name: 'handler', type: cmtimeCallbackType },
1042
+ ],
1043
+ },
1044
+ {
1045
+ name: 'setExposureModeCustomWithDurationISOCompletionHandler',
1046
+ selector: 'setExposureModeCustomWithDuration:ISO:completionHandler:',
1047
+ returns: voidType,
1048
+ parameters: [
1049
+ { name: 'duration', type: { kind: 'struct', name: 'CoreMedia.CMTime' } },
1050
+ { name: 'ISO', type: numberType },
1051
+ { name: 'handler', type: cmtimeCallbackType },
1052
+ ],
1053
+ },
1054
+ ],
1055
+ },
1056
+ {
1057
+ name: 'AVCaptureDeviceInput',
1058
+ extends: 'AVFoundation.AVCaptureInput',
1059
+ methods: [
1060
+ {
1061
+ name: 'deviceInputWithDevice',
1062
+ selector: 'deviceInputWithDevice:error:',
1063
+ static: true,
1064
+ returns: { kind: 'class', name: 'AVFoundation.AVCaptureDeviceInput', nullable: true },
1065
+ parameters: [{ name: 'device', type: { kind: 'class', name: 'AVFoundation.AVCaptureDevice' } }],
1066
+ },
1067
+ ],
1068
+ },
1069
+ {
1070
+ name: 'AVCaptureSession',
1071
+ extends: 'Foundation.NSObject',
1072
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AVFoundation.AVCaptureSession' } }],
1073
+ properties: [{ name: 'sessionPreset', type: stringType }],
1074
+ methods: [
1075
+ { name: 'beginConfiguration', selector: 'beginConfiguration', returns: voidType },
1076
+ { name: 'commitConfiguration', selector: 'commitConfiguration', returns: voidType },
1077
+ {
1078
+ name: 'canAddInput',
1079
+ selector: 'canAddInput:',
1080
+ returns: { kind: 'primitive', name: 'boolean' },
1081
+ parameters: [{ name: 'input', type: { kind: 'class', name: 'AVFoundation.AVCaptureInput' } }],
1082
+ },
1083
+ {
1084
+ name: 'canSetSessionPreset',
1085
+ selector: 'canSetSessionPreset:',
1086
+ returns: { kind: 'primitive', name: 'boolean' },
1087
+ parameters: [{ name: 'preset', type: stringType }],
1088
+ },
1089
+ {
1090
+ name: 'addInput',
1091
+ selector: 'addInput:',
1092
+ returns: voidType,
1093
+ parameters: [{ name: 'input', type: { kind: 'class', name: 'AVFoundation.AVCaptureInput' } }],
1094
+ },
1095
+ {
1096
+ name: 'canAddOutput',
1097
+ selector: 'canAddOutput:',
1098
+ returns: { kind: 'primitive', name: 'boolean' },
1099
+ parameters: [{ name: 'output', type: { kind: 'class', name: 'AVFoundation.AVCaptureOutput' } }],
1100
+ },
1101
+ {
1102
+ name: 'addOutput',
1103
+ selector: 'addOutput:',
1104
+ returns: voidType,
1105
+ parameters: [{ name: 'output', type: { kind: 'class', name: 'AVFoundation.AVCaptureOutput' } }],
1106
+ },
1107
+ { name: 'startRunning', selector: 'startRunning', returns: voidType },
1108
+ { name: 'stopRunning', selector: 'stopRunning', returns: voidType },
1109
+ ],
1110
+ },
1111
+ {
1112
+ name: 'AVCapturePhotoSettings',
1113
+ extends: 'Foundation.NSObject',
1114
+ properties: [
1115
+ { name: 'flashMode', type: captureFlashModeType },
1116
+ { name: 'photoQualityPrioritization', type: capturePhotoQualityPrioritizationType },
1117
+ ],
1118
+ methods: [
1119
+ {
1120
+ name: 'photoSettings',
1121
+ selector: 'photoSettings',
1122
+ static: true,
1123
+ returns: { kind: 'class', name: 'AVFoundation.AVCapturePhotoSettings' },
1124
+ },
1125
+ ],
1126
+ },
1127
+ {
1128
+ name: 'AVCapturePhotoOutput',
1129
+ extends: 'AVFoundation.AVCaptureOutput',
1130
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AVFoundation.AVCapturePhotoOutput' } }],
1131
+ properties: [
1132
+ { name: 'maxPhotoQualityPrioritization', type: capturePhotoQualityPrioritizationType },
1133
+ ],
1134
+ methods: [
1135
+ {
1136
+ name: 'capturePhotoWithSettingsHandler',
1137
+ selector: 'capturePhotoWithSettings:handler:',
1138
+ returns: voidType,
1139
+ parameters: [
1140
+ { name: 'settings', type: { kind: 'class', name: 'AVFoundation.AVCapturePhotoSettings' } },
1141
+ { name: 'handler', type: photoCaptureHandlerType },
1142
+ ],
1143
+ },
1144
+ ],
1145
+ },
1146
+ {
1147
+ name: 'AVCaptureVideoPreviewLayer',
1148
+ extends: 'QuartzCore.CALayer',
1149
+ properties: [
1150
+ { name: 'videoGravity', type: stringType },
1151
+ ],
1152
+ methods: [
1153
+ {
1154
+ name: 'layerWithSession',
1155
+ selector: 'layerWithSession:',
1156
+ static: true,
1157
+ returns: { kind: 'class', name: 'AVFoundation.AVCaptureVideoPreviewLayer' },
1158
+ parameters: [{ name: 'session', type: { kind: 'class', name: 'AVFoundation.AVCaptureSession' } }],
1159
+ },
1160
+ ],
1161
+ },
1162
+ ],
1163
+ },
1164
+ {
1165
+ name: 'Metal',
1166
+ constants: [
1167
+ { name: 'MTLPixelFormatInvalid', type: metalPixelFormatType, value: 0 },
1168
+ { name: 'MTLPixelFormatBGRA8Unorm_sRGB', type: metalPixelFormatType, value: 80 },
1169
+ { name: 'MTLPixelFormatDepth32Float', type: metalPixelFormatType, value: 252 },
1170
+ { name: 'MTLPrimitiveTypeTriangle', type: metalPrimitiveType, value: 3 },
1171
+ { name: 'MTLResourceStorageModeShared', type: metalResourceOptionsType, value: 0 },
1172
+ { name: 'MTLCompareFunctionLess', type: metalCompareFunctionType, value: 2 },
1173
+ ],
1174
+ functions: [
1175
+ {
1176
+ name: 'MTLCreateSystemDefaultDevice',
1177
+ returns: { kind: 'class', name: 'Metal.MTLDevice', nullable: true },
1178
+ },
1179
+ {
1180
+ name: 'MTLClearColorMake',
1181
+ returns: { kind: 'struct', name: 'Metal.MTLClearColor' },
1182
+ parameters: [
1183
+ { name: 'red', type: numberType },
1184
+ { name: 'green', type: numberType },
1185
+ { name: 'blue', type: numberType },
1186
+ { name: 'alpha', type: numberType },
1187
+ ],
1188
+ },
1189
+ ],
1190
+ structs: [
1191
+ {
1192
+ name: 'MTLClearColor',
1193
+ fields: [
1194
+ { name: 'red', type: numberType },
1195
+ { name: 'green', type: numberType },
1196
+ { name: 'blue', type: numberType },
1197
+ { name: 'alpha', type: numberType },
1198
+ ],
1199
+ },
1200
+ ],
1201
+ classes: [
1202
+ {
1203
+ name: 'MTLCompileOptions',
1204
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'Metal.MTLCompileOptions' } }],
1205
+ },
1206
+ {
1207
+ name: 'MTLDevice',
1208
+ methods: [
1209
+ {
1210
+ name: 'newCommandQueue',
1211
+ selector: 'newCommandQueue',
1212
+ returns: { kind: 'class', name: 'Metal.MTLCommandQueue', nullable: true },
1213
+ },
1214
+ {
1215
+ name: 'newLibraryWithSourceOptionsError',
1216
+ selector: 'newLibraryWithSource:options:error:',
1217
+ returns: { kind: 'class', name: 'Metal.MTLLibrary', nullable: true },
1218
+ parameters: [
1219
+ { name: 'source', type: stringType },
1220
+ { name: 'options', type: { kind: 'class', name: 'Metal.MTLCompileOptions' } },
1221
+ ],
1222
+ },
1223
+ {
1224
+ name: 'newBufferWithBytesLengthOptions',
1225
+ selector: 'newBufferWithBytes:length:options:',
1226
+ returns: { kind: 'class', name: 'Metal.MTLBuffer', nullable: true },
1227
+ parameters: [
1228
+ { name: 'bytes', type: numberArrayType },
1229
+ { name: 'length', type: numberType },
1230
+ { name: 'options', type: metalResourceOptionsType },
1231
+ ],
1232
+ },
1233
+ {
1234
+ name: 'newRenderPipelineStateWithDescriptorError',
1235
+ selector: 'newRenderPipelineStateWithDescriptor:error:',
1236
+ returns: { kind: 'class', name: 'Metal.MTLRenderPipelineState', nullable: true },
1237
+ parameters: [{ name: 'descriptor', type: { kind: 'class', name: 'Metal.MTLRenderPipelineDescriptor' } }],
1238
+ },
1239
+ {
1240
+ name: 'newDepthStencilStateWithDescriptor',
1241
+ selector: 'newDepthStencilStateWithDescriptor:',
1242
+ returns: { kind: 'class', name: 'Metal.MTLDepthStencilState', nullable: true },
1243
+ parameters: [{ name: 'descriptor', type: { kind: 'class', name: 'Metal.MTLDepthStencilDescriptor' } }],
1244
+ },
1245
+ ],
1246
+ },
1247
+ {
1248
+ name: 'MTLCommandQueue',
1249
+ methods: [
1250
+ {
1251
+ name: 'commandBuffer',
1252
+ selector: 'commandBuffer',
1253
+ returns: { kind: 'class', name: 'Metal.MTLCommandBuffer', nullable: true },
1254
+ },
1255
+ ],
1256
+ },
1257
+ {
1258
+ name: 'MTLCommandBuffer',
1259
+ methods: [
1260
+ {
1261
+ name: 'renderCommandEncoderWithDescriptor',
1262
+ selector: 'renderCommandEncoderWithDescriptor:',
1263
+ returns: { kind: 'class', name: 'Metal.MTLRenderCommandEncoder', nullable: true },
1264
+ parameters: [{ name: 'descriptor', type: { kind: 'class', name: 'Metal.MTLRenderPassDescriptor' } }],
1265
+ },
1266
+ {
1267
+ name: 'presentDrawable',
1268
+ selector: 'presentDrawable:',
1269
+ returns: voidType,
1270
+ parameters: [{ name: 'drawable', type: { kind: 'class', name: 'Metal.MTLDrawable' } }],
1271
+ },
1272
+ { name: 'commit', selector: 'commit', returns: voidType },
1273
+ ],
1274
+ },
1275
+ {
1276
+ name: 'MTLLibrary',
1277
+ methods: [
1278
+ {
1279
+ name: 'newFunctionWithName',
1280
+ selector: 'newFunctionWithName:',
1281
+ returns: { kind: 'class', name: 'Metal.MTLFunction', nullable: true },
1282
+ parameters: [{ name: 'name', type: stringType }],
1283
+ },
1284
+ ],
1285
+ },
1286
+ { name: 'MTLFunction' },
1287
+ {
1288
+ name: 'MTLRenderPipelineDescriptor',
1289
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'Metal.MTLRenderPipelineDescriptor' } }],
1290
+ properties: [
1291
+ { name: 'vertexFunction', type: { kind: 'class', name: 'Metal.MTLFunction', nullable: true } },
1292
+ { name: 'fragmentFunction', type: { kind: 'class', name: 'Metal.MTLFunction', nullable: true } },
1293
+ { name: 'colorAttachments', type: { kind: 'class', name: 'Metal.MTLRenderPipelineColorAttachmentDescriptorArray' }, readonly: true },
1294
+ { name: 'depthAttachmentPixelFormat', type: metalPixelFormatType },
1295
+ ],
1296
+ },
1297
+ {
1298
+ name: 'MTLRenderPipelineColorAttachmentDescriptorArray',
1299
+ methods: [
1300
+ {
1301
+ name: 'objectAtIndexedSubscript',
1302
+ selector: 'objectAtIndexedSubscript:',
1303
+ returns: { kind: 'class', name: 'Metal.MTLRenderPipelineColorAttachmentDescriptor' },
1304
+ parameters: [{ name: 'index', type: numberType }],
1305
+ },
1306
+ ],
1307
+ },
1308
+ {
1309
+ name: 'MTLRenderPipelineColorAttachmentDescriptor',
1310
+ properties: [{ name: 'pixelFormat', type: metalPixelFormatType }],
1311
+ },
1312
+ { name: 'MTLRenderPipelineState' },
1313
+ { name: 'MTLBuffer' },
1314
+ {
1315
+ name: 'MTLDepthStencilDescriptor',
1316
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'Metal.MTLDepthStencilDescriptor' } }],
1317
+ properties: [
1318
+ { name: 'depthCompareFunction', type: metalCompareFunctionType },
1319
+ { name: 'depthWriteEnabled', type: { kind: 'primitive', name: 'boolean' } },
1320
+ ],
1321
+ },
1322
+ { name: 'MTLDepthStencilState' },
1323
+ {
1324
+ name: 'MTLRenderCommandEncoder',
1325
+ methods: [
1326
+ {
1327
+ name: 'setRenderPipelineState',
1328
+ selector: 'setRenderPipelineState:',
1329
+ returns: voidType,
1330
+ parameters: [{ name: 'pipelineState', type: { kind: 'class', name: 'Metal.MTLRenderPipelineState' } }],
1331
+ },
1332
+ {
1333
+ name: 'setDepthStencilState',
1334
+ selector: 'setDepthStencilState:',
1335
+ returns: voidType,
1336
+ parameters: [{ name: 'depthStencilState', type: { kind: 'class', name: 'Metal.MTLDepthStencilState' } }],
1337
+ },
1338
+ {
1339
+ name: 'setVertexBufferOffsetAtIndex',
1340
+ selector: 'setVertexBuffer:offset:atIndex:',
1341
+ returns: voidType,
1342
+ parameters: [
1343
+ { name: 'buffer', type: { kind: 'class', name: 'Metal.MTLBuffer' } },
1344
+ { name: 'offset', type: numberType },
1345
+ { name: 'index', type: numberType },
1346
+ ],
1347
+ },
1348
+ {
1349
+ name: 'setVertexBytesLengthAtIndex',
1350
+ selector: 'setVertexBytes:length:atIndex:',
1351
+ returns: voidType,
1352
+ parameters: [
1353
+ { name: 'bytes', type: numberArrayType },
1354
+ { name: 'length', type: numberType },
1355
+ { name: 'index', type: numberType },
1356
+ ],
1357
+ },
1358
+ {
1359
+ name: 'drawPrimitivesVertexStartVertexCount',
1360
+ selector: 'drawPrimitives:vertexStart:vertexCount:',
1361
+ returns: voidType,
1362
+ parameters: [
1363
+ { name: 'primitiveType', type: metalPrimitiveType },
1364
+ { name: 'vertexStart', type: numberType },
1365
+ { name: 'vertexCount', type: numberType },
1366
+ ],
1367
+ },
1368
+ { name: 'endEncoding', selector: 'endEncoding', returns: voidType },
1369
+ ],
1370
+ },
1371
+ { name: 'MTLRenderPassDescriptor' },
1372
+ { name: 'MTLDrawable' },
1373
+ ],
1374
+ },
1375
+ {
1376
+ name: 'MetalKit',
1377
+ imports: {
1378
+ CoreGraphics: ['CGSize'],
1379
+ Metal: ['MTLDevice', 'MTLDrawable', 'MTLClearColor', 'MTLRenderPassDescriptor'],
1380
+ UIKit: ['UIView'],
1381
+ },
1382
+ classes: [
1383
+ {
1384
+ name: 'MTKView',
1385
+ extends: 'UIKit.UIView',
1386
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'MetalKit.MTKView' } }],
1387
+ properties: [
1388
+ { name: 'device', type: { kind: 'class', name: 'Metal.MTLDevice', nullable: true } },
1389
+ { name: 'delegate', type: { kind: 'class', name: 'MetalKit.MTKViewDelegate', nullable: true } },
1390
+ { name: 'colorPixelFormat', type: metalPixelFormatType },
1391
+ { name: 'depthStencilPixelFormat', type: metalPixelFormatType },
1392
+ { name: 'clearColor', type: { kind: 'struct', name: 'Metal.MTLClearColor' } },
1393
+ { name: 'preferredFramesPerSecond', type: numberType },
1394
+ { name: 'enableSetNeedsDisplay', type: { kind: 'primitive', name: 'boolean' } },
1395
+ { name: 'paused', type: { kind: 'primitive', name: 'boolean' } },
1396
+ { name: 'drawableSize', type: { kind: 'struct', name: 'CoreGraphics.CGSize' }, readonly: true },
1397
+ { name: 'currentRenderPassDescriptor', type: { kind: 'class', name: 'Metal.MTLRenderPassDescriptor', nullable: true }, readonly: true },
1398
+ { name: 'currentDrawable', type: { kind: 'class', name: 'Metal.MTLDrawable', nullable: true }, readonly: true },
1399
+ ],
1400
+ },
1401
+ {
1402
+ name: 'MTKViewDelegate',
1403
+ methods: [
1404
+ {
1405
+ name: 'create',
1406
+ selector: 'create:',
1407
+ static: true,
1408
+ returns: { kind: 'class', name: 'MetalKit.MTKViewDelegate' },
1409
+ parameters: [{ name: 'drawInMTKView', type: mtkViewDrawCallbackType }],
1410
+ },
1411
+ ],
1412
+ },
1413
+ ],
1414
+ },
1415
+ {
1416
+ name: 'Photos',
1417
+ imports: {
1418
+ Foundation: ['NSData', 'NSObject'],
1419
+ },
1420
+ classes: [
1421
+ {
1422
+ name: 'PHPhotoLibrary',
1423
+ extends: 'Foundation.NSObject',
1424
+ methods: [
1425
+ {
1426
+ name: 'saveImageData',
1427
+ selector: 'saveImageData:handler:',
1428
+ static: true,
1429
+ returns: voidType,
1430
+ parameters: [
1431
+ { name: 'data', type: { kind: 'class', name: 'Foundation.NSData' } },
1432
+ { name: 'handler', type: photoLibrarySaveHandlerType },
1433
+ ],
1434
+ },
1435
+ ],
1436
+ },
1437
+ ],
1438
+ },
1439
+ {
1440
+ name: 'AppKit',
1441
+ imports: {
1442
+ Foundation: ['NSObject'],
1443
+ CoreGraphics: ['CGRect'],
1444
+ QuartzCore: ['CALayer'],
1445
+ },
1446
+ constants: [
1447
+ // NSView.autoresizingMask
1448
+ { name: 'NSViewNotSizable', type: numberType, value: 0 },
1449
+ { name: 'NSViewWidthSizable', type: numberType, value: 2 },
1450
+ { name: 'NSViewHeightSizable', type: numberType, value: 16 },
1451
+ { name: 'NSViewMinXMargin', type: numberType, value: 1 },
1452
+ { name: 'NSViewMaxXMargin', type: numberType, value: 4 },
1453
+ { name: 'NSViewMinYMargin', type: numberType, value: 8 },
1454
+ { name: 'NSViewMaxYMargin', type: numberType, value: 32 },
1455
+ // NSVisualEffectView
1456
+ { name: 'NSVisualEffectMaterialSidebar', type: numberType, value: 7 },
1457
+ { name: 'NSVisualEffectMaterialHeaderView', type: numberType, value: 10 },
1458
+ { name: 'NSVisualEffectMaterialContentBackground', type: numberType, value: 18 },
1459
+ { name: 'NSVisualEffectMaterialUnderWindowBackground', type: numberType, value: 21 },
1460
+ { name: 'NSVisualEffectBlendingModeBehindWindow', type: numberType, value: 0 },
1461
+ { name: 'NSVisualEffectBlendingModeWithinWindow', type: numberType, value: 1 },
1462
+ { name: 'NSVisualEffectStateFollowsWindowActiveState', type: numberType, value: 0 },
1463
+ { name: 'NSVisualEffectStateActive', type: numberType, value: 1 },
1464
+ { name: 'NSVisualEffectStateInactive', type: numberType, value: 2 },
1465
+ // NSSplitView
1466
+ { name: 'NSSplitViewDividerStyleThick', type: numberType, value: 1 },
1467
+ { name: 'NSSplitViewDividerStyleThin', type: numberType, value: 2 },
1468
+ { name: 'NSSplitViewDividerStylePaneSplitter', type: numberType, value: 3 },
1469
+ // NSTextAlignment
1470
+ { name: 'NSTextAlignmentLeft', type: numberType, value: 0 },
1471
+ { name: 'NSTextAlignmentRight', type: numberType, value: 1 },
1472
+ { name: 'NSTextAlignmentCenter', type: numberType, value: 2 },
1473
+ // NSLineBreakMode
1474
+ { name: 'NSLineBreakByWordWrapping', type: numberType, value: 0 },
1475
+ { name: 'NSLineBreakByTruncatingTail', type: numberType, value: 4 },
1476
+ // NSUserInterfaceLayoutOrientation (NSStackView.orientation)
1477
+ { name: 'NSUserInterfaceLayoutOrientationHorizontal', type: numberType, value: 0 },
1478
+ { name: 'NSUserInterfaceLayoutOrientationVertical', type: numberType, value: 1 },
1479
+ // NSStackViewDistribution
1480
+ { name: 'NSStackViewDistributionFill', type: numberType, value: 0 },
1481
+ { name: 'NSStackViewDistributionFillEqually', type: numberType, value: 1 },
1482
+ { name: 'NSStackViewDistributionFillProportionally', type: numberType, value: 2 },
1483
+ { name: 'NSStackViewDistributionEqualSpacing', type: numberType, value: 3 },
1484
+ { name: 'NSStackViewDistributionEqualCentering', type: numberType, value: 4 },
1485
+ { name: 'NSStackViewDistributionGravityAreas', type: numberType, value: -1 },
1486
+ // NSLayoutConstraint.Attribute (NSStackView.alignment)
1487
+ { name: 'NSLayoutAttributeLeft', type: numberType, value: 1 },
1488
+ { name: 'NSLayoutAttributeRight', type: numberType, value: 2 },
1489
+ { name: 'NSLayoutAttributeTop', type: numberType, value: 3 },
1490
+ { name: 'NSLayoutAttributeBottom', type: numberType, value: 4 },
1491
+ { name: 'NSLayoutAttributeLeading', type: numberType, value: 5 },
1492
+ { name: 'NSLayoutAttributeTrailing', type: numberType, value: 6 },
1493
+ { name: 'NSLayoutAttributeWidth', type: numberType, value: 7 },
1494
+ { name: 'NSLayoutAttributeHeight', type: numberType, value: 8 },
1495
+ { name: 'NSLayoutAttributeCenterX', type: numberType, value: 9 },
1496
+ { name: 'NSLayoutAttributeCenterY', type: numberType, value: 10 },
1497
+ // NSLayoutConstraintOrientation (content hugging / compression resistance)
1498
+ { name: 'NSLayoutConstraintOrientationHorizontal', type: numberType, value: 0 },
1499
+ { name: 'NSLayoutConstraintOrientationVertical', type: numberType, value: 1 },
1500
+ // NSLayoutPriority
1501
+ { name: 'NSLayoutPriorityRequired', type: numberType, value: 1000 },
1502
+ { name: 'NSLayoutPriorityDefaultHigh', type: numberType, value: 750 },
1503
+ { name: 'NSLayoutPriorityDefaultLow', type: numberType, value: 250 },
1504
+ // NSBoxType (custom fill/border for rounded selection highlights)
1505
+ { name: 'NSBoxCustom', type: numberType, value: 4 },
1506
+ { name: 'ObjCTargetAction', type: selectorType, value: 'invoke:' },
1507
+ ],
1508
+ classes: [
1509
+ {
1510
+ name: 'NSColor',
1511
+ extends: 'Foundation.NSObject',
1512
+ methods: [
1513
+ { name: 'whiteColor', selector: 'whiteColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1514
+ { name: 'blackColor', selector: 'blackColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1515
+ { name: 'clearColor', selector: 'clearColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1516
+ { name: 'labelColor', selector: 'labelColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1517
+ { name: 'secondaryLabelColor', selector: 'secondaryLabelColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1518
+ { name: 'tertiaryLabelColor', selector: 'tertiaryLabelColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1519
+ { name: 'textColor', selector: 'textColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1520
+ { name: 'controlBackgroundColor', selector: 'controlBackgroundColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1521
+ { name: 'windowBackgroundColor', selector: 'windowBackgroundColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1522
+ { name: 'separatorColor', selector: 'separatorColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1523
+ { name: 'controlAccentColor', selector: 'controlAccentColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1524
+ { name: 'systemBlueColor', selector: 'systemBlueColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1525
+ { name: 'systemYellowColor', selector: 'systemYellowColor', static: true, returns: { kind: 'class', name: 'AppKit.NSColor' } },
1526
+ {
1527
+ name: 'colorWithSRGBRedGreenBlueAlpha',
1528
+ selector: 'colorWithSRGBRed:green:blue:alpha:',
1529
+ static: true,
1530
+ returns: { kind: 'class', name: 'AppKit.NSColor' },
1531
+ parameters: [
1532
+ { name: 'red', type: numberType },
1533
+ { name: 'green', type: numberType },
1534
+ { name: 'blue', type: numberType },
1535
+ { name: 'alpha', type: numberType },
1536
+ ],
1537
+ },
1538
+ {
1539
+ name: 'colorWithWhiteAlpha',
1540
+ selector: 'colorWithWhite:alpha:',
1541
+ static: true,
1542
+ returns: { kind: 'class', name: 'AppKit.NSColor' },
1543
+ parameters: [
1544
+ { name: 'white', type: numberType },
1545
+ { name: 'alpha', type: numberType },
1546
+ ],
1547
+ },
1548
+ ],
1549
+ },
1550
+ {
1551
+ name: 'NSLayoutConstraint',
1552
+ extends: 'Foundation.NSObject',
1553
+ properties: [
1554
+ { name: 'active', type: { kind: 'primitive', name: 'boolean' } },
1555
+ ],
1556
+ },
1557
+ {
1558
+ name: 'NSLayoutXAxisAnchor',
1559
+ extends: 'Foundation.NSObject',
1560
+ methods: [
1561
+ {
1562
+ name: 'constraintEqualToAnchor',
1563
+ selector: 'constraintEqualToAnchor:',
1564
+ returns: { kind: 'class', name: 'AppKit.NSLayoutConstraint' },
1565
+ parameters: [{ name: 'anchor', type: { kind: 'class', name: 'AppKit.NSLayoutXAxisAnchor' } }],
1566
+ },
1567
+ {
1568
+ name: 'constraintEqualToAnchorConstant',
1569
+ selector: 'constraintEqualToAnchor:constant:',
1570
+ returns: { kind: 'class', name: 'AppKit.NSLayoutConstraint' },
1571
+ parameters: [
1572
+ { name: 'anchor', type: { kind: 'class', name: 'AppKit.NSLayoutXAxisAnchor' } },
1573
+ { name: 'constant', type: numberType },
1574
+ ],
1575
+ },
1576
+ ],
1577
+ },
1578
+ {
1579
+ name: 'NSLayoutYAxisAnchor',
1580
+ extends: 'Foundation.NSObject',
1581
+ methods: [
1582
+ {
1583
+ name: 'constraintEqualToAnchor',
1584
+ selector: 'constraintEqualToAnchor:',
1585
+ returns: { kind: 'class', name: 'AppKit.NSLayoutConstraint' },
1586
+ parameters: [{ name: 'anchor', type: { kind: 'class', name: 'AppKit.NSLayoutYAxisAnchor' } }],
1587
+ },
1588
+ {
1589
+ name: 'constraintEqualToAnchorConstant',
1590
+ selector: 'constraintEqualToAnchor:constant:',
1591
+ returns: { kind: 'class', name: 'AppKit.NSLayoutConstraint' },
1592
+ parameters: [
1593
+ { name: 'anchor', type: { kind: 'class', name: 'AppKit.NSLayoutYAxisAnchor' } },
1594
+ { name: 'constant', type: numberType },
1595
+ ],
1596
+ },
1597
+ ],
1598
+ },
1599
+ {
1600
+ name: 'NSLayoutDimension',
1601
+ extends: 'Foundation.NSObject',
1602
+ methods: [
1603
+ {
1604
+ name: 'constraintEqualToAnchor',
1605
+ selector: 'constraintEqualToAnchor:',
1606
+ returns: { kind: 'class', name: 'AppKit.NSLayoutConstraint' },
1607
+ parameters: [{ name: 'anchor', type: { kind: 'class', name: 'AppKit.NSLayoutDimension' } }],
1608
+ },
1609
+ {
1610
+ name: 'constraintEqualToConstant',
1611
+ selector: 'constraintEqualToConstant:',
1612
+ returns: { kind: 'class', name: 'AppKit.NSLayoutConstraint' },
1613
+ parameters: [{ name: 'constant', type: numberType }],
1614
+ },
1615
+ {
1616
+ name: 'constraintEqualToAnchorMultiplier',
1617
+ selector: 'constraintEqualToAnchor:multiplier:',
1618
+ returns: { kind: 'class', name: 'AppKit.NSLayoutConstraint' },
1619
+ parameters: [
1620
+ { name: 'anchor', type: { kind: 'class', name: 'AppKit.NSLayoutDimension' } },
1621
+ { name: 'multiplier', type: numberType },
1622
+ ],
1623
+ },
1624
+ ],
1625
+ },
1626
+ {
1627
+ name: 'NSLayoutGuide',
1628
+ extends: 'Foundation.NSObject',
1629
+ properties: [
1630
+ { name: 'leadingAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutXAxisAnchor' }, readonly: true },
1631
+ { name: 'trailingAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutXAxisAnchor' }, readonly: true },
1632
+ { name: 'topAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutYAxisAnchor' }, readonly: true },
1633
+ { name: 'bottomAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutYAxisAnchor' }, readonly: true },
1634
+ ],
1635
+ },
1636
+ {
1637
+ name: 'ObjCTarget',
1638
+ methods: [
1639
+ {
1640
+ name: 'create',
1641
+ selector: 'create:',
1642
+ static: true,
1643
+ returns: { kind: 'class', name: 'Foundation.NSObject' },
1644
+ parameters: [{ name: 'callback', type: voidCallbackType }],
1645
+ },
1646
+ ],
1647
+ },
1648
+ {
1649
+ name: 'NSClickGestureRecognizer',
1650
+ extends: 'Foundation.NSObject',
1651
+ constructors: [
1652
+ {
1653
+ name: 'initWithTargetAction',
1654
+ selector: 'initWithTarget:action:',
1655
+ returns: { kind: 'class', name: 'AppKit.NSClickGestureRecognizer' },
1656
+ parameters: [
1657
+ { name: 'target', type: { kind: 'class', name: 'Foundation.NSObject', nullable: true } },
1658
+ { name: 'action', type: selectorType },
1659
+ ],
1660
+ },
1661
+ ],
1662
+ properties: [
1663
+ { name: 'numberOfClicksRequired', type: numberType },
1664
+ ],
1665
+ },
1666
+ {
1667
+ name: 'NSView',
1668
+ extends: 'Foundation.NSObject',
1669
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSView' } }],
1670
+ properties: [
1671
+ { name: 'frame', type: { kind: 'struct', name: 'CoreGraphics.CGRect' } },
1672
+ { name: 'bounds', type: { kind: 'struct', name: 'CoreGraphics.CGRect' }, readonly: true },
1673
+ { name: 'wantsLayer', type: { kind: 'primitive', name: 'boolean' } },
1674
+ { name: 'layer', type: { kind: 'class', name: 'QuartzCore.CALayer' }, readonly: true },
1675
+ { name: 'hidden', type: { kind: 'primitive', name: 'boolean' } },
1676
+ { name: 'alphaValue', type: numberType },
1677
+ { name: 'autoresizingMask', type: numberType },
1678
+ { name: 'translatesAutoresizingMaskIntoConstraints', type: { kind: 'primitive', name: 'boolean' } },
1679
+ { name: 'leadingAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutXAxisAnchor' }, readonly: true },
1680
+ { name: 'trailingAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutXAxisAnchor' }, readonly: true },
1681
+ { name: 'centerXAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutXAxisAnchor' }, readonly: true },
1682
+ { name: 'topAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutYAxisAnchor' }, readonly: true },
1683
+ { name: 'bottomAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutYAxisAnchor' }, readonly: true },
1684
+ { name: 'centerYAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutYAxisAnchor' }, readonly: true },
1685
+ { name: 'widthAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutDimension' }, readonly: true },
1686
+ { name: 'heightAnchor', type: { kind: 'class', name: 'AppKit.NSLayoutDimension' }, readonly: true },
1687
+ { name: 'safeAreaLayoutGuide', type: { kind: 'class', name: 'AppKit.NSLayoutGuide' }, readonly: true },
1688
+ ],
1689
+ methods: [
1690
+ {
1691
+ name: 'addSubview',
1692
+ selector: 'addSubview:',
1693
+ returns: voidType,
1694
+ parameters: [{ name: 'view', type: { kind: 'class', name: 'AppKit.NSView' } }],
1695
+ },
1696
+ {
1697
+ name: 'addGestureRecognizer',
1698
+ selector: 'addGestureRecognizer:',
1699
+ returns: voidType,
1700
+ parameters: [{ name: 'recognizer', type: { kind: 'class', name: 'Foundation.NSObject' } }],
1701
+ },
1702
+ {
1703
+ name: 'setContentHuggingPriorityForOrientation',
1704
+ selector: 'setContentHuggingPriority:forOrientation:',
1705
+ returns: voidType,
1706
+ parameters: [
1707
+ { name: 'priority', type: numberType },
1708
+ { name: 'orientation', type: layoutConstraintOrientationType },
1709
+ ],
1710
+ },
1711
+ {
1712
+ name: 'setContentCompressionResistancePriorityForOrientation',
1713
+ selector: 'setContentCompressionResistancePriority:forOrientation:',
1714
+ returns: voidType,
1715
+ parameters: [
1716
+ { name: 'priority', type: numberType },
1717
+ { name: 'orientation', type: layoutConstraintOrientationType },
1718
+ ],
1719
+ },
1720
+ ],
1721
+ },
1722
+ {
1723
+ name: 'NSControl',
1724
+ extends: 'AppKit.NSView',
1725
+ properties: [
1726
+ { name: 'target', type: { kind: 'class', name: 'Foundation.NSObject', nullable: true } },
1727
+ { name: 'action', type: selectorType },
1728
+ { name: 'enabled', type: { kind: 'primitive', name: 'boolean' } },
1729
+ ],
1730
+ },
1731
+ {
1732
+ name: 'NSBox',
1733
+ extends: 'AppKit.NSView',
1734
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSBox' } }],
1735
+ properties: [
1736
+ { name: 'boxType', type: numberType },
1737
+ { name: 'borderWidth', type: numberType },
1738
+ { name: 'cornerRadius', type: numberType },
1739
+ { name: 'fillColor', type: { kind: 'class', name: 'AppKit.NSColor', nullable: true } },
1740
+ { name: 'borderColor', type: { kind: 'class', name: 'AppKit.NSColor', nullable: true } },
1741
+ { name: 'titlePosition', type: numberType },
1742
+ { name: 'contentView', type: { kind: 'class', name: 'AppKit.NSView', nullable: true } },
1743
+ ],
1744
+ },
1745
+ {
1746
+ name: 'NSStackView',
1747
+ extends: 'AppKit.NSView',
1748
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSStackView' } }],
1749
+ properties: [
1750
+ { name: 'orientation', type: numberType },
1751
+ { name: 'spacing', type: numberType },
1752
+ { name: 'alignment', type: numberType },
1753
+ { name: 'distribution', type: numberType },
1754
+ { name: 'detachesHiddenViews', type: { kind: 'primitive', name: 'boolean' } },
1755
+ ],
1756
+ methods: [
1757
+ {
1758
+ name: 'addArrangedSubview',
1759
+ selector: 'addArrangedSubview:',
1760
+ returns: voidType,
1761
+ parameters: [{ name: 'view', type: { kind: 'class', name: 'AppKit.NSView' } }],
1762
+ },
1763
+ {
1764
+ name: 'insertArrangedSubviewAtIndex',
1765
+ selector: 'insertArrangedSubview:atIndex:',
1766
+ returns: voidType,
1767
+ parameters: [
1768
+ { name: 'view', type: { kind: 'class', name: 'AppKit.NSView' } },
1769
+ { name: 'index', type: numberType },
1770
+ ],
1771
+ },
1772
+ {
1773
+ name: 'setHuggingPriorityForOrientation',
1774
+ selector: 'setHuggingPriority:forOrientation:',
1775
+ returns: voidType,
1776
+ parameters: [
1777
+ { name: 'priority', type: numberType },
1778
+ { name: 'orientation', type: layoutConstraintOrientationType },
1779
+ ],
1780
+ },
1781
+ ],
1782
+ },
1783
+ {
1784
+ name: 'NSTextField',
1785
+ extends: 'AppKit.NSView',
1786
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSTextField' } }],
1787
+ properties: [
1788
+ { name: 'stringValue', type: stringType },
1789
+ { name: 'placeholderString', type: { kind: 'primitive', name: 'string' } },
1790
+ { name: 'editable', type: { kind: 'primitive', name: 'boolean' } },
1791
+ { name: 'selectable', type: { kind: 'primitive', name: 'boolean' } },
1792
+ { name: 'bezeled', type: { kind: 'primitive', name: 'boolean' } },
1793
+ { name: 'bordered', type: { kind: 'primitive', name: 'boolean' } },
1794
+ { name: 'drawsBackground', type: { kind: 'primitive', name: 'boolean' } },
1795
+ { name: 'backgroundColor', type: { kind: 'class', name: 'AppKit.NSColor', nullable: true } },
1796
+ { name: 'textColor', type: { kind: 'class', name: 'AppKit.NSColor', nullable: true } },
1797
+ { name: 'font', type: { kind: 'class', name: 'AppKit.NSFont', nullable: true } },
1798
+ { name: 'alignment', type: numberType },
1799
+ { name: 'lineBreakMode', type: numberType },
1800
+ { name: 'maximumNumberOfLines', type: numberType },
1801
+ ],
1802
+ methods: [
1803
+ {
1804
+ // Live edit notifications: the delegate receives controlTextDidChange:
1805
+ // on every keystroke (see ObjCTarget). A method (selector setDelegate:)
1806
+ // rather than a `delegate` property to avoid the member-name collision
1807
+ // with MTKView.delegate for dynamic receivers.
1808
+ name: 'attachTextDelegate',
1809
+ selector: 'setDelegate:',
1810
+ returns: voidType,
1811
+ parameters: [{ name: 'delegate', type: { kind: 'class', name: 'Foundation.NSObject', nullable: true } }],
1812
+ },
1813
+ ],
1814
+ },
1815
+ {
1816
+ name: 'NSFont',
1817
+ extends: 'Foundation.NSObject',
1818
+ methods: [
1819
+ {
1820
+ name: 'systemFontOfSize',
1821
+ selector: 'systemFontOfSize:',
1822
+ static: true,
1823
+ returns: { kind: 'class', name: 'AppKit.NSFont' },
1824
+ parameters: [{ name: 'fontSize', type: numberType }],
1825
+ },
1826
+ {
1827
+ name: 'boldSystemFontOfSize',
1828
+ selector: 'boldSystemFontOfSize:',
1829
+ static: true,
1830
+ returns: { kind: 'class', name: 'AppKit.NSFont' },
1831
+ parameters: [{ name: 'fontSize', type: numberType }],
1832
+ },
1833
+ {
1834
+ name: 'systemFontOfSizeWeight',
1835
+ selector: 'systemFontOfSize:weight:',
1836
+ static: true,
1837
+ returns: { kind: 'class', name: 'AppKit.NSFont' },
1838
+ parameters: [
1839
+ { name: 'fontSize', type: numberType },
1840
+ { name: 'weight', type: numberType },
1841
+ ],
1842
+ },
1843
+ ],
1844
+ },
1845
+ {
1846
+ name: 'NSVisualEffectView',
1847
+ extends: 'AppKit.NSView',
1848
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSVisualEffectView' } }],
1849
+ properties: [
1850
+ { name: 'material', type: numberType },
1851
+ { name: 'blendingMode', type: numberType },
1852
+ { name: 'state', type: numberType },
1853
+ { name: 'emphasized', type: { kind: 'primitive', name: 'boolean' } },
1854
+ ],
1855
+ },
1856
+ {
1857
+ name: 'NSScrollView',
1858
+ extends: 'AppKit.NSView',
1859
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSScrollView' } }],
1860
+ properties: [
1861
+ { name: 'documentView', type: { kind: 'class', name: 'AppKit.NSView', nullable: true } },
1862
+ { name: 'hasVerticalScroller', type: { kind: 'primitive', name: 'boolean' } },
1863
+ { name: 'hasHorizontalScroller', type: { kind: 'primitive', name: 'boolean' } },
1864
+ { name: 'drawsBackground', type: { kind: 'primitive', name: 'boolean' } },
1865
+ { name: 'automaticallyAdjustsContentInsets', type: { kind: 'primitive', name: 'boolean' } },
1866
+ ],
1867
+ },
1868
+ {
1869
+ name: 'NSSplitView',
1870
+ extends: 'AppKit.NSView',
1871
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSSplitView' } }],
1872
+ properties: [
1873
+ { name: 'vertical', type: { kind: 'primitive', name: 'boolean' } },
1874
+ { name: 'dividerStyle', type: numberType },
1875
+ ],
1876
+ methods: [
1877
+ {
1878
+ name: 'addArrangedSubview',
1879
+ selector: 'addArrangedSubview:',
1880
+ returns: voidType,
1881
+ parameters: [{ name: 'view', type: { kind: 'class', name: 'AppKit.NSView' } }],
1882
+ },
1883
+ { name: 'adjustSubviews', selector: 'adjustSubviews', returns: voidType },
1884
+ {
1885
+ name: 'setPositionOfDividerAtIndex',
1886
+ selector: 'setPosition:ofDividerAtIndex:',
1887
+ returns: voidType,
1888
+ parameters: [
1889
+ { name: 'position', type: numberType },
1890
+ { name: 'dividerIndex', type: numberType },
1891
+ ],
1892
+ },
1893
+ ],
1894
+ },
1895
+ {
1896
+ name: 'NSTextView',
1897
+ extends: 'AppKit.NSView',
1898
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSTextView' } }],
1899
+ properties: [
1900
+ { name: 'string', type: stringType },
1901
+ { name: 'editable', type: { kind: 'primitive', name: 'boolean' } },
1902
+ { name: 'selectable', type: { kind: 'primitive', name: 'boolean' } },
1903
+ { name: 'drawsBackground', type: { kind: 'primitive', name: 'boolean' } },
1904
+ { name: 'backgroundColor', type: { kind: 'class', name: 'AppKit.NSColor', nullable: true } },
1905
+ { name: 'textColor', type: { kind: 'class', name: 'AppKit.NSColor', nullable: true } },
1906
+ { name: 'font', type: { kind: 'class', name: 'AppKit.NSFont', nullable: true } },
1907
+ ],
1908
+ methods: [
1909
+ {
1910
+ // Live edit notifications: the delegate receives textDidChange: on
1911
+ // every keystroke (see ObjCTarget).
1912
+ name: 'attachTextDelegate',
1913
+ selector: 'setDelegate:',
1914
+ returns: voidType,
1915
+ parameters: [{ name: 'delegate', type: { kind: 'class', name: 'Foundation.NSObject', nullable: true } }],
1916
+ },
1917
+ ],
1918
+ },
1919
+ {
1920
+ name: 'NSImage',
1921
+ extends: 'Foundation.NSObject',
1922
+ methods: [
1923
+ {
1924
+ name: 'imageWithSystemSymbolNameAccessibilityDescription',
1925
+ selector: 'imageWithSystemSymbolName:accessibilityDescription:',
1926
+ static: true,
1927
+ returns: { kind: 'class', name: 'AppKit.NSImage', nullable: true },
1928
+ parameters: [
1929
+ { name: 'symbolName', type: stringType },
1930
+ { name: 'accessibilityDescription', type: { kind: 'primitive', name: 'string' } },
1931
+ ],
1932
+ },
1933
+ ],
1934
+ },
1935
+ {
1936
+ name: 'NSImageView',
1937
+ extends: 'AppKit.NSView',
1938
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSImageView' } }],
1939
+ properties: [
1940
+ { name: 'image', type: { kind: 'class', name: 'AppKit.NSImage', nullable: true } },
1941
+ { name: 'contentTintColor', type: { kind: 'class', name: 'AppKit.NSColor', nullable: true } },
1942
+ ],
1943
+ },
1944
+ {
1945
+ name: 'NSButton',
1946
+ extends: 'AppKit.NSControl',
1947
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSButton' } }],
1948
+ properties: [
1949
+ { name: 'title', type: stringType },
1950
+ { name: 'bordered', type: { kind: 'primitive', name: 'boolean' } },
1951
+ ],
1952
+ },
1953
+ {
1954
+ name: 'NSViewController',
1955
+ extends: 'Foundation.NSObject',
1956
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSViewController' } }],
1957
+ properties: [
1958
+ { name: 'view', type: { kind: 'class', name: 'AppKit.NSView' } },
1959
+ { name: 'title', type: { kind: 'primitive', name: 'string' } },
1960
+ ],
1961
+ },
1962
+ {
1963
+ name: 'NSSplitViewController',
1964
+ extends: 'AppKit.NSViewController',
1965
+ constructors: [{ name: 'init', selector: 'init', returns: { kind: 'class', name: 'AppKit.NSSplitViewController' } }],
1966
+ methods: [
1967
+ {
1968
+ name: 'addSplitViewItem',
1969
+ selector: 'addSplitViewItem:',
1970
+ returns: voidType,
1971
+ parameters: [{ name: 'item', type: { kind: 'class', name: 'AppKit.NSSplitViewItem' } }],
1972
+ },
1973
+ ],
1974
+ },
1975
+ {
1976
+ name: 'NSSplitViewItem',
1977
+ extends: 'Foundation.NSObject',
1978
+ methods: [
1979
+ {
1980
+ name: 'sidebarWithViewController',
1981
+ selector: 'sidebarWithViewController:',
1982
+ static: true,
1983
+ returns: { kind: 'class', name: 'AppKit.NSSplitViewItem' },
1984
+ parameters: [{ name: 'viewController', type: { kind: 'class', name: 'AppKit.NSViewController' } }],
1985
+ },
1986
+ {
1987
+ name: 'contentListWithViewController',
1988
+ selector: 'contentListWithViewController:',
1989
+ static: true,
1990
+ returns: { kind: 'class', name: 'AppKit.NSSplitViewItem' },
1991
+ parameters: [{ name: 'viewController', type: { kind: 'class', name: 'AppKit.NSViewController' } }],
1992
+ },
1993
+ {
1994
+ name: 'splitViewItemWithViewController',
1995
+ selector: 'splitViewItemWithViewController:',
1996
+ static: true,
1997
+ returns: { kind: 'class', name: 'AppKit.NSSplitViewItem' },
1998
+ parameters: [{ name: 'viewController', type: { kind: 'class', name: 'AppKit.NSViewController' } }],
1999
+ },
2000
+ ],
2001
+ properties: [
2002
+ { name: 'minimumThickness', type: numberType },
2003
+ { name: 'maximumThickness', type: numberType },
2004
+ { name: 'canCollapse', type: { kind: 'primitive', name: 'boolean' } },
2005
+ { name: 'preferredThicknessFraction', type: numberType },
2006
+ ],
2007
+ },
2008
+ ],
2009
+ functions: [
2010
+ {
2011
+ name: 'installRootView',
2012
+ returns: voidType,
2013
+ parameters: [{ name: 'view', type: { kind: 'class', name: 'AppKit.NSView' } }],
2014
+ },
2015
+ {
2016
+ name: 'installRootViewController',
2017
+ returns: voidType,
2018
+ parameters: [{ name: 'viewController', type: { kind: 'class', name: 'AppKit.NSViewController' } }],
2019
+ },
2020
+ {
2021
+ // Attach a real unified-title-bar NSToolbar to the window. `spec` is a
2022
+ // comma-separated list of items: an SF Symbol name renders a borderless
2023
+ // image button, `space` a flexible space, `search` a search field.
2024
+ name: 'installToolbar',
2025
+ returns: voidType,
2026
+ parameters: [
2027
+ { name: 'spec', type: stringType },
2028
+ // ObjCTarget invoked when the `square.and.pencil` (New Note) item is
2029
+ // clicked. Other items are decorative (enabled, bordered, no-op),
2030
+ // matching the reference.
2031
+ { name: 'newNoteTarget', type: { kind: 'class', name: 'Foundation.NSObject', nullable: true } },
2032
+ ],
2033
+ },
2034
+ {
2035
+ // Run a shell command (via /bin/bash -c) and return its combined
2036
+ // stdout+stderr as a string. A small native escape hatch (NSTask) for
2037
+ // companion apps that drive external tooling — e.g. the gea Companion
2038
+ // talking to the watch over USB through scripts/esp32-device-control.py.
2039
+ name: 'runDeviceCommand',
2040
+ returns: stringType,
2041
+ parameters: [{ name: 'command', type: stringType }],
2042
+ },
2043
+ {
2044
+ // Set `content` as the scroll view's document view inside a flipped
2045
+ // container, so a tall vertical list lays out top-down and the scroll
2046
+ // view opens at the top (instead of NSView's default bottom-left origin,
2047
+ // which makes the list open scrolled to the bottom/middle).
2048
+ name: 'setScrollDocumentTopAligned',
2049
+ returns: voidType,
2050
+ parameters: [
2051
+ { name: 'scrollView', type: { kind: 'class', name: 'AppKit.NSScrollView' } },
2052
+ { name: 'content', type: { kind: 'class', name: 'AppKit.NSView' } },
2053
+ ],
2054
+ },
2055
+ ],
2056
+ },
2057
+ {
2058
+ name: 'ActivityKit',
2059
+ classes: [
2060
+ {
2061
+ name: 'LiveActivityHandle',
2062
+ properties: [{ name: 'id', type: stringType, readonly: true }],
2063
+ },
2064
+ ],
2065
+ functions: [
2066
+ {
2067
+ name: 'requestLiveActivity',
2068
+ returns: { kind: 'class', name: 'ActivityKit.LiveActivityHandle' },
2069
+ parameters: [
2070
+ { name: 'attributesJSON', type: stringType },
2071
+ { name: 'contentStateJSON', type: stringType },
2072
+ ],
2073
+ },
2074
+ {
2075
+ name: 'updateLiveActivity',
2076
+ returns: voidType,
2077
+ parameters: [
2078
+ { name: 'activity', type: { kind: 'class', name: 'ActivityKit.LiveActivityHandle' } },
2079
+ { name: 'contentStateJSON', type: stringType },
2080
+ ],
2081
+ },
2082
+ {
2083
+ name: 'endLiveActivity',
2084
+ returns: voidType,
2085
+ parameters: [{ name: 'activity', type: { kind: 'class', name: 'ActivityKit.LiveActivityHandle' } }],
2086
+ },
2087
+ ],
2088
+ },
2089
+ {
2090
+ name: 'SwiftData',
2091
+ classes: [
2092
+ { name: 'ModelContainer' },
2093
+ { name: 'ModelContext' },
2094
+ ],
2095
+ functions: [
2096
+ {
2097
+ name: 'openModelContainer',
2098
+ returns: { kind: 'class', name: 'SwiftData.ModelContainer' },
2099
+ parameters: [{ name: 'schemaJSON', type: stringType }],
2100
+ },
2101
+ {
2102
+ name: 'mainModelContext',
2103
+ returns: { kind: 'class', name: 'SwiftData.ModelContext' },
2104
+ parameters: [{ name: 'container', type: { kind: 'class', name: 'SwiftData.ModelContainer' } }],
2105
+ },
2106
+ {
2107
+ name: 'insertModelJSON',
2108
+ returns: voidType,
2109
+ parameters: [
2110
+ { name: 'context', type: { kind: 'class', name: 'SwiftData.ModelContext' } },
2111
+ { name: 'modelJSON', type: stringType },
2112
+ ],
2113
+ },
2114
+ {
2115
+ name: 'saveModelContext',
2116
+ returns: voidType,
2117
+ parameters: [{ name: 'context', type: { kind: 'class', name: 'SwiftData.ModelContext' } }],
2118
+ },
2119
+ {
2120
+ name: 'fetchModelsJSON',
2121
+ returns: stringType,
2122
+ parameters: [
2123
+ { name: 'context', type: { kind: 'class', name: 'SwiftData.ModelContext' } },
2124
+ { name: 'descriptorJSON', type: stringType },
2125
+ ],
2126
+ },
2127
+ ],
2128
+ },
2129
+ ],
2130
+ };
2131
+ export function generateAppleDeclarations(sdk) {
2132
+ const declarations = {};
2133
+ for (const framework of sdk.frameworks) {
2134
+ declarations[`@geastack/apple/${framework.name}`] = declarationForFramework(framework);
2135
+ }
2136
+ return declarations;
2137
+ }
2138
+ export function generateAppleRuntimeModules(sdk) {
2139
+ const modules = {};
2140
+ for (const framework of sdk.frameworks) {
2141
+ modules[`@geastack/apple/${framework.name}`] = runtimeModuleForFramework(framework);
2142
+ }
2143
+ return modules;
2144
+ }
2145
+ export function generateAppleBridgeMetadata(sdk) {
2146
+ const metadata = {
2147
+ frameworks: sdk.frameworks.map((framework) => ({
2148
+ name: framework.name,
2149
+ ...(framework.bridgeHeaders?.length ? { bridgeHeaders: framework.bridgeHeaders } : {}),
2150
+ })),
2151
+ constants: {},
2152
+ functions: {},
2153
+ classes: {},
2154
+ structs: {},
2155
+ };
2156
+ for (const framework of sdk.frameworks) {
2157
+ for (const constant of framework.constants ?? []) {
2158
+ const key = qualifiedName(framework.name, constant.name);
2159
+ metadata.constants[key] = {
2160
+ framework: framework.name,
2161
+ name: constant.name,
2162
+ type: constant.type,
2163
+ value: constant.value,
2164
+ };
2165
+ }
2166
+ for (const fn of framework.functions ?? []) {
2167
+ const key = qualifiedName(framework.name, fn.name);
2168
+ metadata.functions[key] = functionMetadata(framework.name, fn);
2169
+ }
2170
+ for (const struct of framework.structs ?? []) {
2171
+ const key = qualifiedName(framework.name, struct.name);
2172
+ metadata.structs[key] = {
2173
+ framework: framework.name,
2174
+ name: struct.name,
2175
+ wrapper: cppTypeName(framework.name, struct.name),
2176
+ fields: struct.fields,
2177
+ };
2178
+ }
2179
+ for (const cls of framework.classes ?? []) {
2180
+ const key = qualifiedName(framework.name, cls.name);
2181
+ const constructor = cls.constructors?.[0];
2182
+ metadata.classes[key] = {
2183
+ framework: framework.name,
2184
+ name: cls.name,
2185
+ ...(cls.extends ? { extends: cls.extends } : {}),
2186
+ wrapper: cppTypeName(framework.name, cls.name),
2187
+ ...(constructor ? { constructor: { selector: constructor.selector, thunk: constructorThunk(framework.name, cls.name), parameters: constructor.parameters ?? [] } } : {}),
2188
+ methods: Object.fromEntries((cls.methods ?? []).map((method) => [method.name, methodMetadata(framework.name, cls.name, method)])),
2189
+ properties: Object.fromEntries((cls.properties ?? []).map((property) => [property.name, propertyMetadata(framework.name, cls.name, property)])),
2190
+ };
2191
+ }
2192
+ }
2193
+ return metadata;
2194
+ }
2195
+ export function generateAppleNativeBridgeHeader(metadata) {
2196
+ const lines = [
2197
+ '#pragma once',
2198
+ '',
2199
+ '#import <CoreGraphics/CoreGraphics.h>',
2200
+ ];
2201
+ const importedFrameworks = new Set();
2202
+ for (const framework of metadata.frameworks) {
2203
+ if (objcFrameworkImports[framework.name])
2204
+ importedFrameworks.add(framework.name);
2205
+ }
2206
+ for (const framework of [...importedFrameworks].sort()) {
2207
+ const header = objcFrameworkImports[framework];
2208
+ lines.push(`#if __has_include(<${header}>)`);
2209
+ lines.push(`#import <${header}>`);
2210
+ lines.push('#endif');
2211
+ }
2212
+ for (const framework of metadata.frameworks) {
2213
+ for (const header of framework.bridgeHeaders ?? []) {
2214
+ lines.push(`#if __has_include("${header}")`);
2215
+ lines.push(`#import "${header}"`);
2216
+ lines.push('#endif');
2217
+ }
2218
+ }
2219
+ lines.push('', '#include <cstdint>', '#include <functional>', '#include <string>', '#include <vector>', '', '@class NSString;', 'namespace gea::apple::Foundation {', 'NSString *toNSString(const std::string &value);', 'std::string fromNSString(NSString *value);', '}', '', 'namespace gea::apple::objc {', 'void *object(double handle);', 'double retain(void *object);', 'void release(double handle);', '}', '');
2220
+ for (const framework of metadata.frameworks) {
2221
+ const structs = Object.values(metadata.structs).filter((entry) => entry.framework === framework.name);
2222
+ const classes = Object.values(metadata.classes).filter((entry) => entry.framework === framework.name);
2223
+ if (structs.length === 0 && classes.length === 0)
2224
+ continue;
2225
+ lines.push(`namespace gea::apple::${framework.name} {`);
2226
+ for (const struct of structs) {
2227
+ if (nativeStructFrameworks.has(framework.name)) {
2228
+ lines.push(`using ${struct.name} = ::${struct.name};`, '');
2229
+ }
2230
+ else {
2231
+ lines.push(`struct ${struct.name} {`);
2232
+ for (const field of struct.fields) {
2233
+ lines.push(` ${cppValueType(field.type, framework.name, { preferLocalNames: true })} ${field.name}${defaultInitializer(field.type)};`);
2234
+ }
2235
+ lines.push('};', '');
2236
+ }
2237
+ }
2238
+ for (const cls of classes) {
2239
+ const base = cls.extends ? ` : ${cppValueType({ kind: 'class', name: cls.extends }, framework.name)}` : '';
2240
+ lines.push(`struct ${cls.name}${base} {`);
2241
+ if (cls.extends) {
2242
+ const [, baseName] = splitQualifiedName(cls.extends, framework.name);
2243
+ lines.push(` using ${cppValueType({ kind: 'class', name: cls.extends }, framework.name)}::${baseName};`);
2244
+ }
2245
+ else {
2246
+ lines.push(' double handle = 0;');
2247
+ lines.push(` ${cls.name}() = default;`);
2248
+ lines.push(` explicit ${cls.name}(double rawHandle) : handle(rawHandle) {}`);
2249
+ }
2250
+ lines.push(' explicit operator bool() const { return handle != 0; }');
2251
+ lines.push('};', '');
2252
+ }
2253
+ lines.push('}', '');
2254
+ }
2255
+ appendUIKitCallbackBridgeDeclarations(lines, metadata);
2256
+ appendBridgeDeclarations(lines, metadata);
2257
+ return `${lines.join('\n').trimEnd()}\n`;
2258
+ }
2259
+ function appendBridgeDeclarations(lines, metadata) {
2260
+ const seen = new Set();
2261
+ for (const block of sourceBackedBridgeDeclarations(metadata)) {
2262
+ const signature = block.join('\n');
2263
+ if (seen.has(signature))
2264
+ continue;
2265
+ seen.add(signature);
2266
+ lines.push(...block);
2267
+ }
2268
+ if (seen.size > 0)
2269
+ lines.push('');
2270
+ }
2271
+ function sourceBackedBridgeDeclarations(metadata) {
2272
+ const declarations = [];
2273
+ const append = (name, returnType, params) => {
2274
+ declarations.push(bridgeDeclaration(name, returnType, params));
2275
+ };
2276
+ for (const fn of Object.values(metadata.functions)) {
2277
+ if (fn.framework === 'Dispatch' || fn.framework === 'Metal') {
2278
+ append(fn.thunk, cppValueType(fn.returns, fn.framework), fn.parameters.map((parameter) => bridgeParameter(parameter, fn.framework)).join(', '));
2279
+ }
2280
+ }
2281
+ for (const cls of Object.values(metadata.classes)) {
2282
+ const constructor = Object.prototype.hasOwnProperty.call(cls, 'constructor') ? cls.constructor : undefined;
2283
+ if (constructor && bridgeSourceDefinesConstructor(cls)) {
2284
+ append(constructor.thunk, 'double', (constructor.parameters ?? []).map((parameter) => bridgeParameter(parameter, cls.framework)).join(', '));
2285
+ }
2286
+ for (const method of Object.values(cls.methods)) {
2287
+ if (!bridgeSourceDefinesMethod(cls, method))
2288
+ continue;
2289
+ const parameters = method.static
2290
+ ? method.parameters
2291
+ : [{ name: 'self', type: { kind: 'class', name: `${cls.framework}.${cls.name}` } }, ...method.parameters];
2292
+ append(method.thunk, cppValueType(method.returns, cls.framework), parameters.map((parameter) => bridgeParameter(parameter, cls.framework)).join(', '));
2293
+ }
2294
+ for (const property of Object.values(cls.properties)) {
2295
+ if (!bridgeSourceDefinesProperty(cls, property))
2296
+ continue;
2297
+ append(property.getter, cppValueType(property.type, cls.framework), `${cls.wrapper} self`);
2298
+ if (property.setter)
2299
+ append(property.setter, 'void', `${cls.wrapper} self, ${cppValueType(property.type, cls.framework)} value`);
2300
+ }
2301
+ }
2302
+ return declarations;
2303
+ }
2304
+ function bridgeSourceDefinesConstructor(cls) {
2305
+ return cls.framework === 'Metal' || cls.framework === 'MetalKit';
2306
+ }
2307
+ function bridgeSourceDefinesMethod(cls, method) {
2308
+ if (cls.framework === 'Metal' || cls.framework === 'MetalKit')
2309
+ return true;
2310
+ if (cls.framework === 'AVFoundation' && cls.name === 'AVCaptureDeviceInput' && method.name === 'deviceInputWithDevice')
2311
+ return true;
2312
+ if (cls.framework === 'AVFoundation' && cls.name === 'AVCaptureDevice' && method.name === 'lockForConfiguration')
2313
+ return true;
2314
+ if (cls.framework === 'AVFoundation' && cls.name === 'AVCaptureDevice' && method.name === 'setExposureTargetBiasCompletionHandler')
2315
+ return true;
2316
+ if (cls.framework === 'AVFoundation' && cls.name === 'AVCaptureDevice' && method.name === 'setExposureModeCustomWithDurationISOCompletionHandler')
2317
+ return true;
2318
+ if (cls.framework === 'AVFoundation' && cls.name === 'AVCapturePhotoOutput' && method.name === 'capturePhotoWithSettingsHandler')
2319
+ return true;
2320
+ return cls.framework === 'Photos' && cls.name === 'PHPhotoLibrary' && method.name === 'saveImageData';
2321
+ }
2322
+ function bridgeSourceDefinesProperty(cls, property) {
2323
+ if (cls.framework === 'Metal' || cls.framework === 'MetalKit')
2324
+ return true;
2325
+ return cls.framework === 'AVFoundation' && cls.name === 'AVCaptureDevice' && property.name === 'virtualDeviceSwitchOverVideoZoomFactors';
2326
+ }
2327
+ function bridgeParameter(parameter, localFramework) {
2328
+ return `${cppValueType(parameter.type, localFramework)} ${parameter.name}`;
2329
+ }
2330
+ function bridgeDeclaration(name, returnType, params) {
2331
+ const target = cppFunctionTarget(name);
2332
+ if (!target.namespaceName)
2333
+ return [`${returnType} ${target.bareName}(${params});`];
2334
+ return [`namespace ${target.namespaceName} {`, `${returnType} ${target.bareName}(${params});`, '}'];
2335
+ }
2336
+ export function generateAppleNativeBridgeObjCxxSource(metadata) {
2337
+ const importedFrameworks = new Set();
2338
+ for (const framework of metadata.frameworks) {
2339
+ if (objcFrameworkImports[framework.name])
2340
+ importedFrameworks.add(framework.name);
2341
+ }
2342
+ const lines = [
2343
+ '#include "gea/apple/native_bridge.h"',
2344
+ '',
2345
+ '#import <CoreGraphics/CoreGraphics.h>',
2346
+ ];
2347
+ for (const framework of [...importedFrameworks].sort()) {
2348
+ const header = objcFrameworkImports[framework];
2349
+ lines.push(`#if __has_include(<${header}>)`);
2350
+ lines.push(`#import <${header}>`);
2351
+ lines.push('#endif');
2352
+ }
2353
+ lines.push('', '#include <cstdint>', '#include <functional>', '#include <mutex>', '#include <unordered_map>', '#include <utility>', '#include <vector>', '', 'namespace {', 'std::mutex geaAppleObjectMutex;', 'std::unordered_map<std::uint64_t, void *> geaAppleObjects;', 'std::uint64_t geaAppleNextObjectHandle = 1;', '}', '', 'namespace gea::apple::objc {', 'void *object(double handle) {', ' if (handle <= 0) return nullptr;', ' const auto key = static_cast<std::uint64_t>(handle);', ' std::lock_guard<std::mutex> lock(geaAppleObjectMutex);', ' const auto found = geaAppleObjects.find(key);', ' return found == geaAppleObjects.end() ? nullptr : found->second;', '}', '', 'double retain(void *object) {', ' if (!object) return 0;', ' void *retained = const_cast<void *>(CFRetain(object));', ' std::lock_guard<std::mutex> lock(geaAppleObjectMutex);', ' const auto handle = geaAppleNextObjectHandle++;', ' geaAppleObjects.emplace(handle, retained);', ' return static_cast<double>(handle);', '}', '', 'void release(double handle) {', ' if (handle <= 0) return;', ' void *object = nullptr;', ' {', ' std::lock_guard<std::mutex> lock(geaAppleObjectMutex);', ' const auto key = static_cast<std::uint64_t>(handle);', ' const auto found = geaAppleObjects.find(key);', ' if (found == geaAppleObjects.end()) return;', ' object = found->second;', ' geaAppleObjects.erase(found);', ' }', ' CFRelease(object);', '}', '}', '');
2354
+ appendFoundationStringConversions(lines, metadata);
2355
+ appendDispatchBridges(lines, metadata);
2356
+ appendAVFoundationBridges(lines, metadata);
2357
+ appendPhotosBridges(lines, metadata);
2358
+ appendMetalBridges(lines, metadata);
2359
+ appendMetalKitBridges(lines, metadata);
2360
+ appendUIKitCallbackBridges(lines, metadata);
2361
+ return `${lines.join('\n').trimEnd()}\n`;
2362
+ }
2363
+ function declarationForFramework(framework) {
2364
+ const lines = [];
2365
+ for (const [module, imports] of Object.entries(framework.imports ?? {})) {
2366
+ lines.push(`import type { ${imports.join(', ')} } from '@geastack/apple/${module}'`);
2367
+ }
2368
+ if (lines.length > 0)
2369
+ lines.push('');
2370
+ if (frameworkUsesPrimitive(framework, 'selector')) {
2371
+ lines.push('export type Selector = string', '');
2372
+ }
2373
+ for (const constant of framework.constants ?? []) {
2374
+ lines.push(`export declare const ${constant.name}: ${typeScriptType(constant.type, framework.name)}`);
2375
+ }
2376
+ if ((framework.constants ?? []).length > 0)
2377
+ lines.push('');
2378
+ for (const fn of framework.functions ?? []) {
2379
+ lines.push(`export declare function ${fn.name}(${parametersSignature(fn.parameters ?? [], framework.name)}): ${typeScriptType(fn.returns, framework.name)}`);
2380
+ }
2381
+ if ((framework.functions ?? []).length > 0)
2382
+ lines.push('');
2383
+ for (const struct of framework.structs ?? []) {
2384
+ lines.push(`export interface ${struct.name} {`);
2385
+ for (const field of struct.fields) {
2386
+ lines.push(` ${field.name}: ${typeScriptType(field.type, framework.name)}`);
2387
+ }
2388
+ lines.push('}', '');
2389
+ }
2390
+ for (const cls of framework.classes ?? []) {
2391
+ const base = cls.extends ? ` extends ${shortTypeName(cls.extends)}` : '';
2392
+ lines.push(`export declare class ${cls.name}${base} {`);
2393
+ for (const constructor of cls.constructors ?? []) {
2394
+ lines.push(` constructor(${parametersSignature(constructor.parameters ?? [], framework.name)})`);
2395
+ }
2396
+ for (const property of cls.properties ?? []) {
2397
+ const readonly = property.readonly ? 'readonly ' : '';
2398
+ lines.push(` ${readonly}${property.name}: ${typeScriptType(property.type, framework.name)}`);
2399
+ }
2400
+ for (const method of cls.methods ?? []) {
2401
+ const prefix = method.static ? 'static ' : '';
2402
+ lines.push(` ${prefix}${method.name}(${parametersSignature(method.parameters ?? [], framework.name)}): ${typeScriptType(method.returns, framework.name)}`);
2403
+ }
2404
+ lines.push('}', '');
2405
+ }
2406
+ return `${lines.join('\n').trimEnd()}\n`;
2407
+ }
2408
+ function runtimeModuleForFramework(framework) {
2409
+ if ((framework.constants ?? []).length === 0 && (framework.functions ?? []).length === 0 && (framework.classes ?? []).length === 0) {
2410
+ return 'export {}\n';
2411
+ }
2412
+ const nativeOnly = `geaApple${framework.name}NativeOnly`;
2413
+ const lines = [
2414
+ `function ${nativeOnly}(name) {`,
2415
+ ` throw new Error(\`@geastack/apple/${framework.name} \${name} is native-only and must be lowered by @geastack/geatsc-plugin-apple-native.\`)`,
2416
+ `}`,
2417
+ '',
2418
+ ];
2419
+ for (const constant of framework.constants ?? []) {
2420
+ lines.push(`export const ${constant.name} = ${JSON.stringify(constant.value)}`);
2421
+ }
2422
+ if ((framework.constants ?? []).length > 0)
2423
+ lines.push('');
2424
+ for (const fn of framework.functions ?? []) {
2425
+ lines.push(`export function ${fn.name}() {`);
2426
+ lines.push(` return ${nativeOnly}(${JSON.stringify(fn.name)})`);
2427
+ lines.push('}', '');
2428
+ }
2429
+ for (const cls of framework.classes ?? []) {
2430
+ const constructorDefinition = cls.constructors?.[0];
2431
+ const constructorParameters = (constructorDefinition?.parameters ?? []).map((parameter) => parameter.name).join(', ');
2432
+ const constructor = constructorDefinition ? ` constructor(${constructorParameters}) {\n ${nativeOnly}(${JSON.stringify(`new ${cls.name}`)})\n }` : '';
2433
+ lines.push(`export class ${cls.name} {`);
2434
+ if (constructor)
2435
+ lines.push(constructor);
2436
+ for (const method of cls.methods ?? []) {
2437
+ const prefix = method.static ? 'static ' : '';
2438
+ lines.push(` ${prefix}${method.name}() {`);
2439
+ lines.push(` return ${nativeOnly}(${JSON.stringify(`${cls.name}.${method.name}`)})`);
2440
+ lines.push(' }');
2441
+ }
2442
+ lines.push('}', '');
2443
+ }
2444
+ return `${lines.join('\n').trimEnd()}\n`;
2445
+ }
2446
+ function appendFoundationStringConversions(lines, metadata) {
2447
+ if (!metadata.frameworks.some((framework) => framework.name === 'Foundation'))
2448
+ return;
2449
+ lines.push('#if __has_include(<Foundation/Foundation.h>)');
2450
+ lines.push('namespace gea::apple::Foundation {');
2451
+ lines.push('NSString *toNSString(const std::string &value) {');
2452
+ lines.push(' return [NSString stringWithUTF8String:value.c_str()];');
2453
+ lines.push('}');
2454
+ lines.push('std::string fromNSString(NSString *value) {');
2455
+ lines.push(' if (!value) return {};');
2456
+ lines.push(' const char *utf8 = [value UTF8String];');
2457
+ lines.push(' return utf8 ? std::string(utf8) : std::string();');
2458
+ lines.push('}');
2459
+ lines.push('}', '');
2460
+ lines.push('#endif', '');
2461
+ }
2462
+ function appendDispatchBridges(lines, metadata) {
2463
+ if (!metadata.frameworks.some((framework) => framework.name === 'Dispatch'))
2464
+ return;
2465
+ lines.push('#if __has_include(<dispatch/dispatch.h>)');
2466
+ lines.push('void gea::apple::Dispatch::dispatchAsyncGlobal(std::function<void()> execute) {');
2467
+ lines.push(' dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{');
2468
+ lines.push(' if (execute) execute();');
2469
+ lines.push(' });');
2470
+ lines.push('}');
2471
+ lines.push('void gea::apple::Dispatch::dispatchAsyncMain(std::function<void()> execute) {');
2472
+ lines.push(' dispatch_async(dispatch_get_main_queue(), ^{');
2473
+ lines.push(' if (execute) execute();');
2474
+ lines.push(' });');
2475
+ lines.push('}');
2476
+ lines.push('#endif', '');
2477
+ }
2478
+ function appendAVFoundationBridges(lines, metadata) {
2479
+ if (!metadata.frameworks.some((framework) => framework.name === 'AVFoundation'))
2480
+ return;
2481
+ lines.push('#if __has_include(<AVFoundation/AVFoundation.h>)');
2482
+ lines.push('@interface GeaApplePhotoCaptureDelegate : NSObject <AVCapturePhotoCaptureDelegate>');
2483
+ lines.push('- (instancetype)initWithHandler:(std::function<void(gea::apple::Foundation::NSData, std::string)>)handler;');
2484
+ lines.push('@end', '');
2485
+ lines.push('static NSMutableSet *geaApplePhotoCaptureDelegates() {');
2486
+ lines.push(' static NSMutableSet *delegates = nil;');
2487
+ lines.push(' static dispatch_once_t onceToken;');
2488
+ lines.push(' dispatch_once(&onceToken, ^{ delegates = [NSMutableSet set]; });');
2489
+ lines.push(' return delegates;');
2490
+ lines.push('}', '');
2491
+ lines.push('@implementation GeaApplePhotoCaptureDelegate {');
2492
+ lines.push(' std::function<void(gea::apple::Foundation::NSData, std::string)> _handler;');
2493
+ lines.push('}');
2494
+ lines.push('- (instancetype)initWithHandler:(std::function<void(gea::apple::Foundation::NSData, std::string)>)handler {');
2495
+ lines.push(' self = [super init];');
2496
+ lines.push(' if (self) _handler = std::move(handler);');
2497
+ lines.push(' return self;');
2498
+ lines.push('}');
2499
+ lines.push('- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error {');
2500
+ lines.push(' (void)output;');
2501
+ lines.push(' NSData *data = error ? nil : [photo fileDataRepresentation];');
2502
+ lines.push(' NSData *capturedData = data;');
2503
+ lines.push(' std::string message;');
2504
+ lines.push(' if (error) message = gea::apple::Foundation::fromNSString([error localizedDescription]);');
2505
+ lines.push(' else if (!data) message = "No photo data";');
2506
+ lines.push(' auto handler = _handler;');
2507
+ lines.push(' dispatch_async(dispatch_get_main_queue(), ^{');
2508
+ lines.push(' if (handler) handler(gea::apple::Foundation::NSData(gea::apple::objc::retain((__bridge void *)capturedData)), message);');
2509
+ lines.push(' [geaApplePhotoCaptureDelegates() removeObject:self];');
2510
+ lines.push(' });');
2511
+ lines.push('}');
2512
+ lines.push('@end', '');
2513
+ lines.push('gea::apple::AVFoundation::AVCaptureDeviceInput gea::apple::AVFoundation::AVCaptureDeviceInput_deviceInputWithDevice(gea::apple::AVFoundation::AVCaptureDevice device) {');
2514
+ lines.push(' NSError *error = nil;');
2515
+ lines.push(' ::AVCaptureDevice *nativeDevice = (__bridge ::AVCaptureDevice *)gea::apple::objc::object(device.handle);');
2516
+ lines.push(' ::AVCaptureDeviceInput *input = [::AVCaptureDeviceInput deviceInputWithDevice:nativeDevice error:&error];');
2517
+ lines.push(' if (!input && error) NSLog(@"AVCaptureDeviceInput creation failed: %@", error);');
2518
+ lines.push(' return gea::apple::AVFoundation::AVCaptureDeviceInput(gea::apple::objc::retain((__bridge void *)input));');
2519
+ lines.push('}');
2520
+ lines.push('bool gea::apple::AVFoundation::AVCaptureDevice_lockForConfiguration(gea::apple::AVFoundation::AVCaptureDevice device) {');
2521
+ lines.push(' NSError *error = nil;');
2522
+ lines.push(' ::AVCaptureDevice *nativeDevice = (__bridge ::AVCaptureDevice *)gea::apple::objc::object(device.handle);');
2523
+ lines.push(' if (!nativeDevice) return false;');
2524
+ lines.push(' BOOL locked = [nativeDevice lockForConfiguration:&error];');
2525
+ lines.push(' if (!locked && error) NSLog(@"AVCaptureDevice lockForConfiguration failed: %@", error);');
2526
+ lines.push(' return locked;');
2527
+ lines.push('}');
2528
+ lines.push('void gea::apple::AVFoundation::AVCaptureDevice_setExposureTargetBiasCompletionHandler(gea::apple::AVFoundation::AVCaptureDevice device, double bias, std::function<void(gea::apple::CoreMedia::CMTime)> handler) {');
2529
+ lines.push(' ::AVCaptureDevice *nativeDevice = (__bridge ::AVCaptureDevice *)gea::apple::objc::object(device.handle);');
2530
+ lines.push(' auto callback = handler;');
2531
+ lines.push(' if (!nativeDevice) {');
2532
+ lines.push(' if (callback) callback(kCMTimeInvalid);');
2533
+ lines.push(' return;');
2534
+ lines.push(' }');
2535
+ lines.push(' @try {');
2536
+ lines.push(' [nativeDevice setExposureTargetBias:bias completionHandler:^(CMTime syncTime) {');
2537
+ lines.push(' if (callback) callback(syncTime);');
2538
+ lines.push(' }];');
2539
+ lines.push(' } @catch (NSException *exception) {');
2540
+ lines.push(' NSString *reason = exception.reason ?: exception.name ?: @"AVCaptureDevice exposure bias failed";');
2541
+ lines.push(' NSLog(@"%@", reason);');
2542
+ lines.push(' if (callback) callback(kCMTimeInvalid);');
2543
+ lines.push(' }');
2544
+ lines.push('}');
2545
+ lines.push('void gea::apple::AVFoundation::AVCaptureDevice_setExposureModeCustomWithDurationISOCompletionHandler(gea::apple::AVFoundation::AVCaptureDevice device, gea::apple::CoreMedia::CMTime duration, double ISO, std::function<void(gea::apple::CoreMedia::CMTime)> handler) {');
2546
+ lines.push(' ::AVCaptureDevice *nativeDevice = (__bridge ::AVCaptureDevice *)gea::apple::objc::object(device.handle);');
2547
+ lines.push(' auto callback = handler;');
2548
+ lines.push(' if (!nativeDevice) {');
2549
+ lines.push(' if (callback) callback(kCMTimeInvalid);');
2550
+ lines.push(' return;');
2551
+ lines.push(' }');
2552
+ lines.push(' @try {');
2553
+ lines.push(' [nativeDevice setExposureModeCustomWithDuration:duration ISO:ISO completionHandler:^(CMTime syncTime) {');
2554
+ lines.push(' if (callback) callback(syncTime);');
2555
+ lines.push(' }];');
2556
+ lines.push(' } @catch (NSException *exception) {');
2557
+ lines.push(' NSString *reason = exception.reason ?: exception.name ?: @"AVCaptureDevice custom exposure failed";');
2558
+ lines.push(' NSLog(@"%@", reason);');
2559
+ lines.push(' if (callback) callback(kCMTimeInvalid);');
2560
+ lines.push(' }');
2561
+ lines.push('}');
2562
+ lines.push('std::vector<double> gea::apple::AVFoundation::AVCaptureDevice_get_virtualDeviceSwitchOverVideoZoomFactors(gea::apple::AVFoundation::AVCaptureDevice self) {');
2563
+ lines.push(' ::AVCaptureDevice *nativeDevice = (__bridge ::AVCaptureDevice *)gea::apple::objc::object(self.handle);');
2564
+ lines.push(' std::vector<double> factors;');
2565
+ lines.push(' if (!nativeDevice) return factors;');
2566
+ lines.push(' for (NSNumber *factor in nativeDevice.virtualDeviceSwitchOverVideoZoomFactors) {');
2567
+ lines.push(' factors.push_back([factor doubleValue]);');
2568
+ lines.push(' }');
2569
+ lines.push(' return factors;');
2570
+ lines.push('}');
2571
+ lines.push('void gea::apple::AVFoundation::AVCapturePhotoOutput_capturePhotoWithSettingsHandler(gea::apple::AVFoundation::AVCapturePhotoOutput output, gea::apple::AVFoundation::AVCapturePhotoSettings settings, std::function<void(gea::apple::Foundation::NSData, std::string)> handler) {');
2572
+ lines.push(' ::AVCapturePhotoOutput *nativeOutput = (__bridge ::AVCapturePhotoOutput *)gea::apple::objc::object(output.handle);');
2573
+ lines.push(' ::AVCapturePhotoSettings *nativeSettings = (__bridge ::AVCapturePhotoSettings *)gea::apple::objc::object(settings.handle);');
2574
+ lines.push(' if (!nativeOutput || !nativeSettings) {');
2575
+ lines.push(' if (handler) handler(gea::apple::Foundation::NSData(), "Missing AVCapturePhotoOutput or AVCapturePhotoSettings");');
2576
+ lines.push(' return;');
2577
+ lines.push(' }');
2578
+ lines.push(' auto callback = handler;');
2579
+ lines.push(' GeaApplePhotoCaptureDelegate *delegate = [[GeaApplePhotoCaptureDelegate alloc] initWithHandler:callback];');
2580
+ lines.push(' [geaApplePhotoCaptureDelegates() addObject:delegate];');
2581
+ lines.push(' @try {');
2582
+ lines.push(' [nativeOutput capturePhotoWithSettings:nativeSettings delegate:delegate];');
2583
+ lines.push(' } @catch (NSException *exception) {');
2584
+ lines.push(' [geaApplePhotoCaptureDelegates() removeObject:delegate];');
2585
+ lines.push(' NSString *reason = exception.reason ?: exception.name ?: @"AVCapturePhotoOutput capture failed";');
2586
+ lines.push(' if (callback) callback(gea::apple::Foundation::NSData(), gea::apple::Foundation::fromNSString(reason));');
2587
+ lines.push(' }');
2588
+ lines.push('}');
2589
+ lines.push('#endif', '');
2590
+ }
2591
+ function appendPhotosBridges(lines, metadata) {
2592
+ if (!metadata.frameworks.some((framework) => framework.name === 'Photos'))
2593
+ return;
2594
+ lines.push('#if __has_include(<Photos/Photos.h>)');
2595
+ lines.push('static void geaApplePhotosDispatchSaveResult(std::function<void(bool, std::string)> handler, bool success, NSString *message) {');
2596
+ lines.push(' std::string text = gea::apple::Foundation::fromNSString(message);');
2597
+ lines.push(' dispatch_async(dispatch_get_main_queue(), ^{');
2598
+ lines.push(' if (handler) handler(success, text);');
2599
+ lines.push(' });');
2600
+ lines.push('}');
2601
+ lines.push('static void geaApplePhotosSaveImageDataAuthorized(NSData *data, std::function<void(bool, std::string)> handler) {');
2602
+ lines.push(' __block NSString *creationException = nil;');
2603
+ lines.push(' @try {');
2604
+ lines.push(' [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{');
2605
+ lines.push(' @try {');
2606
+ lines.push(' PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];');
2607
+ lines.push(' [request addResourceWithType:PHAssetResourceTypePhoto data:data options:nil];');
2608
+ lines.push(' } @catch (NSException *exception) {');
2609
+ lines.push(' creationException = exception.reason ?: exception.name ?: @"Photos save failed";');
2610
+ lines.push(' }');
2611
+ lines.push(' } completionHandler:^(BOOL success, NSError *error) {');
2612
+ lines.push(' if (creationException) geaApplePhotosDispatchSaveResult(handler, false, creationException);');
2613
+ lines.push(' else geaApplePhotosDispatchSaveResult(handler, success, error ? [error localizedDescription] : @"");');
2614
+ lines.push(' }];');
2615
+ lines.push(' } @catch (NSException *exception) {');
2616
+ lines.push(' NSString *reason = exception.reason ?: exception.name ?: @"Photos save failed";');
2617
+ lines.push(' geaApplePhotosDispatchSaveResult(handler, false, reason);');
2618
+ lines.push(' }');
2619
+ lines.push('}');
2620
+ lines.push('void gea::apple::Photos::PHPhotoLibrary_saveImageData(gea::apple::Foundation::NSData data, std::function<void(bool, std::string)> handler) {');
2621
+ lines.push(' NSData *nativeData = (__bridge NSData *)gea::apple::objc::object(data.handle);');
2622
+ lines.push(' if (!nativeData) {');
2623
+ lines.push(' geaApplePhotosDispatchSaveResult(handler, false, @"Missing image data");');
2624
+ lines.push(' return;');
2625
+ lines.push(' }');
2626
+ lines.push(' NSData *imageData = [nativeData copy];');
2627
+ lines.push(' if (@available(iOS 14.0, *)) {');
2628
+ lines.push(' [::PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelAddOnly handler:^(PHAuthorizationStatus status) {');
2629
+ lines.push(' if (status == PHAuthorizationStatusAuthorized || status == PHAuthorizationStatusLimited) geaApplePhotosSaveImageDataAuthorized(imageData, handler);');
2630
+ lines.push(' else geaApplePhotosDispatchSaveResult(handler, false, @"Photos add permission denied");');
2631
+ lines.push(' }];');
2632
+ lines.push(' } else {');
2633
+ lines.push(' [::PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {');
2634
+ lines.push(' if (status == PHAuthorizationStatusAuthorized) geaApplePhotosSaveImageDataAuthorized(imageData, handler);');
2635
+ lines.push(' else geaApplePhotosDispatchSaveResult(handler, false, @"Photos permission denied");');
2636
+ lines.push(' }];');
2637
+ lines.push(' }');
2638
+ lines.push('}');
2639
+ lines.push('#endif', '');
2640
+ }
2641
+ function appendMetalBridges(lines, metadata) {
2642
+ if (!metadata.frameworks.some((framework) => framework.name === 'Metal'))
2643
+ return;
2644
+ lines.push('#if __has_include(<Metal/Metal.h>)');
2645
+ lines.push('namespace {');
2646
+ lines.push('id<MTLDevice> geaAppleMTLDevice(gea::apple::Metal::MTLDevice value) { return (__bridge id<MTLDevice>)gea::apple::objc::object(value.handle); }');
2647
+ lines.push('id<MTLCommandQueue> geaAppleMTLCommandQueue(gea::apple::Metal::MTLCommandQueue value) { return (__bridge id<MTLCommandQueue>)gea::apple::objc::object(value.handle); }');
2648
+ lines.push('id<MTLCommandBuffer> geaAppleMTLCommandBuffer(gea::apple::Metal::MTLCommandBuffer value) { return (__bridge id<MTLCommandBuffer>)gea::apple::objc::object(value.handle); }');
2649
+ lines.push('id<MTLLibrary> geaAppleMTLLibrary(gea::apple::Metal::MTLLibrary value) { return (__bridge id<MTLLibrary>)gea::apple::objc::object(value.handle); }');
2650
+ lines.push('id<MTLFunction> geaAppleMTLFunction(gea::apple::Metal::MTLFunction value) { return (__bridge id<MTLFunction>)gea::apple::objc::object(value.handle); }');
2651
+ lines.push('id<MTLRenderPipelineState> geaAppleMTLRenderPipelineState(gea::apple::Metal::MTLRenderPipelineState value) { return (__bridge id<MTLRenderPipelineState>)gea::apple::objc::object(value.handle); }');
2652
+ lines.push('id<MTLBuffer> geaAppleMTLBuffer(gea::apple::Metal::MTLBuffer value) { return (__bridge id<MTLBuffer>)gea::apple::objc::object(value.handle); }');
2653
+ lines.push('id<MTLDepthStencilState> geaAppleMTLDepthStencilState(gea::apple::Metal::MTLDepthStencilState value) { return (__bridge id<MTLDepthStencilState>)gea::apple::objc::object(value.handle); }');
2654
+ lines.push('id<MTLRenderCommandEncoder> geaAppleMTLRenderCommandEncoder(gea::apple::Metal::MTLRenderCommandEncoder value) { return (__bridge id<MTLRenderCommandEncoder>)gea::apple::objc::object(value.handle); }');
2655
+ lines.push('id<MTLDrawable> geaAppleMTLDrawable(gea::apple::Metal::MTLDrawable value) { return (__bridge id<MTLDrawable>)gea::apple::objc::object(value.handle); }');
2656
+ lines.push('MTLCompileOptions *geaAppleMTLCompileOptions(gea::apple::Metal::MTLCompileOptions value) { return (__bridge MTLCompileOptions *)gea::apple::objc::object(value.handle); }');
2657
+ lines.push('MTLRenderPipelineDescriptor *geaAppleMTLRenderPipelineDescriptor(gea::apple::Metal::MTLRenderPipelineDescriptor value) { return (__bridge MTLRenderPipelineDescriptor *)gea::apple::objc::object(value.handle); }');
2658
+ lines.push('MTLRenderPipelineColorAttachmentDescriptorArray *geaAppleMTLColorAttachments(gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptorArray value) { return (__bridge MTLRenderPipelineColorAttachmentDescriptorArray *)gea::apple::objc::object(value.handle); }');
2659
+ lines.push('MTLRenderPipelineColorAttachmentDescriptor *geaAppleMTLColorAttachment(gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptor value) { return (__bridge MTLRenderPipelineColorAttachmentDescriptor *)gea::apple::objc::object(value.handle); }');
2660
+ lines.push('MTLRenderPassDescriptor *geaAppleMTLRenderPassDescriptor(gea::apple::Metal::MTLRenderPassDescriptor value) { return (__bridge MTLRenderPassDescriptor *)gea::apple::objc::object(value.handle); }');
2661
+ lines.push('MTLDepthStencilDescriptor *geaAppleMTLDepthStencilDescriptor(gea::apple::Metal::MTLDepthStencilDescriptor value) { return (__bridge MTLDepthStencilDescriptor *)gea::apple::objc::object(value.handle); }');
2662
+ lines.push('std::vector<float> geaAppleFloatBytes(const std::vector<double> &values) {');
2663
+ lines.push(' std::vector<float> storage;');
2664
+ lines.push(' storage.reserve(values.size());');
2665
+ lines.push(' for (double value : values) storage.push_back(static_cast<float>(value));');
2666
+ lines.push(' return storage;');
2667
+ lines.push('}');
2668
+ lines.push('}', '');
2669
+ lines.push('gea::apple::Metal::MTLDevice gea::apple::Metal::MTLCreateSystemDefaultDevice() {');
2670
+ lines.push(' return gea::apple::Metal::MTLDevice(gea::apple::objc::retain((__bridge void *)::MTLCreateSystemDefaultDevice()));');
2671
+ lines.push('}', '');
2672
+ lines.push('gea::apple::Metal::MTLClearColor gea::apple::Metal::MTLClearColorMake(double red, double green, double blue, double alpha) {');
2673
+ lines.push(' return gea::apple::Metal::MTLClearColor{red, green, blue, alpha};');
2674
+ lines.push('}', '');
2675
+ lines.push('double gea::apple::Metal::MTLCompileOptions_init() {');
2676
+ lines.push(' return gea::apple::objc::retain((__bridge void *)[[::MTLCompileOptions alloc] init]);');
2677
+ lines.push('}', '');
2678
+ lines.push('gea::apple::Metal::MTLCommandQueue gea::apple::Metal::MTLDevice_newCommandQueue(gea::apple::Metal::MTLDevice self) {');
2679
+ lines.push(' return gea::apple::Metal::MTLCommandQueue(gea::apple::objc::retain((__bridge void *)[geaAppleMTLDevice(self) newCommandQueue]));');
2680
+ lines.push('}', '');
2681
+ lines.push('gea::apple::Metal::MTLLibrary gea::apple::Metal::MTLDevice_newLibraryWithSourceOptionsError(gea::apple::Metal::MTLDevice self, std::string source, gea::apple::Metal::MTLCompileOptions options) {');
2682
+ lines.push(' NSError *error = nil;');
2683
+ lines.push(' id<MTLLibrary> library = [geaAppleMTLDevice(self) newLibraryWithSource:gea::apple::Foundation::toNSString(source) options:geaAppleMTLCompileOptions(options) error:&error];');
2684
+ lines.push(' if (!library && error) NSLog(@"Metal library compilation failed: %@", error);');
2685
+ lines.push(' return gea::apple::Metal::MTLLibrary(gea::apple::objc::retain((__bridge void *)library));');
2686
+ lines.push('}', '');
2687
+ lines.push('gea::apple::Metal::MTLBuffer gea::apple::Metal::MTLDevice_newBufferWithBytesLengthOptions(gea::apple::Metal::MTLDevice self, std::vector<double> bytes, double length, double options) {');
2688
+ lines.push(' std::vector<float> storage = geaAppleFloatBytes(bytes);');
2689
+ lines.push(' const NSUInteger byteLength = static_cast<NSUInteger>(length);');
2690
+ lines.push(' id<MTLBuffer> buffer = [geaAppleMTLDevice(self) newBufferWithBytes:storage.data() length:byteLength options:static_cast<MTLResourceOptions>(options)];');
2691
+ lines.push(' return gea::apple::Metal::MTLBuffer(gea::apple::objc::retain((__bridge void *)buffer));');
2692
+ lines.push('}', '');
2693
+ lines.push('gea::apple::Metal::MTLRenderPipelineState gea::apple::Metal::MTLDevice_newRenderPipelineStateWithDescriptorError(gea::apple::Metal::MTLDevice self, gea::apple::Metal::MTLRenderPipelineDescriptor descriptor) {');
2694
+ lines.push(' NSError *error = nil;');
2695
+ lines.push(' id<MTLRenderPipelineState> state = [geaAppleMTLDevice(self) newRenderPipelineStateWithDescriptor:geaAppleMTLRenderPipelineDescriptor(descriptor) error:&error];');
2696
+ lines.push(' if (!state && error) NSLog(@"Metal pipeline creation failed: %@", error);');
2697
+ lines.push(' return gea::apple::Metal::MTLRenderPipelineState(gea::apple::objc::retain((__bridge void *)state));');
2698
+ lines.push('}', '');
2699
+ lines.push('gea::apple::Metal::MTLDepthStencilState gea::apple::Metal::MTLDevice_newDepthStencilStateWithDescriptor(gea::apple::Metal::MTLDevice self, gea::apple::Metal::MTLDepthStencilDescriptor descriptor) {');
2700
+ lines.push(' id<MTLDepthStencilState> state = [geaAppleMTLDevice(self) newDepthStencilStateWithDescriptor:geaAppleMTLDepthStencilDescriptor(descriptor)];');
2701
+ lines.push(' return gea::apple::Metal::MTLDepthStencilState(gea::apple::objc::retain((__bridge void *)state));');
2702
+ lines.push('}', '');
2703
+ lines.push('gea::apple::Metal::MTLCommandBuffer gea::apple::Metal::MTLCommandQueue_commandBuffer(gea::apple::Metal::MTLCommandQueue self) {');
2704
+ lines.push(' return gea::apple::Metal::MTLCommandBuffer(gea::apple::objc::retain((__bridge void *)[geaAppleMTLCommandQueue(self) commandBuffer]));');
2705
+ lines.push('}', '');
2706
+ lines.push('gea::apple::Metal::MTLRenderCommandEncoder gea::apple::Metal::MTLCommandBuffer_renderCommandEncoderWithDescriptor(gea::apple::Metal::MTLCommandBuffer self, gea::apple::Metal::MTLRenderPassDescriptor descriptor) {');
2707
+ lines.push(' return gea::apple::Metal::MTLRenderCommandEncoder(gea::apple::objc::retain((__bridge void *)[geaAppleMTLCommandBuffer(self) renderCommandEncoderWithDescriptor:geaAppleMTLRenderPassDescriptor(descriptor)]));');
2708
+ lines.push('}', '');
2709
+ lines.push('void gea::apple::Metal::MTLCommandBuffer_presentDrawable(gea::apple::Metal::MTLCommandBuffer self, gea::apple::Metal::MTLDrawable drawable) {');
2710
+ lines.push(' [geaAppleMTLCommandBuffer(self) presentDrawable:geaAppleMTLDrawable(drawable)];');
2711
+ lines.push('}', '');
2712
+ lines.push('void gea::apple::Metal::MTLCommandBuffer_commit(gea::apple::Metal::MTLCommandBuffer self) {');
2713
+ lines.push(' [geaAppleMTLCommandBuffer(self) commit];');
2714
+ lines.push('}', '');
2715
+ lines.push('gea::apple::Metal::MTLFunction gea::apple::Metal::MTLLibrary_newFunctionWithName(gea::apple::Metal::MTLLibrary self, std::string name) {');
2716
+ lines.push(' return gea::apple::Metal::MTLFunction(gea::apple::objc::retain((__bridge void *)[geaAppleMTLLibrary(self) newFunctionWithName:gea::apple::Foundation::toNSString(name)]));');
2717
+ lines.push('}', '');
2718
+ lines.push('double gea::apple::Metal::MTLRenderPipelineDescriptor_init() {');
2719
+ lines.push(' return gea::apple::objc::retain((__bridge void *)[[::MTLRenderPipelineDescriptor alloc] init]);');
2720
+ lines.push('}', '');
2721
+ lines.push('gea::apple::Metal::MTLFunction gea::apple::Metal::MTLRenderPipelineDescriptor_get_vertexFunction(gea::apple::Metal::MTLRenderPipelineDescriptor self) {');
2722
+ lines.push(' return gea::apple::Metal::MTLFunction(gea::apple::objc::retain((__bridge void *)geaAppleMTLRenderPipelineDescriptor(self).vertexFunction));');
2723
+ lines.push('}', '');
2724
+ lines.push('void gea::apple::Metal::MTLRenderPipelineDescriptor_set_vertexFunction(gea::apple::Metal::MTLRenderPipelineDescriptor self, gea::apple::Metal::MTLFunction value) {');
2725
+ lines.push(' geaAppleMTLRenderPipelineDescriptor(self).vertexFunction = geaAppleMTLFunction(value);');
2726
+ lines.push('}', '');
2727
+ lines.push('gea::apple::Metal::MTLFunction gea::apple::Metal::MTLRenderPipelineDescriptor_get_fragmentFunction(gea::apple::Metal::MTLRenderPipelineDescriptor self) {');
2728
+ lines.push(' return gea::apple::Metal::MTLFunction(gea::apple::objc::retain((__bridge void *)geaAppleMTLRenderPipelineDescriptor(self).fragmentFunction));');
2729
+ lines.push('}', '');
2730
+ lines.push('void gea::apple::Metal::MTLRenderPipelineDescriptor_set_fragmentFunction(gea::apple::Metal::MTLRenderPipelineDescriptor self, gea::apple::Metal::MTLFunction value) {');
2731
+ lines.push(' geaAppleMTLRenderPipelineDescriptor(self).fragmentFunction = geaAppleMTLFunction(value);');
2732
+ lines.push('}', '');
2733
+ lines.push('gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptorArray gea::apple::Metal::MTLRenderPipelineDescriptor_get_colorAttachments(gea::apple::Metal::MTLRenderPipelineDescriptor self) {');
2734
+ lines.push(' return gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptorArray(gea::apple::objc::retain((__bridge void *)geaAppleMTLRenderPipelineDescriptor(self).colorAttachments));');
2735
+ lines.push('}', '');
2736
+ lines.push('double gea::apple::Metal::MTLRenderPipelineDescriptor_get_depthAttachmentPixelFormat(gea::apple::Metal::MTLRenderPipelineDescriptor self) {');
2737
+ lines.push(' return geaAppleMTLRenderPipelineDescriptor(self).depthAttachmentPixelFormat;');
2738
+ lines.push('}', '');
2739
+ lines.push('void gea::apple::Metal::MTLRenderPipelineDescriptor_set_depthAttachmentPixelFormat(gea::apple::Metal::MTLRenderPipelineDescriptor self, double value) {');
2740
+ lines.push(' geaAppleMTLRenderPipelineDescriptor(self).depthAttachmentPixelFormat = static_cast<MTLPixelFormat>(value);');
2741
+ lines.push('}', '');
2742
+ lines.push('gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptor gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptorArray_objectAtIndexedSubscript(gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptorArray self, double index) {');
2743
+ lines.push(' return gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptor(gea::apple::objc::retain((__bridge void *)[geaAppleMTLColorAttachments(self) objectAtIndexedSubscript:static_cast<NSUInteger>(index)]));');
2744
+ lines.push('}', '');
2745
+ lines.push('double gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptor_get_pixelFormat(gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptor self) {');
2746
+ lines.push(' return geaAppleMTLColorAttachment(self).pixelFormat;');
2747
+ lines.push('}', '');
2748
+ lines.push('void gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptor_set_pixelFormat(gea::apple::Metal::MTLRenderPipelineColorAttachmentDescriptor self, double value) {');
2749
+ lines.push(' geaAppleMTLColorAttachment(self).pixelFormat = static_cast<MTLPixelFormat>(value);');
2750
+ lines.push('}', '');
2751
+ lines.push('double gea::apple::Metal::MTLDepthStencilDescriptor_init() {');
2752
+ lines.push(' return gea::apple::objc::retain((__bridge void *)[[::MTLDepthStencilDescriptor alloc] init]);');
2753
+ lines.push('}', '');
2754
+ lines.push('double gea::apple::Metal::MTLDepthStencilDescriptor_get_depthCompareFunction(gea::apple::Metal::MTLDepthStencilDescriptor self) {');
2755
+ lines.push(' return geaAppleMTLDepthStencilDescriptor(self).depthCompareFunction;');
2756
+ lines.push('}', '');
2757
+ lines.push('void gea::apple::Metal::MTLDepthStencilDescriptor_set_depthCompareFunction(gea::apple::Metal::MTLDepthStencilDescriptor self, double value) {');
2758
+ lines.push(' geaAppleMTLDepthStencilDescriptor(self).depthCompareFunction = static_cast<MTLCompareFunction>(value);');
2759
+ lines.push('}', '');
2760
+ lines.push('bool gea::apple::Metal::MTLDepthStencilDescriptor_get_depthWriteEnabled(gea::apple::Metal::MTLDepthStencilDescriptor self) {');
2761
+ lines.push(' return geaAppleMTLDepthStencilDescriptor(self).depthWriteEnabled;');
2762
+ lines.push('}', '');
2763
+ lines.push('void gea::apple::Metal::MTLDepthStencilDescriptor_set_depthWriteEnabled(gea::apple::Metal::MTLDepthStencilDescriptor self, bool value) {');
2764
+ lines.push(' geaAppleMTLDepthStencilDescriptor(self).depthWriteEnabled = value;');
2765
+ lines.push('}', '');
2766
+ lines.push('void gea::apple::Metal::MTLRenderCommandEncoder_setRenderPipelineState(gea::apple::Metal::MTLRenderCommandEncoder self, gea::apple::Metal::MTLRenderPipelineState pipelineState) {');
2767
+ lines.push(' [geaAppleMTLRenderCommandEncoder(self) setRenderPipelineState:geaAppleMTLRenderPipelineState(pipelineState)];');
2768
+ lines.push('}', '');
2769
+ lines.push('void gea::apple::Metal::MTLRenderCommandEncoder_setDepthStencilState(gea::apple::Metal::MTLRenderCommandEncoder self, gea::apple::Metal::MTLDepthStencilState depthStencilState) {');
2770
+ lines.push(' [geaAppleMTLRenderCommandEncoder(self) setDepthStencilState:geaAppleMTLDepthStencilState(depthStencilState)];');
2771
+ lines.push('}', '');
2772
+ lines.push('void gea::apple::Metal::MTLRenderCommandEncoder_setVertexBufferOffsetAtIndex(gea::apple::Metal::MTLRenderCommandEncoder self, gea::apple::Metal::MTLBuffer buffer, double offset, double index) {');
2773
+ lines.push(' [geaAppleMTLRenderCommandEncoder(self) setVertexBuffer:geaAppleMTLBuffer(buffer) offset:static_cast<NSUInteger>(offset) atIndex:static_cast<NSUInteger>(index)];');
2774
+ lines.push('}', '');
2775
+ lines.push('void gea::apple::Metal::MTLRenderCommandEncoder_setVertexBytesLengthAtIndex(gea::apple::Metal::MTLRenderCommandEncoder self, std::vector<double> bytes, double length, double index) {');
2776
+ lines.push(' std::vector<float> storage = geaAppleFloatBytes(bytes);');
2777
+ lines.push(' [geaAppleMTLRenderCommandEncoder(self) setVertexBytes:storage.data() length:static_cast<NSUInteger>(length) atIndex:static_cast<NSUInteger>(index)];');
2778
+ lines.push('}', '');
2779
+ lines.push('void gea::apple::Metal::MTLRenderCommandEncoder_drawPrimitivesVertexStartVertexCount(gea::apple::Metal::MTLRenderCommandEncoder self, double primitiveType, double vertexStart, double vertexCount) {');
2780
+ lines.push(' [geaAppleMTLRenderCommandEncoder(self) drawPrimitives:static_cast<MTLPrimitiveType>(primitiveType) vertexStart:static_cast<NSUInteger>(vertexStart) vertexCount:static_cast<NSUInteger>(vertexCount)];');
2781
+ lines.push('}', '');
2782
+ lines.push('void gea::apple::Metal::MTLRenderCommandEncoder_endEncoding(gea::apple::Metal::MTLRenderCommandEncoder self) {');
2783
+ lines.push(' [geaAppleMTLRenderCommandEncoder(self) endEncoding];');
2784
+ lines.push('}');
2785
+ lines.push('#endif', '');
2786
+ }
2787
+ function appendMetalKitBridges(lines, metadata) {
2788
+ if (!metadata.frameworks.some((framework) => framework.name === 'MetalKit'))
2789
+ return;
2790
+ lines.push('#if __has_include(<MetalKit/MetalKit.h>)');
2791
+ lines.push('@interface GeaAppleMTKViewDelegate : NSObject <MTKViewDelegate>');
2792
+ lines.push('- (instancetype)initWithDrawCallback:(std::function<void()>)drawCallback;');
2793
+ lines.push('@end', '');
2794
+ lines.push('@implementation GeaAppleMTKViewDelegate {');
2795
+ lines.push(' std::function<void()> _drawCallback;');
2796
+ lines.push('}');
2797
+ lines.push('- (instancetype)initWithDrawCallback:(std::function<void()>)drawCallback {');
2798
+ lines.push(' self = [super init];');
2799
+ lines.push(' if (self) _drawCallback = std::move(drawCallback);');
2800
+ lines.push(' return self;');
2801
+ lines.push('}');
2802
+ lines.push('- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {');
2803
+ lines.push(' (void)view;');
2804
+ lines.push(' (void)size;');
2805
+ lines.push('}');
2806
+ lines.push('- (void)drawInMTKView:(MTKView *)view {');
2807
+ lines.push(' (void)view;');
2808
+ lines.push(' if (_drawCallback) _drawCallback();');
2809
+ lines.push('}');
2810
+ lines.push('@end', '');
2811
+ lines.push('double gea::apple::MetalKit::MTKView_init() {');
2812
+ lines.push(' return gea::apple::objc::retain((__bridge void *)[[::MTKView alloc] init]);');
2813
+ lines.push('}', '');
2814
+ lines.push('gea::apple::Metal::MTLDevice gea::apple::MetalKit::MTKView_get_device(gea::apple::MetalKit::MTKView self) {');
2815
+ lines.push(' ::MTKView *view = (__bridge ::MTKView *)gea::apple::objc::object(self.handle);');
2816
+ lines.push(' return gea::apple::Metal::MTLDevice(gea::apple::objc::retain((__bridge void *)view.device));');
2817
+ lines.push('}', '');
2818
+ lines.push('void gea::apple::MetalKit::MTKView_set_device(gea::apple::MetalKit::MTKView self, gea::apple::Metal::MTLDevice value) {');
2819
+ lines.push(' ::MTKView *view = (__bridge ::MTKView *)gea::apple::objc::object(self.handle);');
2820
+ lines.push(' view.device = (__bridge id<MTLDevice>)gea::apple::objc::object(value.handle);');
2821
+ lines.push('}', '');
2822
+ lines.push('gea::apple::MetalKit::MTKViewDelegate gea::apple::MetalKit::MTKView_get_delegate(gea::apple::MetalKit::MTKView self) {');
2823
+ lines.push(' ::MTKView *view = (__bridge ::MTKView *)gea::apple::objc::object(self.handle);');
2824
+ lines.push(' return gea::apple::MetalKit::MTKViewDelegate(gea::apple::objc::retain((__bridge void *)view.delegate));');
2825
+ lines.push('}', '');
2826
+ lines.push('void gea::apple::MetalKit::MTKView_set_delegate(gea::apple::MetalKit::MTKView self, gea::apple::MetalKit::MTKViewDelegate value) {');
2827
+ lines.push(' ::MTKView *view = (__bridge ::MTKView *)gea::apple::objc::object(self.handle);');
2828
+ lines.push(' view.delegate = (__bridge id<MTKViewDelegate>)gea::apple::objc::object(value.handle);');
2829
+ lines.push('}', '');
2830
+ lines.push('double gea::apple::MetalKit::MTKView_get_colorPixelFormat(gea::apple::MetalKit::MTKView self) {');
2831
+ lines.push(' return ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).colorPixelFormat;');
2832
+ lines.push('}', '');
2833
+ lines.push('void gea::apple::MetalKit::MTKView_set_colorPixelFormat(gea::apple::MetalKit::MTKView self, double value) {');
2834
+ lines.push(' ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).colorPixelFormat = static_cast<MTLPixelFormat>(value);');
2835
+ lines.push('}', '');
2836
+ lines.push('double gea::apple::MetalKit::MTKView_get_depthStencilPixelFormat(gea::apple::MetalKit::MTKView self) {');
2837
+ lines.push(' return ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).depthStencilPixelFormat;');
2838
+ lines.push('}', '');
2839
+ lines.push('void gea::apple::MetalKit::MTKView_set_depthStencilPixelFormat(gea::apple::MetalKit::MTKView self, double value) {');
2840
+ lines.push(' ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).depthStencilPixelFormat = static_cast<MTLPixelFormat>(value);');
2841
+ lines.push('}', '');
2842
+ lines.push('gea::apple::Metal::MTLClearColor gea::apple::MetalKit::MTKView_get_clearColor(gea::apple::MetalKit::MTKView self) {');
2843
+ lines.push(' ::MTLClearColor color = ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).clearColor;');
2844
+ lines.push(' return gea::apple::Metal::MTLClearColor{color.red, color.green, color.blue, color.alpha};');
2845
+ lines.push('}', '');
2846
+ lines.push('void gea::apple::MetalKit::MTKView_set_clearColor(gea::apple::MetalKit::MTKView self, gea::apple::Metal::MTLClearColor value) {');
2847
+ lines.push(' ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).clearColor = ::MTLClearColorMake(value.red, value.green, value.blue, value.alpha);');
2848
+ lines.push('}', '');
2849
+ lines.push('double gea::apple::MetalKit::MTKView_get_preferredFramesPerSecond(gea::apple::MetalKit::MTKView self) {');
2850
+ lines.push(' return ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).preferredFramesPerSecond;');
2851
+ lines.push('}', '');
2852
+ lines.push('void gea::apple::MetalKit::MTKView_set_preferredFramesPerSecond(gea::apple::MetalKit::MTKView self, double value) {');
2853
+ lines.push(' ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).preferredFramesPerSecond = static_cast<NSInteger>(value);');
2854
+ lines.push('}', '');
2855
+ lines.push('bool gea::apple::MetalKit::MTKView_get_enableSetNeedsDisplay(gea::apple::MetalKit::MTKView self) {');
2856
+ lines.push(' return ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).enableSetNeedsDisplay;');
2857
+ lines.push('}', '');
2858
+ lines.push('void gea::apple::MetalKit::MTKView_set_enableSetNeedsDisplay(gea::apple::MetalKit::MTKView self, bool value) {');
2859
+ lines.push(' ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).enableSetNeedsDisplay = value;');
2860
+ lines.push('}', '');
2861
+ lines.push('bool gea::apple::MetalKit::MTKView_get_paused(gea::apple::MetalKit::MTKView self) {');
2862
+ lines.push(' return ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).paused;');
2863
+ lines.push('}', '');
2864
+ lines.push('void gea::apple::MetalKit::MTKView_set_paused(gea::apple::MetalKit::MTKView self, bool value) {');
2865
+ lines.push(' ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).paused = value;');
2866
+ lines.push('}', '');
2867
+ lines.push('gea::apple::CoreGraphics::CGSize gea::apple::MetalKit::MTKView_get_drawableSize(gea::apple::MetalKit::MTKView self) {');
2868
+ lines.push(' return ((__bridge ::MTKView *)gea::apple::objc::object(self.handle)).drawableSize;');
2869
+ lines.push('}', '');
2870
+ lines.push('gea::apple::Metal::MTLRenderPassDescriptor gea::apple::MetalKit::MTKView_get_currentRenderPassDescriptor(gea::apple::MetalKit::MTKView self) {');
2871
+ lines.push(' ::MTKView *view = (__bridge ::MTKView *)gea::apple::objc::object(self.handle);');
2872
+ lines.push(' return gea::apple::Metal::MTLRenderPassDescriptor(gea::apple::objc::retain((__bridge void *)view.currentRenderPassDescriptor));');
2873
+ lines.push('}', '');
2874
+ lines.push('gea::apple::Metal::MTLDrawable gea::apple::MetalKit::MTKView_get_currentDrawable(gea::apple::MetalKit::MTKView self) {');
2875
+ lines.push(' ::MTKView *view = (__bridge ::MTKView *)gea::apple::objc::object(self.handle);');
2876
+ lines.push(' return gea::apple::Metal::MTLDrawable(gea::apple::objc::retain((__bridge void *)view.currentDrawable));');
2877
+ lines.push('}', '');
2878
+ lines.push('gea::apple::MetalKit::MTKViewDelegate gea::apple::MetalKit::MTKViewDelegate_create(std::function<void()> drawInMTKView) {');
2879
+ lines.push(' GeaAppleMTKViewDelegate *delegate = [[GeaAppleMTKViewDelegate alloc] initWithDrawCallback:std::move(drawInMTKView)];');
2880
+ lines.push(' return gea::apple::MetalKit::MTKViewDelegate(gea::apple::objc::retain((__bridge void *)delegate));');
2881
+ lines.push('}');
2882
+ lines.push('#endif', '');
2883
+ }
2884
+ function appendUIKitCallbackBridges(lines, metadata) {
2885
+ if (!metadata.frameworks.some((framework) => framework.name === 'UIKit'))
2886
+ return;
2887
+ lines.push('#if __has_include(<UIKit/UIKit.h>)');
2888
+ lines.push('@implementation GeaAppleObjCTarget');
2889
+ lines.push('- (instancetype)initWithCallback:(std::function<void()>)callback {');
2890
+ lines.push(' self = [super init];');
2891
+ lines.push(' if (self) _callback = std::move(callback);');
2892
+ lines.push(' return self;');
2893
+ lines.push('}');
2894
+ lines.push('- (void)invoke:(id)sender {');
2895
+ lines.push(' (void)sender;');
2896
+ lines.push(' if (_callback) _callback();');
2897
+ lines.push('}');
2898
+ lines.push('@end');
2899
+ lines.push('#endif', '');
2900
+ }
2901
+ function appendUIKitCallbackBridgeDeclarations(lines, metadata) {
2902
+ if (!metadata.frameworks.some((framework) => framework.name === 'UIKit'))
2903
+ return;
2904
+ lines.push('#if __has_include(<UIKit/UIKit.h>)');
2905
+ lines.push('@interface GeaAppleObjCTarget : NSObject {');
2906
+ lines.push(' std::function<void()> _callback;');
2907
+ lines.push('}');
2908
+ lines.push('- (instancetype)initWithCallback:(std::function<void()>)callback;');
2909
+ lines.push('- (void)invoke:(id)sender;');
2910
+ lines.push('@end');
2911
+ lines.push('#endif', '');
2912
+ }
2913
+ function defaultInitializer(type) {
2914
+ if (type.kind === 'primitive') {
2915
+ if (type.name === 'number')
2916
+ return ' = 0';
2917
+ if (type.name === 'boolean')
2918
+ return ' = false';
2919
+ if (type.name === 'string')
2920
+ return '';
2921
+ }
2922
+ return '';
2923
+ }
2924
+ function functionMetadata(framework, fn) {
2925
+ return {
2926
+ framework,
2927
+ name: fn.name,
2928
+ thunk: frameworkFunctionThunk(framework, fn.name),
2929
+ returns: fn.returns,
2930
+ parameters: fn.parameters ?? [],
2931
+ };
2932
+ }
2933
+ function methodMetadata(framework, cls, method) {
2934
+ const thunk = specialMethodThunk(framework, cls, method.name) ?? methodThunk(framework, cls, method.name);
2935
+ return {
2936
+ name: method.name,
2937
+ selector: method.selector,
2938
+ thunk,
2939
+ returns: method.returns,
2940
+ parameters: method.parameters ?? [],
2941
+ ...(method.static ? { static: true } : {}),
2942
+ };
2943
+ }
2944
+ function specialMethodThunk(framework, cls, method) {
2945
+ if (framework === 'AVFoundation' && cls === 'AVCaptureDeviceInput' && method === 'deviceInputWithDevice') {
2946
+ return bridgeFunctionName(framework, `${cls}_${method}`);
2947
+ }
2948
+ if (framework === 'AVFoundation' && cls === 'AVCaptureDevice' && method === 'lockForConfiguration') {
2949
+ return bridgeFunctionName(framework, `${cls}_${method}`);
2950
+ }
2951
+ return undefined;
2952
+ }
2953
+ function propertyMetadata(framework, cls, property) {
2954
+ return {
2955
+ name: property.name,
2956
+ getter: propertyThunk(framework, cls, property.name, 'get'),
2957
+ ...(property.readonly ? {} : { setter: propertyThunk(framework, cls, property.name, 'set') }),
2958
+ type: property.type,
2959
+ };
2960
+ }
2961
+ function parametersSignature(parameters, localFramework) {
2962
+ return parameters.map((parameter) => `${parameter.name}: ${typeScriptType(parameter.type, localFramework)}`).join(', ');
2963
+ }
2964
+ function typeScriptType(type, localFramework) {
2965
+ const base = (() => {
2966
+ if (type.kind === 'function') {
2967
+ return `(${parametersSignature(type.parameters ?? [], localFramework)}) => ${typeScriptType(type.returns, localFramework)}`;
2968
+ }
2969
+ if (type.kind === 'array') {
2970
+ return `${typeScriptType(type.element, localFramework)}[]`;
2971
+ }
2972
+ if (type.kind === 'primitive') {
2973
+ if (type.name === 'void')
2974
+ return 'void';
2975
+ if (type.name === 'boolean')
2976
+ return 'boolean';
2977
+ if (type.name === 'string')
2978
+ return 'string';
2979
+ if (type.name === 'selector')
2980
+ return 'Selector';
2981
+ return 'number';
2982
+ }
2983
+ const [framework, name] = splitQualifiedName(type.name, localFramework);
2984
+ return framework === localFramework ? name : name;
2985
+ })();
2986
+ return type.nullable && base !== 'void' ? `${base} | null` : base;
2987
+ }
2988
+ function cppValueType(type, localFramework, options = {}) {
2989
+ if (type.kind === 'function') {
2990
+ const returns = cppValueType(type.returns, localFramework, options);
2991
+ const params = (type.parameters ?? []).map((parameter) => cppValueType(parameter.type, localFramework, options)).join(', ');
2992
+ return `std::function<${returns}(${params})>`;
2993
+ }
2994
+ if (type.kind === 'array') {
2995
+ return `std::vector<${cppValueType(type.element, localFramework, options)}>`;
2996
+ }
2997
+ if (type.kind === 'primitive') {
2998
+ if (type.name === 'void')
2999
+ return 'void';
3000
+ if (type.name === 'boolean')
3001
+ return 'bool';
3002
+ if (type.name === 'number')
3003
+ return 'double';
3004
+ if (type.name === 'string')
3005
+ return 'std::string';
3006
+ if (type.name === 'selector')
3007
+ return 'SEL';
3008
+ return type.name;
3009
+ }
3010
+ const [framework, name] = splitQualifiedName(type.name, localFramework);
3011
+ if (options.preferLocalNames && framework === localFramework)
3012
+ return name;
3013
+ return `::gea::apple::${framework}::${name}`;
3014
+ }
3015
+ function frameworkUsesPrimitive(framework, primitiveName) {
3016
+ const matches = (type) => {
3017
+ if (type.kind === 'function') {
3018
+ return matches(type.returns) || (type.parameters ?? []).some((parameter) => matches(parameter.type));
3019
+ }
3020
+ if (type.kind === 'array')
3021
+ return matches(type.element);
3022
+ return type.kind === 'primitive' && type.name === primitiveName;
3023
+ };
3024
+ if ((framework.constants ?? []).some((constant) => matches(constant.type)))
3025
+ return true;
3026
+ if ((framework.functions ?? []).some((fn) => matches(fn.returns) || (fn.parameters ?? []).some((parameter) => matches(parameter.type))))
3027
+ return true;
3028
+ if ((framework.structs ?? []).some((struct) => struct.fields.some((field) => matches(field.type))))
3029
+ return true;
3030
+ return (framework.classes ?? []).some((cls) => {
3031
+ const constructors = (cls.constructors ?? []).some((method) => matches(method.returns) || (method.parameters ?? []).some((parameter) => matches(parameter.type)));
3032
+ const methods = (cls.methods ?? []).some((method) => matches(method.returns) || (method.parameters ?? []).some((parameter) => matches(parameter.type)));
3033
+ const properties = (cls.properties ?? []).some((property) => matches(property.type));
3034
+ return constructors || methods || properties;
3035
+ });
3036
+ }
3037
+ function splitQualifiedName(name, fallbackFramework) {
3038
+ const dot = name.indexOf('.');
3039
+ if (dot < 0)
3040
+ return [fallbackFramework, name];
3041
+ return [name.slice(0, dot), name.slice(dot + 1)];
3042
+ }
3043
+ function shortTypeName(name) {
3044
+ return splitQualifiedName(name, '')[1];
3045
+ }
3046
+ function qualifiedName(framework, name) {
3047
+ return `${framework}.${name}`;
3048
+ }
3049
+ function cppTypeName(framework, name) {
3050
+ return `gea::apple::${framework}::${name}`;
3051
+ }
3052
+ function constructorThunk(framework, cls) {
3053
+ return bridgeFunctionName(framework, `${cls}_init`);
3054
+ }
3055
+ function frameworkFunctionThunk(framework, fn) {
3056
+ return bridgeFunctionName(framework, fn);
3057
+ }
3058
+ function methodThunk(framework, cls, method) {
3059
+ return bridgeFunctionName(framework, `${cls}_${method}`);
3060
+ }
3061
+ function propertyThunk(framework, cls, property, kind) {
3062
+ return bridgeFunctionName(framework, `${cls}_${kind}_${property}`);
3063
+ }
3064
+ function bridgeFunctionName(framework, name) {
3065
+ return `gea::apple::${framework}::${name}`;
3066
+ }
3067
+ function cppFunctionTarget(name) {
3068
+ const qualifiedName = name.replace(/^::/, '');
3069
+ const separator = qualifiedName.lastIndexOf('::');
3070
+ if (separator < 0)
3071
+ return { namespaceName: null, bareName: qualifiedName };
3072
+ return {
3073
+ namespaceName: qualifiedName.slice(0, separator),
3074
+ bareName: qualifiedName.slice(separator + 2),
3075
+ };
3076
+ }