@octane-xplat/macos-renderer 0.11.0 → 0.12.0

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.
package/src/appkit.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  // Ambient host globals injected by @nativescript/macos-node-api and the
2
2
  // embedding Node process. The prerelease ships no generated AppKit metadata
3
- // types, so bridge classes expose members loosely while the type names stay
4
- // usable in our own signatures.
3
+ // types, so the declarations below cover the native surface the renderer
4
+ // calls for event and control wiring (target/action, gesture recognizers,
5
+ // tracking areas, notification observers, menus, pickers, sheets). Members
6
+ // outside that surface still resolve to `any` through the index signatures.
5
7
 
6
8
  type NSClass<T> = {
7
9
  new (...args: any[]): T
@@ -9,13 +11,32 @@ type NSClass<T> = {
9
11
  [key: string]: any
10
12
  }
11
13
 
12
- // Objective-C classes. Instances expose bridged members as `any`; the type
13
- // name is real so parameters and node structs can reference them.
14
+ // Core Graphics geometry, bridged as plain objects.
15
+ interface NSPoint {
16
+ x: number
17
+ y: number
18
+ }
19
+
20
+ interface NSSize {
21
+ width: number
22
+ height: number
23
+ }
24
+
25
+ interface NSRect {
26
+ origin: NSPoint
27
+ size: NSSize
28
+ }
29
+
30
+ // Objective-C classes. Instances expose bridged members beyond the declared
31
+ // surface as `any`; the type name is real so parameters and node structs can
32
+ // reference them.
14
33
  declare class NSObject {
15
34
  [key: string]: any
16
35
  static alloc(): any
17
36
  static new(): any
18
37
  static extend(methods: object, options?: object): any
38
+ init(): this
39
+ isEqual?(other: any): boolean
19
40
  }
20
41
 
21
42
  interface NSAttributedString extends NSObject {}
@@ -31,16 +52,52 @@ interface NSURLRequest extends NSObject {}
31
52
  declare const NSURLRequest: NSClass<NSURLRequest>
32
53
 
33
54
  // WebKit is dlopen'd at runtime by the webview leaf.
34
- interface WKWebView extends NSView {}
55
+ interface WKWebView extends NSView {
56
+ navigationDelegate: any
57
+ evaluateJavaScriptCompletionHandler(script: string, handler: any): void
58
+ }
59
+
35
60
  declare const WKWebView: NSClass<WKWebView>
36
61
 
37
62
  interface WKWebViewConfiguration extends NSObject {}
38
63
  declare const WKWebViewConfiguration: NSClass<WKWebViewConfiguration>
39
64
 
40
- interface NSButton extends NSView {}
41
- declare const NSButton: NSClass<NSButton>
65
+ // NSControl carries the target/action channel shared by buttons, sliders,
66
+ // text fields, and date pickers.
67
+ interface NSControl extends NSView {
68
+ target: any
69
+ action: string | null
70
+ enabled: boolean
71
+ doubleValue: number
72
+ font: any
73
+ textColor: any
74
+ cell: any
75
+ }
76
+
77
+ interface NSButton extends NSControl {
78
+ bezelStyle: number
79
+ state: number
80
+ setButtonType(type: number): void
81
+ }
82
+
83
+ interface NSButtonClass extends NSClass<NSButton> {
84
+ buttonWithTitleTargetAction(title: string, target: any, action: string): NSButton
85
+ }
86
+
87
+ declare const NSButton: NSButtonClass
88
+
89
+ interface NSGestureRecognizer extends NSObject {
90
+ initWithTargetAction(target: any, action: string): this
91
+ readonly view: NSView
92
+ state: number
93
+ enabled: boolean
94
+ }
95
+
96
+ interface NSClickGestureRecognizer extends NSGestureRecognizer {
97
+ numberOfClicksRequired: number
98
+ buttonMask: number
99
+ }
42
100
 
43
- interface NSClickGestureRecognizer extends NSObject {}
44
101
  declare const NSClickGestureRecognizer: NSClass<NSClickGestureRecognizer>
45
102
 
46
103
  interface NSColor extends NSObject {}
@@ -52,17 +109,51 @@ declare const NSColorSpace: NSClass<NSColorSpace>
52
109
  interface NSData extends NSObject {}
53
110
  declare const NSData: NSClass<NSData>
54
111
 
55
- interface NSDate extends NSObject {}
56
- declare const NSDate: NSClass<NSDate>
112
+ interface NSDate extends NSObject {
113
+ readonly timeIntervalSince1970: number
114
+ }
115
+
116
+ interface NSDateClass extends NSClass<NSDate> {
117
+ dateWithTimeIntervalSince1970(seconds: number): NSDate
118
+ }
119
+
120
+ declare const NSDate: NSDateClass
121
+
122
+ interface NSDatePicker extends NSControl {
123
+ datePickerElements: number
124
+ datePickerStyle: number
125
+ dateValue: NSDate | null
126
+ minDate: NSDate | null
127
+ maxDate: NSDate | null
128
+ }
57
129
 
58
- interface NSDatePicker extends NSView {}
59
130
  declare const NSDatePicker: NSClass<NSDatePicker>
60
131
 
61
132
  interface NSEdgeInsets extends NSObject {}
62
133
  declare const NSEdgeInsets: NSClass<NSEdgeInsets>
63
134
 
64
- interface NSEvent extends NSObject {}
65
- declare const NSEvent: NSClass<NSEvent>
135
+ interface NSEvent extends NSObject {
136
+ readonly type: number
137
+ readonly keyCode: number
138
+ readonly modifierFlags: number
139
+ readonly window: NSWindow | null
140
+ readonly locationInWindow: NSPoint
141
+ readonly trackingArea: NSTrackingArea
142
+ }
143
+
144
+ interface NSEventClass extends NSClass<NSEvent> {
145
+ addLocalMonitorForEventsMatchingMaskHandler(
146
+ mask: number,
147
+ handler: (event: NSEvent) => NSEvent | null,
148
+ ): any
149
+ addGlobalMonitorForEventsMatchingMaskHandler(
150
+ mask: number,
151
+ handler: (event: NSEvent) => NSEvent | null,
152
+ ): any
153
+ removeMonitor(monitor: any): void
154
+ }
155
+
156
+ declare const NSEvent: NSEventClass
66
157
 
67
158
  interface NSFont extends NSObject {}
68
159
  declare const NSFont: NSClass<NSFont>
@@ -76,63 +167,241 @@ declare const NSFontManager: NSClass<NSFontManager>
76
167
  interface NSImage extends NSObject {}
77
168
  declare const NSImage: NSClass<NSImage>
78
169
 
79
- interface NSImageView extends NSView {}
170
+ interface NSImageView extends NSControl {
171
+ image: NSImage | null
172
+ imageScaling: number
173
+ }
174
+
80
175
  declare const NSImageView: NSClass<NSImageView>
81
176
 
82
- interface NSMenu extends NSObject {}
177
+ interface NSMenu extends NSObject {
178
+ autoenablesItems: boolean
179
+ addItem(item: NSMenuItem): void
180
+ }
181
+
83
182
  declare const NSMenu: NSClass<NSMenu>
84
183
 
85
- interface NSMenuItem extends NSObject {}
86
- declare const NSMenuItem: NSClass<NSMenuItem>
184
+ interface NSMenuItem extends NSObject {
185
+ initWithTitleActionKeyEquivalent(
186
+ title: string,
187
+ action: string | null,
188
+ keyEquivalent: string,
189
+ ): this
190
+ target: any
191
+ action: string | null
192
+ enabled: boolean
193
+ tag?: number
194
+ }
195
+
196
+ interface NSMenuItemClass extends NSClass<NSMenuItem> {
197
+ separatorItem(): NSMenuItem
198
+ }
199
+
200
+ declare const NSMenuItem: NSMenuItemClass
201
+
202
+ interface NSApplication extends NSObject {
203
+ readonly keyWindow: NSWindow | null
204
+ }
205
+
206
+ interface NSApplicationClass extends NSClass<NSApplication> {
207
+ readonly sharedApplication: NSApplication
208
+ }
209
+
210
+ declare const NSApplication: NSApplicationClass
211
+
212
+ interface NSAppearance extends NSObject {}
213
+ interface NSAppearanceClass extends NSClass<NSAppearance> {
214
+ appearanceNamed(name: string): NSAppearance
215
+ }
216
+
217
+ declare const NSAppearance: NSAppearanceClass
87
218
 
88
219
  interface NSMutableParagraphStyle extends NSObject {}
89
220
  declare const NSMutableParagraphStyle: NSClass<NSMutableParagraphStyle>
90
221
 
91
- interface NSNotification extends NSObject {}
222
+ interface NSNotification extends NSObject {
223
+ readonly object: any
224
+ }
225
+
92
226
  declare const NSNotification: NSClass<NSNotification>
93
227
 
94
- interface NSNotificationCenter extends NSObject {}
95
- declare const NSNotificationCenter: NSClass<NSNotificationCenter>
228
+ interface NSNotificationCenter extends NSObject {
229
+ addObserverForNameObjectQueueUsingBlock(
230
+ name: string,
231
+ object: any,
232
+ queue: any,
233
+ block: () => void,
234
+ ): any
235
+ removeObserver(observer: any): void
236
+ }
237
+
238
+ interface NSNotificationCenterClass extends NSClass<NSNotificationCenter> {
239
+ readonly defaultCenter: NSNotificationCenter
240
+ }
241
+
242
+ declare const NSNotificationCenter: NSNotificationCenterClass
96
243
 
97
244
  interface NSNumber extends NSObject {}
98
245
  declare const NSNumber: NSClass<NSNumber>
99
246
 
100
- interface NSPanGestureRecognizer extends NSObject {}
247
+ interface NSPanGestureRecognizer extends NSGestureRecognizer {
248
+ translationInView(view: NSView | null): NSPoint
249
+ velocityInView(view: NSView | null): NSPoint
250
+ }
251
+
101
252
  declare const NSPanGestureRecognizer: NSClass<NSPanGestureRecognizer>
102
253
 
103
- interface NSPopover extends NSObject {}
254
+ interface NSPopover extends NSObject {
255
+ contentViewController: NSViewController
256
+ contentSize: NSSize
257
+ behavior: number
258
+ animates: boolean
259
+ showRelativeToRectOfViewPreferredEdge(rect: NSRect, view: NSView, preferredEdge: number): void
260
+ close(): void
261
+ }
262
+
104
263
  declare const NSPopover: NSClass<NSPopover>
105
264
 
106
- interface NSScrollView extends NSView {}
265
+ interface NSScrollView extends NSView {
266
+ documentView: NSView | null
267
+ contentView: any
268
+ borderType: number
269
+ drawsBackground: boolean
270
+ hasVerticalScroller: boolean
271
+ hasHorizontalScroller: boolean
272
+ reflectScrolledClipView(clipView: any): void
273
+ }
274
+
107
275
  declare const NSScrollView: NSClass<NSScrollView>
108
276
 
109
- interface NSSlider extends NSView {}
277
+ interface NSSlider extends NSControl {
278
+ minValue: number
279
+ maxValue: number
280
+ }
281
+
110
282
  declare const NSSlider: NSClass<NSSlider>
111
283
 
112
284
  interface NSStackView extends NSView {}
113
285
  declare const NSStackView: NSClass<NSStackView>
114
286
 
115
- interface NSTextField extends NSView {}
287
+ interface NSTextField extends NSControl {
288
+ stringValue: string
289
+ placeholderString?: string
290
+ placeholderAttributedString: any
291
+ bezeled: boolean
292
+ drawsBackground: boolean
293
+ editable: boolean
294
+ selectable: boolean
295
+ sendsActionOnEndEditing: boolean
296
+ alignment: number
297
+ }
298
+
116
299
  declare const NSTextField: NSClass<NSTextField>
117
300
 
118
- interface NSTextView extends NSView {}
301
+ interface NSSecureTextField extends NSTextField {}
302
+ declare const NSSecureTextField: NSClass<NSSecureTextField>
303
+
304
+ interface NSTextView extends NSView {
305
+ string: string
306
+ editable: boolean
307
+ selectable: boolean
308
+ drawsBackground: boolean
309
+ delegate: any
310
+ font: any
311
+ textColor: any
312
+ textContainer: any
313
+ textContainerInset: NSSize
314
+ }
315
+
119
316
  declare const NSTextView: NSClass<NSTextView>
120
317
 
121
- interface NSTrackingArea extends NSObject {}
318
+ interface NSTrackingArea extends NSObject {
319
+ initWithRectOptionsOwnerUserInfo(rect: NSRect, options: number, owner: any, userInfo: any): this
320
+ }
321
+
122
322
  declare const NSTrackingArea: NSClass<NSTrackingArea>
123
323
 
124
324
  interface NSURL extends NSObject {}
125
325
  declare const NSURL: NSClass<NSURL>
126
326
 
127
- interface NSView extends NSObject {}
327
+ interface NSView extends NSObject {
328
+ initWithFrame(frame: NSRect): this
329
+ addSubview(child: NSView): void
330
+ removeFromSuperview(): void
331
+ addGestureRecognizer(recognizer: NSGestureRecognizer): void
332
+ removeGestureRecognizer(recognizer: NSGestureRecognizer): void
333
+ addTrackingArea(area: NSTrackingArea): void
334
+ removeTrackingArea(area: NSTrackingArea): void
335
+ hitTest(point: NSPoint): NSView | null
336
+ acceptsFirstResponder(): boolean
337
+ keyDown(event: NSEvent): void
338
+ layout(): void
339
+ layoutSubtreeIfNeeded(): void
340
+ convertRectToView(rect: NSRect, view: NSView | null): NSRect
341
+ isFlipped(): boolean
342
+ frame: NSRect
343
+ bounds: NSRect
344
+ readonly fittingSize: NSSize
345
+ readonly superview: NSView | null
346
+ readonly window: NSWindow | null
347
+ hidden: boolean
348
+ tag?: number
349
+ menu: NSMenu | null
350
+ alphaValue: number
351
+ autoresizingMask?: number
352
+ translatesAutoresizingMaskIntoConstraints: boolean
353
+ wantsLayer: boolean
354
+ postsBoundsChangedNotifications: boolean
355
+ postsFrameChangedNotifications: boolean
356
+ }
357
+
128
358
  declare const NSView: NSClass<NSView>
129
359
 
130
- interface NSViewController extends NSObject {}
360
+ interface NSViewController extends NSObject {
361
+ view: NSView
362
+ preferredContentSize: NSSize
363
+ }
364
+
131
365
  declare const NSViewController: NSClass<NSViewController>
132
366
 
133
- interface NSWindow extends NSObject {}
367
+ interface NSWindow extends NSObject {
368
+ initWithContentRectStyleMaskBackingDefer(
369
+ contentRect: NSRect,
370
+ styleMask: number,
371
+ backing: number,
372
+ defer: boolean,
373
+ ): this
374
+ contentView: NSView
375
+ contentViewController: NSViewController
376
+ frame: NSRect
377
+ firstResponder: any
378
+ delegate: any
379
+ effectiveAppearance: any
380
+ releasedWhenClosed: boolean
381
+ makeFirstResponder(responder: any): boolean
382
+ beginSheetCompletionHandler(sheet: NSWindow, handler: () => void): void
383
+ endSheet(sheet: NSWindow): void
384
+ orderOut(sender: any): void
385
+ center(): void
386
+ makeKeyAndOrderFront(sender: any): void
387
+ }
388
+
134
389
  declare const NSWindow: NSClass<NSWindow>
135
390
 
391
+ // QuartzCore, referenced lazily by the presentation bridge for sheet
392
+ // transition fades.
393
+ interface CABasicAnimation extends NSObject {
394
+ fromValue: any
395
+ toValue: any
396
+ duration: number
397
+ }
398
+
399
+ interface CABasicAnimationClass extends NSClass<CABasicAnimation> {
400
+ animationWithKeyPath(keyPath: string): CABasicAnimation
401
+ }
402
+
403
+ declare const CABasicAnimation: CABasicAnimationClass
404
+
136
405
  // Enum containers. Members resolve to `number`, so bitwise masks compose.
137
406
  declare const NSBackingStoreType: { [key: string]: number }
138
407
  declare const NSBezelStyle: { [key: string]: number }
@@ -145,6 +414,7 @@ declare const NSPopoverBehavior: { [key: string]: number }
145
414
  declare const NSRectEdge: { [key: string]: number }
146
415
  declare const NSStackViewDistribution: { [key: string]: number }
147
416
  declare const NSStackViewGravity: { [key: string]: number }
417
+ declare const NSLineBreakMode: { [key: string]: number }
148
418
  declare const NSTextAlignment: { [key: string]: number }
149
419
  declare const NSTrackingAreaOptions: { [key: string]: number }
150
420
  declare const NSUserInterfaceLayoutOrientation: { [key: string]: number }
@@ -176,9 +446,12 @@ declare function dlopen(path: string, flags: number): unknown
176
446
  declare var __xplatAppKit: {
177
447
  observeHover?: (view: NSView, handlers: any) => void
178
448
  showAnchoredPopup?: (options: any) => void
449
+ showLayer?: (options: any) => any
179
450
  attachContextMenu?: (view: NSView, options: any, onSelect: any) => void
180
451
  attachDatePicker?: (view: NSView, options: any, onChange: any) => void
181
452
  presentSheet?: (view: NSView, options: any) => void
453
+ presentSurface?: (options: any) => any
454
+ setSurfaceAppearance?: (view: NSView, dark: boolean) => void
182
455
  [key: string]: any
183
456
  }
184
457
 
package/src/image.ts CHANGED
@@ -21,3 +21,95 @@ export function loadImage(source: unknown): NSImage | null {
21
21
 
22
22
  return null
23
23
  }
24
+
25
+ /** Per-view load state. The generation invalidates in-flight decodes when the
26
+ * source changes or `disposeImage` runs — the same guard the webview leaf
27
+ * applies to async measurements. */
28
+ interface ImageRequest {
29
+ source: string
30
+ generation: number
31
+ }
32
+
33
+ const requests = new WeakMap<object, ImageRequest>()
34
+
35
+ /** Decoded images shared across views; bounded so galleries cannot retain
36
+ * every source they have ever shown. Failures are not cached — a file that
37
+ * appears later or a retry must still decode. */
38
+ const cache = new Map<string, NSImage>()
39
+ const pending = new Map<string, ((image: NSImage | null) => void)[]>()
40
+ const IMAGE_CACHE_LIMIT = 64
41
+
42
+ function decodeImage(source: string) {
43
+ const callbacks = pending.get(source) ?? []
44
+ pending.delete(source)
45
+
46
+ let image: NSImage | null = null
47
+ try {
48
+ image = loadImage(source)
49
+ } catch (error) {
50
+ console.error('[macos-image] decode failed', error)
51
+ }
52
+
53
+ if (image) {
54
+ cache.delete(source)
55
+ cache.set(source, image)
56
+ while (cache.size > IMAGE_CACHE_LIMIT) {
57
+ cache.delete(cache.keys().next().value!)
58
+ }
59
+ }
60
+
61
+ for (const callback of callbacks) {
62
+ callback(image)
63
+ }
64
+ }
65
+
66
+ /** Points `view` at `source`. Cached decodes assign immediately; anything else
67
+ * decodes on a later run-loop turn so command batches never block on image
68
+ * I/O. The previous image stays visible until its replacement resolves. */
69
+ export function updateImage(view: NSImageView, source: unknown) {
70
+ const src = String(source ?? '')
71
+ let request = requests.get(view)
72
+ if (!request) {
73
+ request = { source: '', generation: 0 }
74
+ requests.set(view, request)
75
+ }
76
+
77
+ if (request.source === src) {
78
+ return
79
+ }
80
+
81
+ request.source = src
82
+ const generation = ++request.generation
83
+ const deliver = (image: NSImage | null) => {
84
+ if (requests.get(view) !== request || request.generation !== generation) {
85
+ return
86
+ }
87
+
88
+ view.image = image
89
+ }
90
+
91
+ if (!src) {
92
+ deliver(null)
93
+ return
94
+ }
95
+
96
+ const cached = cache.get(src)
97
+ if (cached) {
98
+ deliver(cached)
99
+ return
100
+ }
101
+
102
+ let waiters = pending.get(src)
103
+ if (!waiters) {
104
+ waiters = []
105
+ pending.set(src, waiters)
106
+ setTimeout(() => decodeImage(src), 0)
107
+ }
108
+
109
+ waiters.push(deliver)
110
+ }
111
+
112
+ /** Invalidates any in-flight decode for `view`; call when its node is destroyed. */
113
+ export function disposeImage(view: NSImageView) {
114
+ requests.delete(view)
115
+ }