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