1#![allow(unsafe_code)]
20#![allow(non_upper_case_globals)]
21#![allow(missing_docs)] use crate::graphics::{Brush, Color, FontRequest};
24use crate::input::{
25 FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEventResult,
26 KeyEventType, MouseEvent,
27};
28use crate::item_rendering::{CachedRenderingData, RenderBorderRectangle, RenderRectangle};
29pub use crate::item_tree::{ItemRc, ItemTreeVTable};
30use crate::layout::LayoutInfo;
31use crate::lengths::{
32 LogicalBorderRadius, LogicalLength, LogicalRect, LogicalSize, LogicalVector, PointLengths,
33 RectLengths,
34};
35#[cfg(feature = "rtti")]
36use crate::rtti::*;
37use crate::window::{WindowAdapter, WindowAdapterRc, WindowInner};
38use crate::{Callback, Coord, Property, SharedString};
39use alloc::rc::Rc;
40use const_field_offset::FieldOffsets;
41use core::cell::Cell;
42use core::num::NonZeroU32;
43use core::pin::Pin;
44use i_slint_core_macros::*;
45use vtable::*;
46
47mod component_container;
48pub use self::component_container::*;
49mod flickable;
50pub use flickable::Flickable;
51mod text;
52pub use text::*;
53mod input_items;
54pub use input_items::*;
55mod image;
56pub use self::image::*;
57#[cfg(feature = "std")]
58mod path;
59pub use crate::menus::MenuItem;
60#[cfg(feature = "std")]
61pub use path::*;
62
63type ItemRendererRef<'a> = &'a mut dyn crate::item_rendering::ItemRenderer;
66
67pub type VoidArg = ();
69pub type KeyEventArg = (KeyEvent,);
70type FocusReasonArg = (FocusReason,);
71type PointerEventArg = (PointerEvent,);
72type PointerScrollEventArg = (PointerScrollEvent,);
73type PointArg = (crate::api::LogicalPosition,);
74type MenuEntryArg = (MenuEntry,);
75type MenuEntryModel = crate::model::ModelRc<MenuEntry>;
76
77#[cfg(all(feature = "ffi", windows))]
78#[macro_export]
79macro_rules! declare_item_vtable {
80 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
81 ItemVTable_static! {
82 #[unsafe(no_mangle)]
83 pub static $item_vtable_ty for $item_ty
84 }
85 #[unsafe(no_mangle)]
86 pub extern "C" fn $getter() -> *const ItemVTable {
87 use vtable::HasStaticVTable;
88 <$item_ty>::static_vtable()
89 }
90 };
91}
92#[cfg(not(all(feature = "ffi", windows)))]
93#[macro_export]
94macro_rules! declare_item_vtable {
95 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
96 ItemVTable_static! {
97 #[unsafe(no_mangle)]
98 pub static $item_vtable_ty for $item_ty
99 }
100 };
101}
102
103#[repr(C)]
107#[derive(Default)]
108pub enum RenderingResult {
109 #[default]
110 ContinueRenderingChildren,
111 ContinueRenderingWithoutChildren,
112}
113
114#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
116#[vtable]
117#[repr(C)]
118pub struct ItemVTable {
119 pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, my_item: &ItemRc),
123
124 #[allow(non_upper_case_globals)]
127 #[field_offset(CachedRenderingData)]
128 pub cached_rendering_data_offset: usize,
129
130 pub layout_info: extern "C" fn(
132 core::pin::Pin<VRef<ItemVTable>>,
133 orientation: Orientation,
134 window_adapter: &WindowAdapterRc,
135 self_rc: &ItemRc,
136 ) -> LayoutInfo,
137
138 pub input_event_filter_before_children: extern "C" fn(
143 core::pin::Pin<VRef<ItemVTable>>,
144 MouseEvent,
145 window_adapter: &WindowAdapterRc,
146 self_rc: &ItemRc,
147 ) -> InputEventFilterResult,
148
149 pub input_event: extern "C" fn(
151 core::pin::Pin<VRef<ItemVTable>>,
152 MouseEvent,
153 window_adapter: &WindowAdapterRc,
154 self_rc: &ItemRc,
155 ) -> InputEventResult,
156
157 pub focus_event: extern "C" fn(
158 core::pin::Pin<VRef<ItemVTable>>,
159 &FocusEvent,
160 window_adapter: &WindowAdapterRc,
161 self_rc: &ItemRc,
162 ) -> FocusEventResult,
163
164 pub key_event: extern "C" fn(
165 core::pin::Pin<VRef<ItemVTable>>,
166 &KeyEvent,
167 window_adapter: &WindowAdapterRc,
168 self_rc: &ItemRc,
169 ) -> KeyEventResult,
170
171 pub render: extern "C" fn(
172 core::pin::Pin<VRef<ItemVTable>>,
173 backend: &mut ItemRendererRef,
174 self_rc: &ItemRc,
175 size: LogicalSize,
176 ) -> RenderingResult,
177
178 pub bounding_rect: extern "C" fn(
179 core::pin::Pin<VRef<ItemVTable>>,
180 window_adapter: &WindowAdapterRc,
181 self_rc: &ItemRc,
182 geometry: LogicalRect,
183 ) -> LogicalRect,
184
185 pub clips_children: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>) -> bool,
186}
187
188pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
191
192#[repr(C)]
193#[derive(FieldOffsets, Default, SlintElement)]
194#[pin]
195pub struct Empty {
197 pub cached_rendering_data: CachedRenderingData,
198}
199
200impl Item for Empty {
201 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
202
203 fn layout_info(
204 self: Pin<&Self>,
205 _orientation: Orientation,
206 _window_adapter: &Rc<dyn WindowAdapter>,
207 _self_rc: &ItemRc,
208 ) -> LayoutInfo {
209 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
210 }
211
212 fn input_event_filter_before_children(
213 self: Pin<&Self>,
214 _: MouseEvent,
215 _window_adapter: &Rc<dyn WindowAdapter>,
216 _self_rc: &ItemRc,
217 ) -> InputEventFilterResult {
218 InputEventFilterResult::ForwardAndIgnore
219 }
220
221 fn input_event(
222 self: Pin<&Self>,
223 _: MouseEvent,
224 _window_adapter: &Rc<dyn WindowAdapter>,
225 _self_rc: &ItemRc,
226 ) -> InputEventResult {
227 InputEventResult::EventIgnored
228 }
229
230 fn key_event(
231 self: Pin<&Self>,
232 _: &KeyEvent,
233 _window_adapter: &Rc<dyn WindowAdapter>,
234 _self_rc: &ItemRc,
235 ) -> KeyEventResult {
236 KeyEventResult::EventIgnored
237 }
238
239 fn focus_event(
240 self: Pin<&Self>,
241 _: &FocusEvent,
242 _window_adapter: &Rc<dyn WindowAdapter>,
243 _self_rc: &ItemRc,
244 ) -> FocusEventResult {
245 FocusEventResult::FocusIgnored
246 }
247
248 fn render(
249 self: Pin<&Self>,
250 _backend: &mut ItemRendererRef,
251 _self_rc: &ItemRc,
252 _size: LogicalSize,
253 ) -> RenderingResult {
254 RenderingResult::ContinueRenderingChildren
255 }
256
257 fn bounding_rect(
258 self: core::pin::Pin<&Self>,
259 _window_adapter: &Rc<dyn WindowAdapter>,
260 _self_rc: &ItemRc,
261 mut geometry: LogicalRect,
262 ) -> LogicalRect {
263 geometry.size = LogicalSize::zero();
264 geometry
265 }
266
267 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
268 false
269 }
270}
271
272impl ItemConsts for Empty {
273 const cached_rendering_data_offset: const_field_offset::FieldOffset<
274 Empty,
275 CachedRenderingData,
276 > = Empty::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
277}
278
279declare_item_vtable! {
280 fn slint_get_EmptyVTable() -> EmptyVTable for Empty
281}
282
283#[repr(C)]
284#[derive(FieldOffsets, Default, SlintElement)]
285#[pin]
286pub struct Rectangle {
288 pub background: Property<Brush>,
289 pub cached_rendering_data: CachedRenderingData,
290}
291
292impl Item for Rectangle {
293 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
294
295 fn layout_info(
296 self: Pin<&Self>,
297 _orientation: Orientation,
298 _window_adapter: &Rc<dyn WindowAdapter>,
299 _self_rc: &ItemRc,
300 ) -> LayoutInfo {
301 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
302 }
303
304 fn input_event_filter_before_children(
305 self: Pin<&Self>,
306 _: MouseEvent,
307 _window_adapter: &Rc<dyn WindowAdapter>,
308 _self_rc: &ItemRc,
309 ) -> InputEventFilterResult {
310 InputEventFilterResult::ForwardAndIgnore
311 }
312
313 fn input_event(
314 self: Pin<&Self>,
315 _: MouseEvent,
316 _window_adapter: &Rc<dyn WindowAdapter>,
317 _self_rc: &ItemRc,
318 ) -> InputEventResult {
319 InputEventResult::EventIgnored
320 }
321
322 fn key_event(
323 self: Pin<&Self>,
324 _: &KeyEvent,
325 _window_adapter: &Rc<dyn WindowAdapter>,
326 _self_rc: &ItemRc,
327 ) -> KeyEventResult {
328 KeyEventResult::EventIgnored
329 }
330
331 fn focus_event(
332 self: Pin<&Self>,
333 _: &FocusEvent,
334 _window_adapter: &Rc<dyn WindowAdapter>,
335 _self_rc: &ItemRc,
336 ) -> FocusEventResult {
337 FocusEventResult::FocusIgnored
338 }
339
340 fn render(
341 self: Pin<&Self>,
342 backend: &mut ItemRendererRef,
343 self_rc: &ItemRc,
344 size: LogicalSize,
345 ) -> RenderingResult {
346 (*backend).draw_rectangle(self, self_rc, size, &self.cached_rendering_data);
347 RenderingResult::ContinueRenderingChildren
348 }
349
350 fn bounding_rect(
351 self: core::pin::Pin<&Self>,
352 _window_adapter: &Rc<dyn WindowAdapter>,
353 _self_rc: &ItemRc,
354 geometry: LogicalRect,
355 ) -> LogicalRect {
356 geometry
357 }
358
359 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
360 false
361 }
362}
363
364impl RenderRectangle for Rectangle {
365 fn background(self: Pin<&Self>) -> Brush {
366 self.background()
367 }
368}
369
370impl ItemConsts for Rectangle {
371 const cached_rendering_data_offset: const_field_offset::FieldOffset<
372 Rectangle,
373 CachedRenderingData,
374 > = Rectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
375}
376
377declare_item_vtable! {
378 fn slint_get_RectangleVTable() -> RectangleVTable for Rectangle
379}
380
381#[repr(C)]
382#[derive(FieldOffsets, Default, SlintElement)]
383#[pin]
384pub struct BasicBorderRectangle {
386 pub background: Property<Brush>,
387 pub border_width: Property<LogicalLength>,
388 pub border_radius: Property<LogicalLength>,
389 pub border_color: Property<Brush>,
390 pub cached_rendering_data: CachedRenderingData,
391}
392
393impl Item for BasicBorderRectangle {
394 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
395
396 fn layout_info(
397 self: Pin<&Self>,
398 _orientation: Orientation,
399 _window_adapter: &Rc<dyn WindowAdapter>,
400 _self_rc: &ItemRc,
401 ) -> LayoutInfo {
402 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
403 }
404
405 fn input_event_filter_before_children(
406 self: Pin<&Self>,
407 _: MouseEvent,
408 _window_adapter: &Rc<dyn WindowAdapter>,
409 _self_rc: &ItemRc,
410 ) -> InputEventFilterResult {
411 InputEventFilterResult::ForwardAndIgnore
412 }
413
414 fn input_event(
415 self: Pin<&Self>,
416 _: MouseEvent,
417 _window_adapter: &Rc<dyn WindowAdapter>,
418 _self_rc: &ItemRc,
419 ) -> InputEventResult {
420 InputEventResult::EventIgnored
421 }
422
423 fn key_event(
424 self: Pin<&Self>,
425 _: &KeyEvent,
426 _window_adapter: &Rc<dyn WindowAdapter>,
427 _self_rc: &ItemRc,
428 ) -> KeyEventResult {
429 KeyEventResult::EventIgnored
430 }
431
432 fn focus_event(
433 self: Pin<&Self>,
434 _: &FocusEvent,
435 _window_adapter: &Rc<dyn WindowAdapter>,
436 _self_rc: &ItemRc,
437 ) -> FocusEventResult {
438 FocusEventResult::FocusIgnored
439 }
440
441 fn render(
442 self: Pin<&Self>,
443 backend: &mut ItemRendererRef,
444 self_rc: &ItemRc,
445 size: LogicalSize,
446 ) -> RenderingResult {
447 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
448 RenderingResult::ContinueRenderingChildren
449 }
450
451 fn bounding_rect(
452 self: core::pin::Pin<&Self>,
453 _window_adapter: &Rc<dyn WindowAdapter>,
454 _self_rc: &ItemRc,
455 geometry: LogicalRect,
456 ) -> LogicalRect {
457 geometry
458 }
459
460 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
461 false
462 }
463}
464
465impl RenderBorderRectangle for BasicBorderRectangle {
466 fn background(self: Pin<&Self>) -> Brush {
467 self.background()
468 }
469 fn border_width(self: Pin<&Self>) -> LogicalLength {
470 self.border_width()
471 }
472 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
473 LogicalBorderRadius::from_length(self.border_radius())
474 }
475 fn border_color(self: Pin<&Self>) -> Brush {
476 self.border_color()
477 }
478}
479
480impl ItemConsts for BasicBorderRectangle {
481 const cached_rendering_data_offset: const_field_offset::FieldOffset<
482 BasicBorderRectangle,
483 CachedRenderingData,
484 > = BasicBorderRectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
485}
486
487declare_item_vtable! {
488 fn slint_get_BasicBorderRectangleVTable() -> BasicBorderRectangleVTable for BasicBorderRectangle
489}
490
491#[repr(C)]
492#[derive(FieldOffsets, Default, SlintElement)]
493#[pin]
494pub struct BorderRectangle {
496 pub background: Property<Brush>,
497 pub border_width: Property<LogicalLength>,
498 pub border_radius: Property<LogicalLength>,
499 pub border_top_left_radius: Property<LogicalLength>,
500 pub border_top_right_radius: Property<LogicalLength>,
501 pub border_bottom_left_radius: Property<LogicalLength>,
502 pub border_bottom_right_radius: Property<LogicalLength>,
503 pub border_color: Property<Brush>,
504 pub cached_rendering_data: CachedRenderingData,
505}
506
507impl Item for BorderRectangle {
508 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
509
510 fn layout_info(
511 self: Pin<&Self>,
512 _orientation: Orientation,
513 _window_adapter: &Rc<dyn WindowAdapter>,
514 _self_rc: &ItemRc,
515 ) -> LayoutInfo {
516 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
517 }
518
519 fn input_event_filter_before_children(
520 self: Pin<&Self>,
521 _: MouseEvent,
522 _window_adapter: &Rc<dyn WindowAdapter>,
523 _self_rc: &ItemRc,
524 ) -> InputEventFilterResult {
525 InputEventFilterResult::ForwardAndIgnore
526 }
527
528 fn input_event(
529 self: Pin<&Self>,
530 _: MouseEvent,
531 _window_adapter: &Rc<dyn WindowAdapter>,
532 _self_rc: &ItemRc,
533 ) -> InputEventResult {
534 InputEventResult::EventIgnored
535 }
536
537 fn key_event(
538 self: Pin<&Self>,
539 _: &KeyEvent,
540 _window_adapter: &Rc<dyn WindowAdapter>,
541 _self_rc: &ItemRc,
542 ) -> KeyEventResult {
543 KeyEventResult::EventIgnored
544 }
545
546 fn focus_event(
547 self: Pin<&Self>,
548 _: &FocusEvent,
549 _window_adapter: &Rc<dyn WindowAdapter>,
550 _self_rc: &ItemRc,
551 ) -> FocusEventResult {
552 FocusEventResult::FocusIgnored
553 }
554
555 fn render(
556 self: Pin<&Self>,
557 backend: &mut ItemRendererRef,
558 self_rc: &ItemRc,
559 size: LogicalSize,
560 ) -> RenderingResult {
561 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
562 RenderingResult::ContinueRenderingChildren
563 }
564
565 fn bounding_rect(
566 self: core::pin::Pin<&Self>,
567 _window_adapter: &Rc<dyn WindowAdapter>,
568 _self_rc: &ItemRc,
569 geometry: LogicalRect,
570 ) -> LogicalRect {
571 geometry
572 }
573
574 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
575 false
576 }
577}
578
579impl RenderBorderRectangle for BorderRectangle {
580 fn background(self: Pin<&Self>) -> Brush {
581 self.background()
582 }
583 fn border_width(self: Pin<&Self>) -> LogicalLength {
584 self.border_width()
585 }
586 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
587 LogicalBorderRadius::from_lengths(
588 self.border_top_left_radius(),
589 self.border_top_right_radius(),
590 self.border_bottom_right_radius(),
591 self.border_bottom_left_radius(),
592 )
593 }
594 fn border_color(self: Pin<&Self>) -> Brush {
595 self.border_color()
596 }
597}
598
599impl ItemConsts for BorderRectangle {
600 const cached_rendering_data_offset: const_field_offset::FieldOffset<
601 BorderRectangle,
602 CachedRenderingData,
603 > = BorderRectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
604}
605
606declare_item_vtable! {
607 fn slint_get_BorderRectangleVTable() -> BorderRectangleVTable for BorderRectangle
608}
609
610declare_item_vtable! {
611 fn slint_get_TouchAreaVTable() -> TouchAreaVTable for TouchArea
612}
613
614declare_item_vtable! {
615 fn slint_get_FocusScopeVTable() -> FocusScopeVTable for FocusScope
616}
617
618declare_item_vtable! {
619 fn slint_get_SwipeGestureHandlerVTable() -> SwipeGestureHandlerVTable for SwipeGestureHandler
620}
621
622#[repr(C)]
623#[derive(FieldOffsets, Default, SlintElement)]
624#[pin]
625pub struct Clip {
627 pub border_top_left_radius: Property<LogicalLength>,
628 pub border_top_right_radius: Property<LogicalLength>,
629 pub border_bottom_left_radius: Property<LogicalLength>,
630 pub border_bottom_right_radius: Property<LogicalLength>,
631 pub border_width: Property<LogicalLength>,
632 pub cached_rendering_data: CachedRenderingData,
633 pub clip: Property<bool>,
634}
635
636impl Item for Clip {
637 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
638
639 fn layout_info(
640 self: Pin<&Self>,
641 _orientation: Orientation,
642 _window_adapter: &Rc<dyn WindowAdapter>,
643 _self_rc: &ItemRc,
644 ) -> LayoutInfo {
645 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
646 }
647
648 fn input_event_filter_before_children(
649 self: Pin<&Self>,
650 event: MouseEvent,
651 _window_adapter: &Rc<dyn WindowAdapter>,
652 self_rc: &ItemRc,
653 ) -> InputEventFilterResult {
654 if let Some(pos) = event.position() {
655 let geometry = self_rc.geometry();
656 if self.clip()
657 && (pos.x < 0 as Coord
658 || pos.y < 0 as Coord
659 || pos.x_length() > geometry.width_length()
660 || pos.y_length() > geometry.height_length())
661 {
662 return InputEventFilterResult::Intercept;
663 }
664 }
665 InputEventFilterResult::ForwardAndIgnore
666 }
667
668 fn input_event(
669 self: Pin<&Self>,
670 _: MouseEvent,
671 _window_adapter: &Rc<dyn WindowAdapter>,
672 _self_rc: &ItemRc,
673 ) -> InputEventResult {
674 InputEventResult::EventIgnored
675 }
676
677 fn key_event(
678 self: Pin<&Self>,
679 _: &KeyEvent,
680 _window_adapter: &Rc<dyn WindowAdapter>,
681 _self_rc: &ItemRc,
682 ) -> KeyEventResult {
683 KeyEventResult::EventIgnored
684 }
685
686 fn focus_event(
687 self: Pin<&Self>,
688 _: &FocusEvent,
689 _window_adapter: &Rc<dyn WindowAdapter>,
690 _self_rc: &ItemRc,
691 ) -> FocusEventResult {
692 FocusEventResult::FocusIgnored
693 }
694
695 fn render(
696 self: Pin<&Self>,
697 backend: &mut ItemRendererRef,
698 self_rc: &ItemRc,
699 size: LogicalSize,
700 ) -> RenderingResult {
701 (*backend).visit_clip(self, self_rc, size)
702 }
703
704 fn bounding_rect(
705 self: core::pin::Pin<&Self>,
706 _window_adapter: &Rc<dyn WindowAdapter>,
707 _self_rc: &ItemRc,
708 geometry: LogicalRect,
709 ) -> LogicalRect {
710 geometry
711 }
712
713 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
714 self.clip()
715 }
716}
717
718impl Clip {
719 pub fn logical_border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
720 LogicalBorderRadius::from_lengths(
721 self.border_top_left_radius(),
722 self.border_top_right_radius(),
723 self.border_bottom_right_radius(),
724 self.border_bottom_left_radius(),
725 )
726 }
727}
728
729impl ItemConsts for Clip {
730 const cached_rendering_data_offset: const_field_offset::FieldOffset<Clip, CachedRenderingData> =
731 Clip::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
732}
733
734declare_item_vtable! {
735 fn slint_get_ClipVTable() -> ClipVTable for Clip
736}
737
738#[repr(C)]
739#[derive(FieldOffsets, Default, SlintElement)]
740#[pin]
741pub struct Opacity {
743 pub opacity: Property<f32>,
745 pub cached_rendering_data: CachedRenderingData,
746}
747
748impl Item for Opacity {
749 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
750
751 fn layout_info(
752 self: Pin<&Self>,
753 _orientation: Orientation,
754 _window_adapter: &Rc<dyn WindowAdapter>,
755 _self_rc: &ItemRc,
756 ) -> LayoutInfo {
757 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
758 }
759
760 fn input_event_filter_before_children(
761 self: Pin<&Self>,
762 _: MouseEvent,
763 _window_adapter: &Rc<dyn WindowAdapter>,
764 _self_rc: &ItemRc,
765 ) -> InputEventFilterResult {
766 InputEventFilterResult::ForwardAndIgnore
767 }
768
769 fn input_event(
770 self: Pin<&Self>,
771 _: MouseEvent,
772 _window_adapter: &Rc<dyn WindowAdapter>,
773 _self_rc: &ItemRc,
774 ) -> InputEventResult {
775 InputEventResult::EventIgnored
776 }
777
778 fn key_event(
779 self: Pin<&Self>,
780 _: &KeyEvent,
781 _window_adapter: &Rc<dyn WindowAdapter>,
782 _self_rc: &ItemRc,
783 ) -> KeyEventResult {
784 KeyEventResult::EventIgnored
785 }
786
787 fn focus_event(
788 self: Pin<&Self>,
789 _: &FocusEvent,
790 _window_adapter: &Rc<dyn WindowAdapter>,
791 _self_rc: &ItemRc,
792 ) -> FocusEventResult {
793 FocusEventResult::FocusIgnored
794 }
795
796 fn render(
797 self: Pin<&Self>,
798 backend: &mut ItemRendererRef,
799 self_rc: &ItemRc,
800 size: LogicalSize,
801 ) -> RenderingResult {
802 backend.visit_opacity(self, self_rc, size)
803 }
804
805 fn bounding_rect(
806 self: core::pin::Pin<&Self>,
807 _window_adapter: &Rc<dyn WindowAdapter>,
808 _self_rc: &ItemRc,
809 geometry: LogicalRect,
810 ) -> LogicalRect {
811 geometry
812 }
813
814 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
815 false
816 }
817}
818
819impl Opacity {
820 pub fn need_layer(self_rc: &ItemRc, opacity: f32) -> bool {
828 if opacity == 1.0 {
829 return false;
830 }
831
832 let opacity_child = match self_rc.first_child() {
833 Some(first_child) => first_child,
834 None => return false, };
836
837 if opacity_child.next_sibling().is_some() {
838 return true; }
840
841 opacity_child.first_child().is_some()
843 }
844}
845
846impl ItemConsts for Opacity {
847 const cached_rendering_data_offset: const_field_offset::FieldOffset<
848 Opacity,
849 CachedRenderingData,
850 > = Opacity::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
851}
852
853declare_item_vtable! {
854 fn slint_get_OpacityVTable() -> OpacityVTable for Opacity
855}
856
857#[repr(C)]
858#[derive(FieldOffsets, Default, SlintElement)]
859#[pin]
860pub struct Layer {
862 pub cache_rendering_hint: Property<bool>,
863 pub cached_rendering_data: CachedRenderingData,
864}
865
866impl Item for Layer {
867 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
868
869 fn layout_info(
870 self: Pin<&Self>,
871 _orientation: Orientation,
872 _window_adapter: &Rc<dyn WindowAdapter>,
873 _self_rc: &ItemRc,
874 ) -> LayoutInfo {
875 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
876 }
877
878 fn input_event_filter_before_children(
879 self: Pin<&Self>,
880 _: MouseEvent,
881 _window_adapter: &Rc<dyn WindowAdapter>,
882 _self_rc: &ItemRc,
883 ) -> InputEventFilterResult {
884 InputEventFilterResult::ForwardAndIgnore
885 }
886
887 fn input_event(
888 self: Pin<&Self>,
889 _: MouseEvent,
890 _window_adapter: &Rc<dyn WindowAdapter>,
891 _self_rc: &ItemRc,
892 ) -> InputEventResult {
893 InputEventResult::EventIgnored
894 }
895
896 fn key_event(
897 self: Pin<&Self>,
898 _: &KeyEvent,
899 _window_adapter: &Rc<dyn WindowAdapter>,
900 _self_rc: &ItemRc,
901 ) -> KeyEventResult {
902 KeyEventResult::EventIgnored
903 }
904
905 fn focus_event(
906 self: Pin<&Self>,
907 _: &FocusEvent,
908 _window_adapter: &Rc<dyn WindowAdapter>,
909 _self_rc: &ItemRc,
910 ) -> FocusEventResult {
911 FocusEventResult::FocusIgnored
912 }
913
914 fn render(
915 self: Pin<&Self>,
916 backend: &mut ItemRendererRef,
917 self_rc: &ItemRc,
918 size: LogicalSize,
919 ) -> RenderingResult {
920 backend.visit_layer(self, self_rc, size)
921 }
922
923 fn bounding_rect(
924 self: core::pin::Pin<&Self>,
925 _window_adapter: &Rc<dyn WindowAdapter>,
926 _self_rc: &ItemRc,
927 geometry: LogicalRect,
928 ) -> LogicalRect {
929 geometry
930 }
931
932 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
933 false
934 }
935}
936
937impl ItemConsts for Layer {
938 const cached_rendering_data_offset: const_field_offset::FieldOffset<
939 Layer,
940 CachedRenderingData,
941 > = Layer::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
942}
943
944declare_item_vtable! {
945 fn slint_get_LayerVTable() -> LayerVTable for Layer
946}
947
948#[repr(C)]
949#[derive(FieldOffsets, Default, SlintElement)]
950#[pin]
951pub struct Rotate {
953 pub rotation_angle: Property<f32>,
954 pub rotation_origin_x: Property<LogicalLength>,
955 pub rotation_origin_y: Property<LogicalLength>,
956 pub cached_rendering_data: CachedRenderingData,
957}
958
959impl Item for Rotate {
960 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
961
962 fn layout_info(
963 self: Pin<&Self>,
964 _orientation: Orientation,
965 _window_adapter: &Rc<dyn WindowAdapter>,
966 _self_rc: &ItemRc,
967 ) -> LayoutInfo {
968 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
969 }
970
971 fn input_event_filter_before_children(
972 self: Pin<&Self>,
973 _: MouseEvent,
974 _window_adapter: &Rc<dyn WindowAdapter>,
975 _self_rc: &ItemRc,
976 ) -> InputEventFilterResult {
977 InputEventFilterResult::ForwardAndIgnore
978 }
979
980 fn input_event(
981 self: Pin<&Self>,
982 _: MouseEvent,
983 _window_adapter: &Rc<dyn WindowAdapter>,
984 _self_rc: &ItemRc,
985 ) -> InputEventResult {
986 InputEventResult::EventIgnored
987 }
988
989 fn key_event(
990 self: Pin<&Self>,
991 _: &KeyEvent,
992 _window_adapter: &Rc<dyn WindowAdapter>,
993 _self_rc: &ItemRc,
994 ) -> KeyEventResult {
995 KeyEventResult::EventIgnored
996 }
997
998 fn focus_event(
999 self: Pin<&Self>,
1000 _: &FocusEvent,
1001 _window_adapter: &Rc<dyn WindowAdapter>,
1002 _self_rc: &ItemRc,
1003 ) -> FocusEventResult {
1004 FocusEventResult::FocusIgnored
1005 }
1006
1007 fn render(
1008 self: Pin<&Self>,
1009 backend: &mut ItemRendererRef,
1010 _self_rc: &ItemRc,
1011 _size: LogicalSize,
1012 ) -> RenderingResult {
1013 let origin =
1014 LogicalVector::from_lengths(self.rotation_origin_x(), self.rotation_origin_y());
1015 (*backend).translate(origin);
1016 (*backend).rotate(self.rotation_angle());
1017 (*backend).translate(-origin);
1018 RenderingResult::ContinueRenderingChildren
1019 }
1020
1021 fn bounding_rect(
1022 self: core::pin::Pin<&Self>,
1023 _window_adapter: &Rc<dyn WindowAdapter>,
1024 _self_rc: &ItemRc,
1025 geometry: LogicalRect,
1026 ) -> LogicalRect {
1027 geometry
1028 }
1029
1030 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1031 false
1032 }
1033}
1034
1035impl ItemConsts for Rotate {
1036 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1037 Rotate,
1038 CachedRenderingData,
1039 > = Rotate::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1040}
1041
1042declare_item_vtable! {
1043 fn slint_get_RotateVTable() -> RotateVTable for Rotate
1044}
1045
1046declare_item_vtable! {
1047 fn slint_get_FlickableVTable() -> FlickableVTable for Flickable
1048}
1049
1050#[repr(C)]
1052#[derive(FieldOffsets, SlintElement, Clone, Debug)]
1053#[pin]
1054pub struct PropertyAnimation {
1055 #[rtti_field]
1056 pub delay: i32,
1057 #[rtti_field]
1058 pub duration: i32,
1059 #[rtti_field]
1060 pub iteration_count: f32,
1061 #[rtti_field]
1062 pub direction: AnimationDirection,
1063 #[rtti_field]
1064 pub easing: crate::animations::EasingCurve,
1065}
1066
1067impl Default for PropertyAnimation {
1068 fn default() -> Self {
1069 Self {
1072 delay: 0,
1073 duration: 0,
1074 iteration_count: 1.,
1075 direction: Default::default(),
1076 easing: Default::default(),
1077 }
1078 }
1079}
1080
1081#[repr(C)]
1083#[derive(FieldOffsets, Default, SlintElement)]
1084#[pin]
1085pub struct WindowItem {
1086 pub width: Property<LogicalLength>,
1087 pub height: Property<LogicalLength>,
1088 pub background: Property<Brush>,
1089 pub title: Property<SharedString>,
1090 pub no_frame: Property<bool>,
1091 pub resize_border_width: Property<LogicalLength>,
1092 pub always_on_top: Property<bool>,
1093 pub full_screen: Property<bool>,
1094 pub icon: Property<crate::graphics::Image>,
1095 pub default_font_family: Property<SharedString>,
1096 pub default_font_size: Property<LogicalLength>,
1097 pub default_font_weight: Property<i32>,
1098 pub cached_rendering_data: CachedRenderingData,
1099}
1100
1101impl Item for WindowItem {
1102 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {
1103 #[cfg(feature = "std")]
1104 self.full_screen.set(std::env::var("SLINT_FULLSCREEN").is_ok());
1105 }
1106
1107 fn layout_info(
1108 self: Pin<&Self>,
1109 _orientation: Orientation,
1110 _window_adapter: &Rc<dyn WindowAdapter>,
1111 _self_rc: &ItemRc,
1112 ) -> LayoutInfo {
1113 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 ) -> InputEventFilterResult {
1122 InputEventFilterResult::ForwardAndIgnore
1123 }
1124
1125 fn input_event(
1126 self: Pin<&Self>,
1127 _event: MouseEvent,
1128 _window_adapter: &Rc<dyn WindowAdapter>,
1129 _self_rc: &ItemRc,
1130 ) -> InputEventResult {
1131 InputEventResult::EventIgnored
1132 }
1133
1134 fn key_event(
1135 self: Pin<&Self>,
1136 _: &KeyEvent,
1137 _window_adapter: &Rc<dyn WindowAdapter>,
1138 _self_rc: &ItemRc,
1139 ) -> KeyEventResult {
1140 KeyEventResult::EventIgnored
1141 }
1142
1143 fn focus_event(
1144 self: Pin<&Self>,
1145 _: &FocusEvent,
1146 _window_adapter: &Rc<dyn WindowAdapter>,
1147 _self_rc: &ItemRc,
1148 ) -> FocusEventResult {
1149 FocusEventResult::FocusIgnored
1150 }
1151
1152 fn render(
1153 self: Pin<&Self>,
1154 backend: &mut ItemRendererRef,
1155 self_rc: &ItemRc,
1156 size: LogicalSize,
1157 ) -> RenderingResult {
1158 backend.draw_window_background(self, self_rc, size, &self.cached_rendering_data);
1159 RenderingResult::ContinueRenderingChildren
1160 }
1161
1162 fn bounding_rect(
1163 self: core::pin::Pin<&Self>,
1164 _window_adapter: &Rc<dyn WindowAdapter>,
1165 _self_rc: &ItemRc,
1166 geometry: LogicalRect,
1167 ) -> LogicalRect {
1168 geometry
1169 }
1170
1171 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1172 false
1173 }
1174}
1175
1176impl RenderRectangle for WindowItem {
1177 fn background(self: Pin<&Self>) -> Brush {
1178 self.background()
1179 }
1180}
1181
1182fn next_window_item(item: &ItemRc) -> Option<ItemRc> {
1183 let root_item_in_local_item_tree = ItemRc::new(item.item_tree().clone(), 0);
1184
1185 if root_item_in_local_item_tree.downcast::<crate::items::WindowItem>().is_some() {
1186 Some(root_item_in_local_item_tree)
1187 } else {
1188 root_item_in_local_item_tree
1189 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1190 .and_then(|parent| next_window_item(&parent))
1191 }
1192}
1193
1194impl WindowItem {
1195 pub fn font_family(self: Pin<&Self>) -> Option<SharedString> {
1196 let maybe_family = self.default_font_family();
1197 if !maybe_family.is_empty() {
1198 Some(maybe_family)
1199 } else {
1200 None
1201 }
1202 }
1203
1204 pub fn font_size(self: Pin<&Self>) -> Option<LogicalLength> {
1205 let font_size = self.default_font_size();
1206 if font_size.get() <= 0 as Coord {
1207 None
1208 } else {
1209 Some(font_size)
1210 }
1211 }
1212
1213 pub fn font_weight(self: Pin<&Self>) -> Option<i32> {
1214 let font_weight = self.default_font_weight();
1215 if font_weight == 0 {
1216 None
1217 } else {
1218 Some(font_weight)
1219 }
1220 }
1221
1222 pub fn resolve_font_property<T>(
1223 self_rc: &ItemRc,
1224 property_fn: impl Fn(Pin<&Self>) -> Option<T>,
1225 ) -> Option<T> {
1226 let mut window_item_rc = self_rc.clone();
1227 loop {
1228 let window_item = window_item_rc.downcast::<Self>()?;
1229 if let Some(result) = property_fn(window_item.as_pin_ref()) {
1230 return Some(result);
1231 }
1232
1233 match window_item_rc
1234 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1235 .and_then(|p| next_window_item(&p))
1236 {
1237 Some(item) => window_item_rc = item,
1238 None => return None,
1239 }
1240 }
1241 }
1242
1243 pub fn resolved_font_request(
1247 self_rc: &crate::items::ItemRc,
1248 local_font_family: SharedString,
1249 local_font_weight: i32,
1250 local_font_size: LogicalLength,
1251 local_letter_spacing: LogicalLength,
1252 local_italic: bool,
1253 ) -> FontRequest {
1254 let Some(window_item_rc) = next_window_item(self_rc) else {
1255 return FontRequest::default();
1256 };
1257
1258 FontRequest {
1259 family: {
1260 if !local_font_family.is_empty() {
1261 Some(local_font_family)
1262 } else {
1263 crate::items::WindowItem::resolve_font_property(
1264 &window_item_rc,
1265 crate::items::WindowItem::font_family,
1266 )
1267 }
1268 },
1269 weight: {
1270 if local_font_weight == 0 {
1271 crate::items::WindowItem::resolve_font_property(
1272 &window_item_rc,
1273 crate::items::WindowItem::font_weight,
1274 )
1275 } else {
1276 Some(local_font_weight)
1277 }
1278 },
1279 pixel_size: {
1280 if local_font_size.get() == 0 as Coord {
1281 crate::items::WindowItem::resolve_font_property(
1282 &window_item_rc,
1283 crate::items::WindowItem::font_size,
1284 )
1285 } else {
1286 Some(local_font_size)
1287 }
1288 },
1289 letter_spacing: Some(local_letter_spacing),
1290 italic: local_italic,
1291 }
1292 }
1293}
1294
1295impl ItemConsts for WindowItem {
1296 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1297 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1298}
1299
1300declare_item_vtable! {
1301 fn slint_get_WindowItemVTable() -> WindowItemVTable for WindowItem
1302}
1303
1304#[repr(C)]
1306#[derive(FieldOffsets, Default, SlintElement)]
1307#[pin]
1308pub struct ContextMenu {
1309 pub sub_menu: Callback<MenuEntryArg, MenuEntryModel>,
1311 pub activated: Callback<MenuEntryArg>,
1312 pub show: Callback<PointArg>,
1313 pub cached_rendering_data: CachedRenderingData,
1314 pub popup_id: Cell<Option<NonZeroU32>>,
1315 pub enabled: Property<bool>,
1316 #[cfg(target_os = "android")]
1317 long_press_timer: Cell<Option<crate::timers::Timer>>,
1318}
1319
1320impl Item for ContextMenu {
1321 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1322
1323 fn layout_info(
1324 self: Pin<&Self>,
1325 _orientation: Orientation,
1326 _window_adapter: &Rc<dyn WindowAdapter>,
1327 _self_rc: &ItemRc,
1328 ) -> LayoutInfo {
1329 LayoutInfo::default()
1330 }
1331
1332 fn input_event_filter_before_children(
1333 self: Pin<&Self>,
1334 _: MouseEvent,
1335 _window_adapter: &Rc<dyn WindowAdapter>,
1336 _self_rc: &ItemRc,
1337 ) -> InputEventFilterResult {
1338 InputEventFilterResult::ForwardEvent
1339 }
1340
1341 fn input_event(
1342 self: Pin<&Self>,
1343 event: MouseEvent,
1344 _window_adapter: &Rc<dyn WindowAdapter>,
1345 _self_rc: &ItemRc,
1346 ) -> InputEventResult {
1347 if !self.enabled() {
1348 return InputEventResult::EventIgnored;
1349 }
1350 match event {
1351 MouseEvent::Pressed { position, button: PointerEventButton::Right, .. } => {
1352 self.show.call(&(crate::api::LogicalPosition::from_euclid(position),));
1353 InputEventResult::EventAccepted
1354 }
1355 #[cfg(target_os = "android")]
1356 MouseEvent::Pressed { position, button: PointerEventButton::Left, .. } => {
1357 let timer = crate::timers::Timer::default();
1358 let self_weak = _self_rc.downgrade();
1359 timer.start(
1360 crate::timers::TimerMode::SingleShot,
1361 WindowInner::from_pub(_window_adapter.window())
1362 .ctx
1363 .platform()
1364 .long_press_interval(crate::InternalToken),
1365 move || {
1366 let Some(self_rc) = self_weak.upgrade() else { return };
1367 let Some(self_) = self_rc.downcast::<ContextMenu>() else { return };
1368 self_.show.call(&(crate::api::LogicalPosition::from_euclid(position),));
1369 },
1370 );
1371 self.long_press_timer.set(Some(timer));
1372 InputEventResult::GrabMouse
1373 }
1374 #[cfg(target_os = "android")]
1375 MouseEvent::Released { .. } | MouseEvent::Exit => {
1376 if let Some(timer) = self.long_press_timer.take() {
1377 timer.stop();
1378 }
1379 InputEventResult::EventIgnored
1380 }
1381 #[cfg(target_os = "android")]
1382 MouseEvent::Moved { .. } => InputEventResult::EventAccepted,
1383 _ => InputEventResult::EventIgnored,
1384 }
1385 }
1386
1387 fn key_event(
1388 self: Pin<&Self>,
1389 event: &KeyEvent,
1390 _window_adapter: &Rc<dyn WindowAdapter>,
1391 _self_rc: &ItemRc,
1392 ) -> KeyEventResult {
1393 if !self.enabled() {
1394 return KeyEventResult::EventIgnored;
1395 }
1396 if event.event_type == KeyEventType::KeyPressed
1397 && event.text.starts_with(crate::input::key_codes::Menu)
1398 {
1399 self.show.call(&(Default::default(),));
1400 KeyEventResult::EventAccepted
1401 } else {
1402 KeyEventResult::EventIgnored
1403 }
1404 }
1405
1406 fn focus_event(
1407 self: Pin<&Self>,
1408 _: &FocusEvent,
1409 _window_adapter: &Rc<dyn WindowAdapter>,
1410 _self_rc: &ItemRc,
1411 ) -> FocusEventResult {
1412 FocusEventResult::FocusIgnored
1413 }
1414
1415 fn render(
1416 self: Pin<&Self>,
1417 _backend: &mut ItemRendererRef,
1418 _self_rc: &ItemRc,
1419 _size: LogicalSize,
1420 ) -> RenderingResult {
1421 RenderingResult::ContinueRenderingChildren
1422 }
1423
1424 fn bounding_rect(
1425 self: core::pin::Pin<&Self>,
1426 _window_adapter: &Rc<dyn WindowAdapter>,
1427 _self_rc: &ItemRc,
1428 geometry: LogicalRect,
1429 ) -> LogicalRect {
1430 geometry
1431 }
1432
1433 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1434 false
1435 }
1436}
1437
1438impl ContextMenu {
1439 pub fn close(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) {
1440 if let Some(id) = self.popup_id.take() {
1441 WindowInner::from_pub(window_adapter.window()).close_popup(id);
1442 }
1443 }
1444
1445 pub fn is_open(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) -> bool {
1446 self.popup_id.get().is_some_and(|id| {
1447 WindowInner::from_pub(window_adapter.window())
1448 .active_popups()
1449 .iter()
1450 .any(|p| p.popup_id == id)
1451 })
1452 }
1453}
1454
1455impl ItemConsts for ContextMenu {
1456 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1457 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1458}
1459
1460declare_item_vtable! {
1461 fn slint_get_ContextMenuVTable() -> ContextMenuVTable for ContextMenu
1462}
1463
1464#[cfg(feature = "ffi")]
1465#[unsafe(no_mangle)]
1466pub unsafe extern "C" fn slint_contextmenu_close(
1467 s: Pin<&ContextMenu>,
1468 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1469 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1470 self_index: u32,
1471) {
1472 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1473 let self_rc = ItemRc::new(self_component.clone(), self_index);
1474 s.close(window_adapter, &self_rc);
1475}
1476
1477#[cfg(feature = "ffi")]
1478#[unsafe(no_mangle)]
1479pub unsafe extern "C" fn slint_contextmenu_is_open(
1480 s: Pin<&ContextMenu>,
1481 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1482 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1483 self_index: u32,
1484) -> bool {
1485 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1486 let self_rc = ItemRc::new(self_component.clone(), self_index);
1487 s.is_open(window_adapter, &self_rc)
1488}
1489
1490#[repr(C)]
1492#[derive(FieldOffsets, Default, SlintElement)]
1493#[pin]
1494pub struct BoxShadow {
1495 pub border_radius: Property<LogicalLength>,
1496 pub offset_x: Property<LogicalLength>,
1498 pub offset_y: Property<LogicalLength>,
1499 pub color: Property<Color>,
1500 pub blur: Property<LogicalLength>,
1501 pub cached_rendering_data: CachedRenderingData,
1502}
1503
1504impl Item for BoxShadow {
1505 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1506
1507 fn layout_info(
1508 self: Pin<&Self>,
1509 _orientation: Orientation,
1510 _window_adapter: &Rc<dyn WindowAdapter>,
1511 _self_rc: &ItemRc,
1512 ) -> LayoutInfo {
1513 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1514 }
1515
1516 fn input_event_filter_before_children(
1517 self: Pin<&Self>,
1518 _: MouseEvent,
1519 _window_adapter: &Rc<dyn WindowAdapter>,
1520 _self_rc: &ItemRc,
1521 ) -> InputEventFilterResult {
1522 InputEventFilterResult::ForwardAndIgnore
1523 }
1524
1525 fn input_event(
1526 self: Pin<&Self>,
1527 _event: MouseEvent,
1528 _window_adapter: &Rc<dyn WindowAdapter>,
1529 _self_rc: &ItemRc,
1530 ) -> InputEventResult {
1531 InputEventResult::EventIgnored
1532 }
1533
1534 fn key_event(
1535 self: Pin<&Self>,
1536 _: &KeyEvent,
1537 _window_adapter: &Rc<dyn WindowAdapter>,
1538 _self_rc: &ItemRc,
1539 ) -> KeyEventResult {
1540 KeyEventResult::EventIgnored
1541 }
1542
1543 fn focus_event(
1544 self: Pin<&Self>,
1545 _: &FocusEvent,
1546 _window_adapter: &Rc<dyn WindowAdapter>,
1547 _self_rc: &ItemRc,
1548 ) -> FocusEventResult {
1549 FocusEventResult::FocusIgnored
1550 }
1551
1552 fn render(
1553 self: Pin<&Self>,
1554 backend: &mut ItemRendererRef,
1555 self_rc: &ItemRc,
1556 size: LogicalSize,
1557 ) -> RenderingResult {
1558 (*backend).draw_box_shadow(self, self_rc, size);
1559 RenderingResult::ContinueRenderingChildren
1560 }
1561
1562 fn bounding_rect(
1563 self: core::pin::Pin<&Self>,
1564 _window_adapter: &Rc<dyn WindowAdapter>,
1565 _self_rc: &ItemRc,
1566 geometry: LogicalRect,
1567 ) -> LogicalRect {
1568 geometry
1569 .outer_rect(euclid::SideOffsets2D::from_length_all_same(self.blur()))
1570 .translate(LogicalVector::from_lengths(self.offset_x(), self.offset_y()))
1571 }
1572
1573 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1574 false
1575 }
1576}
1577
1578impl ItemConsts for BoxShadow {
1579 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1580 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1581}
1582
1583declare_item_vtable! {
1584 fn slint_get_BoxShadowVTable() -> BoxShadowVTable for BoxShadow
1585}
1586
1587declare_item_vtable! {
1588 fn slint_get_ComponentContainerVTable() -> ComponentContainerVTable for ComponentContainer
1589}
1590
1591declare_item_vtable! {
1592 fn slint_get_ComplexTextVTable() -> ComplexTextVTable for ComplexText
1593}
1594
1595declare_item_vtable! {
1596 fn slint_get_SimpleTextVTable() -> SimpleTextVTable for SimpleText
1597}
1598
1599declare_item_vtable! {
1600 fn slint_get_TextInputVTable() -> TextInputVTable for TextInput
1601}
1602
1603declare_item_vtable! {
1604 fn slint_get_ImageItemVTable() -> ImageItemVTable for ImageItem
1605}
1606
1607declare_item_vtable! {
1608 fn slint_get_ClippedImageVTable() -> ClippedImageVTable for ClippedImage
1609}
1610
1611#[cfg(feature = "std")]
1612declare_item_vtable! {
1613 fn slint_get_PathVTable() -> PathVTable for Path
1614}
1615
1616declare_item_vtable! {
1617 fn slint_get_MenuItemVTable() -> MenuItemVTable for MenuItem
1618}
1619
1620macro_rules! declare_enums {
1621 ($( $(#[$enum_doc:meta])* enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
1622 $(
1623 #[derive(Copy, Clone, Debug, PartialEq, Eq, strum::EnumString, strum::Display, Hash)]
1624 #[repr(u32)]
1625 #[strum(serialize_all = "kebab-case")]
1626 $(#[$enum_doc])*
1627 pub enum $Name {
1628 $( $(#[$value_doc])* $Value),*
1629 }
1630
1631 impl Default for $Name {
1632 fn default() -> Self {
1633 ($(Self::$Value,)*).0
1635 }
1636 }
1637 )*
1638 };
1639}
1640
1641i_slint_common::for_each_enums!(declare_enums);
1642
1643macro_rules! declare_builtin_structs {
1644 ($(
1645 $(#[$struct_attr:meta])*
1646 struct $Name:ident {
1647 @name = $inner_name:literal
1648 export {
1649 $( $(#[$pub_attr:meta])* $pub_field:ident : $pub_type:ty, )*
1650 }
1651 private {
1652 $( $(#[$pri_attr:meta])* $pri_field:ident : $pri_type:ty, )*
1653 }
1654 }
1655 )*) => {
1656 $(
1657 #[derive(Clone, Debug, Default, PartialEq)]
1658 #[repr(C)]
1659 $(#[$struct_attr])*
1660 pub struct $Name {
1661 $(
1662 $(#[$pub_attr])*
1663 pub $pub_field : $pub_type,
1664 )*
1665 $(
1666 $(#[$pri_attr])*
1667 pub $pri_field : $pri_type,
1668 )*
1669 }
1670 )*
1671 };
1672}
1673
1674i_slint_common::for_each_builtin_structs!(declare_builtin_structs);
1675
1676#[cfg(feature = "ffi")]
1677#[unsafe(no_mangle)]
1678pub unsafe extern "C" fn slint_item_absolute_position(
1679 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1680 self_index: u32,
1681) -> crate::lengths::LogicalPoint {
1682 let self_rc = ItemRc::new(self_component.clone(), self_index);
1683 self_rc.map_to_window(Default::default())
1684}