1use super::*;
4use crate::abi;
5use crate::resolve;
6use core::ffi::c_void;
7use crate::mangle;
8
9mangle::modifier_types! {
12 pub(crate) TRANSITION_T = ty("_TraitWritingModifier").of(vec![ty("TransitionTraitKey")]);
15 pub(crate) ON_APPEAR_T = ty("_AppearanceActionModifier");
18 pub(crate) ANIMATION_T = ty("_AnimationModifier").of(vec![Type::Verbatim("Si".into())]);
21}
22
23
24
25pub(crate) unsafe fn opaque_modifier_for_transition(
34 view: &ViewHandle,
35 boxed: u64,
36) -> ViewHandle {
37 unsafe {
38 let (_, _, size) = TRANSITION_T.applied_to(view.meta);
39 let r = abi::call_modifier(
40 resolve::transition_fn(),
41 view.value_ptr(),
42 view.meta,
43 view.wt,
44 &[boxed],
45 [0.0; 4],
46 size,
47 );
48 wrap_modified(r, &TRANSITION_T, view)
49 }
50}
51
52pub fn transition_opacity(view: &ViewHandle) -> ViewHandle {
60 unsafe {
61 let meta = abi::metadata0(resolve::any_transition_ma());
62 let (value, _) = static_getter(resolve::transition_opacity(), meta);
63 let (_, _, size) = TRANSITION_T.applied_to(view.meta);
64 let r = abi::call_modifier(resolve::transition_fn(), view.value_ptr(), view.meta, view.wt, &[value], [0.0; 4], size);
65 wrap_modified(r, &TRANSITION_T, view)
66 }
67}
68
69pub fn transition_slide(view: &ViewHandle) -> ViewHandle {
71 unsafe {
72 let meta = abi::metadata0(resolve::any_transition_ma());
73 let (value, _) = static_getter(resolve::transition_slide(), meta);
74 let (_, _, size) = TRANSITION_T.applied_to(view.meta);
75 let r = abi::call_modifier(
76 resolve::transition_fn(),
77 view.value_ptr(),
78 view.meta,
79 view.wt,
80 &[value],
81 [0.0; 4],
82 size,
83 );
84 wrap_modified(r, &TRANSITION_T, view)
85 }
86}
87
88swift_statics! {
89 pub enum AnimationKind {
99 Default = c"$s7SwiftUI9AnimationV7defaultACvgZ",
100 EaseIn = c"$s7SwiftUI9AnimationV6easeInACvgZ",
101 EaseInOut = c"$s7SwiftUI9AnimationV9easeInOutACvgZ",
102 EaseOut = c"$s7SwiftUI9AnimationV7easeOutACvgZ",
103 Linear = c"$s7SwiftUI9AnimationV6linearACvgZ",
104 }
110}
111
112pub(crate) unsafe fn animation_word(view: &ViewHandle, anim: u64, value: i64) -> ViewHandle {
120 unsafe {
121 let int_meta = resolve::int_meta();
122 let eq_wt = abi::get_view_wt_for_proto(int_meta, resolve::equatable_proto());
123 assert!(!eq_wt.is_null(), "Int: Equatable");
124 let (_, _, size) = ANIMATION_T.applied_to(view.meta);
125 let mut result = vec![0u8; size];
126 let this = view.value_ptr();
127 let mut v = value;
128 core::arch::asm!("blr {f}", f = in(reg) resolve::animation_fn(),
129 in("x0") anim,
130 in("x1") &mut v as *mut i64,
131 in("x2") view.meta,
132 in("x3") int_meta,
133 in("x4") view.wt,
134 in("x5") eq_wt,
135 in("x8") result.as_mut_ptr(),
136 in("x20") this,
137 lateout("x6") _, lateout("x7") _,
138 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
139 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
140 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
141 );
142 wrap_modified(result, &ANIMATION_T, view)
143 }
144}
145
146pub fn animation(view: &ViewHandle, value: i64) -> ViewHandle {
151 animation_kind(view, AnimationKind::Default, value)
152}
153
154pub fn animation_kind(view: &ViewHandle, kind: AnimationKind, value: i64) -> ViewHandle {
156 unsafe {
157 let anim_meta = abi::metadata0(resolve::animation_ma());
158 let (anim, _) = static_getter(kind.resolved(), anim_meta);
159
160 let int_meta = resolve::int_meta();
161 let eq_wt = abi::get_view_wt_for_proto(int_meta, resolve::equatable_proto());
162 assert!(!eq_wt.is_null(), "Int: Equatable");
163
164 let (_, _, size) = ANIMATION_T.applied_to(view.meta);
165 let mut result = vec![0u8; size];
166 let this = view.value_ptr();
167 let mut v = value;
168 core::arch::asm!("blr {f}", f = in(reg) resolve::animation_fn(),
173 in("x0") anim,
174 in("x1") &mut v as *mut i64,
175 in("x2") view.meta,
176 in("x3") int_meta,
177 in("x4") view.wt,
178 in("x5") eq_wt,
179 in("x8") result.as_mut_ptr(),
180 in("x20") this,
181 lateout("x6") _, lateout("x7") _,
182 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
183 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
184 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
185 );
186 wrap_modified(result, &ANIMATION_T, view)
187 }
188}
189
190pub fn on_appear(view: &ViewHandle, action: impl Fn() + 'static) -> ViewHandle {
192 unsafe {
193 let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
195 invoke_action,
196 boxed_ctx(Box::new(action) as Box<dyn Fn()>),
197 ))) as *mut abi::ClosureCtx;
198 let (_, _, size) = ON_APPEAR_T.applied_to(view.meta);
199 let r = abi::call_modifier(resolve::on_appear_fn(), view.value_ptr(), view.meta, view.wt,
202 &[abi::swift_closure_thunk as *const () as u64, ctx as u64],
203 [0.0; 4],
204 size,
205 );
206 wrap_modified(r, &ON_APPEAR_T, view)
207 }
208}
209
210pub fn on_tap_gesture(view: &ViewHandle, count: i64, action: impl Fn() + 'static) -> ViewHandle {
214 unsafe {
215 let boxed: Box<dyn Fn()> = Box::new(action);
216 let payload = Box::into_raw(Box::new(boxed)) as *mut c_void;
217 let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
218 super::run_boxed_action,
219 payload,
220 ))) as *mut abi::ClosureCtx;
221 let subst = [view.meta, view.wt];
222 let (meta, wt, size) = opaque_result_type(resolve::on_tap_oret(), &subst);
223 let r = abi::call_modifier(resolve::on_tap_fn(), view.value_ptr(), view.meta, view.wt,
224 &[count as u64, abi::swift_closure_thunk as *const () as u64, ctx as u64],
225 [0.0; 4],
226 size,
227 );
228 wrap_owned(r, meta, wt)
229 }
230}
231
232pub fn on_long_press_gesture(
238 view: &ViewHandle,
239 duration: f64,
240 max_distance: f64,
241 action: impl Fn() + 'static,
242) -> ViewHandle {
243 unsafe {
244 let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
245 invoke_action,
246 boxed_ctx(Box::new(action) as Box<dyn Fn()>),
247 ))) as *mut abi::ClosureCtx;
248 let subst = [view.meta, view.wt];
249 let (meta, wt, size) = opaque_result_type(resolve::on_long_press_oret(), &subst);
250 let r = abi::call_modifier(resolve::on_long_press_fn(), view.value_ptr(), view.meta, view.wt,
252 &[0, 0, abi::swift_closure_thunk as *const () as u64, ctx as u64],
253 [duration, max_distance, 0.0, 0.0],
254 size,
255 );
256 wrap_owned(r, meta, wt)
257 }
258}
259
260pub fn context_menu(view: &ViewHandle, items: &ViewHandle) -> ViewHandle {
275 unsafe {
276 let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
279 emit_tuple,
280 Child::leak(items, Content::Concrete),
281 ))) as *mut abi::ClosureCtx;
282
283 let subst = [
285 view.meta,
286 items.meta,
287 view.wt,
288 items.wt,
289 ];
290 let (meta, wt, size) = opaque_result_type(resolve::context_menu_oret(), &subst);
291 let mut result = vec![0u8; size];
292 let this = view.value_ptr();
293 core::arch::asm!("blr {f}", f = in(reg) resolve::context_menu_fn(),
297 in("x0") abi::swift_closure_thunk as *const c_void,
298 in("x1") ctx,
299 in("x2") view.meta, in("x3") items.meta, in("x4") view.wt, in("x5") items.wt, in("x8") result.as_mut_ptr(),
304 in("x20") this,
305 lateout("x6") _, lateout("x7") _,
306 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
307 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
308 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
309 );
310 wrap_owned(result, meta, wt)
311 }
312}
313
314pub fn transition_scale(scale: f64, anchor: (f64, f64)) -> u64 {
319 unsafe {
320 let out: u64;
321 core::arch::asm!("blr {f}", f = in(reg) resolve::transition_scale_anchor(),
325 in("d0") scale, in("d1") anchor.0, in("d2") anchor.1,
326 lateout("x0") out,
327 lateout("x20") _,
328 lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
329 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
330 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
331 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
332 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
333 );
334 out
335 }
336}
337
338pub fn transition_opacity_value() -> u64 {
340 unsafe {
341 let meta = abi::metadata0(resolve::any_transition_ma());
342 static_getter(resolve::transition_opacity(), meta).0
343 }
344}
345
346pub fn transition_identity_value() -> u64 {
352 unsafe {
353 let meta = abi::metadata0(resolve::any_transition_ma());
354 static_getter(resolve::transition_identity(), meta).0
355 }
356}
357
358pub fn transition_scale_value() -> u64 {
364 unsafe {
365 let meta = abi::metadata0(resolve::any_transition_ma());
366 static_getter(resolve::transition_scale(), meta).0
367 }
368}
369
370pub fn transition_combined(lhs: u64, rhs: u64) -> u64 {
372 unsafe {
373 let out: u64;
374 core::arch::asm!("blr {f}", f = in(reg) resolve::transition_combined(),
378 in("x0") rhs,
379 in("x1") lhs,
380 lateout("x0") out,
381 lateout("x20") _,
382 lateout("x2") _, lateout("x3") _, lateout("x4") _,
383 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
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 out
389 }
390}
391
392pub fn transition(view: &ViewHandle, value: u64) -> ViewHandle {
394 unsafe {
395 let (_, _, size) = TRANSITION_T.applied_to(view.meta);
396 let r = abi::call_modifier(resolve::transition_fn(), view.value_ptr(), view.meta, view.wt, &[value], [0.0; 4], size);
397 wrap_modified(r, &TRANSITION_T, view)
398 }
399}
400
401
402pub fn context_menu_preview(
415 view: &ViewHandle,
416 items: &ViewHandle,
417 preview: &ViewHandle,
418) -> ViewHandle {
419 unsafe {
420 let items_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
421 emit_tuple,
422 Child::leak(items, Content::Concrete),
423 ))) as *mut abi::ClosureCtx;
424 let preview_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
425 emit_tuple,
426 Child::leak(preview, Content::Concrete),
427 ))) as *mut abi::ClosureCtx;
428
429 let subst = [view.meta, items.meta, preview.meta, view.wt, items.wt, preview.wt];
430 let (meta, wt, size) = opaque_result_type(resolve::context_menu_preview_oret(), &subst);
431 let mut result = vec![0u8; size];
432 let this = view.value_ptr();
433 core::arch::asm!(
438 "sub sp, sp, #16",
439 "stp {mw}, {pw}, [sp]",
440 "blr {f}",
441 "add sp, sp, #16",
442 f = in(reg) resolve::context_menu_preview_fn(),
443 mw = in(reg) items.wt,
444 pw = in(reg) preview.wt,
445 in("x0") abi::swift_closure_thunk as *const c_void,
446 in("x1") items_ctx,
447 in("x2") abi::swift_closure_thunk as *const c_void,
448 in("x3") preview_ctx,
449 in("x4") view.meta,
450 in("x5") items.meta,
451 in("x6") preview.meta,
452 in("x7") view.wt,
453 in("x8") result.as_mut_ptr(),
454 in("x20") this,
455 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
456 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
457 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
458 );
459 wrap_owned(result, meta, wt)
460 }
461}