1use super::*;
4use crate::abi;
5use crate::resolve;
6use core::ffi::c_void;
7use crate::mangle;
8
9mangle::result_types! {
12 pub(crate) TOOLBAR_ITEM_T = ty("ToolbarItem").of(vec![Type::Void, ty("AnyView")]);
15 pub(crate) TOOLBAR_TUPLE_T = ty("TupleToolbarContent").of(vec![ty("ToolbarItem").of(vec![Type::Void, ty("AnyView")])]);
18 pub(crate) TOOLBAR_ITEM_ID_T = ty("ToolbarItem").of(vec![Type::Verbatim("SS".into()), ty("AnyView")]);
21 pub(crate) TOOLBAR_TUPLE_ID_T = ty("TupleToolbarContent").of(vec![ty("ToolbarItem").of(vec![Type::Verbatim("SS".into()), ty("AnyView")])]);
24}
25mangle::modifier_types! {
26 pub(crate) TOOLBAR_T = ty("ToolbarModifier").of(vec![Type::Void, ty("TupleToolbarContent").of(vec![ty("ToolbarItem").of(vec![Type::Void, ty("AnyView")])])]);
29}
30
31
32
33swift_statics! {
34 pub enum ToolbarItemPlacement {
42 Automatic = c"$s7SwiftUI20ToolbarItemPlacementV9automaticACvgZ",
43 CancellationAction = c"$s7SwiftUI20ToolbarItemPlacementV18cancellationActionACvgZ",
44 ConfirmationAction = c"$s7SwiftUI20ToolbarItemPlacementV18confirmationActionACvgZ",
45 DestructiveAction = c"$s7SwiftUI20ToolbarItemPlacementV17destructiveActionACvgZ",
46 Keyboard = c"$s7SwiftUI20ToolbarItemPlacementV8keyboardACvgZ",
47 Navigation = c"$s7SwiftUI20ToolbarItemPlacementV10navigationACvgZ",
48 PrimaryAction = c"$s7SwiftUI20ToolbarItemPlacementV13primaryActionACvgZ",
49 Principal = c"$s7SwiftUI20ToolbarItemPlacementV9principalACvgZ",
50 SecondaryAction = c"$s7SwiftUI20ToolbarItemPlacementV15secondaryActionACvgZ",
51 Status = c"$s7SwiftUI20ToolbarItemPlacementV6statusACvgZ",
52 }
53}
54
55#[repr(C)]
57pub(crate) struct BytesPayload {
58 pub(crate) data: *const u8,
59 pub(crate) len: usize,
60}
61
62pub(crate) unsafe extern "C" fn emit_bytes(out: *mut u8, payload: *mut c_void) {
63 let p = unsafe { &*(payload as *const BytesPayload) };
64 unsafe { core::ptr::copy_nonoverlapping(p.data, out, p.len) };
65}
66
67pub fn toolbar(view: &ViewHandle, content: &ViewHandle) -> ViewHandle {
74 toolbar_placed(view, ToolbarItemPlacement::Automatic, content)
75}
76
77pub fn toolbar_placed(
82 view: &ViewHandle,
83 placement: ToolbarItemPlacement,
84 content: &ViewHandle,
85) -> ViewHandle {
86 unsafe {
87 let placement_meta = abi::metadata0(resolve::toolbar_placement_ma());
89 let mut placement =
90 static_getter_indirect(placement.resolved(), placement_meta, 0);
91
92 let item_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
94 emit_tuple,
95 Child::leak(content, Content::Erased),
96 ))) as *mut abi::ClosureCtx;
97
98 let (item_meta, _, item_size) = {
99 let m = abi::resolve_type_by_mangled_name(&TOOLBAR_ITEM_T);
100 assert!(!m.is_null(), "ToolbarItem<(), AnyView> metadata");
101 (m, (), abi::type_bytes(m))
102 };
103 let mut item = vec![0u8; item_size];
104 core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_item_init(),
108 in("x0") placement.as_mut_ptr(),
109 in("x1") abi::swift_closure_thunk as *const c_void,
110 in("x2") item_ctx,
111 in("x3") resolve::anyview_meta(),
112 in("x4") resolve::anyview_wt(),
113 in("x8") item.as_mut_ptr(),
114 lateout("x5") _, lateout("x6") _, lateout("x7") _,
115 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
116 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
117 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
118 clobber_abi("C"),
119 );
120
121 let item_tc_wt =
122 abi::get_view_wt_for_proto(item_meta, resolve::toolbar_content_proto());
123 assert!(!item_tc_wt.is_null(), "ToolbarItem: ToolbarContent");
124
125 let tuple_meta = abi::resolve_type_by_mangled_name(&TOOLBAR_TUPLE_T);
128 assert!(!tuple_meta.is_null(), "TupleToolbarContent metadata");
129 let mut tuple = vec![0u8; abi::type_bytes(tuple_meta)];
130 core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_build_block(),
131 in("x0") item.as_mut_ptr(),
132 in("x1") item_meta,
133 in("x2") item_tc_wt,
134 in("x8") tuple.as_mut_ptr(),
135 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
136 lateout("x7") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
137 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
138 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
139 lateout("x21") _, clobber_abi("C"),
140 );
141
142 let tuple_tc_wt =
143 abi::get_view_wt_for_proto(tuple_meta, resolve::toolbar_content_proto());
144 assert!(!tuple_tc_wt.is_null(), "TupleToolbarContent: ToolbarContent");
145
146 let leaked = Box::leak(tuple.into_boxed_slice());
148 let bytes = Box::leak(Box::new(BytesPayload {
149 data: leaked.as_ptr(),
150 len: leaked.len(),
151 }));
152 let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
153 emit_bytes,
154 bytes as *mut BytesPayload as *mut c_void,
155 ))) as *mut abi::ClosureCtx;
156
157 let (_, _, size) = TOOLBAR_T.applied_to(view.meta);
158 let mut result = vec![0u8; size];
159 let this = view.value_ptr();
160 core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_fn(),
164 in("x0") abi::swift_closure_thunk as *const c_void,
165 in("x1") ctx,
166 in("x2") view.meta,
167 in("x3") tuple_meta,
168 in("x4") content.wt,
169 in("x5") tuple_tc_wt,
170 in("x8") result.as_mut_ptr(),
171 in("x20") this,
172 lateout("x6") _, lateout("x7") _,
173 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
174 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
175 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
176 );
177 wrap_modified(result, &TOOLBAR_T, view)
178 }
179}
180
181pub fn toolbar_customizable(
198 view: &ViewHandle,
199 toolbar_id: &str,
200 item_id: &str,
201 shows_by_default: bool,
202 content: &ViewHandle,
203) -> ViewHandle {
204 toolbar_customizable_placed(
205 view,
206 toolbar_id,
207 item_id,
208 ToolbarItemPlacement::Automatic,
209 shows_by_default,
210 content,
211 )
212}
213
214pub fn toolbar_customizable_placed(
216 view: &ViewHandle,
217 toolbar_id: &str,
218 item_id: &str,
219 placement: ToolbarItemPlacement,
220 shows_by_default: bool,
221 content: &ViewHandle,
222) -> ViewHandle {
223 unsafe {
224 let placement_meta = abi::metadata0(resolve::toolbar_placement_ma());
225 let mut placement =
226 static_getter_indirect(placement.resolved(), placement_meta, 0);
227
228 let item_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
229 emit_tuple,
230 Child::leak(content, Content::Erased),
231 ))) as *mut abi::ClosureCtx;
232
233 let item_meta = abi::resolve_type_by_mangled_name(&TOOLBAR_ITEM_ID_T);
234 assert!(!item_meta.is_null(), "ToolbarItem<String, AnyView> metadata");
235 let mut item = vec![0u8; abi::type_bytes(item_meta)];
236 let id = abi::swift_string(item_id);
237 core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_item_id_init(),
242 in("x0") u64::from_le_bytes(id[..8].try_into().expect("id lo")),
243 in("x1") u64::from_le_bytes(id[8..].try_into().expect("id hi")),
244 in("x2") placement.as_mut_ptr(),
245 in("x3") u64::from(shows_by_default),
246 in("x4") abi::swift_closure_thunk as *const c_void,
247 in("x5") item_ctx,
248 in("x6") resolve::anyview_meta(),
249 in("x7") resolve::anyview_wt(),
250 in("x8") item.as_mut_ptr(),
251 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
252 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
253 lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
254 clobber_abi("C"),
255 );
256
257 let item_tc_wt = abi::get_view_wt_for_proto(item_meta, resolve::toolbar_content_proto());
260 assert!(!item_tc_wt.is_null(), "ToolbarItem<String, _>: ToolbarContent");
261
262 let tuple_meta = abi::resolve_type_by_mangled_name(&TOOLBAR_TUPLE_ID_T);
263 assert!(!tuple_meta.is_null(), "TupleToolbarContent<ToolbarItem<String, _>> metadata");
264 let mut tuple = vec![0u8; abi::type_bytes(tuple_meta)];
265 core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_build_block(),
266 in("x0") item.as_mut_ptr(),
267 in("x1") item_meta,
268 in("x2") item_tc_wt,
269 in("x8") tuple.as_mut_ptr(),
270 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
271 lateout("x7") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
272 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
273 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
274 lateout("x21") _, clobber_abi("C"),
275 );
276
277 let tuple_custom_wt = abi::get_view_wt_for_proto(
280 tuple_meta,
281 resolve::customizable_toolbar_content_proto(),
282 );
283 assert!(
284 !tuple_custom_wt.is_null(),
285 "TupleToolbarContent<ToolbarItem<String, _>>: CustomizableToolbarContent"
286 );
287
288 let leaked = Box::leak(tuple.into_boxed_slice());
289 let bytes = Box::leak(Box::new(BytesPayload {
290 data: leaked.as_ptr(),
291 len: leaked.len(),
292 }));
293 let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
294 emit_bytes,
295 bytes as *mut BytesPayload as *mut c_void,
296 ))) as *mut abi::ClosureCtx;
297
298 let tid = abi::swift_string(toolbar_id);
299 super::generic1_modifier_ints(
304 resolve::toolbar_id_fn(),
305 resolve::toolbar_id_oret(),
306 view,
307 tuple_meta,
308 tuple_custom_wt,
309 &[
310 u64::from_le_bytes(tid[..8].try_into().expect("toolbar id lo")),
311 u64::from_le_bytes(tid[8..].try_into().expect("toolbar id hi")),
312 abi::swift_closure_thunk as *const c_void as u64,
313 ctx as u64,
314 ],
315 [0.0; 4],
316 )
317 }
318}
319
320#[cfg(not(target_os = "macos"))]
321swift_statics! {
322 pub enum ContentToolbarPlacement {
329 NavigationSplitView = c"$s7SwiftUI23ContentToolbarPlacementV19navigationSplitViewACvgZ",
330 TabViewAccessory = c"$s7SwiftUI23ContentToolbarPlacementV16tabViewAccessoryACvgZ",
331 TabViewSidebar = c"$s7SwiftUI23ContentToolbarPlacementV14tabViewSidebarACvgZ",
332 }
333}
334
335#[cfg(not(target_os = "macos"))]
343pub fn content_toolbar(
344 view: &ViewHandle,
345 placement: ContentToolbarPlacement,
346 content: &ViewHandle,
347) -> ViewHandle {
348 unsafe {
349 let placement_meta = abi::metadata0(resolve::content_toolbar_placement_ma());
350 assert!(!placement_meta.is_null(), "ContentToolbarPlacement metadata");
351 let mut placement =
352 static_getter_indirect(placement.resolved(), placement_meta, 0);
353
354 let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
356 emit_tuple,
357 Child::leak(content, Content::Erased),
358 ))) as *mut abi::ClosureCtx;
359
360 let subst = [
361 view.meta,
362 resolve::anyview_meta(),
363 view.wt,
364 resolve::anyview_wt(),
365 ];
366 let (meta, wt, size) =
367 super::opaque_result_type(resolve::content_toolbar_oret(), &subst);
368 let mut result = vec![0u8; size];
369 let this = view.value_ptr();
370 core::arch::asm!("blr {f}", f = in(reg) resolve::content_toolbar_fn(),
374 in("x0") placement.as_mut_ptr(),
375 in("x1") abi::swift_closure_thunk as *const c_void,
376 in("x2") ctx,
377 in("x3") view.meta,
378 in("x4") resolve::anyview_meta(),
379 in("x5") view.wt,
380 in("x6") resolve::anyview_wt(),
381 in("x8") result.as_mut_ptr(),
382 in("x20") this,
383 lateout("x7") _,
384 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
385 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
386 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
387 );
388 wrap_owned(result, meta, wt)
389 }
390}