1#![allow(unsafe_code)]
20#![allow(non_upper_case_globals)]
21#![allow(missing_docs)] use crate::api::LogicalPosition;
24use crate::data_transfer::DataTransfer;
25use crate::graphics::{Brush, Color, FontRequest, Image};
26use crate::input::{
27 FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, InternalKeyEvent,
28 KeyEventResult, KeyEventType, Keys, MouseEvent,
29};
30use crate::item_rendering::{CachedRenderingData, RenderBorderRectangle, RenderRectangle};
31use crate::item_tree::ItemTreeRc;
32pub use crate::item_tree::{ItemRc, ItemTreeVTable};
33use crate::layout::LayoutInfo;
34use crate::lengths::{
35 LogicalBorderRadius, LogicalLength, LogicalRect, LogicalSize, LogicalVector, PointLengths,
36 RectLengths,
37};
38pub use crate::menus::MenuItem;
39#[cfg(feature = "rtti")]
40use crate::rtti::*;
41use crate::window::{WindowAdapter, WindowAdapterRc, WindowInner};
42use crate::{Callback, Coord, Property, SharedString};
43use alloc::rc::Rc;
44use const_field_offset::FieldOffsets;
45use core::cell::Cell;
46use core::num::NonZeroU32;
47use core::pin::Pin;
48use core::time::Duration;
49use i_slint_core_macros::*;
50pub use system_tray::SystemTrayIcon;
51use vtable::*;
52
53mod component_container;
54pub use self::component_container::*;
55mod flickable;
56pub use flickable::Flickable;
57mod text;
58pub use text::*;
59mod input_items;
60pub use input_items::*;
61mod image;
62pub use self::image::*;
63mod drag_n_drop;
64pub use drag_n_drop::*;
65#[cfg(feature = "path")]
66mod path;
67#[cfg(feature = "path")]
68pub use path::*;
69pub mod system_tray;
70
71type ItemRendererRef<'a> = &'a mut dyn crate::item_rendering::ItemRenderer;
74
75pub type VoidArg = ();
77pub type KeyEventArg = (KeyEvent,);
78pub type DragActionArg = (DragAction,);
79type FocusReasonArg = (FocusReason,);
80type PointerEventArg = (PointerEvent,);
81type PointerScrollEventArg = (PointerScrollEvent,);
82type PointArg = (LogicalPosition,);
83type MenuEntryArg = (MenuEntry,);
84type StringArg = (SharedString,);
85type MenuEntryModel = crate::model::ModelRc<MenuEntry>;
86
87#[cfg(all(feature = "ffi", windows))]
88#[macro_export]
89macro_rules! declare_item_vtable {
90 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
91 ItemVTable_static! {
92 #[unsafe(no_mangle)]
93 pub static $item_vtable_ty for $item_ty
94 }
95 #[unsafe(no_mangle)]
96 pub extern "C" fn $getter() -> *const ItemVTable {
97 use vtable::HasStaticVTable;
98 <$item_ty>::static_vtable()
99 }
100 };
101}
102#[cfg(not(all(feature = "ffi", windows)))]
103#[macro_export]
104macro_rules! declare_item_vtable {
105 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
106 ItemVTable_static! {
107 #[unsafe(no_mangle)]
108 pub static $item_vtable_ty for $item_ty
109 }
110 };
111}
112
113#[repr(C)]
117#[derive(Default)]
118pub enum RenderingResult {
119 #[default]
120 ContinueRenderingChildren,
121 ContinueRenderingWithoutChildren,
122}
123
124#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
126#[vtable]
127#[repr(C)]
128pub struct ItemVTable {
129 pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, my_item: &ItemRc),
133
134 pub deinit: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, window_adapter: &WindowAdapterRc),
135
136 #[allow(non_upper_case_globals)]
139 #[field_offset(CachedRenderingData)]
140 pub cached_rendering_data_offset: usize,
141
142 pub layout_info: extern "C" fn(
147 core::pin::Pin<VRef<ItemVTable>>,
148 orientation: Orientation,
149 cross_axis_constraint: Coord,
150 window_adapter: &WindowAdapterRc,
151 self_rc: &ItemRc,
152 ) -> LayoutInfo,
153
154 pub input_event_filter_before_children: extern "C" fn(
164 core::pin::Pin<VRef<ItemVTable>>,
165 &MouseEvent,
166 window_adapter: &WindowAdapterRc,
167 self_rc: &ItemRc,
168 cursor: &mut MouseCursor,
169 ) -> InputEventFilterResult,
170
171 pub input_event: extern "C" fn(
173 core::pin::Pin<VRef<ItemVTable>>,
174 &MouseEvent,
175 window_adapter: &WindowAdapterRc,
176 self_rc: &ItemRc,
177 cursor: &mut MouseCursor,
178 ) -> InputEventResult,
179
180 pub focus_event: extern "C" fn(
181 core::pin::Pin<VRef<ItemVTable>>,
182 &FocusEvent,
183 window_adapter: &WindowAdapterRc,
184 self_rc: &ItemRc,
185 ) -> FocusEventResult,
186
187 pub capture_key_event: extern "C" fn(
190 core::pin::Pin<VRef<ItemVTable>>,
191 &InternalKeyEvent,
192 window_adapter: &WindowAdapterRc,
193 self_rc: &ItemRc,
194 ) -> KeyEventResult,
195
196 pub key_event: extern "C" fn(
197 core::pin::Pin<VRef<ItemVTable>>,
198 &InternalKeyEvent,
199 window_adapter: &WindowAdapterRc,
200 self_rc: &ItemRc,
201 ) -> KeyEventResult,
202
203 pub render: extern "C" fn(
204 core::pin::Pin<VRef<ItemVTable>>,
205 backend: &mut ItemRendererRef,
206 self_rc: &ItemRc,
207 size: LogicalSize,
208 ) -> RenderingResult,
209
210 pub bounding_rect: extern "C" fn(
213 core::pin::Pin<VRef<ItemVTable>>,
214 window_adapter: &WindowAdapterRc,
215 self_rc: &ItemRc,
216 geometry: LogicalRect,
217 ) -> LogicalRect,
218
219 pub clips_children: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>) -> bool,
220}
221
222pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
225
226#[repr(C)]
227#[derive(FieldOffsets, Default, SlintElement)]
228#[pin]
229pub struct Empty {
231 pub cached_rendering_data: CachedRenderingData,
232}
233
234impl Item for Empty {
235 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
236
237 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
238
239 fn layout_info(
240 self: Pin<&Self>,
241 _orientation: Orientation,
242 _cross_axis_constraint: Coord,
243 _window_adapter: &Rc<dyn WindowAdapter>,
244 _self_rc: &ItemRc,
245 ) -> LayoutInfo {
246 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
247 }
248
249 fn input_event_filter_before_children(
250 self: Pin<&Self>,
251 _: &MouseEvent,
252 _window_adapter: &Rc<dyn WindowAdapter>,
253 _self_rc: &ItemRc,
254 _: &mut MouseCursor,
255 ) -> InputEventFilterResult {
256 InputEventFilterResult::ForwardAndIgnore
257 }
258
259 fn input_event(
260 self: Pin<&Self>,
261 _: &MouseEvent,
262 _window_adapter: &Rc<dyn WindowAdapter>,
263 _self_rc: &ItemRc,
264 _: &mut MouseCursor,
265 ) -> InputEventResult {
266 InputEventResult::EventIgnored
267 }
268
269 fn capture_key_event(
270 self: Pin<&Self>,
271 _: &InternalKeyEvent,
272 _window_adapter: &Rc<dyn WindowAdapter>,
273 _self_rc: &ItemRc,
274 ) -> KeyEventResult {
275 KeyEventResult::EventIgnored
276 }
277
278 fn key_event(
279 self: Pin<&Self>,
280 _: &InternalKeyEvent,
281 _window_adapter: &Rc<dyn WindowAdapter>,
282 _self_rc: &ItemRc,
283 ) -> KeyEventResult {
284 KeyEventResult::EventIgnored
285 }
286
287 fn focus_event(
288 self: Pin<&Self>,
289 _: &FocusEvent,
290 _window_adapter: &Rc<dyn WindowAdapter>,
291 _self_rc: &ItemRc,
292 ) -> FocusEventResult {
293 FocusEventResult::FocusIgnored
294 }
295
296 fn render(
297 self: Pin<&Self>,
298 _backend: &mut ItemRendererRef,
299 _self_rc: &ItemRc,
300 _size: LogicalSize,
301 ) -> RenderingResult {
302 RenderingResult::ContinueRenderingChildren
303 }
304
305 fn bounding_rect(
306 self: core::pin::Pin<&Self>,
307 _window_adapter: &Rc<dyn WindowAdapter>,
308 _self_rc: &ItemRc,
309 mut geometry: LogicalRect,
310 ) -> LogicalRect {
311 geometry.size = LogicalSize::zero();
312 geometry
313 }
314
315 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
316 false
317 }
318}
319
320impl ItemConsts for Empty {
321 const cached_rendering_data_offset: const_field_offset::FieldOffset<
322 Empty,
323 CachedRenderingData,
324 > = Empty::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
325}
326
327declare_item_vtable! {
328 fn slint_get_EmptyVTable() -> EmptyVTable for Empty
329}
330
331#[repr(C)]
332#[derive(FieldOffsets, Default, SlintElement)]
333#[pin]
334pub struct Rectangle {
336 pub background: Property<Brush>,
337 pub cached_rendering_data: CachedRenderingData,
338}
339
340impl Item for Rectangle {
341 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
342
343 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
344
345 fn layout_info(
346 self: Pin<&Self>,
347 _orientation: Orientation,
348 _cross_axis_constraint: Coord,
349 _window_adapter: &Rc<dyn WindowAdapter>,
350 _self_rc: &ItemRc,
351 ) -> LayoutInfo {
352 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
353 }
354
355 fn input_event_filter_before_children(
356 self: Pin<&Self>,
357 _: &MouseEvent,
358 _window_adapter: &Rc<dyn WindowAdapter>,
359 _self_rc: &ItemRc,
360 _: &mut MouseCursor,
361 ) -> InputEventFilterResult {
362 InputEventFilterResult::ForwardAndIgnore
363 }
364
365 fn input_event(
366 self: Pin<&Self>,
367 _: &MouseEvent,
368 _window_adapter: &Rc<dyn WindowAdapter>,
369 _self_rc: &ItemRc,
370 _: &mut MouseCursor,
371 ) -> InputEventResult {
372 InputEventResult::EventIgnored
373 }
374
375 fn capture_key_event(
376 self: Pin<&Self>,
377 _: &InternalKeyEvent,
378 _window_adapter: &Rc<dyn WindowAdapter>,
379 _self_rc: &ItemRc,
380 ) -> KeyEventResult {
381 KeyEventResult::EventIgnored
382 }
383
384 fn key_event(
385 self: Pin<&Self>,
386 _: &InternalKeyEvent,
387 _window_adapter: &Rc<dyn WindowAdapter>,
388 _self_rc: &ItemRc,
389 ) -> KeyEventResult {
390 KeyEventResult::EventIgnored
391 }
392
393 fn focus_event(
394 self: Pin<&Self>,
395 _: &FocusEvent,
396 _window_adapter: &Rc<dyn WindowAdapter>,
397 _self_rc: &ItemRc,
398 ) -> FocusEventResult {
399 FocusEventResult::FocusIgnored
400 }
401
402 fn render(
403 self: Pin<&Self>,
404 backend: &mut ItemRendererRef,
405 self_rc: &ItemRc,
406 size: LogicalSize,
407 ) -> RenderingResult {
408 (*backend).draw_rectangle(self, self_rc, size, &self.cached_rendering_data);
409 RenderingResult::ContinueRenderingChildren
410 }
411
412 fn bounding_rect(
413 self: core::pin::Pin<&Self>,
414 _window_adapter: &Rc<dyn WindowAdapter>,
415 _self_rc: &ItemRc,
416 geometry: LogicalRect,
417 ) -> LogicalRect {
418 geometry
419 }
420
421 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
422 false
423 }
424}
425
426impl RenderRectangle for Rectangle {
427 fn background(self: Pin<&Self>) -> Brush {
428 self.background()
429 }
430}
431
432impl ItemConsts for Rectangle {
433 const cached_rendering_data_offset: const_field_offset::FieldOffset<
434 Rectangle,
435 CachedRenderingData,
436 > = Rectangle::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
437}
438
439declare_item_vtable! {
440 fn slint_get_RectangleVTable() -> RectangleVTable for Rectangle
441}
442
443#[repr(C)]
444#[derive(FieldOffsets, Default, SlintElement)]
445#[pin]
446pub struct BasicBorderRectangle {
448 pub background: Property<Brush>,
449 pub border_width: Property<LogicalLength>,
450 pub border_radius: Property<LogicalLength>,
451 pub border_color: Property<Brush>,
452 pub cached_rendering_data: CachedRenderingData,
453}
454
455impl Item for BasicBorderRectangle {
456 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
457
458 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
459
460 fn layout_info(
461 self: Pin<&Self>,
462 _orientation: Orientation,
463 _cross_axis_constraint: Coord,
464 _window_adapter: &Rc<dyn WindowAdapter>,
465 _self_rc: &ItemRc,
466 ) -> LayoutInfo {
467 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
468 }
469
470 fn input_event_filter_before_children(
471 self: Pin<&Self>,
472 _: &MouseEvent,
473 _window_adapter: &Rc<dyn WindowAdapter>,
474 _self_rc: &ItemRc,
475 _: &mut MouseCursor,
476 ) -> InputEventFilterResult {
477 InputEventFilterResult::ForwardAndIgnore
478 }
479
480 fn input_event(
481 self: Pin<&Self>,
482 _: &MouseEvent,
483 _window_adapter: &Rc<dyn WindowAdapter>,
484 _self_rc: &ItemRc,
485 _: &mut MouseCursor,
486 ) -> InputEventResult {
487 InputEventResult::EventIgnored
488 }
489
490 fn capture_key_event(
491 self: Pin<&Self>,
492 _: &InternalKeyEvent,
493 _window_adapter: &Rc<dyn WindowAdapter>,
494 _self_rc: &ItemRc,
495 ) -> KeyEventResult {
496 KeyEventResult::EventIgnored
497 }
498
499 fn key_event(
500 self: Pin<&Self>,
501 _: &InternalKeyEvent,
502 _window_adapter: &Rc<dyn WindowAdapter>,
503 _self_rc: &ItemRc,
504 ) -> KeyEventResult {
505 KeyEventResult::EventIgnored
506 }
507
508 fn focus_event(
509 self: Pin<&Self>,
510 _: &FocusEvent,
511 _window_adapter: &Rc<dyn WindowAdapter>,
512 _self_rc: &ItemRc,
513 ) -> FocusEventResult {
514 FocusEventResult::FocusIgnored
515 }
516
517 fn render(
518 self: Pin<&Self>,
519 backend: &mut ItemRendererRef,
520 self_rc: &ItemRc,
521 size: LogicalSize,
522 ) -> RenderingResult {
523 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
524 RenderingResult::ContinueRenderingChildren
525 }
526
527 fn bounding_rect(
528 self: core::pin::Pin<&Self>,
529 _window_adapter: &Rc<dyn WindowAdapter>,
530 _self_rc: &ItemRc,
531 geometry: LogicalRect,
532 ) -> LogicalRect {
533 geometry
534 }
535
536 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
537 false
538 }
539}
540
541impl RenderBorderRectangle for BasicBorderRectangle {
542 fn background(self: Pin<&Self>) -> Brush {
543 self.background()
544 }
545 fn border_width(self: Pin<&Self>) -> LogicalLength {
546 self.border_width()
547 }
548 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
549 LogicalBorderRadius::from_length(self.border_radius())
550 }
551 fn border_color(self: Pin<&Self>) -> Brush {
552 self.border_color()
553 }
554}
555
556impl ItemConsts for BasicBorderRectangle {
557 const cached_rendering_data_offset: const_field_offset::FieldOffset<
558 BasicBorderRectangle,
559 CachedRenderingData,
560 > = BasicBorderRectangle::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
561}
562
563declare_item_vtable! {
564 fn slint_get_BasicBorderRectangleVTable() -> BasicBorderRectangleVTable for BasicBorderRectangle
565}
566
567#[repr(C)]
568#[derive(FieldOffsets, Default, SlintElement)]
569#[pin]
570pub struct BorderRectangle {
572 pub background: Property<Brush>,
573 pub border_width: Property<LogicalLength>,
574 pub border_radius: Property<LogicalLength>,
575 pub border_top_left_radius: Property<LogicalLength>,
576 pub border_top_right_radius: Property<LogicalLength>,
577 pub border_bottom_left_radius: Property<LogicalLength>,
578 pub border_bottom_right_radius: Property<LogicalLength>,
579 pub border_color: Property<Brush>,
580 pub cached_rendering_data: CachedRenderingData,
581}
582
583impl Item for BorderRectangle {
584 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
585
586 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
587
588 fn layout_info(
589 self: Pin<&Self>,
590 _orientation: Orientation,
591 _cross_axis_constraint: Coord,
592 _window_adapter: &Rc<dyn WindowAdapter>,
593 _self_rc: &ItemRc,
594 ) -> LayoutInfo {
595 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
596 }
597
598 fn input_event_filter_before_children(
599 self: Pin<&Self>,
600 _: &MouseEvent,
601 _window_adapter: &Rc<dyn WindowAdapter>,
602 _self_rc: &ItemRc,
603 _: &mut MouseCursor,
604 ) -> InputEventFilterResult {
605 InputEventFilterResult::ForwardAndIgnore
606 }
607
608 fn input_event(
609 self: Pin<&Self>,
610 _: &MouseEvent,
611 _window_adapter: &Rc<dyn WindowAdapter>,
612 _self_rc: &ItemRc,
613 _: &mut MouseCursor,
614 ) -> InputEventResult {
615 InputEventResult::EventIgnored
616 }
617
618 fn capture_key_event(
619 self: Pin<&Self>,
620 _: &InternalKeyEvent,
621 _window_adapter: &Rc<dyn WindowAdapter>,
622 _self_rc: &ItemRc,
623 ) -> KeyEventResult {
624 KeyEventResult::EventIgnored
625 }
626
627 fn key_event(
628 self: Pin<&Self>,
629 _: &InternalKeyEvent,
630 _window_adapter: &Rc<dyn WindowAdapter>,
631 _self_rc: &ItemRc,
632 ) -> KeyEventResult {
633 KeyEventResult::EventIgnored
634 }
635
636 fn focus_event(
637 self: Pin<&Self>,
638 _: &FocusEvent,
639 _window_adapter: &Rc<dyn WindowAdapter>,
640 _self_rc: &ItemRc,
641 ) -> FocusEventResult {
642 FocusEventResult::FocusIgnored
643 }
644
645 fn render(
646 self: Pin<&Self>,
647 backend: &mut ItemRendererRef,
648 self_rc: &ItemRc,
649 size: LogicalSize,
650 ) -> RenderingResult {
651 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
652 RenderingResult::ContinueRenderingChildren
653 }
654
655 fn bounding_rect(
656 self: core::pin::Pin<&Self>,
657 _window_adapter: &Rc<dyn WindowAdapter>,
658 _self_rc: &ItemRc,
659 geometry: LogicalRect,
660 ) -> LogicalRect {
661 geometry
662 }
663
664 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
665 false
666 }
667}
668
669impl RenderBorderRectangle for BorderRectangle {
670 fn background(self: Pin<&Self>) -> Brush {
671 self.background()
672 }
673 fn border_width(self: Pin<&Self>) -> LogicalLength {
674 self.border_width()
675 }
676 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
677 LogicalBorderRadius::from_lengths(
678 self.border_top_left_radius(),
679 self.border_top_right_radius(),
680 self.border_bottom_right_radius(),
681 self.border_bottom_left_radius(),
682 )
683 }
684 fn border_color(self: Pin<&Self>) -> Brush {
685 self.border_color()
686 }
687}
688
689impl ItemConsts for BorderRectangle {
690 const cached_rendering_data_offset: const_field_offset::FieldOffset<
691 BorderRectangle,
692 CachedRenderingData,
693 > = BorderRectangle::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
694}
695
696declare_item_vtable! {
697 fn slint_get_BorderRectangleVTable() -> BorderRectangleVTable for BorderRectangle
698}
699
700declare_item_vtable! {
701 fn slint_get_TouchAreaVTable() -> TouchAreaVTable for TouchArea
702}
703
704declare_item_vtable! {
705 fn slint_get_FocusScopeVTable() -> FocusScopeVTable for FocusScope
706}
707
708crate::declare_item_vtable! {
709 fn slint_get_KeyBindingVTable() -> KeyBindingVTable for KeyBinding
710}
711
712declare_item_vtable! {
713 fn slint_get_SwipeGestureHandlerVTable() -> SwipeGestureHandlerVTable for SwipeGestureHandler
714}
715
716declare_item_vtable! {
717 fn slint_get_ScaleRotateGestureHandlerVTable() -> ScaleRotateGestureHandlerVTable for ScaleRotateGestureHandler
718}
719
720#[repr(C)]
721#[derive(FieldOffsets, Default, SlintElement)]
722#[pin]
723pub struct Clip {
725 pub border_top_left_radius: Property<LogicalLength>,
726 pub border_top_right_radius: Property<LogicalLength>,
727 pub border_bottom_left_radius: Property<LogicalLength>,
728 pub border_bottom_right_radius: Property<LogicalLength>,
729 pub border_width: Property<LogicalLength>,
730 pub cached_rendering_data: CachedRenderingData,
731 pub clip: Property<bool>,
732}
733
734impl Item for Clip {
735 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
736
737 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
738
739 fn layout_info(
740 self: Pin<&Self>,
741 _orientation: Orientation,
742 _cross_axis_constraint: Coord,
743 _window_adapter: &Rc<dyn WindowAdapter>,
744 _self_rc: &ItemRc,
745 ) -> LayoutInfo {
746 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
747 }
748
749 fn input_event_filter_before_children(
750 self: Pin<&Self>,
751 event: &MouseEvent,
752 _window_adapter: &Rc<dyn WindowAdapter>,
753 self_rc: &ItemRc,
754 _: &mut MouseCursor,
755 ) -> InputEventFilterResult {
756 if let Some(pos) = event.position() {
757 let geometry = self_rc.geometry();
758 if self.clip()
759 && (pos.x < 0 as Coord
760 || pos.y < 0 as Coord
761 || pos.x_length() > geometry.width_length()
762 || pos.y_length() > geometry.height_length())
763 {
764 return InputEventFilterResult::Intercept;
765 }
766 }
767 InputEventFilterResult::ForwardAndIgnore
768 }
769
770 fn input_event(
771 self: Pin<&Self>,
772 _: &MouseEvent,
773 _window_adapter: &Rc<dyn WindowAdapter>,
774 _self_rc: &ItemRc,
775 _: &mut MouseCursor,
776 ) -> InputEventResult {
777 InputEventResult::EventIgnored
778 }
779
780 fn capture_key_event(
781 self: Pin<&Self>,
782 _: &InternalKeyEvent,
783 _window_adapter: &Rc<dyn WindowAdapter>,
784 _self_rc: &ItemRc,
785 ) -> KeyEventResult {
786 KeyEventResult::EventIgnored
787 }
788
789 fn key_event(
790 self: Pin<&Self>,
791 _: &InternalKeyEvent,
792 _window_adapter: &Rc<dyn WindowAdapter>,
793 _self_rc: &ItemRc,
794 ) -> KeyEventResult {
795 KeyEventResult::EventIgnored
796 }
797
798 fn focus_event(
799 self: Pin<&Self>,
800 _: &FocusEvent,
801 _window_adapter: &Rc<dyn WindowAdapter>,
802 _self_rc: &ItemRc,
803 ) -> FocusEventResult {
804 FocusEventResult::FocusIgnored
805 }
806
807 fn render(
808 self: Pin<&Self>,
809 backend: &mut ItemRendererRef,
810 self_rc: &ItemRc,
811 size: LogicalSize,
812 ) -> RenderingResult {
813 (*backend).visit_clip(self, self_rc, size)
814 }
815
816 fn bounding_rect(
817 self: core::pin::Pin<&Self>,
818 _window_adapter: &Rc<dyn WindowAdapter>,
819 _self_rc: &ItemRc,
820 geometry: LogicalRect,
821 ) -> LogicalRect {
822 geometry
823 }
824
825 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
826 self.clip()
827 }
828}
829
830impl Clip {
831 pub fn logical_border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
832 LogicalBorderRadius::from_lengths(
833 self.border_top_left_radius(),
834 self.border_top_right_radius(),
835 self.border_bottom_right_radius(),
836 self.border_bottom_left_radius(),
837 )
838 }
839}
840
841impl ItemConsts for Clip {
842 const cached_rendering_data_offset: const_field_offset::FieldOffset<Clip, CachedRenderingData> =
843 Clip::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
844}
845
846declare_item_vtable! {
847 fn slint_get_ClipVTable() -> ClipVTable for Clip
848}
849
850#[repr(C)]
851#[derive(FieldOffsets, Default, SlintElement)]
852#[pin]
853pub struct Opacity {
855 pub opacity: Property<f32>,
857 pub cached_rendering_data: CachedRenderingData,
858}
859
860impl Item for Opacity {
861 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
862
863 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
864
865 fn layout_info(
866 self: Pin<&Self>,
867 _orientation: Orientation,
868 _cross_axis_constraint: Coord,
869 _window_adapter: &Rc<dyn WindowAdapter>,
870 _self_rc: &ItemRc,
871 ) -> LayoutInfo {
872 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
873 }
874
875 fn input_event_filter_before_children(
876 self: Pin<&Self>,
877 _: &MouseEvent,
878 _window_adapter: &Rc<dyn WindowAdapter>,
879 _self_rc: &ItemRc,
880 _: &mut MouseCursor,
881 ) -> InputEventFilterResult {
882 InputEventFilterResult::ForwardAndIgnore
883 }
884
885 fn input_event(
886 self: Pin<&Self>,
887 _: &MouseEvent,
888 _window_adapter: &Rc<dyn WindowAdapter>,
889 _self_rc: &ItemRc,
890 _: &mut MouseCursor,
891 ) -> InputEventResult {
892 InputEventResult::EventIgnored
893 }
894
895 fn capture_key_event(
896 self: Pin<&Self>,
897 _: &InternalKeyEvent,
898 _window_adapter: &Rc<dyn WindowAdapter>,
899 _self_rc: &ItemRc,
900 ) -> KeyEventResult {
901 KeyEventResult::EventIgnored
902 }
903
904 fn key_event(
905 self: Pin<&Self>,
906 _: &InternalKeyEvent,
907 _window_adapter: &Rc<dyn WindowAdapter>,
908 _self_rc: &ItemRc,
909 ) -> KeyEventResult {
910 KeyEventResult::EventIgnored
911 }
912
913 fn focus_event(
914 self: Pin<&Self>,
915 _: &FocusEvent,
916 _window_adapter: &Rc<dyn WindowAdapter>,
917 _self_rc: &ItemRc,
918 ) -> FocusEventResult {
919 FocusEventResult::FocusIgnored
920 }
921
922 fn render(
923 self: Pin<&Self>,
924 backend: &mut ItemRendererRef,
925 self_rc: &ItemRc,
926 size: LogicalSize,
927 ) -> RenderingResult {
928 backend.visit_opacity(self, self_rc, size)
929 }
930
931 fn bounding_rect(
932 self: core::pin::Pin<&Self>,
933 _window_adapter: &Rc<dyn WindowAdapter>,
934 _self_rc: &ItemRc,
935 geometry: LogicalRect,
936 ) -> LogicalRect {
937 geometry
938 }
939
940 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
941 false
942 }
943}
944
945impl Opacity {
946 pub fn need_layer(self_rc: &ItemRc, opacity: f32) -> bool {
954 if opacity == 1.0 {
955 return false;
956 }
957
958 let opacity_child = match self_rc.first_child() {
959 Some(first_child) => first_child,
960 None => return false, };
962
963 if opacity_child.next_sibling().is_some() {
964 return true; }
966
967 opacity_child.first_child().is_some()
969 }
970}
971
972impl ItemConsts for Opacity {
973 const cached_rendering_data_offset: const_field_offset::FieldOffset<
974 Opacity,
975 CachedRenderingData,
976 > = Opacity::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
977}
978
979declare_item_vtable! {
980 fn slint_get_OpacityVTable() -> OpacityVTable for Opacity
981}
982
983#[repr(C)]
984#[derive(FieldOffsets, Default, SlintElement)]
985#[pin]
986pub struct Layer {
988 pub cache_rendering_hint: Property<bool>,
989 pub cached_rendering_data: CachedRenderingData,
990}
991
992impl Item for Layer {
993 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
994
995 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
996
997 fn layout_info(
998 self: Pin<&Self>,
999 _orientation: Orientation,
1000 _cross_axis_constraint: Coord,
1001 _window_adapter: &Rc<dyn WindowAdapter>,
1002 _self_rc: &ItemRc,
1003 ) -> LayoutInfo {
1004 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1005 }
1006
1007 fn input_event_filter_before_children(
1008 self: Pin<&Self>,
1009 _: &MouseEvent,
1010 _window_adapter: &Rc<dyn WindowAdapter>,
1011 _self_rc: &ItemRc,
1012 _: &mut MouseCursor,
1013 ) -> InputEventFilterResult {
1014 InputEventFilterResult::ForwardAndIgnore
1015 }
1016
1017 fn input_event(
1018 self: Pin<&Self>,
1019 _: &MouseEvent,
1020 _window_adapter: &Rc<dyn WindowAdapter>,
1021 _self_rc: &ItemRc,
1022 _: &mut MouseCursor,
1023 ) -> InputEventResult {
1024 InputEventResult::EventIgnored
1025 }
1026
1027 fn capture_key_event(
1028 self: Pin<&Self>,
1029 _: &InternalKeyEvent,
1030 _window_adapter: &Rc<dyn WindowAdapter>,
1031 _self_rc: &ItemRc,
1032 ) -> KeyEventResult {
1033 KeyEventResult::EventIgnored
1034 }
1035
1036 fn key_event(
1037 self: Pin<&Self>,
1038 _: &InternalKeyEvent,
1039 _window_adapter: &Rc<dyn WindowAdapter>,
1040 _self_rc: &ItemRc,
1041 ) -> KeyEventResult {
1042 KeyEventResult::EventIgnored
1043 }
1044
1045 fn focus_event(
1046 self: Pin<&Self>,
1047 _: &FocusEvent,
1048 _window_adapter: &Rc<dyn WindowAdapter>,
1049 _self_rc: &ItemRc,
1050 ) -> FocusEventResult {
1051 FocusEventResult::FocusIgnored
1052 }
1053
1054 fn render(
1055 self: Pin<&Self>,
1056 backend: &mut ItemRendererRef,
1057 self_rc: &ItemRc,
1058 size: LogicalSize,
1059 ) -> RenderingResult {
1060 backend.visit_layer(self, self_rc, size)
1061 }
1062
1063 fn bounding_rect(
1064 self: core::pin::Pin<&Self>,
1065 _window_adapter: &Rc<dyn WindowAdapter>,
1066 _self_rc: &ItemRc,
1067 geometry: LogicalRect,
1068 ) -> LogicalRect {
1069 geometry
1070 }
1071
1072 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1073 false
1074 }
1075}
1076
1077impl ItemConsts for Layer {
1078 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1079 Layer,
1080 CachedRenderingData,
1081 > = Layer::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1082}
1083
1084declare_item_vtable! {
1085 fn slint_get_LayerVTable() -> LayerVTable for Layer
1086}
1087
1088#[repr(C)]
1089#[derive(FieldOffsets, Default, SlintElement)]
1090#[pin]
1091pub struct Transform {
1094 pub transform_rotation: Property<f32>,
1095 pub transform_scale_x: Property<f32>,
1096 pub transform_scale_y: Property<f32>,
1097 pub transform_origin: Property<LogicalPosition>,
1098 pub cached_rendering_data: CachedRenderingData,
1099}
1100
1101impl Item for Transform {
1102 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1103
1104 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1105
1106 fn layout_info(
1107 self: Pin<&Self>,
1108 _orientation: Orientation,
1109 _cross_axis_constraint: Coord,
1110 _window_adapter: &Rc<dyn WindowAdapter>,
1111 _self_rc: &ItemRc,
1112 ) -> LayoutInfo {
1113 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1114 }
1115
1116 fn input_event_filter_before_children(
1117 self: Pin<&Self>,
1118 _: &MouseEvent,
1119 _window_adapter: &Rc<dyn WindowAdapter>,
1120 _self_rc: &ItemRc,
1121 _: &mut MouseCursor,
1122 ) -> InputEventFilterResult {
1123 InputEventFilterResult::ForwardAndIgnore
1124 }
1125
1126 fn input_event(
1127 self: Pin<&Self>,
1128 _: &MouseEvent,
1129 _window_adapter: &Rc<dyn WindowAdapter>,
1130 _self_rc: &ItemRc,
1131 _: &mut MouseCursor,
1132 ) -> InputEventResult {
1133 InputEventResult::EventIgnored
1134 }
1135
1136 fn capture_key_event(
1137 self: Pin<&Self>,
1138 _: &InternalKeyEvent,
1139 _window_adapter: &Rc<dyn WindowAdapter>,
1140 _self_rc: &ItemRc,
1141 ) -> KeyEventResult {
1142 KeyEventResult::EventIgnored
1143 }
1144
1145 fn key_event(
1146 self: Pin<&Self>,
1147 _: &InternalKeyEvent,
1148 _window_adapter: &Rc<dyn WindowAdapter>,
1149 _self_rc: &ItemRc,
1150 ) -> KeyEventResult {
1151 KeyEventResult::EventIgnored
1152 }
1153
1154 fn focus_event(
1155 self: Pin<&Self>,
1156 _: &FocusEvent,
1157 _window_adapter: &Rc<dyn WindowAdapter>,
1158 _self_rc: &ItemRc,
1159 ) -> FocusEventResult {
1160 FocusEventResult::FocusIgnored
1161 }
1162
1163 fn render(
1164 self: Pin<&Self>,
1165 backend: &mut ItemRendererRef,
1166 _self_rc: &ItemRc,
1167 _size: LogicalSize,
1168 ) -> RenderingResult {
1169 let origin = self.transform_origin().to_euclid().to_vector();
1170 (*backend).translate(origin);
1171 (*backend).scale(self.transform_scale_x(), self.transform_scale_y());
1172 (*backend).rotate(self.transform_rotation());
1173 (*backend).translate(-origin);
1174 RenderingResult::ContinueRenderingChildren
1175 }
1176
1177 fn bounding_rect(
1178 self: core::pin::Pin<&Self>,
1179 _window_adapter: &Rc<dyn WindowAdapter>,
1180 _self_rc: &ItemRc,
1181 geometry: LogicalRect,
1182 ) -> LogicalRect {
1183 geometry
1184 }
1185
1186 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1187 false
1188 }
1189}
1190
1191impl ItemConsts for Transform {
1192 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1193 Transform,
1194 CachedRenderingData,
1195 > = Transform::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1196}
1197
1198declare_item_vtable! {
1199 fn slint_get_TransformVTable() -> TransformVTable for Transform
1200}
1201
1202declare_item_vtable! {
1203 fn slint_get_FlickableVTable() -> FlickableVTable for Flickable
1204}
1205
1206declare_item_vtable! {
1207 fn slint_get_DragAreaVTable() -> DragAreaVTable for DragArea
1208}
1209
1210declare_item_vtable! {
1211 fn slint_get_DropAreaVTable() -> DropAreaVTable for DropArea
1212}
1213
1214#[repr(C)]
1217#[derive(FieldOffsets, SlintElement, Clone, Debug)]
1218#[pin]
1219pub struct PropertyAnimation {
1220 #[rtti_field]
1221 pub delay: i32,
1222 #[rtti_field]
1224 pub duration: i32,
1225 #[rtti_field]
1226 pub iteration_count: f32,
1227 #[rtti_field]
1228 pub direction: AnimationDirection,
1229 #[rtti_field]
1230 pub easing: crate::animations::EasingCurve,
1231 #[rtti_field]
1232 pub enabled: bool,
1233}
1234
1235impl Default for PropertyAnimation {
1236 fn default() -> Self {
1237 Self {
1240 delay: 0,
1241 duration: 0,
1242 iteration_count: 1.,
1243 direction: Default::default(),
1244 easing: Default::default(),
1245 enabled: true,
1246 }
1247 }
1248}
1249
1250#[repr(C)]
1252#[derive(FieldOffsets, Default, SlintElement)]
1253#[pin]
1254pub struct WindowItem {
1255 pub width: Property<LogicalLength>,
1256 pub height: Property<LogicalLength>,
1257 pub safe_area_insets: Property<crate::lengths::LogicalEdges>,
1258 pub virtual_keyboard_position: Property<crate::lengths::LogicalPoint>,
1259 pub virtual_keyboard_size: Property<crate::lengths::LogicalSize>,
1260 pub background: Property<Brush>,
1261 pub title: Property<SharedString>,
1262 pub no_frame: Property<bool>,
1263 pub resize_border_width: Property<LogicalLength>,
1264 pub always_on_top: Property<bool>,
1265 pub full_screen: Property<bool>,
1266 pub minimized: Property<bool>,
1267 pub maximized: Property<bool>,
1268 pub icon: Property<crate::graphics::Image>,
1269 pub default_font_family: Property<SharedString>,
1270 pub default_font_size: Property<LogicalLength>,
1271 pub default_font_weight: Property<i32>,
1272 pub cached_rendering_data: CachedRenderingData,
1273}
1274
1275impl Item for WindowItem {
1276 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {
1277 #[cfg(feature = "std")]
1278 self.full_screen.set(std::env::var("SLINT_FULLSCREEN").is_ok());
1279 }
1280
1281 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1282
1283 fn layout_info(
1284 self: Pin<&Self>,
1285 _orientation: Orientation,
1286 _cross_axis_constraint: Coord,
1287 _window_adapter: &Rc<dyn WindowAdapter>,
1288 _self_rc: &ItemRc,
1289 ) -> LayoutInfo {
1290 LayoutInfo::default()
1291 }
1292
1293 fn input_event_filter_before_children(
1294 self: Pin<&Self>,
1295 _: &MouseEvent,
1296 _window_adapter: &Rc<dyn WindowAdapter>,
1297 _self_rc: &ItemRc,
1298 _: &mut MouseCursor,
1299 ) -> InputEventFilterResult {
1300 InputEventFilterResult::ForwardAndIgnore
1301 }
1302
1303 fn input_event(
1304 self: Pin<&Self>,
1305 _: &MouseEvent,
1306 _window_adapter: &Rc<dyn WindowAdapter>,
1307 _self_rc: &ItemRc,
1308 _: &mut MouseCursor,
1309 ) -> InputEventResult {
1310 InputEventResult::EventIgnored
1311 }
1312
1313 fn capture_key_event(
1314 self: Pin<&Self>,
1315 _: &InternalKeyEvent,
1316 _window_adapter: &Rc<dyn WindowAdapter>,
1317 _self_rc: &ItemRc,
1318 ) -> KeyEventResult {
1319 KeyEventResult::EventIgnored
1320 }
1321
1322 fn key_event(
1323 self: Pin<&Self>,
1324 _: &InternalKeyEvent,
1325 _window_adapter: &Rc<dyn WindowAdapter>,
1326 _self_rc: &ItemRc,
1327 ) -> KeyEventResult {
1328 KeyEventResult::EventIgnored
1329 }
1330
1331 fn focus_event(
1332 self: Pin<&Self>,
1333 _: &FocusEvent,
1334 _window_adapter: &Rc<dyn WindowAdapter>,
1335 _self_rc: &ItemRc,
1336 ) -> FocusEventResult {
1337 FocusEventResult::FocusIgnored
1338 }
1339
1340 fn render(
1341 self: Pin<&Self>,
1342 backend: &mut ItemRendererRef,
1343 self_rc: &ItemRc,
1344 size: LogicalSize,
1345 ) -> RenderingResult {
1346 if self_rc.parent_item(crate::item_tree::ParentItemTraversalMode::StopAtPopups).is_none() {
1347 backend.draw_window_background(self, self_rc, size, &self.cached_rendering_data);
1348 } else {
1349 backend.draw_rectangle(self, self_rc, size, &self.cached_rendering_data);
1351 }
1352 RenderingResult::ContinueRenderingChildren
1353 }
1354
1355 fn bounding_rect(
1356 self: core::pin::Pin<&Self>,
1357 _window_adapter: &Rc<dyn WindowAdapter>,
1358 _self_rc: &ItemRc,
1359 geometry: LogicalRect,
1360 ) -> LogicalRect {
1361 geometry
1362 }
1363
1364 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1365 false
1366 }
1367}
1368
1369impl RenderRectangle for WindowItem {
1370 fn background(self: Pin<&Self>) -> Brush {
1371 self.background()
1372 }
1373}
1374
1375fn next_window_item(item: &ItemRc) -> Option<ItemRc> {
1376 let root_item_in_local_item_tree = ItemRc::new_root(item.item_tree().clone());
1377
1378 if root_item_in_local_item_tree.downcast::<crate::items::WindowItem>().is_some() {
1379 Some(root_item_in_local_item_tree)
1380 } else {
1381 root_item_in_local_item_tree
1382 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1383 .and_then(|parent| next_window_item(&parent))
1384 }
1385}
1386
1387impl WindowItem {
1388 pub fn font_family(self: Pin<&Self>) -> Option<SharedString> {
1389 let maybe_family = self.default_font_family();
1390 if !maybe_family.is_empty() { Some(maybe_family) } else { None }
1391 }
1392
1393 pub fn font_size(self: Pin<&Self>) -> Option<LogicalLength> {
1394 let font_size = self.default_font_size();
1395 if font_size.get() <= 0 as Coord { None } else { Some(font_size) }
1396 }
1397
1398 pub fn font_weight(self: Pin<&Self>) -> Option<i32> {
1399 let font_weight = self.default_font_weight();
1400 if font_weight == 0 { None } else { Some(font_weight) }
1401 }
1402
1403 pub fn resolved_default_font_size(item_tree: ItemTreeRc) -> LogicalLength {
1404 let first_item = ItemRc::new_root(item_tree);
1405 let window_item = next_window_item(&first_item).unwrap();
1406 Self::resolve_font_property(&window_item, Self::font_size)
1407 .or_else(|| Self::platform_default_font_size(&first_item))
1408 .unwrap_or(crate::textlayout::DEFAULT_FONT_SIZE)
1409 }
1410
1411 fn platform_default_font_size(item: &ItemRc) -> Option<LogicalLength> {
1416 item.window_adapter().and_then(|adapter| {
1417 WindowInner::from_pub(adapter.window()).context().platform_default_font_size()
1418 })
1419 }
1420
1421 fn resolve_font_property<T>(
1422 self_rc: &ItemRc,
1423 property_fn: impl Fn(Pin<&Self>) -> Option<T>,
1424 ) -> Option<T> {
1425 let mut window_item_rc = self_rc.clone();
1426 loop {
1427 let window_item = window_item_rc.downcast::<Self>()?;
1428 if let Some(result) = property_fn(window_item.as_pin_ref()) {
1429 return Some(result);
1430 }
1431
1432 match window_item_rc
1433 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1434 .and_then(|p| next_window_item(&p))
1435 {
1436 Some(item) => window_item_rc = item,
1437 None => return None,
1438 }
1439 }
1440 }
1441
1442 pub fn resolved_font_request(
1446 self_rc: &crate::items::ItemRc,
1447 local_font_family: SharedString,
1448 local_font_weight: i32,
1449 local_font_size: LogicalLength,
1450 local_letter_spacing: LogicalLength,
1451 local_italic: bool,
1452 ) -> FontRequest {
1453 let Some(window_item_rc) = next_window_item(self_rc) else {
1454 return FontRequest::default();
1455 };
1456
1457 FontRequest {
1458 family: {
1459 if !local_font_family.is_empty() {
1460 Some(local_font_family)
1461 } else {
1462 Self::resolve_font_property(
1463 &window_item_rc,
1464 crate::items::WindowItem::font_family,
1465 )
1466 }
1467 },
1468 weight: {
1469 if local_font_weight == 0 {
1470 Self::resolve_font_property(
1471 &window_item_rc,
1472 crate::items::WindowItem::font_weight,
1473 )
1474 } else {
1475 Some(local_font_weight)
1476 }
1477 },
1478 pixel_size: {
1479 if local_font_size.get() == 0 as Coord {
1480 Self::resolve_font_property(
1481 &window_item_rc,
1482 crate::items::WindowItem::font_size,
1483 )
1484 .or_else(|| Self::platform_default_font_size(self_rc))
1485 } else {
1486 Some(local_font_size)
1487 }
1488 },
1489 letter_spacing: Some(local_letter_spacing),
1490 italic: local_italic,
1491 }
1492 }
1493
1494 pub fn close(
1495 self: Pin<&Self>,
1496 window_adapter: &Rc<dyn WindowAdapter>,
1497 self_rc: &ItemRc,
1498 ) -> bool {
1499 if !is_root_window_item(window_adapter, self_rc) {
1500 return false;
1501 }
1502 let inner = WindowInner::from_pub(window_adapter.window());
1503 if inner.request_close()
1504 && let Err(err) = inner.hide()
1505 {
1506 crate::debug_log!("Slint: Failed to hide window after close request: {err}");
1507 }
1508 true
1509 }
1510
1511 pub fn hide(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, self_rc: &ItemRc) {
1512 if !is_root_window_item(window_adapter, self_rc) {
1513 return;
1514 }
1515 let _ = WindowInner::from_pub(window_adapter.window()).hide();
1516 }
1517}
1518
1519fn is_root_window_item(window_adapter: &Rc<dyn WindowAdapter>, self_rc: &ItemRc) -> bool {
1522 if !self_rc.is_root() {
1523 return false;
1524 }
1525
1526 WindowInner::from_pub(window_adapter.window())
1527 .try_component()
1528 .is_some_and(|component| VRc::ptr_eq(&component, self_rc.item_tree()))
1529}
1530
1531impl ItemConsts for WindowItem {
1532 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1533 Self::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1534}
1535
1536#[cfg(feature = "ffi")]
1537#[unsafe(no_mangle)]
1538pub unsafe extern "C" fn slint_windowitem_close(
1539 window_item: Pin<&WindowItem>,
1540 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1541 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1542 self_index: u32,
1543) -> bool {
1544 unsafe {
1545 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1546 let item_rc = ItemRc::new(self_component.clone(), self_index);
1547 window_item.close(window_adapter, &item_rc)
1548 }
1549}
1550
1551#[cfg(feature = "ffi")]
1552#[unsafe(no_mangle)]
1553pub unsafe extern "C" fn slint_windowitem_hide(
1554 window_item: Pin<&WindowItem>,
1555 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1556 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1557 self_index: u32,
1558) {
1559 unsafe {
1560 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1561 let item_rc = ItemRc::new(self_component.clone(), self_index);
1562 window_item.hide(window_adapter, &item_rc);
1563 }
1564}
1565
1566declare_item_vtable! {
1567 fn slint_get_WindowItemVTable() -> WindowItemVTable for WindowItem
1568}
1569
1570#[repr(C)]
1572#[derive(FieldOffsets, Default, SlintElement)]
1573#[pin]
1574pub struct ContextMenu {
1575 pub sub_menu: Callback<MenuEntryArg, MenuEntryModel>,
1577 pub activated: Callback<MenuEntryArg>,
1578 pub show: Callback<PointArg>,
1579 pub cached_rendering_data: CachedRenderingData,
1580 pub popup_id: Cell<Option<NonZeroU32>>,
1581 pub enabled: Property<bool>,
1582 #[cfg(target_os = "android")]
1583 long_press_timer: crate::timers::Timer,
1584}
1585
1586impl Item for ContextMenu {
1587 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1588
1589 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1590
1591 fn layout_info(
1592 self: Pin<&Self>,
1593 _orientation: Orientation,
1594 _cross_axis_constraint: Coord,
1595 _window_adapter: &Rc<dyn WindowAdapter>,
1596 _self_rc: &ItemRc,
1597 ) -> LayoutInfo {
1598 LayoutInfo::default()
1599 }
1600
1601 fn input_event_filter_before_children(
1602 self: Pin<&Self>,
1603 _: &MouseEvent,
1604 _window_adapter: &Rc<dyn WindowAdapter>,
1605 _self_rc: &ItemRc,
1606 _: &mut MouseCursor,
1607 ) -> InputEventFilterResult {
1608 InputEventFilterResult::ForwardEvent
1609 }
1610
1611 fn input_event(
1612 self: Pin<&Self>,
1613 event: &MouseEvent,
1614 _window_adapter: &Rc<dyn WindowAdapter>,
1615 _self_rc: &ItemRc,
1616 _: &mut MouseCursor,
1617 ) -> InputEventResult {
1618 if !self.enabled() {
1619 return InputEventResult::EventIgnored;
1620 }
1621 match event {
1622 MouseEvent::Pressed { position, button: PointerEventButton::Right, .. } => {
1623 self.show.call(&(LogicalPosition::from_euclid(*position),));
1624 InputEventResult::EventAccepted
1625 }
1626 #[cfg(target_os = "android")]
1627 MouseEvent::Pressed { position, button: PointerEventButton::Left, .. } => {
1628 let self_weak = _self_rc.downgrade();
1629 let position = *position;
1630 self.long_press_timer.start(
1631 crate::timers::TimerMode::SingleShot,
1632 WindowInner::from_pub(_window_adapter.window())
1633 .context()
1634 .platform()
1635 .long_press_interval(crate::InternalToken),
1636 move || {
1637 let Some(self_rc) = self_weak.upgrade() else { return };
1638 let Some(self_) = self_rc.downcast::<ContextMenu>() else { return };
1639 self_.show.call(&(LogicalPosition::from_euclid(position),));
1640 },
1641 );
1642 InputEventResult::GrabMouse
1643 }
1644 #[cfg(target_os = "android")]
1645 MouseEvent::Released { .. } | MouseEvent::Exit => {
1646 self.long_press_timer.stop();
1647 InputEventResult::EventIgnored
1648 }
1649 #[cfg(target_os = "android")]
1650 MouseEvent::Moved { .. } => InputEventResult::EventAccepted,
1651 _ => InputEventResult::EventIgnored,
1652 }
1653 }
1654
1655 fn capture_key_event(
1656 self: Pin<&Self>,
1657 _: &InternalKeyEvent,
1658 _window_adapter: &Rc<dyn WindowAdapter>,
1659 _self_rc: &ItemRc,
1660 ) -> KeyEventResult {
1661 KeyEventResult::EventIgnored
1662 }
1663
1664 fn key_event(
1665 self: Pin<&Self>,
1666 event: &InternalKeyEvent,
1667 _window_adapter: &Rc<dyn WindowAdapter>,
1668 _self_rc: &ItemRc,
1669 ) -> KeyEventResult {
1670 if !self.enabled() {
1671 return KeyEventResult::EventIgnored;
1672 }
1673
1674 fn is_menu_key(event: &InternalKeyEvent) -> bool {
1675 #[allow(unused_mut)]
1676 let mut is_menu_key = event.key_event.text.contains(crate::input::key_codes::Menu);
1677 #[cfg(target_os = "windows")]
1678 {
1679 is_menu_key |= event.key_event.text.contains(crate::input::key_codes::F10)
1681 && event.key_event.modifiers.shift;
1682 }
1683 is_menu_key
1684 }
1685
1686 if is_menu_key(event) {
1687 self.show.call(&(Default::default(),));
1688 KeyEventResult::EventAccepted
1689 } else {
1690 KeyEventResult::EventIgnored
1691 }
1692 }
1693
1694 fn focus_event(
1695 self: Pin<&Self>,
1696 _: &FocusEvent,
1697 _window_adapter: &Rc<dyn WindowAdapter>,
1698 _self_rc: &ItemRc,
1699 ) -> FocusEventResult {
1700 FocusEventResult::FocusIgnored
1701 }
1702
1703 fn render(
1704 self: Pin<&Self>,
1705 _backend: &mut ItemRendererRef,
1706 _self_rc: &ItemRc,
1707 _size: LogicalSize,
1708 ) -> RenderingResult {
1709 RenderingResult::ContinueRenderingChildren
1710 }
1711
1712 fn bounding_rect(
1713 self: core::pin::Pin<&Self>,
1714 _window_adapter: &Rc<dyn WindowAdapter>,
1715 _self_rc: &ItemRc,
1716 geometry: LogicalRect,
1717 ) -> LogicalRect {
1718 geometry
1719 }
1720
1721 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1722 false
1723 }
1724}
1725
1726impl ContextMenu {
1727 pub fn close(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) {
1728 if let Some(id) = self.popup_id.take() {
1729 WindowInner::from_pub(window_adapter.window()).close_popup(id);
1730 }
1731 }
1732
1733 pub fn is_open(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) -> bool {
1734 self.popup_id.get().is_some_and(|id| {
1735 WindowInner::from_pub(window_adapter.window())
1736 .active_popups()
1737 .iter()
1738 .any(|p| p.popup_id == id)
1739 })
1740 }
1741}
1742
1743impl ItemConsts for ContextMenu {
1744 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1745 Self::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1746}
1747
1748declare_item_vtable! {
1749 fn slint_get_ContextMenuVTable() -> ContextMenuVTable for ContextMenu
1750}
1751
1752#[cfg(feature = "ffi")]
1753#[unsafe(no_mangle)]
1754pub unsafe extern "C" fn slint_contextmenu_close(
1755 s: Pin<&ContextMenu>,
1756 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1757 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1758 self_index: u32,
1759) {
1760 unsafe {
1761 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1762 let self_rc = ItemRc::new(self_component.clone(), self_index);
1763 s.close(window_adapter, &self_rc);
1764 }
1765}
1766
1767#[cfg(feature = "ffi")]
1768#[unsafe(no_mangle)]
1769pub unsafe extern "C" fn slint_contextmenu_is_open(
1770 s: Pin<&ContextMenu>,
1771 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1772 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1773 self_index: u32,
1774) -> bool {
1775 unsafe {
1776 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1777 let self_rc = ItemRc::new(self_component.clone(), self_index);
1778 s.is_open(window_adapter, &self_rc)
1779 }
1780}
1781
1782#[repr(C)]
1784#[derive(FieldOffsets, Default, SlintElement)]
1785#[pin]
1786pub struct BoxShadow {
1787 pub border_top_left_radius: Property<LogicalLength>,
1788 pub border_top_right_radius: Property<LogicalLength>,
1789 pub border_bottom_left_radius: Property<LogicalLength>,
1790 pub border_bottom_right_radius: Property<LogicalLength>,
1791 pub offset_x: Property<LogicalLength>,
1793 pub offset_y: Property<LogicalLength>,
1794 pub color: Property<Color>,
1795 pub blur: Property<LogicalLength>,
1796 pub spread: Property<LogicalLength>,
1797 pub inset: Property<bool>,
1798 pub cached_rendering_data: CachedRenderingData,
1799}
1800
1801impl BoxShadow {
1802 pub fn logical_border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
1803 LogicalBorderRadius::from_lengths(
1804 self.border_top_left_radius(),
1805 self.border_top_right_radius(),
1806 self.border_bottom_right_radius(),
1807 self.border_bottom_left_radius(),
1808 )
1809 }
1810}
1811
1812impl Item for BoxShadow {
1813 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1814
1815 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1816
1817 fn layout_info(
1818 self: Pin<&Self>,
1819 _orientation: Orientation,
1820 _cross_axis_constraint: Coord,
1821 _window_adapter: &Rc<dyn WindowAdapter>,
1822 _self_rc: &ItemRc,
1823 ) -> LayoutInfo {
1824 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1825 }
1826
1827 fn input_event_filter_before_children(
1828 self: Pin<&Self>,
1829 _: &MouseEvent,
1830 _window_adapter: &Rc<dyn WindowAdapter>,
1831 _self_rc: &ItemRc,
1832 _: &mut MouseCursor,
1833 ) -> InputEventFilterResult {
1834 InputEventFilterResult::ForwardAndIgnore
1835 }
1836
1837 fn input_event(
1838 self: Pin<&Self>,
1839 _: &MouseEvent,
1840 _window_adapter: &Rc<dyn WindowAdapter>,
1841 _self_rc: &ItemRc,
1842 _: &mut MouseCursor,
1843 ) -> InputEventResult {
1844 InputEventResult::EventIgnored
1845 }
1846
1847 fn capture_key_event(
1848 self: Pin<&Self>,
1849 _: &InternalKeyEvent,
1850 _window_adapter: &Rc<dyn WindowAdapter>,
1851 _self_rc: &ItemRc,
1852 ) -> KeyEventResult {
1853 KeyEventResult::EventIgnored
1854 }
1855
1856 fn key_event(
1857 self: Pin<&Self>,
1858 _: &InternalKeyEvent,
1859 _window_adapter: &Rc<dyn WindowAdapter>,
1860 _self_rc: &ItemRc,
1861 ) -> KeyEventResult {
1862 KeyEventResult::EventIgnored
1863 }
1864
1865 fn focus_event(
1866 self: Pin<&Self>,
1867 _: &FocusEvent,
1868 _window_adapter: &Rc<dyn WindowAdapter>,
1869 _self_rc: &ItemRc,
1870 ) -> FocusEventResult {
1871 FocusEventResult::FocusIgnored
1872 }
1873
1874 fn render(
1875 self: Pin<&Self>,
1876 backend: &mut ItemRendererRef,
1877 self_rc: &ItemRc,
1878 size: LogicalSize,
1879 ) -> RenderingResult {
1880 (*backend).draw_box_shadow(self, self_rc, size);
1881 RenderingResult::ContinueRenderingChildren
1882 }
1883
1884 fn bounding_rect(
1885 self: core::pin::Pin<&Self>,
1886 _window_adapter: &Rc<dyn WindowAdapter>,
1887 _self_rc: &ItemRc,
1888 geometry: LogicalRect,
1889 ) -> LogicalRect {
1890 if self.inset() {
1891 geometry
1893 } else {
1894 let pad = self.blur() + LogicalLength::new(self.spread().get().max(0 as crate::Coord));
1895 geometry
1896 .outer_rect(euclid::SideOffsets2D::from_length_all_same(pad))
1897 .translate(LogicalVector::from_lengths(self.offset_x(), self.offset_y()))
1898 }
1899 }
1900
1901 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1902 false
1903 }
1904}
1905
1906impl ItemConsts for BoxShadow {
1907 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1908 Self::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1909}
1910
1911declare_item_vtable! {
1912 fn slint_get_BoxShadowVTable() -> BoxShadowVTable for BoxShadow
1913}
1914
1915declare_item_vtable! {
1916 fn slint_get_ComponentContainerVTable() -> ComponentContainerVTable for ComponentContainer
1917}
1918
1919declare_item_vtable! {
1920 fn slint_get_ComplexTextVTable() -> ComplexTextVTable for ComplexText
1921}
1922
1923declare_item_vtable! {
1924 fn slint_get_StyledTextItemVTable() -> StyledTextItemVTable for StyledTextItem
1925}
1926
1927declare_item_vtable! {
1928 fn slint_get_SimpleTextVTable() -> SimpleTextVTable for SimpleText
1929}
1930
1931declare_item_vtable! {
1932 fn slint_get_TextInputVTable() -> TextInputVTable for TextInput
1933}
1934
1935declare_item_vtable! {
1936 fn slint_get_ImageItemVTable() -> ImageItemVTable for ImageItem
1937}
1938
1939declare_item_vtable! {
1940 fn slint_get_ClippedImageVTable() -> ClippedImageVTable for ClippedImage
1941}
1942
1943#[cfg(feature = "path")]
1944declare_item_vtable! {
1945 fn slint_get_PathVTable() -> PathVTable for Path
1946}
1947
1948declare_item_vtable! {
1949 fn slint_get_MenuItemVTable() -> MenuItemVTable for MenuItem
1950}
1951
1952declare_item_vtable! {
1953 fn slint_get_SystemTrayIconVTable() -> SystemTrayIconVTable for SystemTrayIcon
1954}
1955
1956macro_rules! declare_enums {
1957 ($( $(#[$enum_doc:meta])* $vis:vis enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
1958 $(
1959 #[derive(Copy, Clone, Debug, PartialEq, Eq, strum::EnumString, strum::Display, Hash)]
1960 #[repr(u32)]
1961 #[strum(serialize_all = "kebab-case")]
1962 $(#[$enum_doc])*
1963 pub enum $Name {
1964 $( $(#[$value_doc])* $Value),*
1965 }
1966
1967 impl Default for $Name {
1968 fn default() -> Self {
1969 ($(Self::$Value,)*).0
1971 }
1972 }
1973 )*
1974 };
1975}
1976
1977i_slint_common::for_each_enums!(declare_enums);
1978
1979#[repr(C)]
1981#[derive(FieldOffsets, Default, SlintElement)]
1982#[pin]
1983pub struct TooltipArea {
1984 pub has_hover: Property<bool>,
1985 pub mouse_x: Property<LogicalLength>,
1986 pub mouse_y: Property<LogicalLength>,
1987 pub text: Property<crate::styled_text::StyledText>,
1988 pub delay: Property<i64>,
1989 pub offset: Property<LogicalLength>,
1990 pub show: Callback<VoidArg>,
1991 pub hide: Callback<VoidArg>,
1992 pub cached_rendering_data: CachedRenderingData,
1993 popup_visible: Cell<bool>,
1994 timer: crate::timers::Timer,
1995}
1996
1997impl Item for TooltipArea {
1998 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1999
2000 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
2001
2002 fn layout_info(
2003 self: Pin<&Self>,
2004 _orientation: Orientation,
2005 _cross_axis_constraint: Coord,
2006 _window_adapter: &Rc<dyn WindowAdapter>,
2007 _self_rc: &ItemRc,
2008 ) -> LayoutInfo {
2009 LayoutInfo::default()
2010 }
2011
2012 fn input_event_filter_before_children(
2013 self: Pin<&Self>,
2014 event: &MouseEvent,
2015 _window_adapter: &Rc<dyn WindowAdapter>,
2016 self_rc: &ItemRc,
2017 _: &mut MouseCursor,
2018 ) -> InputEventFilterResult {
2019 if matches!(event, MouseEvent::DragMove { .. } | MouseEvent::Drop { .. }) {
2022 self.set_hover_state(false, self_rc);
2023 return InputEventFilterResult::ForwardAndIgnore;
2024 }
2025
2026 if let Some(pos) = event.position() {
2027 Self::FIELD_OFFSETS.mouse_x().apply_pin(self).set(pos.x_length());
2028 Self::FIELD_OFFSETS.mouse_y().apply_pin(self).set(pos.y_length());
2029 }
2030
2031 let next_hover = !matches!(event, MouseEvent::Exit);
2032 self.set_hover_state(next_hover, self_rc);
2033
2034 if next_hover && !self.popup_visible.get() && matches!(event, MouseEvent::Moved { .. }) {
2035 self.schedule_show(self_rc);
2036 }
2037
2038 InputEventFilterResult::ForwardAndObserve
2041 }
2042
2043 fn input_event(
2044 self: Pin<&Self>,
2045 event: &MouseEvent,
2046 _window_adapter: &Rc<dyn WindowAdapter>,
2047 _self_rc: &ItemRc,
2048 _: &mut MouseCursor,
2049 ) -> InputEventResult {
2050 if matches!(event, MouseEvent::Exit) {
2051 self.set_hover_state(false, _self_rc);
2052 }
2053 InputEventResult::EventIgnored
2054 }
2055
2056 fn capture_key_event(
2057 self: Pin<&Self>,
2058 _: &InternalKeyEvent,
2059 _window_adapter: &Rc<dyn WindowAdapter>,
2060 _self_rc: &ItemRc,
2061 ) -> KeyEventResult {
2062 KeyEventResult::EventIgnored
2063 }
2064
2065 fn key_event(
2066 self: Pin<&Self>,
2067 _: &InternalKeyEvent,
2068 _window_adapter: &Rc<dyn WindowAdapter>,
2069 _self_rc: &ItemRc,
2070 ) -> KeyEventResult {
2071 KeyEventResult::EventIgnored
2072 }
2073
2074 fn focus_event(
2075 self: Pin<&Self>,
2076 _: &FocusEvent,
2077 _window_adapter: &Rc<dyn WindowAdapter>,
2078 _self_rc: &ItemRc,
2079 ) -> FocusEventResult {
2080 FocusEventResult::FocusIgnored
2081 }
2082
2083 fn render(
2084 self: Pin<&Self>,
2085 _backend: &mut ItemRendererRef,
2086 _self_rc: &ItemRc,
2087 _size: LogicalSize,
2088 ) -> RenderingResult {
2089 RenderingResult::ContinueRenderingChildren
2090 }
2091
2092 fn bounding_rect(
2093 self: core::pin::Pin<&Self>,
2094 _window_adapter: &Rc<dyn WindowAdapter>,
2095 _self_rc: &ItemRc,
2096 geometry: LogicalRect,
2097 ) -> LogicalRect {
2098 geometry
2099 }
2100
2101 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
2102 false
2103 }
2104}
2105
2106impl TooltipArea {
2107 fn schedule_show(self: Pin<&Self>, self_rc: &ItemRc) {
2108 let delay_ms = self.delay().max(0) as u64;
2109 if delay_ms == 0 {
2110 if self.has_hover() {
2111 self.show.call(&());
2112 self.popup_visible.set(true);
2113 }
2114 return;
2115 }
2116
2117 let self_weak = self_rc.downgrade();
2118 self.timer.start(
2119 crate::timers::TimerMode::SingleShot,
2120 Duration::from_millis(delay_ms),
2121 move || {
2122 let Some(self_rc) = self_weak.upgrade() else { return };
2123 let Some(tooltip_area) = self_rc.downcast::<TooltipArea>() else { return };
2124 let tooltip_area = tooltip_area.as_pin_ref();
2125 if tooltip_area.has_hover() {
2126 tooltip_area.show.call(&());
2127 tooltip_area.popup_visible.set(true);
2128 }
2129 },
2130 );
2131 }
2132
2133 fn hide_now(self: Pin<&Self>) {
2134 self.timer.stop();
2135 if self.popup_visible.replace(false) {
2136 self.hide.call(&());
2137 }
2138 }
2139
2140 fn set_hover_state(self: Pin<&Self>, new_hover: bool, self_rc: &ItemRc) {
2141 let old_hover = self.has_hover();
2142 if old_hover == new_hover {
2143 return;
2144 }
2145
2146 Self::FIELD_OFFSETS.has_hover().apply_pin(self).set(new_hover);
2147 if new_hover {
2148 self.schedule_show(self_rc);
2149 } else {
2150 self.hide_now();
2151 }
2152 }
2153}
2154
2155impl ItemConsts for TooltipArea {
2156 const cached_rendering_data_offset: const_field_offset::FieldOffset<
2157 TooltipArea,
2158 CachedRenderingData,
2159 > = TooltipArea::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
2160}
2161
2162declare_item_vtable! {
2163 fn slint_get_TooltipAreaVTable() -> TooltipAreaVTable for TooltipArea
2164}
2165
2166macro_rules! declare_builtin_structs {
2167 ($(
2168 $(#[$struct_attr:meta])*
2169 $vis:vis struct $Name:ident {
2170 $( $(#[$field_attr:meta])* $field:ident : $field_type:ty, )*
2171 }
2172 )*) => {
2173 $(
2174 #[derive(Clone, Debug, Default, PartialEq)]
2175 #[repr(C)]
2176 $(#[$struct_attr])*
2177 pub struct $Name {
2178 $(
2179 $(#[$field_attr])*
2180 pub $field : $field_type,
2181 )*
2182 }
2183 )*
2184 };
2185}
2186
2187i_slint_common::for_each_builtin_structs!(declare_builtin_structs);
2188
2189#[cfg(feature = "ffi")]
2190#[unsafe(no_mangle)]
2191pub unsafe extern "C" fn slint_item_absolute_position(
2192 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
2193 self_index: u32,
2194) -> crate::lengths::LogicalPoint {
2195 let self_rc = ItemRc::new(self_component.clone(), self_index);
2196 self_rc.map_to_window(Default::default())
2197}