1#![allow(unsafe_code)]
20#![allow(non_upper_case_globals)]
21#![allow(missing_docs)] use crate::api::LogicalPosition;
24use crate::cursor::MouseCursorInner;
25use crate::data_transfer::DataTransfer;
26use crate::graphics::{Brush, Color, FontRequest, Image};
27use crate::input::{
28 FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, InternalKeyEvent,
29 KeyEventResult, KeyEventType, Keys, MouseEvent,
30};
31use crate::item_rendering::{CachedRenderingData, RenderBorderRectangle, RenderRectangle};
32use crate::item_tree::ItemTreeRc;
33pub use crate::item_tree::{ItemRc, ItemTreeVTable};
34use crate::layout::LayoutInfo;
35use crate::lengths::{
36 LogicalBorderRadius, LogicalLength, LogicalRect, LogicalSize, LogicalVector, PointLengths,
37 RectLengths,
38};
39pub use crate::menus::MenuItem;
40#[cfg(feature = "rtti")]
41use crate::rtti::*;
42use crate::window::{WindowAdapter, WindowAdapterRc, WindowInner};
43use crate::{Callback, Coord, Property, SharedString};
44use alloc::rc::Rc;
45use const_field_offset::FieldOffsets;
46use core::cell::Cell;
47use core::num::NonZeroU32;
48use core::pin::Pin;
49use core::time::Duration;
50use i_slint_core_macros::*;
51pub use system_tray::SystemTrayIcon;
52use vtable::*;
53
54mod component_container;
55pub use self::component_container::*;
56mod flickable;
57pub use flickable::Flickable;
58mod text;
59pub use text::*;
60mod input_items;
61pub use input_items::*;
62mod image;
63pub use self::image::*;
64mod drag_n_drop;
65pub use drag_n_drop::*;
66#[cfg(feature = "path")]
67mod path;
68#[cfg(feature = "path")]
69pub use path::*;
70pub mod system_tray;
71
72type ItemRendererRef<'a> = &'a mut dyn crate::item_rendering::ItemRenderer;
75
76pub type VoidArg = ();
78pub type KeyEventArg = (KeyEvent,);
79pub type DragActionArg = (DragAction,);
80type FocusReasonArg = (FocusReason,);
81type PointerEventArg = (PointerEvent,);
82type PointerScrollEventArg = (PointerScrollEvent,);
83type PointArg = (LogicalPosition,);
84type MenuEntryArg = (MenuEntry,);
85type StringArg = (SharedString,);
86type MenuEntryModel = crate::model::ModelRc<MenuEntry>;
87
88#[cfg(all(feature = "ffi", windows))]
89#[macro_export]
90macro_rules! declare_item_vtable {
91 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
92 ItemVTable_static! {
93 #[unsafe(no_mangle)]
94 pub static $item_vtable_ty for $item_ty
95 }
96 #[unsafe(no_mangle)]
97 pub extern "C" fn $getter() -> *const ItemVTable {
98 use vtable::HasStaticVTable;
99 <$item_ty>::STATIC_VTABLE
100 }
101 };
102}
103#[cfg(not(all(feature = "ffi", windows)))]
104#[macro_export]
105macro_rules! declare_item_vtable {
106 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
107 ItemVTable_static! {
108 #[unsafe(no_mangle)]
109 pub static $item_vtable_ty for $item_ty
110 }
111 };
112}
113
114#[repr(C)]
118#[derive(Default)]
119pub enum RenderingResult {
120 #[default]
121 ContinueRenderingChildren,
122 ContinueRenderingWithoutChildren,
123}
124
125#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
127#[vtable]
128#[repr(C)]
129pub struct ItemVTable {
130 pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, my_item: &ItemRc),
134
135 pub deinit: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, window_adapter: &WindowAdapterRc),
136
137 #[allow(non_upper_case_globals)]
140 #[field_offset(CachedRenderingData)]
141 pub cached_rendering_data_offset: usize,
142
143 pub layout_info: extern "C" fn(
148 core::pin::Pin<VRef<ItemVTable>>,
149 orientation: Orientation,
150 cross_axis_constraint: Coord,
151 window_adapter: &WindowAdapterRc,
152 self_rc: &ItemRc,
153 ) -> LayoutInfo,
154
155 pub input_event_filter_before_children: extern "C" fn(
165 core::pin::Pin<VRef<ItemVTable>>,
166 &MouseEvent,
167 window_adapter: &WindowAdapterRc,
168 self_rc: &ItemRc,
169 cursor: &mut MouseCursorInner,
170 ) -> InputEventFilterResult,
171
172 pub input_event: extern "C" fn(
174 core::pin::Pin<VRef<ItemVTable>>,
175 &MouseEvent,
176 window_adapter: &WindowAdapterRc,
177 self_rc: &ItemRc,
178 cursor: &mut MouseCursorInner,
179 ) -> InputEventResult,
180
181 pub focus_event: extern "C" fn(
182 core::pin::Pin<VRef<ItemVTable>>,
183 &FocusEvent,
184 window_adapter: &WindowAdapterRc,
185 self_rc: &ItemRc,
186 ) -> FocusEventResult,
187
188 pub capture_key_event: extern "C" fn(
191 core::pin::Pin<VRef<ItemVTable>>,
192 &InternalKeyEvent,
193 window_adapter: &WindowAdapterRc,
194 self_rc: &ItemRc,
195 ) -> KeyEventResult,
196
197 pub key_event: extern "C" fn(
198 core::pin::Pin<VRef<ItemVTable>>,
199 &InternalKeyEvent,
200 window_adapter: &WindowAdapterRc,
201 self_rc: &ItemRc,
202 ) -> KeyEventResult,
203
204 pub render: extern "C" fn(
205 core::pin::Pin<VRef<ItemVTable>>,
206 backend: &mut ItemRendererRef,
207 self_rc: &ItemRc,
208 size: LogicalSize,
209 ) -> RenderingResult,
210
211 pub bounding_rect: extern "C" fn(
214 core::pin::Pin<VRef<ItemVTable>>,
215 window_adapter: &WindowAdapterRc,
216 self_rc: &ItemRc,
217 geometry: LogicalRect,
218 ) -> LogicalRect,
219
220 pub clips_children: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>) -> bool,
221}
222
223pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
226
227#[repr(C)]
228#[derive(FieldOffsets, Default, SlintElement)]
229#[pin]
230pub struct Empty {
232 pub cached_rendering_data: CachedRenderingData,
233}
234
235impl Item for Empty {
236 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
237
238 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
239
240 fn layout_info(
241 self: Pin<&Self>,
242 _orientation: Orientation,
243 _cross_axis_constraint: Coord,
244 _window_adapter: &Rc<dyn WindowAdapter>,
245 _self_rc: &ItemRc,
246 ) -> LayoutInfo {
247 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
248 }
249
250 fn input_event_filter_before_children(
251 self: Pin<&Self>,
252 _: &MouseEvent,
253 _window_adapter: &Rc<dyn WindowAdapter>,
254 _self_rc: &ItemRc,
255 _: &mut MouseCursorInner,
256 ) -> InputEventFilterResult {
257 InputEventFilterResult::ForwardAndIgnore
258 }
259
260 fn input_event(
261 self: Pin<&Self>,
262 _: &MouseEvent,
263 _window_adapter: &Rc<dyn WindowAdapter>,
264 _self_rc: &ItemRc,
265 _: &mut MouseCursorInner,
266 ) -> InputEventResult {
267 InputEventResult::EventIgnored
268 }
269
270 fn capture_key_event(
271 self: Pin<&Self>,
272 _: &InternalKeyEvent,
273 _window_adapter: &Rc<dyn WindowAdapter>,
274 _self_rc: &ItemRc,
275 ) -> KeyEventResult {
276 KeyEventResult::EventIgnored
277 }
278
279 fn key_event(
280 self: Pin<&Self>,
281 _: &InternalKeyEvent,
282 _window_adapter: &Rc<dyn WindowAdapter>,
283 _self_rc: &ItemRc,
284 ) -> KeyEventResult {
285 KeyEventResult::EventIgnored
286 }
287
288 fn focus_event(
289 self: Pin<&Self>,
290 _: &FocusEvent,
291 _window_adapter: &Rc<dyn WindowAdapter>,
292 _self_rc: &ItemRc,
293 ) -> FocusEventResult {
294 FocusEventResult::FocusIgnored
295 }
296
297 fn render(
298 self: Pin<&Self>,
299 _backend: &mut ItemRendererRef,
300 _self_rc: &ItemRc,
301 _size: LogicalSize,
302 ) -> RenderingResult {
303 RenderingResult::ContinueRenderingChildren
304 }
305
306 fn bounding_rect(
307 self: core::pin::Pin<&Self>,
308 _window_adapter: &Rc<dyn WindowAdapter>,
309 _self_rc: &ItemRc,
310 mut geometry: LogicalRect,
311 ) -> LogicalRect {
312 geometry.size = LogicalSize::zero();
313 geometry
314 }
315
316 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
317 false
318 }
319}
320
321impl ItemConsts for Empty {
322 const cached_rendering_data_offset: const_field_offset::FieldOffset<
323 Empty,
324 CachedRenderingData,
325 > = Empty::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
326}
327
328declare_item_vtable! {
329 fn slint_get_EmptyVTable() -> EmptyVTable for Empty
330}
331
332#[repr(C)]
333#[derive(FieldOffsets, Default, SlintElement)]
334#[pin]
335pub struct Rectangle {
337 pub background: Property<Brush>,
338 pub cached_rendering_data: CachedRenderingData,
339}
340
341impl Item for Rectangle {
342 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
343
344 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
345
346 fn layout_info(
347 self: Pin<&Self>,
348 _orientation: Orientation,
349 _cross_axis_constraint: Coord,
350 _window_adapter: &Rc<dyn WindowAdapter>,
351 _self_rc: &ItemRc,
352 ) -> LayoutInfo {
353 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
354 }
355
356 fn input_event_filter_before_children(
357 self: Pin<&Self>,
358 _: &MouseEvent,
359 _window_adapter: &Rc<dyn WindowAdapter>,
360 _self_rc: &ItemRc,
361 _: &mut MouseCursorInner,
362 ) -> InputEventFilterResult {
363 InputEventFilterResult::ForwardAndIgnore
364 }
365
366 fn input_event(
367 self: Pin<&Self>,
368 _: &MouseEvent,
369 _window_adapter: &Rc<dyn WindowAdapter>,
370 _self_rc: &ItemRc,
371 _: &mut MouseCursorInner,
372 ) -> InputEventResult {
373 InputEventResult::EventIgnored
374 }
375
376 fn capture_key_event(
377 self: Pin<&Self>,
378 _: &InternalKeyEvent,
379 _window_adapter: &Rc<dyn WindowAdapter>,
380 _self_rc: &ItemRc,
381 ) -> KeyEventResult {
382 KeyEventResult::EventIgnored
383 }
384
385 fn key_event(
386 self: Pin<&Self>,
387 _: &InternalKeyEvent,
388 _window_adapter: &Rc<dyn WindowAdapter>,
389 _self_rc: &ItemRc,
390 ) -> KeyEventResult {
391 KeyEventResult::EventIgnored
392 }
393
394 fn focus_event(
395 self: Pin<&Self>,
396 _: &FocusEvent,
397 _window_adapter: &Rc<dyn WindowAdapter>,
398 _self_rc: &ItemRc,
399 ) -> FocusEventResult {
400 FocusEventResult::FocusIgnored
401 }
402
403 fn render(
404 self: Pin<&Self>,
405 backend: &mut ItemRendererRef,
406 self_rc: &ItemRc,
407 size: LogicalSize,
408 ) -> RenderingResult {
409 (*backend).draw_rectangle(self, self_rc, size, &self.cached_rendering_data);
410 RenderingResult::ContinueRenderingChildren
411 }
412
413 fn bounding_rect(
414 self: core::pin::Pin<&Self>,
415 _window_adapter: &Rc<dyn WindowAdapter>,
416 _self_rc: &ItemRc,
417 geometry: LogicalRect,
418 ) -> LogicalRect {
419 geometry
420 }
421
422 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
423 false
424 }
425}
426
427impl RenderRectangle for Rectangle {
428 fn background(self: Pin<&Self>) -> Brush {
429 self.background()
430 }
431}
432
433impl ItemConsts for Rectangle {
434 const cached_rendering_data_offset: const_field_offset::FieldOffset<
435 Rectangle,
436 CachedRenderingData,
437 > = Rectangle::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
438}
439
440declare_item_vtable! {
441 fn slint_get_RectangleVTable() -> RectangleVTable for Rectangle
442}
443
444#[repr(C)]
445#[derive(FieldOffsets, Default, SlintElement)]
446#[pin]
447pub struct BasicBorderRectangle {
449 pub background: Property<Brush>,
450 pub border_width: Property<LogicalLength>,
451 pub border_radius: Property<LogicalLength>,
452 pub border_color: Property<Brush>,
453 pub cached_rendering_data: CachedRenderingData,
454}
455
456impl Item for BasicBorderRectangle {
457 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
458
459 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
460
461 fn layout_info(
462 self: Pin<&Self>,
463 _orientation: Orientation,
464 _cross_axis_constraint: Coord,
465 _window_adapter: &Rc<dyn WindowAdapter>,
466 _self_rc: &ItemRc,
467 ) -> LayoutInfo {
468 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
469 }
470
471 fn input_event_filter_before_children(
472 self: Pin<&Self>,
473 _: &MouseEvent,
474 _window_adapter: &Rc<dyn WindowAdapter>,
475 _self_rc: &ItemRc,
476 _: &mut MouseCursorInner,
477 ) -> InputEventFilterResult {
478 InputEventFilterResult::ForwardAndIgnore
479 }
480
481 fn input_event(
482 self: Pin<&Self>,
483 _: &MouseEvent,
484 _window_adapter: &Rc<dyn WindowAdapter>,
485 _self_rc: &ItemRc,
486 _: &mut MouseCursorInner,
487 ) -> InputEventResult {
488 InputEventResult::EventIgnored
489 }
490
491 fn capture_key_event(
492 self: Pin<&Self>,
493 _: &InternalKeyEvent,
494 _window_adapter: &Rc<dyn WindowAdapter>,
495 _self_rc: &ItemRc,
496 ) -> KeyEventResult {
497 KeyEventResult::EventIgnored
498 }
499
500 fn key_event(
501 self: Pin<&Self>,
502 _: &InternalKeyEvent,
503 _window_adapter: &Rc<dyn WindowAdapter>,
504 _self_rc: &ItemRc,
505 ) -> KeyEventResult {
506 KeyEventResult::EventIgnored
507 }
508
509 fn focus_event(
510 self: Pin<&Self>,
511 _: &FocusEvent,
512 _window_adapter: &Rc<dyn WindowAdapter>,
513 _self_rc: &ItemRc,
514 ) -> FocusEventResult {
515 FocusEventResult::FocusIgnored
516 }
517
518 fn render(
519 self: Pin<&Self>,
520 backend: &mut ItemRendererRef,
521 self_rc: &ItemRc,
522 size: LogicalSize,
523 ) -> RenderingResult {
524 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
525 RenderingResult::ContinueRenderingChildren
526 }
527
528 fn bounding_rect(
529 self: core::pin::Pin<&Self>,
530 _window_adapter: &Rc<dyn WindowAdapter>,
531 _self_rc: &ItemRc,
532 geometry: LogicalRect,
533 ) -> LogicalRect {
534 geometry
535 }
536
537 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
538 false
539 }
540}
541
542impl RenderBorderRectangle for BasicBorderRectangle {
543 fn background(self: Pin<&Self>) -> Brush {
544 self.background()
545 }
546 fn border_width(self: Pin<&Self>) -> LogicalLength {
547 self.border_width()
548 }
549 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
550 LogicalBorderRadius::from_length(self.border_radius())
551 }
552 fn border_color(self: Pin<&Self>) -> Brush {
553 self.border_color()
554 }
555}
556
557impl ItemConsts for BasicBorderRectangle {
558 const cached_rendering_data_offset: const_field_offset::FieldOffset<
559 BasicBorderRectangle,
560 CachedRenderingData,
561 > = BasicBorderRectangle::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
562}
563
564declare_item_vtable! {
565 fn slint_get_BasicBorderRectangleVTable() -> BasicBorderRectangleVTable for BasicBorderRectangle
566}
567
568#[repr(C)]
569#[derive(FieldOffsets, Default, SlintElement)]
570#[pin]
571pub struct BorderRectangle {
573 pub background: Property<Brush>,
574 pub border_width: Property<LogicalLength>,
575 pub border_radius: Property<LogicalLength>,
576 pub border_top_left_radius: Property<LogicalLength>,
577 pub border_top_right_radius: Property<LogicalLength>,
578 pub border_bottom_left_radius: Property<LogicalLength>,
579 pub border_bottom_right_radius: Property<LogicalLength>,
580 pub border_color: Property<Brush>,
581 pub cached_rendering_data: CachedRenderingData,
582}
583
584impl Item for BorderRectangle {
585 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
586
587 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
588
589 fn layout_info(
590 self: Pin<&Self>,
591 _orientation: Orientation,
592 _cross_axis_constraint: Coord,
593 _window_adapter: &Rc<dyn WindowAdapter>,
594 _self_rc: &ItemRc,
595 ) -> LayoutInfo {
596 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
597 }
598
599 fn input_event_filter_before_children(
600 self: Pin<&Self>,
601 _: &MouseEvent,
602 _window_adapter: &Rc<dyn WindowAdapter>,
603 _self_rc: &ItemRc,
604 _: &mut MouseCursorInner,
605 ) -> InputEventFilterResult {
606 InputEventFilterResult::ForwardAndIgnore
607 }
608
609 fn input_event(
610 self: Pin<&Self>,
611 _: &MouseEvent,
612 _window_adapter: &Rc<dyn WindowAdapter>,
613 _self_rc: &ItemRc,
614 _: &mut MouseCursorInner,
615 ) -> InputEventResult {
616 InputEventResult::EventIgnored
617 }
618
619 fn capture_key_event(
620 self: Pin<&Self>,
621 _: &InternalKeyEvent,
622 _window_adapter: &Rc<dyn WindowAdapter>,
623 _self_rc: &ItemRc,
624 ) -> KeyEventResult {
625 KeyEventResult::EventIgnored
626 }
627
628 fn key_event(
629 self: Pin<&Self>,
630 _: &InternalKeyEvent,
631 _window_adapter: &Rc<dyn WindowAdapter>,
632 _self_rc: &ItemRc,
633 ) -> KeyEventResult {
634 KeyEventResult::EventIgnored
635 }
636
637 fn focus_event(
638 self: Pin<&Self>,
639 _: &FocusEvent,
640 _window_adapter: &Rc<dyn WindowAdapter>,
641 _self_rc: &ItemRc,
642 ) -> FocusEventResult {
643 FocusEventResult::FocusIgnored
644 }
645
646 fn render(
647 self: Pin<&Self>,
648 backend: &mut ItemRendererRef,
649 self_rc: &ItemRc,
650 size: LogicalSize,
651 ) -> RenderingResult {
652 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
653 RenderingResult::ContinueRenderingChildren
654 }
655
656 fn bounding_rect(
657 self: core::pin::Pin<&Self>,
658 _window_adapter: &Rc<dyn WindowAdapter>,
659 _self_rc: &ItemRc,
660 geometry: LogicalRect,
661 ) -> LogicalRect {
662 geometry
663 }
664
665 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
666 false
667 }
668}
669
670impl RenderBorderRectangle for BorderRectangle {
671 fn background(self: Pin<&Self>) -> Brush {
672 self.background()
673 }
674 fn border_width(self: Pin<&Self>) -> LogicalLength {
675 self.border_width()
676 }
677 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
678 LogicalBorderRadius::from_lengths(
679 self.border_top_left_radius(),
680 self.border_top_right_radius(),
681 self.border_bottom_right_radius(),
682 self.border_bottom_left_radius(),
683 )
684 }
685 fn border_color(self: Pin<&Self>) -> Brush {
686 self.border_color()
687 }
688}
689
690impl ItemConsts for BorderRectangle {
691 const cached_rendering_data_offset: const_field_offset::FieldOffset<
692 BorderRectangle,
693 CachedRenderingData,
694 > = BorderRectangle::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
695}
696
697declare_item_vtable! {
698 fn slint_get_BorderRectangleVTable() -> BorderRectangleVTable for BorderRectangle
699}
700
701declare_item_vtable! {
702 fn slint_get_TouchAreaVTable() -> TouchAreaVTable for TouchArea
703}
704
705declare_item_vtable! {
706 fn slint_get_FocusScopeVTable() -> FocusScopeVTable for FocusScope
707}
708
709crate::declare_item_vtable! {
710 fn slint_get_KeyBindingVTable() -> KeyBindingVTable for KeyBinding
711}
712
713declare_item_vtable! {
714 fn slint_get_SwipeGestureHandlerVTable() -> SwipeGestureHandlerVTable for SwipeGestureHandler
715}
716
717declare_item_vtable! {
718 fn slint_get_ScaleRotateGestureHandlerVTable() -> ScaleRotateGestureHandlerVTable for ScaleRotateGestureHandler
719}
720
721#[repr(C)]
722#[derive(FieldOffsets, Default, SlintElement)]
723#[pin]
724pub struct Clip {
726 pub border_top_left_radius: Property<LogicalLength>,
727 pub border_top_right_radius: Property<LogicalLength>,
728 pub border_bottom_left_radius: Property<LogicalLength>,
729 pub border_bottom_right_radius: Property<LogicalLength>,
730 pub border_width: Property<LogicalLength>,
731 pub cached_rendering_data: CachedRenderingData,
732 pub clip: Property<bool>,
733 pub is_visibility_clip: Property<bool>,
734}
735
736impl Item for Clip {
737 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
738
739 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
740
741 fn layout_info(
742 self: Pin<&Self>,
743 _orientation: Orientation,
744 _cross_axis_constraint: Coord,
745 _window_adapter: &Rc<dyn WindowAdapter>,
746 _self_rc: &ItemRc,
747 ) -> LayoutInfo {
748 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
749 }
750
751 fn input_event_filter_before_children(
752 self: Pin<&Self>,
753 event: &MouseEvent,
754 _window_adapter: &Rc<dyn WindowAdapter>,
755 self_rc: &ItemRc,
756 _: &mut MouseCursorInner,
757 ) -> InputEventFilterResult {
758 if let Some(pos) = event.position() {
759 let geometry = self_rc.geometry();
760 if self.clip()
761 && (pos.x < 0 as Coord
762 || pos.y < 0 as Coord
763 || pos.x_length() > geometry.width_length()
764 || pos.y_length() > geometry.height_length())
765 {
766 return InputEventFilterResult::Intercept;
767 }
768 }
769 InputEventFilterResult::ForwardAndIgnore
770 }
771
772 fn input_event(
773 self: Pin<&Self>,
774 _: &MouseEvent,
775 _window_adapter: &Rc<dyn WindowAdapter>,
776 _self_rc: &ItemRc,
777 _: &mut MouseCursorInner,
778 ) -> InputEventResult {
779 InputEventResult::EventIgnored
780 }
781
782 fn capture_key_event(
783 self: Pin<&Self>,
784 _: &InternalKeyEvent,
785 _window_adapter: &Rc<dyn WindowAdapter>,
786 _self_rc: &ItemRc,
787 ) -> KeyEventResult {
788 KeyEventResult::EventIgnored
789 }
790
791 fn key_event(
792 self: Pin<&Self>,
793 _: &InternalKeyEvent,
794 _window_adapter: &Rc<dyn WindowAdapter>,
795 _self_rc: &ItemRc,
796 ) -> KeyEventResult {
797 KeyEventResult::EventIgnored
798 }
799
800 fn focus_event(
801 self: Pin<&Self>,
802 _: &FocusEvent,
803 _window_adapter: &Rc<dyn WindowAdapter>,
804 _self_rc: &ItemRc,
805 ) -> FocusEventResult {
806 FocusEventResult::FocusIgnored
807 }
808
809 fn render(
810 self: Pin<&Self>,
811 backend: &mut ItemRendererRef,
812 self_rc: &ItemRc,
813 size: LogicalSize,
814 ) -> RenderingResult {
815 (*backend).visit_clip(self, self_rc, size)
816 }
817
818 fn bounding_rect(
819 self: core::pin::Pin<&Self>,
820 _window_adapter: &Rc<dyn WindowAdapter>,
821 _self_rc: &ItemRc,
822 geometry: LogicalRect,
823 ) -> LogicalRect {
824 geometry
825 }
826
827 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
828 self.clip()
829 }
830}
831
832impl Clip {
833 pub fn logical_border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
834 LogicalBorderRadius::from_lengths(
835 self.border_top_left_radius(),
836 self.border_top_right_radius(),
837 self.border_bottom_right_radius(),
838 self.border_bottom_left_radius(),
839 )
840 }
841}
842
843impl ItemConsts for Clip {
844 const cached_rendering_data_offset: const_field_offset::FieldOffset<Clip, CachedRenderingData> =
845 Clip::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
846}
847
848declare_item_vtable! {
849 fn slint_get_ClipVTable() -> ClipVTable for Clip
850}
851
852#[repr(C)]
853#[derive(FieldOffsets, Default, SlintElement)]
854#[pin]
855pub struct Opacity {
857 pub opacity: Property<f32>,
859 pub cached_rendering_data: CachedRenderingData,
860}
861
862impl Item for Opacity {
863 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
864
865 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
866
867 fn layout_info(
868 self: Pin<&Self>,
869 _orientation: Orientation,
870 _cross_axis_constraint: Coord,
871 _window_adapter: &Rc<dyn WindowAdapter>,
872 _self_rc: &ItemRc,
873 ) -> LayoutInfo {
874 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
875 }
876
877 fn input_event_filter_before_children(
878 self: Pin<&Self>,
879 _: &MouseEvent,
880 _window_adapter: &Rc<dyn WindowAdapter>,
881 _self_rc: &ItemRc,
882 _: &mut MouseCursorInner,
883 ) -> InputEventFilterResult {
884 InputEventFilterResult::ForwardAndIgnore
885 }
886
887 fn input_event(
888 self: Pin<&Self>,
889 _: &MouseEvent,
890 _window_adapter: &Rc<dyn WindowAdapter>,
891 _self_rc: &ItemRc,
892 _: &mut MouseCursorInner,
893 ) -> InputEventResult {
894 InputEventResult::EventIgnored
895 }
896
897 fn capture_key_event(
898 self: Pin<&Self>,
899 _: &InternalKeyEvent,
900 _window_adapter: &Rc<dyn WindowAdapter>,
901 _self_rc: &ItemRc,
902 ) -> KeyEventResult {
903 KeyEventResult::EventIgnored
904 }
905
906 fn key_event(
907 self: Pin<&Self>,
908 _: &InternalKeyEvent,
909 _window_adapter: &Rc<dyn WindowAdapter>,
910 _self_rc: &ItemRc,
911 ) -> KeyEventResult {
912 KeyEventResult::EventIgnored
913 }
914
915 fn focus_event(
916 self: Pin<&Self>,
917 _: &FocusEvent,
918 _window_adapter: &Rc<dyn WindowAdapter>,
919 _self_rc: &ItemRc,
920 ) -> FocusEventResult {
921 FocusEventResult::FocusIgnored
922 }
923
924 fn render(
925 self: Pin<&Self>,
926 backend: &mut ItemRendererRef,
927 self_rc: &ItemRc,
928 size: LogicalSize,
929 ) -> RenderingResult {
930 backend.visit_opacity(self, self_rc, size)
931 }
932
933 fn bounding_rect(
934 self: core::pin::Pin<&Self>,
935 _window_adapter: &Rc<dyn WindowAdapter>,
936 _self_rc: &ItemRc,
937 geometry: LogicalRect,
938 ) -> LogicalRect {
939 geometry
940 }
941
942 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
943 false
944 }
945}
946
947impl Opacity {
948 pub fn need_layer(self_rc: &ItemRc, opacity: f32) -> bool {
956 if opacity == 1.0 {
957 return false;
958 }
959
960 let opacity_child = match self_rc.first_child() {
961 Some(first_child) => first_child,
962 None => return false, };
964
965 if opacity_child.next_sibling().is_some() {
966 return true; }
968
969 opacity_child.first_child().is_some()
971 }
972}
973
974impl ItemConsts for Opacity {
975 const cached_rendering_data_offset: const_field_offset::FieldOffset<
976 Opacity,
977 CachedRenderingData,
978 > = Opacity::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
979}
980
981declare_item_vtable! {
982 fn slint_get_OpacityVTable() -> OpacityVTable for Opacity
983}
984
985#[repr(C)]
986#[derive(FieldOffsets, Default, SlintElement)]
987#[pin]
988pub struct Layer {
990 pub cache_rendering_hint: Property<bool>,
991 pub cached_rendering_data: CachedRenderingData,
992}
993
994impl Item for Layer {
995 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
996
997 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
998
999 fn layout_info(
1000 self: Pin<&Self>,
1001 _orientation: Orientation,
1002 _cross_axis_constraint: Coord,
1003 _window_adapter: &Rc<dyn WindowAdapter>,
1004 _self_rc: &ItemRc,
1005 ) -> LayoutInfo {
1006 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1007 }
1008
1009 fn input_event_filter_before_children(
1010 self: Pin<&Self>,
1011 _: &MouseEvent,
1012 _window_adapter: &Rc<dyn WindowAdapter>,
1013 _self_rc: &ItemRc,
1014 _: &mut MouseCursorInner,
1015 ) -> InputEventFilterResult {
1016 InputEventFilterResult::ForwardAndIgnore
1017 }
1018
1019 fn input_event(
1020 self: Pin<&Self>,
1021 _: &MouseEvent,
1022 _window_adapter: &Rc<dyn WindowAdapter>,
1023 _self_rc: &ItemRc,
1024 _: &mut MouseCursorInner,
1025 ) -> InputEventResult {
1026 InputEventResult::EventIgnored
1027 }
1028
1029 fn capture_key_event(
1030 self: Pin<&Self>,
1031 _: &InternalKeyEvent,
1032 _window_adapter: &Rc<dyn WindowAdapter>,
1033 _self_rc: &ItemRc,
1034 ) -> KeyEventResult {
1035 KeyEventResult::EventIgnored
1036 }
1037
1038 fn key_event(
1039 self: Pin<&Self>,
1040 _: &InternalKeyEvent,
1041 _window_adapter: &Rc<dyn WindowAdapter>,
1042 _self_rc: &ItemRc,
1043 ) -> KeyEventResult {
1044 KeyEventResult::EventIgnored
1045 }
1046
1047 fn focus_event(
1048 self: Pin<&Self>,
1049 _: &FocusEvent,
1050 _window_adapter: &Rc<dyn WindowAdapter>,
1051 _self_rc: &ItemRc,
1052 ) -> FocusEventResult {
1053 FocusEventResult::FocusIgnored
1054 }
1055
1056 fn render(
1057 self: Pin<&Self>,
1058 backend: &mut ItemRendererRef,
1059 self_rc: &ItemRc,
1060 size: LogicalSize,
1061 ) -> RenderingResult {
1062 backend.visit_layer(self, self_rc, size)
1063 }
1064
1065 fn bounding_rect(
1066 self: core::pin::Pin<&Self>,
1067 _window_adapter: &Rc<dyn WindowAdapter>,
1068 _self_rc: &ItemRc,
1069 geometry: LogicalRect,
1070 ) -> LogicalRect {
1071 geometry
1072 }
1073
1074 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1075 false
1076 }
1077}
1078
1079impl ItemConsts for Layer {
1080 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1081 Layer,
1082 CachedRenderingData,
1083 > = Layer::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1084}
1085
1086declare_item_vtable! {
1087 fn slint_get_LayerVTable() -> LayerVTable for Layer
1088}
1089
1090#[repr(C)]
1091#[derive(FieldOffsets, Default, SlintElement)]
1092#[pin]
1093pub struct Transform {
1096 pub transform_rotation: Property<f32>,
1097 pub transform_scale_x: Property<f32>,
1098 pub transform_scale_y: Property<f32>,
1099 pub transform_origin: Property<LogicalPosition>,
1100 pub cached_rendering_data: CachedRenderingData,
1101}
1102
1103impl Item for Transform {
1104 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1105
1106 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1107
1108 fn layout_info(
1109 self: Pin<&Self>,
1110 _orientation: Orientation,
1111 _cross_axis_constraint: Coord,
1112 _window_adapter: &Rc<dyn WindowAdapter>,
1113 _self_rc: &ItemRc,
1114 ) -> LayoutInfo {
1115 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1116 }
1117
1118 fn input_event_filter_before_children(
1119 self: Pin<&Self>,
1120 _: &MouseEvent,
1121 _window_adapter: &Rc<dyn WindowAdapter>,
1122 _self_rc: &ItemRc,
1123 _: &mut MouseCursorInner,
1124 ) -> InputEventFilterResult {
1125 InputEventFilterResult::ForwardAndIgnore
1126 }
1127
1128 fn input_event(
1129 self: Pin<&Self>,
1130 _: &MouseEvent,
1131 _window_adapter: &Rc<dyn WindowAdapter>,
1132 _self_rc: &ItemRc,
1133 _: &mut MouseCursorInner,
1134 ) -> InputEventResult {
1135 InputEventResult::EventIgnored
1136 }
1137
1138 fn capture_key_event(
1139 self: Pin<&Self>,
1140 _: &InternalKeyEvent,
1141 _window_adapter: &Rc<dyn WindowAdapter>,
1142 _self_rc: &ItemRc,
1143 ) -> KeyEventResult {
1144 KeyEventResult::EventIgnored
1145 }
1146
1147 fn key_event(
1148 self: Pin<&Self>,
1149 _: &InternalKeyEvent,
1150 _window_adapter: &Rc<dyn WindowAdapter>,
1151 _self_rc: &ItemRc,
1152 ) -> KeyEventResult {
1153 KeyEventResult::EventIgnored
1154 }
1155
1156 fn focus_event(
1157 self: Pin<&Self>,
1158 _: &FocusEvent,
1159 _window_adapter: &Rc<dyn WindowAdapter>,
1160 _self_rc: &ItemRc,
1161 ) -> FocusEventResult {
1162 FocusEventResult::FocusIgnored
1163 }
1164
1165 fn render(
1166 self: Pin<&Self>,
1167 backend: &mut ItemRendererRef,
1168 _self_rc: &ItemRc,
1169 _size: LogicalSize,
1170 ) -> RenderingResult {
1171 let origin = self.transform_origin().to_euclid().to_vector();
1172 (*backend).translate(origin);
1173 (*backend).scale(self.transform_scale_x(), self.transform_scale_y());
1174 (*backend).rotate(self.transform_rotation());
1175 (*backend).translate(-origin);
1176 RenderingResult::ContinueRenderingChildren
1177 }
1178
1179 fn bounding_rect(
1180 self: core::pin::Pin<&Self>,
1181 _window_adapter: &Rc<dyn WindowAdapter>,
1182 _self_rc: &ItemRc,
1183 geometry: LogicalRect,
1184 ) -> LogicalRect {
1185 geometry
1186 }
1187
1188 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1189 false
1190 }
1191}
1192
1193impl ItemConsts for Transform {
1194 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1195 Transform,
1196 CachedRenderingData,
1197 > = Transform::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1198}
1199
1200declare_item_vtable! {
1201 fn slint_get_TransformVTable() -> TransformVTable for Transform
1202}
1203
1204declare_item_vtable! {
1205 fn slint_get_FlickableVTable() -> FlickableVTable for Flickable
1206}
1207
1208declare_item_vtable! {
1209 fn slint_get_DragAreaVTable() -> DragAreaVTable for DragArea
1210}
1211
1212declare_item_vtable! {
1213 fn slint_get_DropAreaVTable() -> DropAreaVTable for DropArea
1214}
1215
1216declare_item_vtable! {
1217 fn slint_get_WindowMoveAreaVTable() -> WindowMoveAreaVTable for WindowMoveArea
1218}
1219
1220#[repr(C)]
1223#[derive(FieldOffsets, SlintElement, Clone, Debug)]
1224#[pin]
1225pub struct PropertyAnimation {
1226 #[rtti_field]
1227 pub delay: i32,
1228 #[rtti_field]
1230 pub duration: i32,
1231 #[rtti_field]
1232 pub iteration_count: f32,
1233 #[rtti_field]
1234 pub direction: AnimationDirection,
1235 #[rtti_field]
1236 pub easing: crate::animations::EasingCurve,
1237 #[rtti_field]
1238 pub enabled: bool,
1239}
1240
1241impl Default for PropertyAnimation {
1242 fn default() -> Self {
1243 Self {
1246 delay: 0,
1247 duration: 0,
1248 iteration_count: 1.,
1249 direction: Default::default(),
1250 easing: Default::default(),
1251 enabled: true,
1252 }
1253 }
1254}
1255
1256#[repr(C)]
1258#[derive(FieldOffsets, Default, SlintElement)]
1259#[pin]
1260pub struct WindowItem {
1261 pub width: Property<LogicalLength>,
1262 pub height: Property<LogicalLength>,
1263 pub safe_area_insets: Property<crate::lengths::LogicalEdges>,
1264 pub virtual_keyboard_position: Property<crate::lengths::LogicalPoint>,
1265 pub virtual_keyboard_size: Property<crate::lengths::LogicalSize>,
1266 pub background: Property<Brush>,
1267 pub title: Property<SharedString>,
1268 pub no_frame: Property<bool>,
1269 pub resize_border_width: Property<LogicalLength>,
1270 pub always_on_top: Property<bool>,
1271 pub full_screen: Property<bool>,
1272 pub minimized: Property<bool>,
1273 pub maximized: Property<bool>,
1274 pub icon: Property<crate::graphics::Image>,
1275 pub default_font_family: Property<SharedString>,
1276 pub default_font_size: Property<LogicalLength>,
1277 pub default_font_weight: Property<i32>,
1278 pub cached_rendering_data: CachedRenderingData,
1279}
1280
1281impl Item for WindowItem {
1282 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {
1283 #[cfg(feature = "std")]
1284 self.full_screen.set(std::env::var("SLINT_FULLSCREEN").is_ok());
1285 }
1286
1287 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1288
1289 fn layout_info(
1290 self: Pin<&Self>,
1291 _orientation: Orientation,
1292 _cross_axis_constraint: Coord,
1293 _window_adapter: &Rc<dyn WindowAdapter>,
1294 _self_rc: &ItemRc,
1295 ) -> LayoutInfo {
1296 LayoutInfo::default()
1297 }
1298
1299 fn input_event_filter_before_children(
1300 self: Pin<&Self>,
1301 _: &MouseEvent,
1302 _window_adapter: &Rc<dyn WindowAdapter>,
1303 _self_rc: &ItemRc,
1304 _: &mut MouseCursorInner,
1305 ) -> InputEventFilterResult {
1306 InputEventFilterResult::ForwardAndIgnore
1307 }
1308
1309 fn input_event(
1310 self: Pin<&Self>,
1311 _: &MouseEvent,
1312 _window_adapter: &Rc<dyn WindowAdapter>,
1313 _self_rc: &ItemRc,
1314 _: &mut MouseCursorInner,
1315 ) -> InputEventResult {
1316 InputEventResult::EventIgnored
1317 }
1318
1319 fn capture_key_event(
1320 self: Pin<&Self>,
1321 _: &InternalKeyEvent,
1322 _window_adapter: &Rc<dyn WindowAdapter>,
1323 _self_rc: &ItemRc,
1324 ) -> KeyEventResult {
1325 KeyEventResult::EventIgnored
1326 }
1327
1328 fn key_event(
1329 self: Pin<&Self>,
1330 _: &InternalKeyEvent,
1331 _window_adapter: &Rc<dyn WindowAdapter>,
1332 _self_rc: &ItemRc,
1333 ) -> KeyEventResult {
1334 KeyEventResult::EventIgnored
1335 }
1336
1337 fn focus_event(
1338 self: Pin<&Self>,
1339 _: &FocusEvent,
1340 _window_adapter: &Rc<dyn WindowAdapter>,
1341 _self_rc: &ItemRc,
1342 ) -> FocusEventResult {
1343 FocusEventResult::FocusIgnored
1344 }
1345
1346 fn render(
1347 self: Pin<&Self>,
1348 backend: &mut ItemRendererRef,
1349 self_rc: &ItemRc,
1350 size: LogicalSize,
1351 ) -> RenderingResult {
1352 if self_rc.parent_item(crate::item_tree::ParentItemTraversalMode::StopAtPopups).is_none() {
1353 backend.draw_window_background(self, self_rc, size, &self.cached_rendering_data);
1354 } else {
1355 backend.draw_rectangle(self, self_rc, size, &self.cached_rendering_data);
1357 }
1358 RenderingResult::ContinueRenderingChildren
1359 }
1360
1361 fn bounding_rect(
1362 self: core::pin::Pin<&Self>,
1363 _window_adapter: &Rc<dyn WindowAdapter>,
1364 _self_rc: &ItemRc,
1365 geometry: LogicalRect,
1366 ) -> LogicalRect {
1367 geometry
1368 }
1369
1370 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1371 false
1372 }
1373}
1374
1375impl RenderRectangle for WindowItem {
1376 fn background(self: Pin<&Self>) -> Brush {
1377 self.background()
1378 }
1379}
1380
1381fn next_window_item(item: &ItemRc) -> Option<ItemRc> {
1382 let root_item_in_local_item_tree = ItemRc::new_root(item.item_tree().clone());
1383
1384 if root_item_in_local_item_tree.downcast::<crate::items::WindowItem>().is_some() {
1385 Some(root_item_in_local_item_tree)
1386 } else {
1387 root_item_in_local_item_tree
1388 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1389 .and_then(|parent| next_window_item(&parent))
1390 }
1391}
1392
1393impl WindowItem {
1394 pub fn font_family(self: Pin<&Self>) -> Option<SharedString> {
1395 let maybe_family = self.default_font_family();
1396 if !maybe_family.is_empty() { Some(maybe_family) } else { None }
1397 }
1398
1399 pub fn font_size(self: Pin<&Self>) -> Option<LogicalLength> {
1400 let font_size = self.default_font_size();
1401 if font_size.get() <= 0 as Coord { None } else { Some(font_size) }
1402 }
1403
1404 pub fn font_weight(self: Pin<&Self>) -> Option<i32> {
1405 let font_weight = self.default_font_weight();
1406 if font_weight == 0 { None } else { Some(font_weight) }
1407 }
1408
1409 pub fn resolved_default_font_size(item_tree: ItemTreeRc) -> LogicalLength {
1410 let first_item = ItemRc::new_root(item_tree);
1411 let window_item = next_window_item(&first_item).unwrap();
1412 Self::resolve_font_property(&window_item, Self::font_size)
1413 .or_else(|| Self::platform_default_font_size(&first_item))
1414 .unwrap_or(crate::textlayout::DEFAULT_FONT_SIZE)
1415 }
1416
1417 fn platform_default_font_size(item: &ItemRc) -> Option<LogicalLength> {
1422 item.window_adapter().and_then(|adapter| {
1423 WindowInner::from_pub(adapter.window()).context().platform_default_font_size()
1424 })
1425 }
1426
1427 fn resolve_font_property<T>(
1428 self_rc: &ItemRc,
1429 property_fn: impl Fn(Pin<&Self>) -> Option<T>,
1430 ) -> Option<T> {
1431 let mut window_item_rc = self_rc.clone();
1432 loop {
1433 let window_item = window_item_rc.downcast::<Self>()?;
1434 if let Some(result) = property_fn(window_item.as_pin_ref()) {
1435 return Some(result);
1436 }
1437
1438 window_item_rc = window_item_rc
1439 .parent_item(crate::item_tree::ParentItemTraversalMode::FindAllParents)
1440 .and_then(|p| next_window_item(&p))?;
1441 }
1442 }
1443
1444 pub fn resolved_font_request(
1448 self_rc: &crate::items::ItemRc,
1449 local_font_family: SharedString,
1450 local_font_weight: i32,
1451 local_font_size: LogicalLength,
1452 local_letter_spacing: LogicalLength,
1453 local_line_height_factor: f32,
1454 local_italic: bool,
1455 ) -> FontRequest {
1456 let Some(window_item_rc) = next_window_item(self_rc) else {
1457 return FontRequest::default();
1458 };
1459
1460 FontRequest {
1461 family: {
1462 if !local_font_family.is_empty() {
1463 Some(local_font_family)
1464 } else {
1465 Self::resolve_font_property(
1466 &window_item_rc,
1467 crate::items::WindowItem::font_family,
1468 )
1469 }
1470 },
1471 weight: {
1472 if local_font_weight == 0 {
1473 Self::resolve_font_property(
1474 &window_item_rc,
1475 crate::items::WindowItem::font_weight,
1476 )
1477 } else {
1478 Some(local_font_weight)
1479 }
1480 },
1481 pixel_size: {
1482 if local_font_size.get() == 0 as Coord {
1483 Self::resolve_font_property(
1484 &window_item_rc,
1485 crate::items::WindowItem::font_size,
1486 )
1487 .or_else(|| Self::platform_default_font_size(self_rc))
1488 } else {
1489 Some(local_font_size)
1490 }
1491 },
1492 letter_spacing: Some(local_letter_spacing),
1493 line_height_factor: (local_line_height_factor.is_finite()
1496 && local_line_height_factor >= 0.0
1497 && local_line_height_factor != 1.0)
1498 .then_some(local_line_height_factor),
1499 italic: local_italic,
1500 }
1501 }
1502
1503 pub fn close(
1504 self: Pin<&Self>,
1505 window_adapter: &Rc<dyn WindowAdapter>,
1506 self_rc: &ItemRc,
1507 ) -> bool {
1508 if !is_root_window_item(window_adapter, self_rc) {
1509 return false;
1510 }
1511 let inner = WindowInner::from_pub(window_adapter.window());
1512 let accepted = inner.request_close();
1513 if accepted && let Err(err) = inner.hide() {
1514 crate::debug_log!("Slint: Failed to hide window after close request: {err}");
1515 }
1516 accepted
1517 }
1518
1519 pub fn hide(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, self_rc: &ItemRc) {
1520 if !is_root_window_item(window_adapter, self_rc) {
1521 return;
1522 }
1523 let _ = WindowInner::from_pub(window_adapter.window()).hide();
1524 }
1525}
1526
1527fn is_root_window_item(window_adapter: &Rc<dyn WindowAdapter>, self_rc: &ItemRc) -> bool {
1530 if !self_rc.is_root() {
1531 return false;
1532 }
1533
1534 WindowInner::from_pub(window_adapter.window())
1535 .try_component()
1536 .is_some_and(|component| VRc::ptr_eq(&component, self_rc.item_tree()))
1537}
1538
1539impl ItemConsts for WindowItem {
1540 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1541 Self::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1542}
1543
1544#[cfg(feature = "ffi")]
1545#[unsafe(no_mangle)]
1546pub unsafe extern "C" fn slint_windowitem_close(
1547 window_item: Pin<&WindowItem>,
1548 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1549 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1550 self_index: u32,
1551) -> bool {
1552 unsafe {
1553 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1554 let item_rc = ItemRc::new(self_component.clone(), self_index);
1555 window_item.close(window_adapter, &item_rc)
1556 }
1557}
1558
1559#[cfg(feature = "ffi")]
1560#[unsafe(no_mangle)]
1561pub unsafe extern "C" fn slint_windowitem_hide(
1562 window_item: Pin<&WindowItem>,
1563 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1564 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1565 self_index: u32,
1566) {
1567 unsafe {
1568 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1569 let item_rc = ItemRc::new(self_component.clone(), self_index);
1570 window_item.hide(window_adapter, &item_rc);
1571 }
1572}
1573
1574declare_item_vtable! {
1575 fn slint_get_WindowItemVTable() -> WindowItemVTable for WindowItem
1576}
1577
1578#[repr(C)]
1580#[derive(FieldOffsets, Default, SlintElement)]
1581#[pin]
1582pub struct ContextMenu {
1583 pub sub_menu: Callback<MenuEntryArg, MenuEntryModel>,
1585 pub activated: Callback<MenuEntryArg>,
1586 pub show: Callback<PointArg>,
1587 pub cached_rendering_data: CachedRenderingData,
1588 pub popup_id: Cell<Option<NonZeroU32>>,
1589 pub enabled: Property<bool>,
1590 #[cfg(target_os = "android")]
1591 long_press_timer: crate::timers::Timer,
1592}
1593
1594impl Item for ContextMenu {
1595 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1596
1597 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1598
1599 fn layout_info(
1600 self: Pin<&Self>,
1601 _orientation: Orientation,
1602 _cross_axis_constraint: Coord,
1603 _window_adapter: &Rc<dyn WindowAdapter>,
1604 _self_rc: &ItemRc,
1605 ) -> LayoutInfo {
1606 LayoutInfo::default()
1607 }
1608
1609 fn input_event_filter_before_children(
1610 self: Pin<&Self>,
1611 _: &MouseEvent,
1612 _window_adapter: &Rc<dyn WindowAdapter>,
1613 _self_rc: &ItemRc,
1614 _: &mut MouseCursorInner,
1615 ) -> InputEventFilterResult {
1616 InputEventFilterResult::ForwardEvent
1617 }
1618
1619 fn input_event(
1620 self: Pin<&Self>,
1621 event: &MouseEvent,
1622 _window_adapter: &Rc<dyn WindowAdapter>,
1623 _self_rc: &ItemRc,
1624 _: &mut MouseCursorInner,
1625 ) -> InputEventResult {
1626 if !self.enabled() {
1627 return InputEventResult::EventIgnored;
1628 }
1629 match event {
1630 MouseEvent::Pressed { position, button: PointerEventButton::Right, .. } => {
1631 self.show.call(&(LogicalPosition::from_euclid(*position),));
1632 InputEventResult::EventAccepted
1633 }
1634 #[cfg(target_os = "android")]
1635 MouseEvent::Pressed { position, button: PointerEventButton::Left, .. } => {
1636 let self_weak = _self_rc.downgrade();
1637 let position = *position;
1638 let ctx = WindowInner::from_pub(_window_adapter.window()).context();
1639 self.long_press_timer.start_on(
1640 ctx,
1641 crate::timers::TimerMode::SingleShot,
1642 ctx.platform().long_press_interval(crate::InternalToken),
1643 move || {
1644 let Some(self_rc) = self_weak.upgrade() else { return };
1645 let Some(self_) = self_rc.downcast::<ContextMenu>() else { return };
1646 self_.show.call(&(LogicalPosition::from_euclid(position),));
1647 },
1648 );
1649 InputEventResult::GrabMouse
1650 }
1651 #[cfg(target_os = "android")]
1652 MouseEvent::Released { .. } | MouseEvent::Exit => {
1653 self.long_press_timer.stop();
1654 InputEventResult::EventIgnored
1655 }
1656 #[cfg(target_os = "android")]
1657 MouseEvent::Moved { .. } => InputEventResult::EventAccepted,
1658 _ => InputEventResult::EventIgnored,
1659 }
1660 }
1661
1662 fn capture_key_event(
1663 self: Pin<&Self>,
1664 _: &InternalKeyEvent,
1665 _window_adapter: &Rc<dyn WindowAdapter>,
1666 _self_rc: &ItemRc,
1667 ) -> KeyEventResult {
1668 KeyEventResult::EventIgnored
1669 }
1670
1671 fn key_event(
1672 self: Pin<&Self>,
1673 event: &InternalKeyEvent,
1674 _window_adapter: &Rc<dyn WindowAdapter>,
1675 _self_rc: &ItemRc,
1676 ) -> KeyEventResult {
1677 if !self.enabled() {
1678 return KeyEventResult::EventIgnored;
1679 }
1680
1681 fn is_menu_key(event: &InternalKeyEvent) -> bool {
1682 #[allow(unused_mut)]
1683 let mut is_menu_key = event.key_event.text.contains(crate::input::key_codes::Menu);
1684 #[cfg(target_os = "windows")]
1685 {
1686 is_menu_key |= event.key_event.text.contains(crate::input::key_codes::F10)
1688 && event.key_event.modifiers.shift;
1689 }
1690 is_menu_key
1691 }
1692
1693 if is_menu_key(event) {
1694 self.show.call(&(Default::default(),));
1695 KeyEventResult::EventAccepted
1696 } else {
1697 KeyEventResult::EventIgnored
1698 }
1699 }
1700
1701 fn focus_event(
1702 self: Pin<&Self>,
1703 _: &FocusEvent,
1704 _window_adapter: &Rc<dyn WindowAdapter>,
1705 _self_rc: &ItemRc,
1706 ) -> FocusEventResult {
1707 FocusEventResult::FocusIgnored
1708 }
1709
1710 fn render(
1711 self: Pin<&Self>,
1712 _backend: &mut ItemRendererRef,
1713 _self_rc: &ItemRc,
1714 _size: LogicalSize,
1715 ) -> RenderingResult {
1716 RenderingResult::ContinueRenderingChildren
1717 }
1718
1719 fn bounding_rect(
1720 self: core::pin::Pin<&Self>,
1721 _window_adapter: &Rc<dyn WindowAdapter>,
1722 _self_rc: &ItemRc,
1723 geometry: LogicalRect,
1724 ) -> LogicalRect {
1725 geometry
1726 }
1727
1728 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1729 false
1730 }
1731}
1732
1733impl ContextMenu {
1734 pub fn close(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) {
1735 if let Some(id) = self.popup_id.take() {
1736 WindowInner::from_pub(window_adapter.window()).close_popup(id);
1737 }
1738 }
1739
1740 pub fn is_open(self: Pin<&Self>, window_adapter: &Rc<dyn WindowAdapter>, _: &ItemRc) -> bool {
1741 self.popup_id.get().is_some_and(|id| {
1742 WindowInner::from_pub(window_adapter.window())
1743 .active_popups()
1744 .iter()
1745 .any(|p| p.popup_id == id)
1746 })
1747 }
1748}
1749
1750impl ItemConsts for ContextMenu {
1751 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1752 Self::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1753}
1754
1755declare_item_vtable! {
1756 fn slint_get_ContextMenuVTable() -> ContextMenuVTable for ContextMenu
1757}
1758
1759#[cfg(feature = "ffi")]
1760#[unsafe(no_mangle)]
1761pub unsafe extern "C" fn slint_contextmenu_close(
1762 s: Pin<&ContextMenu>,
1763 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1764 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1765 self_index: u32,
1766) {
1767 unsafe {
1768 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1769 let self_rc = ItemRc::new(self_component.clone(), self_index);
1770 s.close(window_adapter, &self_rc);
1771 }
1772}
1773
1774#[cfg(feature = "ffi")]
1775#[unsafe(no_mangle)]
1776pub unsafe extern "C" fn slint_contextmenu_is_open(
1777 s: Pin<&ContextMenu>,
1778 window_adapter: *const crate::window::ffi::WindowAdapterRcOpaque,
1779 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1780 self_index: u32,
1781) -> bool {
1782 unsafe {
1783 let window_adapter = &*(window_adapter as *const Rc<dyn WindowAdapter>);
1784 let self_rc = ItemRc::new(self_component.clone(), self_index);
1785 s.is_open(window_adapter, &self_rc)
1786 }
1787}
1788
1789#[repr(C)]
1791#[derive(FieldOffsets, Default, SlintElement)]
1792#[pin]
1793pub struct BoxShadow {
1794 pub border_top_left_radius: Property<LogicalLength>,
1795 pub border_top_right_radius: Property<LogicalLength>,
1796 pub border_bottom_left_radius: Property<LogicalLength>,
1797 pub border_bottom_right_radius: Property<LogicalLength>,
1798 pub offset_x: Property<LogicalLength>,
1800 pub offset_y: Property<LogicalLength>,
1801 pub color: Property<Color>,
1802 pub blur: Property<LogicalLength>,
1803 pub spread: Property<LogicalLength>,
1804 pub inset: Property<bool>,
1805 pub cached_rendering_data: CachedRenderingData,
1806}
1807
1808impl BoxShadow {
1809 pub fn logical_border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
1810 LogicalBorderRadius::from_lengths(
1811 self.border_top_left_radius(),
1812 self.border_top_right_radius(),
1813 self.border_bottom_right_radius(),
1814 self.border_bottom_left_radius(),
1815 )
1816 }
1817}
1818
1819impl Item for BoxShadow {
1820 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1821
1822 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
1823
1824 fn layout_info(
1825 self: Pin<&Self>,
1826 _orientation: Orientation,
1827 _cross_axis_constraint: Coord,
1828 _window_adapter: &Rc<dyn WindowAdapter>,
1829 _self_rc: &ItemRc,
1830 ) -> LayoutInfo {
1831 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1832 }
1833
1834 fn input_event_filter_before_children(
1835 self: Pin<&Self>,
1836 _: &MouseEvent,
1837 _window_adapter: &Rc<dyn WindowAdapter>,
1838 _self_rc: &ItemRc,
1839 _: &mut MouseCursorInner,
1840 ) -> InputEventFilterResult {
1841 InputEventFilterResult::ForwardAndIgnore
1842 }
1843
1844 fn input_event(
1845 self: Pin<&Self>,
1846 _: &MouseEvent,
1847 _window_adapter: &Rc<dyn WindowAdapter>,
1848 _self_rc: &ItemRc,
1849 _: &mut MouseCursorInner,
1850 ) -> InputEventResult {
1851 InputEventResult::EventIgnored
1852 }
1853
1854 fn capture_key_event(
1855 self: Pin<&Self>,
1856 _: &InternalKeyEvent,
1857 _window_adapter: &Rc<dyn WindowAdapter>,
1858 _self_rc: &ItemRc,
1859 ) -> KeyEventResult {
1860 KeyEventResult::EventIgnored
1861 }
1862
1863 fn key_event(
1864 self: Pin<&Self>,
1865 _: &InternalKeyEvent,
1866 _window_adapter: &Rc<dyn WindowAdapter>,
1867 _self_rc: &ItemRc,
1868 ) -> KeyEventResult {
1869 KeyEventResult::EventIgnored
1870 }
1871
1872 fn focus_event(
1873 self: Pin<&Self>,
1874 _: &FocusEvent,
1875 _window_adapter: &Rc<dyn WindowAdapter>,
1876 _self_rc: &ItemRc,
1877 ) -> FocusEventResult {
1878 FocusEventResult::FocusIgnored
1879 }
1880
1881 fn render(
1882 self: Pin<&Self>,
1883 backend: &mut ItemRendererRef,
1884 self_rc: &ItemRc,
1885 size: LogicalSize,
1886 ) -> RenderingResult {
1887 (*backend).draw_box_shadow(self, self_rc, size);
1888 RenderingResult::ContinueRenderingChildren
1889 }
1890
1891 fn bounding_rect(
1892 self: core::pin::Pin<&Self>,
1893 _window_adapter: &Rc<dyn WindowAdapter>,
1894 _self_rc: &ItemRc,
1895 geometry: LogicalRect,
1896 ) -> LogicalRect {
1897 if self.inset() {
1898 geometry
1900 } else {
1901 let pad = self.blur() + LogicalLength::new(self.spread().get().max(0 as crate::Coord));
1902 geometry
1903 .outer_rect(euclid::SideOffsets2D::from_length_all_same(pad))
1904 .translate(LogicalVector::from_lengths(self.offset_x(), self.offset_y()))
1905 }
1906 }
1907
1908 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
1909 false
1910 }
1911}
1912
1913impl ItemConsts for BoxShadow {
1914 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1915 Self::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
1916}
1917
1918declare_item_vtable! {
1919 fn slint_get_BoxShadowVTable() -> BoxShadowVTable for BoxShadow
1920}
1921
1922declare_item_vtable! {
1923 fn slint_get_ComponentContainerVTable() -> ComponentContainerVTable for ComponentContainer
1924}
1925
1926declare_item_vtable! {
1927 fn slint_get_ComplexTextVTable() -> ComplexTextVTable for ComplexText
1928}
1929
1930declare_item_vtable! {
1931 fn slint_get_StyledTextItemVTable() -> StyledTextItemVTable for StyledTextItem
1932}
1933
1934declare_item_vtable! {
1935 fn slint_get_SimpleTextVTable() -> SimpleTextVTable for SimpleText
1936}
1937
1938declare_item_vtable! {
1939 fn slint_get_TextInputVTable() -> TextInputVTable for TextInput
1940}
1941
1942declare_item_vtable! {
1943 fn slint_get_ImageItemVTable() -> ImageItemVTable for ImageItem
1944}
1945
1946declare_item_vtable! {
1947 fn slint_get_ClippedImageVTable() -> ClippedImageVTable for ClippedImage
1948}
1949
1950#[cfg(feature = "path")]
1951declare_item_vtable! {
1952 fn slint_get_PathVTable() -> PathVTable for Path
1953}
1954
1955declare_item_vtable! {
1956 fn slint_get_MenuItemVTable() -> MenuItemVTable for MenuItem
1957}
1958
1959declare_item_vtable! {
1960 fn slint_get_SystemTrayIconVTable() -> SystemTrayIconVTable for SystemTrayIcon
1961}
1962
1963macro_rules! declare_enums {
1964 ($( $(#[$enum_doc:meta])* $vis:vis enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
1965 $(
1966 #[derive(Copy, Clone, Debug, PartialEq, Eq, strum::EnumString, strum::Display, Hash)]
1967 #[repr(u32)]
1968 #[strum(serialize_all = "kebab-case")]
1969 $(#[$enum_doc])*
1970 pub enum $Name {
1971 $( $(#[$value_doc])* $Value),*
1972 }
1973
1974 impl Default for $Name {
1975 fn default() -> Self {
1976 ($(Self::$Value,)*).0
1978 }
1979 }
1980 )*
1981 };
1982}
1983
1984i_slint_common::for_each_enums!(declare_enums);
1985
1986#[repr(C)]
1988#[derive(FieldOffsets, Default, SlintElement)]
1989#[pin]
1990pub struct TooltipArea {
1991 pub has_hover: Property<bool>,
1992 pub mouse_x: Property<LogicalLength>,
1993 pub mouse_y: Property<LogicalLength>,
1994 pub text: Property<crate::styled_text::StyledText>,
1995 pub delay: Property<i64>,
1996 pub offset: Property<LogicalLength>,
1997 pub show: Callback<VoidArg>,
1998 pub hide: Callback<VoidArg>,
1999 pub cached_rendering_data: CachedRenderingData,
2000 popup_visible: Cell<bool>,
2001 timer: crate::timers::Timer,
2002}
2003
2004impl Item for TooltipArea {
2005 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
2006
2007 fn deinit(self: Pin<&Self>, _window_adapter: &Rc<dyn WindowAdapter>) {}
2008
2009 fn layout_info(
2010 self: Pin<&Self>,
2011 _orientation: Orientation,
2012 _cross_axis_constraint: Coord,
2013 _window_adapter: &Rc<dyn WindowAdapter>,
2014 _self_rc: &ItemRc,
2015 ) -> LayoutInfo {
2016 LayoutInfo::default()
2017 }
2018
2019 fn input_event_filter_before_children(
2020 self: Pin<&Self>,
2021 event: &MouseEvent,
2022 _window_adapter: &Rc<dyn WindowAdapter>,
2023 self_rc: &ItemRc,
2024 _: &mut MouseCursorInner,
2025 ) -> InputEventFilterResult {
2026 if matches!(event, MouseEvent::DragMove { .. } | MouseEvent::Drop { .. }) {
2029 self.set_hover_state(false, self_rc);
2030 return InputEventFilterResult::ForwardAndIgnore;
2031 }
2032
2033 if let Some(pos) = event.position() {
2034 Self::FIELD_OFFSETS.mouse_x().apply_pin(self).set(pos.x_length());
2035 Self::FIELD_OFFSETS.mouse_y().apply_pin(self).set(pos.y_length());
2036 }
2037
2038 let next_hover = !matches!(event, MouseEvent::Exit);
2039 self.set_hover_state(next_hover, self_rc);
2040
2041 if next_hover && !self.popup_visible.get() && matches!(event, MouseEvent::Moved { .. }) {
2042 self.schedule_show(self_rc);
2043 }
2044
2045 InputEventFilterResult::ForwardAndObserve
2048 }
2049
2050 fn input_event(
2051 self: Pin<&Self>,
2052 event: &MouseEvent,
2053 _window_adapter: &Rc<dyn WindowAdapter>,
2054 _self_rc: &ItemRc,
2055 _: &mut MouseCursorInner,
2056 ) -> InputEventResult {
2057 if matches!(event, MouseEvent::Exit) {
2058 self.set_hover_state(false, _self_rc);
2059 }
2060 InputEventResult::EventIgnored
2061 }
2062
2063 fn capture_key_event(
2064 self: Pin<&Self>,
2065 _: &InternalKeyEvent,
2066 _window_adapter: &Rc<dyn WindowAdapter>,
2067 _self_rc: &ItemRc,
2068 ) -> KeyEventResult {
2069 KeyEventResult::EventIgnored
2070 }
2071
2072 fn key_event(
2073 self: Pin<&Self>,
2074 _: &InternalKeyEvent,
2075 _window_adapter: &Rc<dyn WindowAdapter>,
2076 _self_rc: &ItemRc,
2077 ) -> KeyEventResult {
2078 KeyEventResult::EventIgnored
2079 }
2080
2081 fn focus_event(
2082 self: Pin<&Self>,
2083 _: &FocusEvent,
2084 _window_adapter: &Rc<dyn WindowAdapter>,
2085 _self_rc: &ItemRc,
2086 ) -> FocusEventResult {
2087 FocusEventResult::FocusIgnored
2088 }
2089
2090 fn render(
2091 self: Pin<&Self>,
2092 _backend: &mut ItemRendererRef,
2093 _self_rc: &ItemRc,
2094 _size: LogicalSize,
2095 ) -> RenderingResult {
2096 RenderingResult::ContinueRenderingChildren
2097 }
2098
2099 fn bounding_rect(
2100 self: core::pin::Pin<&Self>,
2101 _window_adapter: &Rc<dyn WindowAdapter>,
2102 _self_rc: &ItemRc,
2103 geometry: LogicalRect,
2104 ) -> LogicalRect {
2105 geometry
2106 }
2107
2108 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
2109 false
2110 }
2111}
2112
2113impl TooltipArea {
2114 fn schedule_show(self: Pin<&Self>, self_rc: &ItemRc) {
2115 let delay_ms = self.delay().max(0) as u64;
2116 if delay_ms == 0 {
2117 if self.has_hover() {
2118 self.show.call(&());
2119 self.popup_visible.set(true);
2120 }
2121 return;
2122 }
2123
2124 let self_weak = self_rc.downgrade();
2125 let Some(window_adapter) = self_rc.window_adapter() else { return };
2128 let ctx = crate::window::WindowInner::from_pub(window_adapter.window()).context();
2129 self.timer.start_on(
2130 ctx,
2131 crate::timers::TimerMode::SingleShot,
2132 Duration::from_millis(delay_ms),
2133 move || {
2134 let Some(self_rc) = self_weak.upgrade() else { return };
2135 let Some(tooltip_area) = self_rc.downcast::<TooltipArea>() else { return };
2136 let tooltip_area = tooltip_area.as_pin_ref();
2137 if tooltip_area.has_hover() {
2138 tooltip_area.show.call(&());
2139 tooltip_area.popup_visible.set(true);
2140 }
2141 },
2142 );
2143 }
2144
2145 fn hide_now(self: Pin<&Self>) {
2146 self.timer.stop();
2147 if self.popup_visible.replace(false) {
2148 self.hide.call(&());
2149 }
2150 }
2151
2152 fn set_hover_state(self: Pin<&Self>, new_hover: bool, self_rc: &ItemRc) {
2153 let old_hover = self.has_hover();
2154 if old_hover == new_hover {
2155 return;
2156 }
2157
2158 Self::FIELD_OFFSETS.has_hover().apply_pin(self).set(new_hover);
2159 if new_hover {
2160 self.schedule_show(self_rc);
2161 } else {
2162 self.hide_now();
2163 }
2164 }
2165}
2166
2167impl ItemConsts for TooltipArea {
2168 const cached_rendering_data_offset: const_field_offset::FieldOffset<
2169 TooltipArea,
2170 CachedRenderingData,
2171 > = TooltipArea::FIELD_OFFSETS.cached_rendering_data().as_unpinned_projection();
2172}
2173
2174declare_item_vtable! {
2175 fn slint_get_TooltipAreaVTable() -> TooltipAreaVTable for TooltipArea
2176}
2177
2178macro_rules! builtin_struct_field_default {
2183 (Coord, $default:expr) => {
2184 ($default) as Coord
2185 };
2186 ($field_type:ident, $default:expr) => {
2187 $default
2188 };
2189 ($field_type:ident) => {
2190 ::core::default::Default::default()
2191 };
2192}
2193
2194macro_rules! builtin_struct_field_default_doc {
2198 (($($default:tt)*)) => {
2199 builtin_struct_field_default_doc!($($default)*)
2200 };
2201 ($enum:ident :: $value:ident) => {
2202 concat!("[`", stringify!($enum), "::", stringify!($value), "`]")
2203 };
2204 ($default:literal) => {
2205 concat!("`", stringify!($default), "`")
2206 };
2207}
2208
2209macro_rules! declare_builtin_structs {
2210 ($(
2211 $(#[$struct_attr:meta])*
2212 $vis:vis struct $Name:ident {
2213 $( $(#[$field_attr:meta])* $field:ident : $field_type:ident $(= $field_default:tt)?, )*
2214 }
2215 )*) => {
2216 $(
2217 #[derive(Clone, Debug, PartialEq)]
2218 #[repr(C)]
2219 $(#[$struct_attr])*
2220 pub struct $Name {
2221 $(
2222 $(#[$field_attr])*
2223 $(
2224 #[doc = ""]
2225 #[doc = concat!("Defaults to ", builtin_struct_field_default_doc!($field_default), ".")]
2226 )?
2227 pub $field : $field_type,
2228 )*
2229 }
2230
2231 impl ::core::default::Default for $Name {
2233 fn default() -> Self {
2234 Self {
2235 $($field: builtin_struct_field_default!($field_type $(, $field_default)?),)*
2236 }
2237 }
2238 }
2239 )*
2240 };
2241}
2242
2243i_slint_common::for_each_builtin_structs!(declare_builtin_structs);
2244
2245#[test]
2246fn builtin_struct_field_defaults() {
2247 let table_column = TableColumn::default();
2250 assert_eq!(table_column.sort_order, SortOrder::Unsorted);
2251 assert_eq!(table_column.min_width, 0 as Coord);
2252 assert_eq!(table_column.horizontal_stretch, 0.0);
2253 assert_eq!(table_column.title, SharedString::default());
2254 assert!(!KeyEvent::default().repeat);
2255 assert_eq!(PointerEvent::default().touch_finger_id, 0);
2256
2257 let hints = InputMethodHints::default();
2259 assert_eq!(hints.capitalization, CapitalizationMode::Sentences);
2260 assert!(hints.auto_correct);
2261 assert!(hints.auto_complete);
2262}
2263
2264#[cfg(feature = "ffi")]
2265#[unsafe(no_mangle)]
2266pub unsafe extern "C" fn slint_item_absolute_position(
2267 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
2268 self_index: u32,
2269) -> crate::lengths::LogicalPoint {
2270 let self_rc = ItemRc::new(self_component.clone(), self_index);
2271 self_rc.map_to_window(self_rc.geometry().origin)
2274}