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 Rotate {
1029 pub rotation_angle: Property<f32>,
1030 pub rotation_origin_x: Property<LogicalLength>,
1031 pub rotation_origin_y: Property<LogicalLength>,
1032 pub cached_rendering_data: CachedRenderingData,
1033}
1034
1035impl Item for Rotate {
1036 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1037
1038 fn layout_info(
1039 self: Pin<&Self>,
1040 _orientation: Orientation,
1041 _window_adapter: &Rc<dyn WindowAdapter>,
1042 _self_rc: &ItemRc,
1043 ) -> LayoutInfo {
1044 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1045 }
1046
1047 fn input_event_filter_before_children(
1048 self: Pin<&Self>,
1049 _: &MouseEvent,
1050 _window_adapter: &Rc<dyn WindowAdapter>,
1051 _self_rc: &ItemRc,
1052 ) -> InputEventFilterResult {
1053 InputEventFilterResult::ForwardAndIgnore
1054 }
1055
1056 fn input_event(
1057 self: Pin<&Self>,
1058 _: &MouseEvent,
1059 _window_adapter: &Rc<dyn WindowAdapter>,
1060 _self_rc: &ItemRc,
1061 ) -> InputEventResult {
1062 InputEventResult::EventIgnored
1063 }
1064
1065 fn capture_key_event(
1066 self: Pin<&Self>,
1067 _: &KeyEvent,
1068 _window_adapter: &Rc<dyn WindowAdapter>,
1069 _self_rc: &ItemRc,
1070 ) -> KeyEventResult {
1071 KeyEventResult::EventIgnored
1072 }
1073
1074 fn key_event(
1075 self: Pin<&Self>,
1076 _: &KeyEvent,
1077 _window_adapter: &Rc<dyn WindowAdapter>,
1078 _self_rc: &ItemRc,
1079 ) -> KeyEventResult {
1080 KeyEventResult::EventIgnored
1081 }
1082
1083 fn focus_event(
1084 self: Pin<&Self>,
1085 _: &FocusEvent,
1086 _window_adapter: &Rc<dyn WindowAdapter>,
1087 _self_rc: &ItemRc,
1088 ) -> FocusEventResult {
1089 FocusEventResult::FocusIgnored
1090 }
1091
1092 fn render(
1093 self: Pin<&Self>,
1094 backend: &mut ItemRendererRef,
1095 _self_rc: &ItemRc,
1096 _size: LogicalSize,
1097 ) -> RenderingResult {
1098 let origin =
1099 LogicalVector::from_lengths(self.rotation_origin_x(), self.rotation_origin_y());
1100 (*backend).translate(origin);
1101 (*backend).rotate(self.rotation_angle());
1102 (*backend).translate(-origin);
1103 RenderingResult::ContinueRenderingChildren
1104 }
1105
1106 fn bounding_rect(
1107 self: core::pin::Pin<&Self>,
1108 _window_adapter: &Rc<dyn WindowAdapter>,
1109 _self_rc: &ItemRc,
1110 geometry: LogicalRect,
1111 ) -> LogicalRect {
1112 geometry
1113 }
1114
1115 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1116 false
1117 }
1118}
1119
1120impl ItemConsts for Rotate {
1121 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1122 Rotate,
1123 CachedRenderingData,
1124 > = Rotate::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1125}
1126
1127declare_item_vtable! {
1128 fn slint_get_RotateVTable() -> RotateVTable for Rotate
1129}
1130
1131declare_item_vtable! {
1132 fn slint_get_FlickableVTable() -> FlickableVTable for Flickable
1133}
1134
1135declare_item_vtable! {
1136 fn slint_get_DragAreaVTable() -> DragAreaVTable for DragArea
1137}
1138
1139declare_item_vtable! {
1140 fn slint_get_DropAreaVTable() -> DropAreaVTable for DropArea
1141}
1142
1143#[repr(C)]
1145#[derive(FieldOffsets, SlintElement, Clone, Debug)]
1146#[pin]
1147pub struct PropertyAnimation {
1148 #[rtti_field]
1149 pub delay: i32,
1150 #[rtti_field]
1151 pub duration: i32,
1152 #[rtti_field]
1153 pub iteration_count: f32,
1154 #[rtti_field]
1155 pub direction: AnimationDirection,
1156 #[rtti_field]
1157 pub easing: crate::animations::EasingCurve,
1158}
1159
1160impl Default for PropertyAnimation {
1161 fn default() -> Self {
1162 Self {
1165 delay: 0,
1166 duration: 0,
1167 iteration_count: 1.,
1168 direction: Default::default(),
1169 easing: Default::default(),
1170 }
1171 }
1172}
1173
1174#[repr(C)]
1176#[derive(FieldOffsets, Default, SlintElement)]
1177#[pin]
1178pub struct WindowItem {
1179 pub width: Property<LogicalLength>,
1180 pub height: Property<LogicalLength>,
1181 pub background: Property<Brush>,
1182 pub title: Property<SharedString>,
1183 pub no_frame: Property<bool>,
1184 pub resize_border_width: Property<LogicalLength>,
1185 pub always_on_top: Property<bool>,
1186 pub full_screen: Property<bool>,
1187 pub icon: Property<crate::graphics::Image>,
1188 pub default_font_family: Property<SharedString>,
1189 pub default_font_size: Property<LogicalLength>,
1190 pub default_font_weight: Property<i32>,
1191 pub cached_rendering_data: CachedRenderingData,
1192}
1193
1194impl Item for WindowItem {
1195 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {
1196 #[cfg(feature = "std")]
1197 self.full_screen.set(std::env::var("SLINT_FULLSCREEN").is_ok());
1198 }
1199
1200 fn layout_info(
1201 self: Pin<&Self>,
1202 _orientation: Orientation,
1203 _window_adapter: &Rc<dyn WindowAdapter>,
1204 _self_rc: &ItemRc,
1205 ) -> LayoutInfo {
1206 LayoutInfo::default()
1207 }
1208
1209 fn input_event_filter_before_children(
1210 self: Pin<&Self>,
1211 _: &MouseEvent,
1212 _window_adapter: &Rc<dyn WindowAdapter>,
1213 _self_rc: &ItemRc,
1214 ) -> InputEventFilterResult {
1215 InputEventFilterResult::ForwardAndIgnore
1216 }
1217
1218 fn input_event(
1219 self: Pin<&Self>,
1220 _: &MouseEvent,
1221 _window_adapter: &Rc<dyn WindowAdapter>,
1222 _self_rc: &ItemRc,
1223 ) -> InputEventResult {
1224 InputEventResult::EventIgnored
1225 }
1226
1227 fn capture_key_event(
1228 self: Pin<&Self>,
1229 _: &KeyEvent,
1230 _window_adapter: &Rc<dyn WindowAdapter>,
1231 _self_rc: &ItemRc,
1232 ) -> KeyEventResult {
1233 KeyEventResult::EventIgnored
1234 }
1235
1236 fn key_event(
1237 self: Pin<&Self>,
1238 _: &KeyEvent,
1239 _window_adapter: &Rc<dyn WindowAdapter>,
1240 _self_rc: &ItemRc,
1241 ) -> KeyEventResult {
1242 KeyEventResult::EventIgnored
1243 }
1244
1245 fn focus_event(
1246 self: Pin<&Self>,
1247 _: &FocusEvent,
1248 _window_adapter: &Rc<dyn WindowAdapter>,
1249 _self_rc: &ItemRc,
1250 ) -> FocusEventResult {
1251 FocusEventResult::FocusIgnored
1252 }
1253
1254 fn render(
1255 self: Pin<&Self>,
1256 backend: &mut ItemRendererRef,
1257 self_rc: &ItemRc,
1258 size: LogicalSize,
1259 ) -> RenderingResult {
1260 if self_rc.parent_item(crate::item_tree::ParentItemTraversalMode::StopAtPopups).is_none() {
1261 backend.draw_window_background(self, self_rc, size, &self.cached_rendering_data);
1262 } else {
1263 backend.draw_rectangle(self, self_rc, size, &self.cached_rendering_data);
1265 }
1266 RenderingResult::ContinueRenderingChildren
1267 }
1268
1269 fn bounding_rect(
1270 self: core::pin::Pin<&Self>,
1271 _window_adapter: &Rc<dyn WindowAdapter>,
1272 _self_rc: &ItemRc,
1273 geometry: LogicalRect,
1274 ) -> LogicalRect {
1275 geometry
1276 }
1277
1278 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1279 false
1280 }
1281}
1282
1283impl RenderRectangle for WindowItem {
1284 fn background(self: Pin<&Self>) -> Brush {
1285 self.background()
1286 }
1287}
1288
1289fn next_window_item(item: &ItemRc) -> Option<ItemRc> {
1290 let root_item_in_local_item_tree = ItemRc::new(item.item_tree().clone(), 0);
1291
1292 if root_item_in_local_item_tree.downcast::<crate::items::WindowItem>().is_some() {
1293 Some(root_item_in_local_item_tree)
1294 } else {
1295 root_item_in_local_item_tree
1296 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1297 .and_then(|parent| next_window_item(&parent))
1298 }
1299}
1300
1301impl WindowItem {
1302 pub fn font_family(self: Pin<&Self>) -> Option<SharedString> {
1303 let maybe_family = self.default_font_family();
1304 if !maybe_family.is_empty() {
1305 Some(maybe_family)
1306 } else {
1307 None
1308 }
1309 }
1310
1311 pub fn font_size(self: Pin<&Self>) -> Option<LogicalLength> {
1312 let font_size = self.default_font_size();
1313 if font_size.get() <= 0 as Coord {
1314 None
1315 } else {
1316 Some(font_size)
1317 }
1318 }
1319
1320 pub fn font_weight(self: Pin<&Self>) -> Option<i32> {
1321 let font_weight = self.default_font_weight();
1322 if font_weight == 0 {
1323 None
1324 } else {
1325 Some(font_weight)
1326 }
1327 }
1328
1329 pub fn resolved_default_font_size(item_tree: ItemTreeRc) -> LogicalLength {
1330 let first_item = ItemRc::new(item_tree, 0);
1331 let window_item = next_window_item(&first_item).unwrap();
1332 Self::resolve_font_property(&window_item, Self::font_size)
1333 .unwrap_or_else(|| first_item.window_adapter().unwrap().renderer().default_font_size())
1334 }
1335
1336 fn resolve_font_property<T>(
1337 self_rc: &ItemRc,
1338 property_fn: impl Fn(Pin<&Self>) -> Option<T>,
1339 ) -> Option<T> {
1340 let mut window_item_rc = self_rc.clone();
1341 loop {
1342 let window_item = window_item_rc.downcast::<Self>()?;
1343 if let Some(result) = property_fn(window_item.as_pin_ref()) {
1344 return Some(result);
1345 }
1346
1347 match window_item_rc
1348 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1349 .and_then(|p| next_window_item(&p))
1350 {
1351 Some(item) => window_item_rc = item,
1352 None => return None,
1353 }
1354 }
1355 }
1356
1357 pub fn resolved_font_request(
1361 self_rc: &crate::items::ItemRc,
1362 local_font_family: SharedString,
1363 local_font_weight: i32,
1364 local_font_size: LogicalLength,
1365 local_letter_spacing: LogicalLength,
1366 local_italic: bool,
1367 ) -> FontRequest {
1368 let Some(window_item_rc) = next_window_item(self_rc) else {
1369 return FontRequest::default();
1370 };
1371
1372 FontRequest {
1373 family: {
1374 if !local_font_family.is_empty() {
1375 Some(local_font_family)
1376 } else {
1377 Self::resolve_font_property(
1378 &window_item_rc,
1379 crate::items::WindowItem::font_family,
1380 )
1381 }
1382 },
1383 weight: {
1384 if local_font_weight == 0 {
1385 Self::resolve_font_property(
1386 &window_item_rc,
1387 crate::items::WindowItem::font_weight,
1388 )
1389 } else {
1390 Some(local_font_weight)
1391 }
1392 },
1393 pixel_size: {
1394 if local_font_size.get() == 0 as Coord {
1395 Self::resolve_font_property(
1396 &window_item_rc,
1397 crate::items::WindowItem::font_size,
1398 )
1399 } else {
1400 Some(local_font_size)
1401 }
1402 },
1403 letter_spacing: Some(local_letter_spacing),
1404 italic: local_italic,
1405 }
1406 }
1407}
1408
1409impl ItemConsts for WindowItem {
1410 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1411 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1412}
1413
1414declare_item_vtable! {
1415 fn slint_get_WindowItemVTable() -> WindowItemVTable for WindowItem
1416}
1417
1418#[repr(C)]
1420#[derive(FieldOffsets, Default, SlintElement)]
1421#[pin]
1422pub struct ContextMenu {
1423 pub sub_menu: Callback<MenuEntryArg, MenuEntryModel>,
1425 pub activated: Callback<MenuEntryArg>,
1426 pub show: Callback<PointArg>,
1427 pub cached_rendering_data: CachedRenderingData,
1428 pub popup_id: Cell<Option<NonZeroU32>>,
1429 pub enabled: Property<bool>,
1430 #[cfg(target_os = "android")]
1431 long_press_timer: Cell<Option<crate::timers::Timer>>,
1432}
1433
1434impl Item for ContextMenu {
1435 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1436
1437 fn layout_info(
1438 self: Pin<&Self>,
1439 _orientation: Orientation,
1440 _window_adapter: &Rc<dyn WindowAdapter>,
1441 _self_rc: &ItemRc,
1442 ) -> LayoutInfo {
1443 LayoutInfo::default()
1444 }
1445
1446 fn input_event_filter_before_children(
1447 self: Pin<&Self>,
1448 _: &MouseEvent,
1449 _window_adapter: &Rc<dyn WindowAdapter>,
1450 _self_rc: &ItemRc,
1451 ) -> InputEventFilterResult {
1452 InputEventFilterResult::ForwardEvent
1453 }
1454
1455 fn input_event(
1456 self: Pin<&Self>,
1457 event: &MouseEvent,
1458 _window_adapter: &Rc<dyn WindowAdapter>,
1459 _self_rc: &ItemRc,
1460 ) -> InputEventResult {
1461 if !self.enabled() {
1462 return InputEventResult::EventIgnored;
1463 }
1464 match event {
1465 MouseEvent::Pressed { position, button: PointerEventButton::Right, .. } => {
1466 self.show.call(&(LogicalPosition::from_euclid(*position),));
1467 InputEventResult::EventAccepted
1468 }
1469 #[cfg(target_os = "android")]
1470 MouseEvent::Pressed { position, button: PointerEventButton::Left, .. } => {
1471 let timer = crate::timers::Timer::default();
1472 let self_weak = _self_rc.downgrade();
1473 let position = *position;
1474 timer.start(
1475 crate::timers::TimerMode::SingleShot,
1476 WindowInner::from_pub(_window_adapter.window())
1477 .ctx
1478 .platform()
1479 .long_press_interval(crate::InternalToken),
1480 move || {
1481 let Some(self_rc) = self_weak.upgrade() else { return };
1482 let Some(self_) = self_rc.downcast::<ContextMenu>() else { return };
1483 self_.show.call(&(LogicalPosition::from_euclid(position),));
1484 },
1485 );
1486 self.long_press_timer.set(Some(timer));
1487 InputEventResult::GrabMouse
1488 }
1489 #[cfg(target_os = "android")]
1490 MouseEvent::Released { .. } | MouseEvent::Exit => {
1491 if let Some(timer) = self.long_press_timer.take() {
1492 timer.stop();
1493 }
1494 InputEventResult::EventIgnored
1495 }
1496 #[cfg(target_os = "android")]
1497 MouseEvent::Moved { .. } => InputEventResult::EventAccepted,
1498 _ => InputEventResult::EventIgnored,
1499 }
1500 }
1501
1502 fn capture_key_event(
1503 self: Pin<&Self>,
1504 _: &KeyEvent,
1505 _window_adapter: &Rc<dyn WindowAdapter>,
1506 _self_rc: &ItemRc,
1507 ) -> KeyEventResult {
1508 KeyEventResult::EventIgnored
1509 }
1510
1511 fn key_event(
1512 self: Pin<&Self>,
1513 event: &KeyEvent,
1514 _window_adapter: &Rc<dyn WindowAdapter>,
1515 _self_rc: &ItemRc,
1516 ) -> KeyEventResult {
1517 if !self.enabled() {
1518 return KeyEventResult::EventIgnored;
1519 }
1520 if event.event_type == KeyEventType::KeyPressed
1521 && event.text.starts_with(crate::input::key_codes::Menu)
1522 {
1523 self.show.call(&(Default::default(),));
1524 KeyEventResult::EventAccepted
1525 } else {
1526 KeyEventResult::EventIgnored
1527 }
1528 }
1529
1530 fn focus_event(
1531 self: Pin<&Self>,
1532 _: &FocusEvent,
1533 _window_adapter: &Rc<dyn WindowAdapter>,
1534 _self_rc: &ItemRc,
1535 ) -> FocusEventResult {
1536 FocusEventResult::FocusIgnored
1537 }
1538
1539 fn render(
1540 self: Pin<&Self>,
1541 _backend: &mut ItemRendererRef,
1542 _self_rc: &ItemRc,
1543 _size: LogicalSize,
1544 ) -> RenderingResult {
1545 RenderingResult::ContinueRenderingChildren
1546 }
1547
1548 fn bounding_rect(
1549 self: core::pin::Pin<&Self>,
1550 _window_adapter: &Rc<dyn WindowAdapter>,
1551 _self_rc: &ItemRc,
1552 geometry: LogicalRect,
1553 ) -> LogicalRect {
1554 geometry
1555 }
1556
1557 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1558 false
1559 }
1560}
1561
1562impl ContextMenu {
1563 pub fn close(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) {
1564 if let Some(id) = self.popup_id.take() {
1565 WindowInner::from_pub(window_adapter.window()).close_popup(id);
1566 }
1567 }
1568
1569 pub fn is_open(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) -> bool {
1570 self.popup_id.get().is_some_and(|id| {
1571 WindowInner::from_pub(window_adapter.window())
1572 .active_popups()
1573 .iter()
1574 .any(|p| p.popup_id == id)
1575 })
1576 }
1577}
1578
1579impl ItemConsts for ContextMenu {
1580 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1581 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1582}
1583
1584declare_item_vtable! {
1585 fn slint_get_ContextMenuVTable() -> ContextMenuVTable for ContextMenu
1586}
1587
1588#[cfg(feature = "ffi")]
1589#[unsafe(no_mangle)]
1590pub unsafe extern "C" fn slint_contextmenu_close(
1591 s: Pin<&ContextMenu>,
1592 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1593 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1594 self_index: u32,
1595) {
1596 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1597 let self_rc = ItemRc::new(self_component.clone(), self_index);
1598 s.close(window_adapter, &self_rc);
1599}
1600
1601#[cfg(feature = "ffi")]
1602#[unsafe(no_mangle)]
1603pub unsafe extern "C" fn slint_contextmenu_is_open(
1604 s: Pin<&ContextMenu>,
1605 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1606 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1607 self_index: u32,
1608) -> bool {
1609 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1610 let self_rc = ItemRc::new(self_component.clone(), self_index);
1611 s.is_open(window_adapter, &self_rc)
1612}
1613
1614#[repr(C)]
1616#[derive(FieldOffsets, Default, SlintElement)]
1617#[pin]
1618pub struct BoxShadow {
1619 pub border_radius: Property<LogicalLength>,
1620 pub offset_x: Property<LogicalLength>,
1622 pub offset_y: Property<LogicalLength>,
1623 pub color: Property<Color>,
1624 pub blur: Property<LogicalLength>,
1625 pub cached_rendering_data: CachedRenderingData,
1626}
1627
1628impl Item for BoxShadow {
1629 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1630
1631 fn layout_info(
1632 self: Pin<&Self>,
1633 _orientation: Orientation,
1634 _window_adapter: &Rc<dyn WindowAdapter>,
1635 _self_rc: &ItemRc,
1636 ) -> LayoutInfo {
1637 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1638 }
1639
1640 fn input_event_filter_before_children(
1641 self: Pin<&Self>,
1642 _: &MouseEvent,
1643 _window_adapter: &Rc<dyn WindowAdapter>,
1644 _self_rc: &ItemRc,
1645 ) -> InputEventFilterResult {
1646 InputEventFilterResult::ForwardAndIgnore
1647 }
1648
1649 fn input_event(
1650 self: Pin<&Self>,
1651 _: &MouseEvent,
1652 _window_adapter: &Rc<dyn WindowAdapter>,
1653 _self_rc: &ItemRc,
1654 ) -> InputEventResult {
1655 InputEventResult::EventIgnored
1656 }
1657
1658 fn capture_key_event(
1659 self: Pin<&Self>,
1660 _: &KeyEvent,
1661 _window_adapter: &Rc<dyn WindowAdapter>,
1662 _self_rc: &ItemRc,
1663 ) -> KeyEventResult {
1664 KeyEventResult::EventIgnored
1665 }
1666
1667 fn key_event(
1668 self: Pin<&Self>,
1669 _: &KeyEvent,
1670 _window_adapter: &Rc<dyn WindowAdapter>,
1671 _self_rc: &ItemRc,
1672 ) -> KeyEventResult {
1673 KeyEventResult::EventIgnored
1674 }
1675
1676 fn focus_event(
1677 self: Pin<&Self>,
1678 _: &FocusEvent,
1679 _window_adapter: &Rc<dyn WindowAdapter>,
1680 _self_rc: &ItemRc,
1681 ) -> FocusEventResult {
1682 FocusEventResult::FocusIgnored
1683 }
1684
1685 fn render(
1686 self: Pin<&Self>,
1687 backend: &mut ItemRendererRef,
1688 self_rc: &ItemRc,
1689 size: LogicalSize,
1690 ) -> RenderingResult {
1691 (*backend).draw_box_shadow(self, self_rc, size);
1692 RenderingResult::ContinueRenderingChildren
1693 }
1694
1695 fn bounding_rect(
1696 self: core::pin::Pin<&Self>,
1697 _window_adapter: &Rc<dyn WindowAdapter>,
1698 _self_rc: &ItemRc,
1699 geometry: LogicalRect,
1700 ) -> LogicalRect {
1701 geometry
1702 .outer_rect(euclid::SideOffsets2D::from_length_all_same(self.blur()))
1703 .translate(LogicalVector::from_lengths(self.offset_x(), self.offset_y()))
1704 }
1705
1706 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1707 false
1708 }
1709}
1710
1711impl ItemConsts for BoxShadow {
1712 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1713 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1714}
1715
1716declare_item_vtable! {
1717 fn slint_get_BoxShadowVTable() -> BoxShadowVTable for BoxShadow
1718}
1719
1720declare_item_vtable! {
1721 fn slint_get_ComponentContainerVTable() -> ComponentContainerVTable for ComponentContainer
1722}
1723
1724declare_item_vtable! {
1725 fn slint_get_ComplexTextVTable() -> ComplexTextVTable for ComplexText
1726}
1727
1728declare_item_vtable! {
1729 fn slint_get_SimpleTextVTable() -> SimpleTextVTable for SimpleText
1730}
1731
1732declare_item_vtable! {
1733 fn slint_get_TextInputVTable() -> TextInputVTable for TextInput
1734}
1735
1736declare_item_vtable! {
1737 fn slint_get_ImageItemVTable() -> ImageItemVTable for ImageItem
1738}
1739
1740declare_item_vtable! {
1741 fn slint_get_ClippedImageVTable() -> ClippedImageVTable for ClippedImage
1742}
1743
1744#[cfg(feature = "std")]
1745declare_item_vtable! {
1746 fn slint_get_PathVTable() -> PathVTable for Path
1747}
1748
1749declare_item_vtable! {
1750 fn slint_get_MenuItemVTable() -> MenuItemVTable for MenuItem
1751}
1752
1753macro_rules! declare_enums {
1754 ($( $(#[$enum_doc:meta])* enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
1755 $(
1756 #[derive(Copy, Clone, Debug, PartialEq, Eq, strum::EnumString, strum::Display, Hash)]
1757 #[repr(u32)]
1758 #[strum(serialize_all = "kebab-case")]
1759 $(#[$enum_doc])*
1760 pub enum $Name {
1761 $( $(#[$value_doc])* $Value),*
1762 }
1763
1764 impl Default for $Name {
1765 fn default() -> Self {
1766 ($(Self::$Value,)*).0
1768 }
1769 }
1770 )*
1771 };
1772}
1773
1774i_slint_common::for_each_enums!(declare_enums);
1775
1776macro_rules! declare_builtin_structs {
1777 ($(
1778 $(#[$struct_attr:meta])*
1779 struct $Name:ident {
1780 @name = $inner_name:literal
1781 export {
1782 $( $(#[$pub_attr:meta])* $pub_field:ident : $pub_type:ty, )*
1783 }
1784 private {
1785 $( $(#[$pri_attr:meta])* $pri_field:ident : $pri_type:ty, )*
1786 }
1787 }
1788 )*) => {
1789 $(
1790 #[derive(Clone, Debug, Default, PartialEq)]
1791 #[repr(C)]
1792 $(#[$struct_attr])*
1793 pub struct $Name {
1794 $(
1795 $(#[$pub_attr])*
1796 pub $pub_field : $pub_type,
1797 )*
1798 $(
1799 $(#[$pri_attr])*
1800 pub $pri_field : $pri_type,
1801 )*
1802 }
1803 )*
1804 };
1805}
1806
1807i_slint_common::for_each_builtin_structs!(declare_builtin_structs);
1808
1809#[cfg(feature = "ffi")]
1810#[unsafe(no_mangle)]
1811pub unsafe extern "C" fn slint_item_absolute_position(
1812 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1813 self_index: u32,
1814) -> crate::lengths::LogicalPoint {
1815 let self_rc = ItemRc::new(self_component.clone(), self_index);
1816 self_rc.map_to_window(Default::default())
1817}