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