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