Skip to main content

i_slint_core/
items.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4// cSpell: ignore nesw
5
6/*!
7This module contains the builtin items, either in this file or in sub-modules.
8
9When adding an item or a property, it needs to be kept in sync with different place.
10(This is less than ideal and maybe we can have some automation later)
11
12 - It needs to be changed in this module
13 - In the compiler: builtins.slint
14 - In the interpreter (new item only): dynamic_item_tree.rs
15 - For the C++ code (new item only): the cbindgen.rs to export the new item
16 - Don't forget to update the documentation
17*/
18
19#![allow(unsafe_code)]
20#![allow(non_upper_case_globals)]
21#![allow(missing_docs)] // because documenting each property of items is redundant
22
23use 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
67/// Alias for `&mut dyn ItemRenderer`. Required so cbindgen generates the ItemVTable
68/// despite the presence of trait object
69type ItemRendererRef<'a> = &'a mut dyn crate::item_rendering::ItemRenderer;
70
71/// Workarounds for cbindgen
72pub 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/// Returned by the `render()` function on items to indicate whether the rendering of
109/// children should be handled by the caller, of if the item took care of that (for example
110/// through layer indirection)
111#[repr(C)]
112#[derive(Default)]
113pub enum RenderingResult {
114    #[default]
115    ContinueRenderingChildren,
116    ContinueRenderingWithoutChildren,
117}
118
119/// Items are the nodes in the render tree.
120#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
121#[vtable]
122#[repr(C)]
123pub struct ItemVTable {
124    /// This function is called by the run-time after the memory for the item
125    /// has been allocated and initialized. It will be called before any user specified
126    /// bindings are set.
127    pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, my_item: &ItemRc),
128
129    /// offset in bytes from the *const ItemImpl.
130    /// isize::MAX  means None
131    #[allow(non_upper_case_globals)]
132    #[field_offset(CachedRenderingData)]
133    pub cached_rendering_data_offset: usize,
134
135    /// We would need max/min/preferred size, and all layout info
136    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    /// Event handler for mouse and touch event. This function is called before being called on children.
144    /// Then, depending on the return value, it is called for the children, and their children, then
145    /// [`Self::input_event`] is called on the children, and finally [`Self::input_event`] is called
146    /// on this item again.
147    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    /// Handle input event for mouse and touch event
155    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    /// Called on the parents of the focused item, allowing for global shortcuts and similar
170    /// overrides of the default actions.
171    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    /// Returns the rendering bounding rect for that particular item in the parent's item coordinate
193    /// (same coordinate system as the geometry)
194    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
204/// Alias for `vtable::VRef<ItemVTable>` which represent a pointer to a `dyn Item` with
205/// the associated vtable
206pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
207
208#[repr(C)]
209#[derive(FieldOffsets, Default, SlintElement)]
210#[pin]
211/// The implementation of an empty items that does nothing
212pub 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]
311/// The implementation of the `Rectangle` element
312pub 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]
418/// The implementation of the `BasicBorderRectangle` element
419pub 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]
537/// The implementation of the `BorderRectangle` element
538pub 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]
677/// The implementation of the `Clip` element
678pub 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]
802/// The Opacity Item is not meant to be used directly by the .slint code, instead, the `opacity: xxx` or `visible: false` should be used
803pub struct Opacity {
804    // FIXME: this element shouldn't need these geometry property
805    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    // This function determines the optimization opportunities for not having to render the
891    // children of the Opacity element into a layer:
892    //  *  The opacity item typically only one child (this is not guaranteed). If that item has
893    //     no children, then we can skip the layer and apply the opacity directly. This is not perfect though,
894    //     for example if the compiler inserts another synthetic element between the `Opacity` and the actual child,
895    //     then this check will apply a layer even though it might not actually be necessary.
896    //  * If the vale of the opacity is 1.0 then we don't need to do anything.
897    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, // No children? Don't need a layer then.
905        };
906
907        if opacity_child.next_sibling().is_some() {
908            return true; // If the opacity item has more than one child, then we need a layer
909        }
910
911        // If the target of the opacity has any children then we need a layer
912        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]
930/// The Layer Item is not meant to be used directly by the .slint code, instead, the `layer: xxx` property should be used
931pub 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]
1030/// The implementation of the `Transform` item.
1031/// This item is generated by the compiler  as soon as any transform property is used on any element.
1032pub 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/// The implementation of the `PropertyAnimation` element
1149#[repr(C)]
1150#[derive(FieldOffsets, SlintElement, Clone, Debug)]
1151#[pin]
1152pub struct PropertyAnimation {
1153    #[rtti_field]
1154    pub delay: i32,
1155    /// duration in millisecond
1156    #[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        // Defaults for PropertyAnimation are defined here (for internal Rust code doing programmatic animations)
1169        // as well as in `builtins.slint` (for generated C++ and Rust code)
1170        Self {
1171            delay: 0,
1172            duration: 0,
1173            iteration_count: 1.,
1174            direction: Default::default(),
1175            easing: Default::default(),
1176        }
1177    }
1178}
1179
1180/// The implementation of the `Window` element
1181#[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            // Dialogs and other nested Window items
1273            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    /// Creates a new FontRequest that uses the provide local font properties. If they're not set, i.e.
1355    /// the family is an empty string, or the weight is zero, the corresponding properties are fetched
1356    /// from the next parent WindowItem.
1357    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/// The implementation used for `ContextMenuArea` and `ContextMenuInternal` elements
1434#[repr(C)]
1435#[derive(FieldOffsets, Default, SlintElement)]
1436#[pin]
1437pub struct ContextMenu {
1438    //pub entries: Property<crate::model::ModelRc<MenuEntry>>,
1439    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/// The implementation of the `BoxShadow` element
1634#[repr(C)]
1635#[derive(FieldOffsets, Default, SlintElement)]
1636#[pin]
1637pub struct BoxShadow {
1638    pub border_radius: Property<LogicalLength>,
1639    // Shadow specific properties
1640    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                    // Always return the first value
1790                    ($(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}