1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! [`NativeCtx`] — the scoped call context every macOS
//! [`NativeWidget`](crate::runtime::NativeWidget) builds its views through:
//! the AppKit twin of `crate::apple::ctx`, and just as small, for the same
//! reason — AppKit needs almost nothing threaded through a call.
//!
//! # What it carries, and why that is all
//!
//! A [`MainThreadMarker`] — nothing else. The table in `crate::apple::ctx`'s
//! module doc holds verbatim here: the Objective-C runtime is globally
//! reachable, ARC and `Retained<T>` replace Android's local frames and global
//! references, and `NSView::new(mtm)` needs no `Context` to construct against.
//! The one thing an AppKit call genuinely cannot do without is **proof that it
//! is on the main thread**, and that is what this type carries: every
//! `objc2-app-kit` view class is `MainThreadOnly`, so a control's
//! `create`/`update`/`dispose` gets a [`MainThreadMarker`] out of its
//! `&mut NativeCtx<'_, '_>` and every constructor that demands one is then
//! callable, checked once by the type system.
//!
//! # No `CATransaction` batch helper here either
//!
//! The iOS arm ships none because `FrustViewHost` already wraps its per-poll
//! command loop in a transaction that disables implicit animations. The
//! desktop host (`crates/frust-shell-macos`' platform-view host) opens none,
//! and this arm still adds none, because the thing that batch exists to
//! suppress does not happen here: AppKit does not implicitly animate a
//! property changed through an `NSView`/`NSControl` setter (animation needs
//! the view's `animator()` proxy or an `NSAnimationContext` that allows it),
//! and a layer-backed view is its backing layer's delegate, answering "no
//! action" for a direct layer property write outside such a context. The whole
//! host command batch (create, `setFrame:`, `setHidden:`, `update_params`)
//! runs inside one run-loop turn and is displayed together at its end. The
//! case that would change this is a control driving a sublayer of its own
//! (which has no view delegate to veto its implicit actions); that is the
//! moment to add a batch, and this comment is why it was not added sooner.
//!
//! # Frame-setting layout only
//!
//! Nothing here (or in `crate::appkit::factory`) installs an Auto Layout
//! constraint or touches `translatesAutoresizingMaskIntoConstraints`: the
//! desktop host positions a slot's view by assigning its frame from the
//! differ's rect (`setFrame:` in logical points, top-left origin — winit's
//! content view is flipped), and shrinks that frame to the slot's clip. A
//! control that installed constraints would fight it.
//!
//! # Hierarchy: `addSubview`, and nothing else
//!
//! [`NativeCtx::add_child`] is this arm's whole subtree surface — the mirror
//! of `crate::apple::ctx`'s `addSubview` wrapper, and the seam the `DemoCard`
//! composite's macOS arm and any future composite build on. **The platform
//! lays the subtree out**, not frust: a component positions its children with
//! explicit frames of its own, and frust keeps seeing one opaque slot with one
//! rect.
//!
//! There is deliberately **no local-frame wrapper on this arm**, for the same
//! ARC reason as iOS.
use PhantomData;
use MainThreadMarker;
use NSView;
/// The scoped call context handed to every macOS
/// [`NativeWidget`](crate::runtime::NativeWidget) method — see the module doc.
///
/// The two lifetime parameters exist only to match the shape
/// `crate::runtime`'s trait signatures were written against (`NativeCtx<'local,
/// 'env>`, bound to a JNI frame and `Env` borrow on Android); like the iOS arm,
/// this one borrows nothing, so both are phantom.
pub