1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
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_component.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::graphics::{Brush, Color, Point};
24use crate::input::{
25 FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEventResult,
26 KeyEventType, MouseEvent,
27};
28use crate::item_rendering::{CachedRenderingData, RenderBorderRectangle};
29pub use crate::item_tree::ItemRc;
30use crate::layout::LayoutInfo;
31use crate::lengths::{
32 LogicalBorderRadius, LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector,
33 PointLengths, RectLengths,
34};
35#[cfg(feature = "rtti")]
36use crate::rtti::*;
37use crate::window::{WindowAdapter, WindowAdapterRc, WindowInner};
38use crate::{Callback, Coord, Property, SharedString};
39use alloc::rc::Rc;
40use const_field_offset::FieldOffsets;
41use core::cell::Cell;
42use core::pin::Pin;
43use i_slint_core_macros::*;
44use vtable::*;
45
46mod component_container;
47pub use self::component_container::*;
48mod flickable;
49pub use flickable::*;
50mod text;
51pub use text::*;
52mod image;
53pub use self::image::*;
54#[cfg(feature = "std")]
55mod path;
56#[cfg(feature = "std")]
57pub use path::*;
58
59/// Alias for `&mut dyn ItemRenderer`. Required so cbindgen generates the ItemVTable
60/// despite the presence of trait object
61type ItemRendererRef<'a> = &'a mut dyn crate::item_rendering::ItemRenderer;
62
63/// Workarounds for cbindgen
64pub type VoidArg = ();
65pub type KeyEventArg = (KeyEvent,);
66type PointerEventArg = (PointerEvent,);
67type PointerScrollEventArg = (PointerScrollEvent,);
68type PointArg = (Point,);
69
70#[cfg(all(feature = "ffi", windows))]
71#[macro_export]
72macro_rules! declare_item_vtable {
73 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
74 ItemVTable_static! {
75 #[no_mangle]
76 pub static $item_vtable_ty for $item_ty
77 }
78 #[no_mangle]
79 pub extern "C" fn $getter() -> *const ItemVTable {
80 use vtable::HasStaticVTable;
81 <$item_ty>::static_vtable()
82 }
83 };
84}
85#[cfg(not(all(feature = "ffi", windows)))]
86#[macro_export]
87macro_rules! declare_item_vtable {
88 (fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
89 ItemVTable_static! {
90 #[no_mangle]
91 pub static $item_vtable_ty for $item_ty
92 }
93 };
94}
95
96/// Returned by the `render()` function on items to indicate whether the rendering of
97/// children should be handled by the caller, of if the item took care of that (for example
98/// through layer indirection)
99#[repr(C)]
100#[derive(Default)]
101pub enum RenderingResult {
102 #[default]
103 ContinueRenderingChildren,
104 ContinueRenderingWithoutChildren,
105}
106
107/// Items are the nodes in the render tree.
108#[vtable]
109#[repr(C)]
110pub struct ItemVTable {
111 /// This function is called by the run-time after the memory for the item
112 /// has been allocated and initialized. It will be called before any user specified
113 /// bindings are set.
114 pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, my_item: &ItemRc),
115
116 /// offset in bytes from the *const ItemImpl.
117 /// isize::MAX means None
118 #[allow(non_upper_case_globals)]
119 #[field_offset(CachedRenderingData)]
120 pub cached_rendering_data_offset: usize,
121
122 /// We would need max/min/preferred size, and all layout info
123 pub layout_info: extern "C" fn(
124 core::pin::Pin<VRef<ItemVTable>>,
125 orientation: Orientation,
126 window_adapter: &WindowAdapterRc,
127 ) -> LayoutInfo,
128
129 /// Event handler for mouse and touch event. This function is called before being called on children.
130 /// Then, depending on the return value, it is called for the children, and their children, then
131 /// [`Self::input_event`] is called on the children, and finally [`Self::input_event`] is called
132 /// on this item again.
133 pub input_event_filter_before_children: extern "C" fn(
134 core::pin::Pin<VRef<ItemVTable>>,
135 MouseEvent,
136 window_adapter: &WindowAdapterRc,
137 self_rc: &ItemRc,
138 ) -> InputEventFilterResult,
139
140 /// Handle input event for mouse and touch event
141 pub input_event: extern "C" fn(
142 core::pin::Pin<VRef<ItemVTable>>,
143 MouseEvent,
144 window_adapter: &WindowAdapterRc,
145 self_rc: &ItemRc,
146 ) -> InputEventResult,
147
148 pub focus_event: extern "C" fn(
149 core::pin::Pin<VRef<ItemVTable>>,
150 &FocusEvent,
151 window_adapter: &WindowAdapterRc,
152 self_rc: &ItemRc,
153 ) -> FocusEventResult,
154
155 pub key_event: extern "C" fn(
156 core::pin::Pin<VRef<ItemVTable>>,
157 &KeyEvent,
158 window_adapter: &WindowAdapterRc,
159 self_rc: &ItemRc,
160 ) -> KeyEventResult,
161
162 pub render: extern "C" fn(
163 core::pin::Pin<VRef<ItemVTable>>,
164 backend: &mut ItemRendererRef,
165 self_rc: &ItemRc,
166 size: LogicalSize,
167 ) -> RenderingResult,
168}
169
170/// Alias for `vtable::VRef<ItemVTable>` which represent a pointer to a `dyn Item` with
171/// the associated vtable
172pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
173
174#[repr(C)]
175#[derive(FieldOffsets, Default, SlintElement)]
176#[pin]
177/// The implementation of an empty items that does nothing
178pub struct Empty {
179 pub cached_rendering_data: CachedRenderingData,
180}
181
182impl Item for Empty {
183 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
184
185 fn layout_info(
186 self: Pin<&Self>,
187 _orientation: Orientation,
188 _window_adapter: &Rc<dyn WindowAdapter>,
189 ) -> LayoutInfo {
190 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
191 }
192
193 fn input_event_filter_before_children(
194 self: Pin<&Self>,
195 _: MouseEvent,
196 _window_adapter: &Rc<dyn WindowAdapter>,
197 _self_rc: &ItemRc,
198 ) -> InputEventFilterResult {
199 InputEventFilterResult::ForwardAndIgnore
200 }
201
202 fn input_event(
203 self: Pin<&Self>,
204 _: MouseEvent,
205 _window_adapter: &Rc<dyn WindowAdapter>,
206 _self_rc: &ItemRc,
207 ) -> InputEventResult {
208 InputEventResult::EventIgnored
209 }
210
211 fn key_event(
212 self: Pin<&Self>,
213 _: &KeyEvent,
214 _window_adapter: &Rc<dyn WindowAdapter>,
215 _self_rc: &ItemRc,
216 ) -> KeyEventResult {
217 KeyEventResult::EventIgnored
218 }
219
220 fn focus_event(
221 self: Pin<&Self>,
222 _: &FocusEvent,
223 _window_adapter: &Rc<dyn WindowAdapter>,
224 _self_rc: &ItemRc,
225 ) -> FocusEventResult {
226 FocusEventResult::FocusIgnored
227 }
228
229 fn render(
230 self: Pin<&Self>,
231 _backend: &mut ItemRendererRef,
232 _self_rc: &ItemRc,
233 _size: LogicalSize,
234 ) -> RenderingResult {
235 RenderingResult::ContinueRenderingChildren
236 }
237}
238
239impl ItemConsts for Empty {
240 const cached_rendering_data_offset: const_field_offset::FieldOffset<
241 Empty,
242 CachedRenderingData,
243 > = Empty::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
244}
245
246declare_item_vtable! {
247 fn slint_get_EmptyVTable() -> EmptyVTable for Empty
248}
249
250#[repr(C)]
251#[derive(FieldOffsets, Default, SlintElement)]
252#[pin]
253/// The implementation of the `Rectangle` element
254pub struct Rectangle {
255 pub background: Property<Brush>,
256 pub cached_rendering_data: CachedRenderingData,
257}
258
259impl Item for Rectangle {
260 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
261
262 fn layout_info(
263 self: Pin<&Self>,
264 _orientation: Orientation,
265 _window_adapter: &Rc<dyn WindowAdapter>,
266 ) -> LayoutInfo {
267 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
268 }
269
270 fn input_event_filter_before_children(
271 self: Pin<&Self>,
272 _: MouseEvent,
273 _window_adapter: &Rc<dyn WindowAdapter>,
274 _self_rc: &ItemRc,
275 ) -> InputEventFilterResult {
276 InputEventFilterResult::ForwardAndIgnore
277 }
278
279 fn input_event(
280 self: Pin<&Self>,
281 _: MouseEvent,
282 _window_adapter: &Rc<dyn WindowAdapter>,
283 _self_rc: &ItemRc,
284 ) -> InputEventResult {
285 InputEventResult::EventIgnored
286 }
287
288 fn key_event(
289 self: Pin<&Self>,
290 _: &KeyEvent,
291 _window_adapter: &Rc<dyn WindowAdapter>,
292 _self_rc: &ItemRc,
293 ) -> KeyEventResult {
294 KeyEventResult::EventIgnored
295 }
296
297 fn focus_event(
298 self: Pin<&Self>,
299 _: &FocusEvent,
300 _window_adapter: &Rc<dyn WindowAdapter>,
301 _self_rc: &ItemRc,
302 ) -> FocusEventResult {
303 FocusEventResult::FocusIgnored
304 }
305
306 fn render(
307 self: Pin<&Self>,
308 backend: &mut ItemRendererRef,
309 self_rc: &ItemRc,
310 size: LogicalSize,
311 ) -> RenderingResult {
312 (*backend).draw_rectangle(self, self_rc, size);
313 RenderingResult::ContinueRenderingChildren
314 }
315}
316
317impl ItemConsts for Rectangle {
318 const cached_rendering_data_offset: const_field_offset::FieldOffset<
319 Rectangle,
320 CachedRenderingData,
321 > = Rectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
322}
323
324declare_item_vtable! {
325 fn slint_get_RectangleVTable() -> RectangleVTable for Rectangle
326}
327
328#[repr(C)]
329#[derive(FieldOffsets, Default, SlintElement)]
330#[pin]
331/// The implementation of the `BasicBorderRectangle` element
332pub struct BasicBorderRectangle {
333 pub background: Property<Brush>,
334 pub border_width: Property<LogicalLength>,
335 pub border_radius: Property<LogicalLength>,
336 pub border_color: Property<Brush>,
337 pub cached_rendering_data: CachedRenderingData,
338}
339
340impl Item for BasicBorderRectangle {
341 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
342
343 fn layout_info(
344 self: Pin<&Self>,
345 _orientation: Orientation,
346 _window_adapter: &Rc<dyn WindowAdapter>,
347 ) -> LayoutInfo {
348 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
349 }
350
351 fn input_event_filter_before_children(
352 self: Pin<&Self>,
353 _: MouseEvent,
354 _window_adapter: &Rc<dyn WindowAdapter>,
355 _self_rc: &ItemRc,
356 ) -> InputEventFilterResult {
357 InputEventFilterResult::ForwardAndIgnore
358 }
359
360 fn input_event(
361 self: Pin<&Self>,
362 _: MouseEvent,
363 _window_adapter: &Rc<dyn WindowAdapter>,
364 _self_rc: &ItemRc,
365 ) -> InputEventResult {
366 InputEventResult::EventIgnored
367 }
368
369 fn key_event(
370 self: Pin<&Self>,
371 _: &KeyEvent,
372 _window_adapter: &Rc<dyn WindowAdapter>,
373 _self_rc: &ItemRc,
374 ) -> KeyEventResult {
375 KeyEventResult::EventIgnored
376 }
377
378 fn focus_event(
379 self: Pin<&Self>,
380 _: &FocusEvent,
381 _window_adapter: &Rc<dyn WindowAdapter>,
382 _self_rc: &ItemRc,
383 ) -> FocusEventResult {
384 FocusEventResult::FocusIgnored
385 }
386
387 fn render(
388 self: Pin<&Self>,
389 backend: &mut ItemRendererRef,
390 self_rc: &ItemRc,
391 size: LogicalSize,
392 ) -> RenderingResult {
393 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
394 RenderingResult::ContinueRenderingChildren
395 }
396}
397
398impl RenderBorderRectangle for BasicBorderRectangle {
399 fn background(self: Pin<&Self>) -> Brush {
400 self.background()
401 }
402 fn border_width(self: Pin<&Self>) -> LogicalLength {
403 self.border_width()
404 }
405 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
406 LogicalBorderRadius::from_length(self.border_radius())
407 }
408 fn border_color(self: Pin<&Self>) -> Brush {
409 self.border_color()
410 }
411}
412
413impl ItemConsts for BasicBorderRectangle {
414 const cached_rendering_data_offset: const_field_offset::FieldOffset<
415 BasicBorderRectangle,
416 CachedRenderingData,
417 > = BasicBorderRectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
418}
419
420declare_item_vtable! {
421 fn slint_get_BasicBorderRectangleVTable() -> BasicBorderRectangleVTable for BasicBorderRectangle
422}
423
424#[repr(C)]
425#[derive(FieldOffsets, Default, SlintElement)]
426#[pin]
427/// The implementation of the `BorderRectangle` element
428pub struct BorderRectangle {
429 pub background: Property<Brush>,
430 pub border_width: Property<LogicalLength>,
431 pub border_radius: Property<LogicalLength>,
432 pub border_top_left_radius: Property<LogicalLength>,
433 pub border_top_right_radius: Property<LogicalLength>,
434 pub border_bottom_left_radius: Property<LogicalLength>,
435 pub border_bottom_right_radius: Property<LogicalLength>,
436 pub border_color: Property<Brush>,
437 pub cached_rendering_data: CachedRenderingData,
438}
439
440impl Item for BorderRectangle {
441 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
442
443 fn layout_info(
444 self: Pin<&Self>,
445 _orientation: Orientation,
446 _window_adapter: &Rc<dyn WindowAdapter>,
447 ) -> LayoutInfo {
448 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
449 }
450
451 fn input_event_filter_before_children(
452 self: Pin<&Self>,
453 _: MouseEvent,
454 _window_adapter: &Rc<dyn WindowAdapter>,
455 _self_rc: &ItemRc,
456 ) -> InputEventFilterResult {
457 InputEventFilterResult::ForwardAndIgnore
458 }
459
460 fn input_event(
461 self: Pin<&Self>,
462 _: MouseEvent,
463 _window_adapter: &Rc<dyn WindowAdapter>,
464 _self_rc: &ItemRc,
465 ) -> InputEventResult {
466 InputEventResult::EventIgnored
467 }
468
469 fn key_event(
470 self: Pin<&Self>,
471 _: &KeyEvent,
472 _window_adapter: &Rc<dyn WindowAdapter>,
473 _self_rc: &ItemRc,
474 ) -> KeyEventResult {
475 KeyEventResult::EventIgnored
476 }
477
478 fn focus_event(
479 self: Pin<&Self>,
480 _: &FocusEvent,
481 _window_adapter: &Rc<dyn WindowAdapter>,
482 _self_rc: &ItemRc,
483 ) -> FocusEventResult {
484 FocusEventResult::FocusIgnored
485 }
486
487 fn render(
488 self: Pin<&Self>,
489 backend: &mut ItemRendererRef,
490 self_rc: &ItemRc,
491 size: LogicalSize,
492 ) -> RenderingResult {
493 (*backend).draw_border_rectangle(self, self_rc, size, &self.cached_rendering_data);
494 RenderingResult::ContinueRenderingChildren
495 }
496}
497
498impl RenderBorderRectangle for BorderRectangle {
499 fn background(self: Pin<&Self>) -> Brush {
500 self.background()
501 }
502 fn border_width(self: Pin<&Self>) -> LogicalLength {
503 self.border_width()
504 }
505 fn border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
506 LogicalBorderRadius::from_lengths(
507 self.border_top_left_radius(),
508 self.border_top_right_radius(),
509 self.border_bottom_right_radius(),
510 self.border_bottom_left_radius(),
511 )
512 }
513 fn border_color(self: Pin<&Self>) -> Brush {
514 self.border_color()
515 }
516}
517
518impl ItemConsts for BorderRectangle {
519 const cached_rendering_data_offset: const_field_offset::FieldOffset<
520 BorderRectangle,
521 CachedRenderingData,
522 > = BorderRectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
523}
524
525declare_item_vtable! {
526 fn slint_get_BorderRectangleVTable() -> BorderRectangleVTable for BorderRectangle
527}
528
529/// The implementation of the `TouchArea` element
530#[repr(C)]
531#[derive(FieldOffsets, SlintElement, Default)]
532#[pin]
533pub struct TouchArea {
534 pub enabled: Property<bool>,
535 /// FIXME: We should annotate this as an "output" property.
536 pub pressed: Property<bool>,
537 pub has_hover: Property<bool>,
538 /// FIXME: there should be just one property for the point instead of two.
539 /// Could even be merged with pressed in a `Property<Option<Point>>` (of course, in the
540 /// implementation item only, for the compiler it would stay separate properties)
541 pub pressed_x: Property<LogicalLength>,
542 pub pressed_y: Property<LogicalLength>,
543 /// FIXME: should maybe be as parameter to the mouse event instead. Or at least just one property
544 pub mouse_x: Property<LogicalLength>,
545 pub mouse_y: Property<LogicalLength>,
546 pub mouse_cursor: Property<MouseCursor>,
547 pub clicked: Callback<VoidArg>,
548 pub double_clicked: Callback<VoidArg>,
549 pub moved: Callback<VoidArg>,
550 pub pointer_event: Callback<PointerEventArg>,
551 pub scroll_event: Callback<PointerScrollEventArg, EventResult>,
552 /// FIXME: remove this
553 pub cached_rendering_data: CachedRenderingData,
554 /// true when we are currently grabbing the mouse
555 grabbed: Cell<bool>,
556}
557
558impl Item for TouchArea {
559 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
560
561 fn layout_info(
562 self: Pin<&Self>,
563 _orientation: Orientation,
564 _window_adapter: &Rc<dyn WindowAdapter>,
565 ) -> LayoutInfo {
566 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
567 }
568
569 fn input_event_filter_before_children(
570 self: Pin<&Self>,
571 event: MouseEvent,
572 window_adapter: &Rc<dyn WindowAdapter>,
573 _self_rc: &ItemRc,
574 ) -> InputEventFilterResult {
575 if !self.enabled() {
576 return InputEventFilterResult::ForwardAndIgnore;
577 }
578 if let Some(pos) = event.position() {
579 Self::FIELD_OFFSETS.mouse_x.apply_pin(self).set(pos.x_length());
580 Self::FIELD_OFFSETS.mouse_y.apply_pin(self).set(pos.y_length());
581 }
582 let hovering = !matches!(event, MouseEvent::Exit);
583 Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(hovering);
584 if hovering {
585 if let Some(x) = window_adapter.internal(crate::InternalToken) {
586 x.set_mouse_cursor(self.mouse_cursor());
587 }
588 }
589 InputEventFilterResult::ForwardAndInterceptGrab
590 }
591
592 fn input_event(
593 self: Pin<&Self>,
594 event: MouseEvent,
595 window_adapter: &Rc<dyn WindowAdapter>,
596 self_rc: &ItemRc,
597 ) -> InputEventResult {
598 if matches!(event, MouseEvent::Exit) {
599 Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
600 if let Some(x) = window_adapter.internal(crate::InternalToken) {
601 x.set_mouse_cursor(MouseCursor::Default);
602 }
603 }
604 if !self.enabled() {
605 return InputEventResult::EventIgnored;
606 }
607
608 match event {
609 MouseEvent::Pressed { position, button, .. } => {
610 self.grabbed.set(true);
611 if button == PointerEventButton::Left {
612 Self::FIELD_OFFSETS.pressed_x.apply_pin(self).set(position.x_length());
613 Self::FIELD_OFFSETS.pressed_y.apply_pin(self).set(position.y_length());
614 Self::FIELD_OFFSETS.pressed.apply_pin(self).set(true);
615 }
616 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
617 button,
618 kind: PointerEventKind::Down,
619 modifiers: window_adapter.window().0.modifiers.get().into(),
620 },));
621
622 InputEventResult::GrabMouse
623 }
624 MouseEvent::Exit => {
625 Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false);
626 if self.grabbed.replace(false) {
627 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
628 button: PointerEventButton::Other,
629 kind: PointerEventKind::Cancel,
630 modifiers: window_adapter.window().0.modifiers.get().into(),
631 },));
632 }
633
634 InputEventResult::EventAccepted
635 }
636
637 MouseEvent::Released { button, position, click_count } => {
638 let geometry = self_rc.geometry();
639 if button == PointerEventButton::Left
640 && LogicalRect::new(LogicalPoint::default(), geometry.size).contains(position)
641 && self.pressed()
642 {
643 Self::FIELD_OFFSETS.clicked.apply_pin(self).call(&());
644 if (click_count % 2) == 1 {
645 Self::FIELD_OFFSETS.double_clicked.apply_pin(self).call(&())
646 }
647 }
648
649 self.grabbed.set(false);
650 if button == PointerEventButton::Left {
651 Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false);
652 }
653 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
654 button,
655 kind: PointerEventKind::Up,
656 modifiers: window_adapter.window().0.modifiers.get().into(),
657 },));
658
659 InputEventResult::EventAccepted
660 }
661 MouseEvent::Moved { .. } => {
662 Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
663 button: PointerEventButton::Other,
664 kind: PointerEventKind::Move,
665 modifiers: window_adapter.window().0.modifiers.get().into(),
666 },));
667 return if self.grabbed.get() {
668 Self::FIELD_OFFSETS.moved.apply_pin(self).call(&());
669 InputEventResult::GrabMouse
670 } else {
671 InputEventResult::EventAccepted
672 };
673 }
674 MouseEvent::Wheel { delta_x, delta_y, .. } => {
675 let modifiers = window_adapter.window().0.modifiers.get().into();
676 let r = Self::FIELD_OFFSETS
677 .scroll_event
678 .apply_pin(self)
679 .call(&(PointerScrollEvent { delta_x, delta_y, modifiers },));
680 if self.grabbed.get() {
681 InputEventResult::GrabMouse
682 } else {
683 match r {
684 EventResult::Reject => {
685 // We are ignoring the event, so we will be removed from the item_stack,
686 // therefore we must remove the has_hover flag as there might be a scroll under us.
687 // It will be put back later.
688 Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
689 InputEventResult::EventIgnored
690 }
691 EventResult::Accept => InputEventResult::EventAccepted,
692 }
693 }
694 }
695 }
696 }
697
698 fn key_event(
699 self: Pin<&Self>,
700 _: &KeyEvent,
701 _window_adapter: &Rc<dyn WindowAdapter>,
702 _self_rc: &ItemRc,
703 ) -> KeyEventResult {
704 KeyEventResult::EventIgnored
705 }
706
707 fn focus_event(
708 self: Pin<&Self>,
709 _: &FocusEvent,
710 _window_adapter: &Rc<dyn WindowAdapter>,
711 _self_rc: &ItemRc,
712 ) -> FocusEventResult {
713 FocusEventResult::FocusIgnored
714 }
715
716 fn render(
717 self: Pin<&Self>,
718 _backend: &mut ItemRendererRef,
719 _self_rc: &ItemRc,
720 _size: LogicalSize,
721 ) -> RenderingResult {
722 RenderingResult::ContinueRenderingChildren
723 }
724}
725
726impl ItemConsts for TouchArea {
727 const cached_rendering_data_offset: const_field_offset::FieldOffset<
728 TouchArea,
729 CachedRenderingData,
730 > = TouchArea::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
731}
732
733declare_item_vtable! {
734 fn slint_get_TouchAreaVTable() -> TouchAreaVTable for TouchArea
735}
736
737/// A runtime item that exposes key
738#[repr(C)]
739#[derive(FieldOffsets, Default, SlintElement)]
740#[pin]
741pub struct FocusScope {
742 pub enabled: Property<bool>,
743 pub has_focus: Property<bool>,
744 pub key_pressed: Callback<KeyEventArg, EventResult>,
745 pub key_released: Callback<KeyEventArg, EventResult>,
746 pub focus_changed_event: Callback<VoidArg>,
747 /// FIXME: remove this
748 pub cached_rendering_data: CachedRenderingData,
749}
750
751impl Item for FocusScope {
752 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
753
754 fn layout_info(
755 self: Pin<&Self>,
756 _orientation: Orientation,
757 _window_adapter: &Rc<dyn WindowAdapter>,
758 ) -> LayoutInfo {
759 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
760 }
761
762 fn input_event_filter_before_children(
763 self: Pin<&Self>,
764 _: MouseEvent,
765 _window_adapter: &Rc<dyn WindowAdapter>,
766 _self_rc: &ItemRc,
767 ) -> InputEventFilterResult {
768 InputEventFilterResult::ForwardEvent
769 }
770
771 fn input_event(
772 self: Pin<&Self>,
773 event: MouseEvent,
774 window_adapter: &Rc<dyn WindowAdapter>,
775 self_rc: &ItemRc,
776 ) -> InputEventResult {
777 if self.enabled() && matches!(event, MouseEvent::Pressed { .. }) && !self.has_focus() {
778 WindowInner::from_pub(window_adapter.window()).set_focus_item(self_rc);
779 InputEventResult::EventAccepted
780 } else {
781 InputEventResult::EventIgnored
782 }
783 }
784
785 fn key_event(
786 self: Pin<&Self>,
787 event: &KeyEvent,
788 _window_adapter: &Rc<dyn WindowAdapter>,
789 _self_rc: &ItemRc,
790 ) -> KeyEventResult {
791 let r = match event.event_type {
792 KeyEventType::KeyPressed => {
793 Self::FIELD_OFFSETS.key_pressed.apply_pin(self).call(&(event.clone(),))
794 }
795 KeyEventType::KeyReleased => {
796 Self::FIELD_OFFSETS.key_released.apply_pin(self).call(&(event.clone(),))
797 }
798 KeyEventType::UpdateComposition | KeyEventType::CommitComposition => {
799 EventResult::Reject
800 }
801 };
802 match r {
803 EventResult::Accept => KeyEventResult::EventAccepted,
804 EventResult::Reject => KeyEventResult::EventIgnored,
805 }
806 }
807
808 fn focus_event(
809 self: Pin<&Self>,
810 event: &FocusEvent,
811 _window_adapter: &Rc<dyn WindowAdapter>,
812 _self_rc: &ItemRc,
813 ) -> FocusEventResult {
814 if !self.enabled() {
815 return FocusEventResult::FocusIgnored;
816 }
817
818 match event {
819 FocusEvent::FocusIn | FocusEvent::WindowReceivedFocus => {
820 self.has_focus.set(true);
821 Self::FIELD_OFFSETS.focus_changed_event.apply_pin(self).call(&());
822 }
823 FocusEvent::FocusOut | FocusEvent::WindowLostFocus => {
824 self.has_focus.set(false);
825 Self::FIELD_OFFSETS.focus_changed_event.apply_pin(self).call(&());
826 }
827 }
828 FocusEventResult::FocusAccepted
829 }
830
831 fn render(
832 self: Pin<&Self>,
833 _backend: &mut ItemRendererRef,
834 _self_rc: &ItemRc,
835 _size: LogicalSize,
836 ) -> RenderingResult {
837 RenderingResult::ContinueRenderingChildren
838 }
839}
840
841impl ItemConsts for FocusScope {
842 const cached_rendering_data_offset: const_field_offset::FieldOffset<
843 FocusScope,
844 CachedRenderingData,
845 > = FocusScope::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
846}
847
848declare_item_vtable! {
849 fn slint_get_FocusScopeVTable() -> FocusScopeVTable for FocusScope
850}
851
852#[repr(C)]
853#[derive(FieldOffsets, Default, SlintElement)]
854#[pin]
855/// The implementation of the `Clip` element
856pub struct Clip {
857 pub border_top_left_radius: Property<LogicalLength>,
858 pub border_top_right_radius: Property<LogicalLength>,
859 pub border_bottom_left_radius: Property<LogicalLength>,
860 pub border_bottom_right_radius: Property<LogicalLength>,
861 pub border_width: Property<LogicalLength>,
862 pub cached_rendering_data: CachedRenderingData,
863 pub clip: Property<bool>,
864}
865
866impl Item for Clip {
867 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
868
869 fn layout_info(
870 self: Pin<&Self>,
871 _orientation: Orientation,
872 _window_adapter: &Rc<dyn WindowAdapter>,
873 ) -> LayoutInfo {
874 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
875 }
876
877 fn input_event_filter_before_children(
878 self: Pin<&Self>,
879 event: MouseEvent,
880 _window_adapter: &Rc<dyn WindowAdapter>,
881 self_rc: &ItemRc,
882 ) -> InputEventFilterResult {
883 if let Some(pos) = event.position() {
884 let geometry = self_rc.geometry();
885 if self.clip()
886 && (pos.x < 0 as Coord
887 || pos.y < 0 as Coord
888 || pos.x_length() > geometry.width_length()
889 || pos.y_length() > geometry.height_length())
890 {
891 return InputEventFilterResult::Intercept;
892 }
893 }
894 InputEventFilterResult::ForwardAndIgnore
895 }
896
897 fn input_event(
898 self: Pin<&Self>,
899 _: MouseEvent,
900 _window_adapter: &Rc<dyn WindowAdapter>,
901 _self_rc: &ItemRc,
902 ) -> InputEventResult {
903 InputEventResult::EventIgnored
904 }
905
906 fn key_event(
907 self: Pin<&Self>,
908 _: &KeyEvent,
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_clip(self, self_rc, size)
931 }
932}
933
934impl Clip {
935 pub fn logical_border_radius(self: Pin<&Self>) -> LogicalBorderRadius {
936 LogicalBorderRadius::from_lengths(
937 self.border_top_left_radius(),
938 self.border_top_right_radius(),
939 self.border_bottom_right_radius(),
940 self.border_bottom_left_radius(),
941 )
942 }
943}
944
945impl ItemConsts for Clip {
946 const cached_rendering_data_offset: const_field_offset::FieldOffset<Clip, CachedRenderingData> =
947 Clip::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
948}
949
950declare_item_vtable! {
951 fn slint_get_ClipVTable() -> ClipVTable for Clip
952}
953
954#[repr(C)]
955#[derive(FieldOffsets, Default, SlintElement)]
956#[pin]
957/// The Opacity Item is not meant to be used directly by the .slint code, instead, the `opacity: xxx` or `visible: false` should be used
958pub struct Opacity {
959 // FIXME: this element shouldn't need these geometry property
960 pub opacity: Property<f32>,
961 pub cached_rendering_data: CachedRenderingData,
962}
963
964impl Item for Opacity {
965 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
966
967 fn layout_info(
968 self: Pin<&Self>,
969 _orientation: Orientation,
970 _window_adapter: &Rc<dyn WindowAdapter>,
971 ) -> LayoutInfo {
972 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
973 }
974
975 fn input_event_filter_before_children(
976 self: Pin<&Self>,
977 _: MouseEvent,
978 _window_adapter: &Rc<dyn WindowAdapter>,
979 _self_rc: &ItemRc,
980 ) -> InputEventFilterResult {
981 InputEventFilterResult::ForwardAndIgnore
982 }
983
984 fn input_event(
985 self: Pin<&Self>,
986 _: MouseEvent,
987 _window_adapter: &Rc<dyn WindowAdapter>,
988 _self_rc: &ItemRc,
989 ) -> InputEventResult {
990 InputEventResult::EventIgnored
991 }
992
993 fn key_event(
994 self: Pin<&Self>,
995 _: &KeyEvent,
996 _window_adapter: &Rc<dyn WindowAdapter>,
997 _self_rc: &ItemRc,
998 ) -> KeyEventResult {
999 KeyEventResult::EventIgnored
1000 }
1001
1002 fn focus_event(
1003 self: Pin<&Self>,
1004 _: &FocusEvent,
1005 _window_adapter: &Rc<dyn WindowAdapter>,
1006 _self_rc: &ItemRc,
1007 ) -> FocusEventResult {
1008 FocusEventResult::FocusIgnored
1009 }
1010
1011 fn render(
1012 self: Pin<&Self>,
1013 backend: &mut ItemRendererRef,
1014 self_rc: &ItemRc,
1015 size: LogicalSize,
1016 ) -> RenderingResult {
1017 backend.visit_opacity(self, self_rc, size)
1018 }
1019}
1020
1021impl Opacity {
1022 // This function determines the optimization opportunities for not having to render the
1023 // children of the Opacity element into a layer:
1024 // * The opacity item typically only one child (this is not guaranteed). If that item has
1025 // no children, then we can skip the layer and apply the opacity directly. This is not perfect though,
1026 // for example if the compiler inserts another synthetic element between the `Opacity` and the actual child,
1027 // then this check will apply a layer even though it might not actually be necessary.
1028 // * If the vale of the opacity is 1.0 then we don't need to do anything.
1029 pub fn need_layer(self_rc: &ItemRc, opacity: f32) -> bool {
1030 if opacity == 1.0 {
1031 return false;
1032 }
1033
1034 let opacity_child = match self_rc.first_child() {
1035 Some(first_child) => first_child,
1036 None => return false, // No children? Don't need a layer then.
1037 };
1038
1039 if opacity_child.next_sibling().is_some() {
1040 return true; // If the opacity item has more than one child, then we need a layer
1041 }
1042
1043 // If the target of the opacity has any children then we need a layer
1044 opacity_child.first_child().is_some()
1045 }
1046}
1047
1048impl ItemConsts for Opacity {
1049 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1050 Opacity,
1051 CachedRenderingData,
1052 > = Opacity::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1053}
1054
1055declare_item_vtable! {
1056 fn slint_get_OpacityVTable() -> OpacityVTable for Opacity
1057}
1058
1059#[repr(C)]
1060#[derive(FieldOffsets, Default, SlintElement)]
1061#[pin]
1062/// The Layer Item is not meant to be used directly by the .slint code, instead, the `layer: xxx` property should be used
1063pub struct Layer {
1064 pub cache_rendering_hint: Property<bool>,
1065 pub cached_rendering_data: CachedRenderingData,
1066}
1067
1068impl Item for Layer {
1069 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1070
1071 fn layout_info(
1072 self: Pin<&Self>,
1073 _orientation: Orientation,
1074 _window_adapter: &Rc<dyn WindowAdapter>,
1075 ) -> LayoutInfo {
1076 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1077 }
1078
1079 fn input_event_filter_before_children(
1080 self: Pin<&Self>,
1081 _: MouseEvent,
1082 _window_adapter: &Rc<dyn WindowAdapter>,
1083 _self_rc: &ItemRc,
1084 ) -> InputEventFilterResult {
1085 InputEventFilterResult::ForwardAndIgnore
1086 }
1087
1088 fn input_event(
1089 self: Pin<&Self>,
1090 _: MouseEvent,
1091 _window_adapter: &Rc<dyn WindowAdapter>,
1092 _self_rc: &ItemRc,
1093 ) -> InputEventResult {
1094 InputEventResult::EventIgnored
1095 }
1096
1097 fn key_event(
1098 self: Pin<&Self>,
1099 _: &KeyEvent,
1100 _window_adapter: &Rc<dyn WindowAdapter>,
1101 _self_rc: &ItemRc,
1102 ) -> KeyEventResult {
1103 KeyEventResult::EventIgnored
1104 }
1105
1106 fn focus_event(
1107 self: Pin<&Self>,
1108 _: &FocusEvent,
1109 _window_adapter: &Rc<dyn WindowAdapter>,
1110 _self_rc: &ItemRc,
1111 ) -> FocusEventResult {
1112 FocusEventResult::FocusIgnored
1113 }
1114
1115 fn render(
1116 self: Pin<&Self>,
1117 backend: &mut ItemRendererRef,
1118 self_rc: &ItemRc,
1119 size: LogicalSize,
1120 ) -> RenderingResult {
1121 backend.visit_layer(self, self_rc, size)
1122 }
1123}
1124
1125impl ItemConsts for Layer {
1126 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1127 Layer,
1128 CachedRenderingData,
1129 > = Layer::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1130}
1131
1132declare_item_vtable! {
1133 fn slint_get_LayerVTable() -> LayerVTable for Layer
1134}
1135
1136#[repr(C)]
1137#[derive(FieldOffsets, Default, SlintElement)]
1138#[pin]
1139/// The implementation of the `Rotate` element
1140pub struct Rotate {
1141 pub rotation_angle: Property<f32>,
1142 pub rotation_origin_x: Property<LogicalLength>,
1143 pub rotation_origin_y: Property<LogicalLength>,
1144 pub cached_rendering_data: CachedRenderingData,
1145}
1146
1147impl Item for Rotate {
1148 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1149
1150 fn layout_info(
1151 self: Pin<&Self>,
1152 _orientation: Orientation,
1153 _window_adapter: &Rc<dyn WindowAdapter>,
1154 ) -> LayoutInfo {
1155 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1156 }
1157
1158 fn input_event_filter_before_children(
1159 self: Pin<&Self>,
1160 _: MouseEvent,
1161 _window_adapter: &Rc<dyn WindowAdapter>,
1162 _self_rc: &ItemRc,
1163 ) -> InputEventFilterResult {
1164 InputEventFilterResult::ForwardAndIgnore
1165 }
1166
1167 fn input_event(
1168 self: Pin<&Self>,
1169 _: MouseEvent,
1170 _window_adapter: &Rc<dyn WindowAdapter>,
1171 _self_rc: &ItemRc,
1172 ) -> InputEventResult {
1173 InputEventResult::EventIgnored
1174 }
1175
1176 fn key_event(
1177 self: Pin<&Self>,
1178 _: &KeyEvent,
1179 _window_adapter: &Rc<dyn WindowAdapter>,
1180 _self_rc: &ItemRc,
1181 ) -> KeyEventResult {
1182 KeyEventResult::EventIgnored
1183 }
1184
1185 fn focus_event(
1186 self: Pin<&Self>,
1187 _: &FocusEvent,
1188 _window_adapter: &Rc<dyn WindowAdapter>,
1189 _self_rc: &ItemRc,
1190 ) -> FocusEventResult {
1191 FocusEventResult::FocusIgnored
1192 }
1193
1194 fn render(
1195 self: Pin<&Self>,
1196 backend: &mut ItemRendererRef,
1197 _self_rc: &ItemRc,
1198 _size: LogicalSize,
1199 ) -> RenderingResult {
1200 let origin =
1201 LogicalVector::from_lengths(self.rotation_origin_x(), self.rotation_origin_y());
1202 (*backend).translate(origin);
1203 (*backend).rotate(self.rotation_angle());
1204 (*backend).translate(-origin);
1205 RenderingResult::ContinueRenderingChildren
1206 }
1207}
1208
1209impl ItemConsts for Rotate {
1210 const cached_rendering_data_offset: const_field_offset::FieldOffset<
1211 Rotate,
1212 CachedRenderingData,
1213 > = Rotate::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1214}
1215
1216declare_item_vtable! {
1217 fn slint_get_RotateVTable() -> RotateVTable for Rotate
1218}
1219
1220declare_item_vtable! {
1221 fn slint_get_FlickableVTable() -> FlickableVTable for Flickable
1222}
1223
1224/// The implementation of the `PropertyAnimation` element
1225#[repr(C)]
1226#[derive(FieldOffsets, SlintElement, Clone, Debug)]
1227#[pin]
1228pub struct PropertyAnimation {
1229 #[rtti_field]
1230 pub delay: i32,
1231 #[rtti_field]
1232 pub duration: i32,
1233 #[rtti_field]
1234 pub iteration_count: f32,
1235 #[rtti_field]
1236 pub easing: crate::animations::EasingCurve,
1237}
1238
1239impl Default for PropertyAnimation {
1240 fn default() -> Self {
1241 // Defaults for PropertyAnimation are defined here (for internal Rust code doing programmatic animations)
1242 // as well as in `builtins.slint` (for generated C++ and Rust code)
1243 Self { delay: 0, duration: 0, iteration_count: 1., easing: Default::default() }
1244 }
1245}
1246
1247/// The implementation of the `Window` element
1248#[repr(C)]
1249#[derive(FieldOffsets, Default, SlintElement)]
1250#[pin]
1251pub struct WindowItem {
1252 pub width: Property<LogicalLength>,
1253 pub height: Property<LogicalLength>,
1254 pub background: Property<Brush>,
1255 pub title: Property<SharedString>,
1256 pub no_frame: Property<bool>,
1257 pub always_on_top: Property<bool>,
1258 pub icon: Property<crate::graphics::Image>,
1259 pub default_font_family: Property<SharedString>,
1260 pub default_font_size: Property<LogicalLength>,
1261 pub default_font_weight: Property<i32>,
1262 pub cached_rendering_data: CachedRenderingData,
1263}
1264
1265impl Item for WindowItem {
1266 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1267
1268 fn layout_info(
1269 self: Pin<&Self>,
1270 _orientation: Orientation,
1271 _window_adapter: &Rc<dyn WindowAdapter>,
1272 ) -> LayoutInfo {
1273 LayoutInfo::default()
1274 }
1275
1276 fn input_event_filter_before_children(
1277 self: Pin<&Self>,
1278 _: MouseEvent,
1279 _window_adapter: &Rc<dyn WindowAdapter>,
1280 _self_rc: &ItemRc,
1281 ) -> InputEventFilterResult {
1282 InputEventFilterResult::ForwardAndIgnore
1283 }
1284
1285 fn input_event(
1286 self: Pin<&Self>,
1287 _event: MouseEvent,
1288 _window_adapter: &Rc<dyn WindowAdapter>,
1289 _self_rc: &ItemRc,
1290 ) -> InputEventResult {
1291 InputEventResult::EventIgnored
1292 }
1293
1294 fn key_event(
1295 self: Pin<&Self>,
1296 _: &KeyEvent,
1297 _window_adapter: &Rc<dyn WindowAdapter>,
1298 _self_rc: &ItemRc,
1299 ) -> KeyEventResult {
1300 KeyEventResult::EventIgnored
1301 }
1302
1303 fn focus_event(
1304 self: Pin<&Self>,
1305 _: &FocusEvent,
1306 _window_adapter: &Rc<dyn WindowAdapter>,
1307 _self_rc: &ItemRc,
1308 ) -> FocusEventResult {
1309 FocusEventResult::FocusIgnored
1310 }
1311
1312 fn render(
1313 self: Pin<&Self>,
1314 _backend: &mut ItemRendererRef,
1315 _self_rc: &ItemRc,
1316 _size: LogicalSize,
1317 ) -> RenderingResult {
1318 RenderingResult::ContinueRenderingChildren
1319 }
1320}
1321
1322impl WindowItem {
1323 pub fn font_family(self: Pin<&Self>) -> Option<SharedString> {
1324 let maybe_family = self.default_font_family();
1325 if !maybe_family.is_empty() {
1326 Some(maybe_family)
1327 } else {
1328 None
1329 }
1330 }
1331
1332 pub fn font_size(self: Pin<&Self>) -> Option<LogicalLength> {
1333 let font_size = self.default_font_size();
1334 if font_size.get() <= 0 as Coord {
1335 None
1336 } else {
1337 Some(font_size)
1338 }
1339 }
1340
1341 pub fn font_weight(self: Pin<&Self>) -> Option<i32> {
1342 let font_weight = self.default_font_weight();
1343 if font_weight == 0 {
1344 None
1345 } else {
1346 Some(font_weight)
1347 }
1348 }
1349}
1350
1351impl ItemConsts for WindowItem {
1352 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1353 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1354}
1355
1356declare_item_vtable! {
1357 fn slint_get_WindowItemVTable() -> WindowItemVTable for WindowItem
1358}
1359
1360/// The implementation of the `BoxShadow` element
1361#[repr(C)]
1362#[derive(FieldOffsets, Default, SlintElement)]
1363#[pin]
1364pub struct BoxShadow {
1365 pub border_radius: Property<LogicalLength>,
1366 // Shadow specific properties
1367 pub offset_x: Property<LogicalLength>,
1368 pub offset_y: Property<LogicalLength>,
1369 pub color: Property<Color>,
1370 pub blur: Property<LogicalLength>,
1371 pub cached_rendering_data: CachedRenderingData,
1372}
1373
1374impl Item for BoxShadow {
1375 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {}
1376
1377 fn layout_info(
1378 self: Pin<&Self>,
1379 _orientation: Orientation,
1380 _window_adapter: &Rc<dyn WindowAdapter>,
1381 ) -> LayoutInfo {
1382 LayoutInfo { stretch: 1., ..LayoutInfo::default() }
1383 }
1384
1385 fn input_event_filter_before_children(
1386 self: Pin<&Self>,
1387 _: MouseEvent,
1388 _window_adapter: &Rc<dyn WindowAdapter>,
1389 _self_rc: &ItemRc,
1390 ) -> InputEventFilterResult {
1391 InputEventFilterResult::ForwardAndIgnore
1392 }
1393
1394 fn input_event(
1395 self: Pin<&Self>,
1396 _event: MouseEvent,
1397 _window_adapter: &Rc<dyn WindowAdapter>,
1398 _self_rc: &ItemRc,
1399 ) -> InputEventResult {
1400 InputEventResult::EventIgnored
1401 }
1402
1403 fn key_event(
1404 self: Pin<&Self>,
1405 _: &KeyEvent,
1406 _window_adapter: &Rc<dyn WindowAdapter>,
1407 _self_rc: &ItemRc,
1408 ) -> KeyEventResult {
1409 KeyEventResult::EventIgnored
1410 }
1411
1412 fn focus_event(
1413 self: Pin<&Self>,
1414 _: &FocusEvent,
1415 _window_adapter: &Rc<dyn WindowAdapter>,
1416 _self_rc: &ItemRc,
1417 ) -> FocusEventResult {
1418 FocusEventResult::FocusIgnored
1419 }
1420
1421 fn render(
1422 self: Pin<&Self>,
1423 backend: &mut ItemRendererRef,
1424 self_rc: &ItemRc,
1425 size: LogicalSize,
1426 ) -> RenderingResult {
1427 (*backend).draw_box_shadow(self, self_rc, size);
1428 RenderingResult::ContinueRenderingChildren
1429 }
1430}
1431
1432impl ItemConsts for BoxShadow {
1433 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
1434 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
1435}
1436
1437declare_item_vtable! {
1438 fn slint_get_BoxShadowVTable() -> BoxShadowVTable for BoxShadow
1439}
1440
1441declare_item_vtable! {
1442 fn slint_get_ComponentContainerVTable() -> ComponentContainerVTable for ComponentContainer
1443}
1444
1445declare_item_vtable! {
1446 fn slint_get_TextVTable() -> TextVTable for Text
1447}
1448
1449declare_item_vtable! {
1450 fn slint_get_TextInputVTable() -> TextInputVTable for TextInput
1451}
1452
1453declare_item_vtable! {
1454 fn slint_get_ImageItemVTable() -> ImageItemVTable for ImageItem
1455}
1456
1457declare_item_vtable! {
1458 fn slint_get_ClippedImageVTable() -> ClippedImageVTable for ClippedImage
1459}
1460
1461#[cfg(feature = "std")]
1462declare_item_vtable! {
1463 fn slint_get_PathVTable() -> PathVTable for Path
1464}
1465
1466macro_rules! declare_enums {
1467 ($( $(#[$enum_doc:meta])* enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
1468 $(
1469 #[derive(Copy, Clone, Debug, PartialEq, Eq, strum::EnumString, strum::Display, Hash)]
1470 #[repr(u32)]
1471 #[strum(serialize_all = "kebab-case")]
1472 $(#[$enum_doc])*
1473 pub enum $Name {
1474 $( $(#[$value_doc])* $Value),*
1475 }
1476
1477 impl Default for $Name {
1478 fn default() -> Self {
1479 // Always return the first value
1480 ($(Self::$Value,)*).0
1481 }
1482 }
1483 )*
1484 };
1485}
1486
1487i_slint_common::for_each_enums!(declare_enums);
1488
1489macro_rules! declare_builtin_structs {
1490 ($(
1491 $(#[$struct_attr:meta])*
1492 struct $Name:ident {
1493 @name = $inner_name:literal
1494 export {
1495 $( $(#[$pub_attr:meta])* $pub_field:ident : $pub_type:ty, )*
1496 }
1497 private {
1498 $( $(#[$pri_attr:meta])* $pri_field:ident : $pri_type:ty, )*
1499 }
1500 }
1501 )*) => {
1502 $(
1503 #[derive(Clone, Debug, Default, PartialEq)]
1504 #[repr(C)]
1505 $(#[$struct_attr])*
1506 pub struct $Name {
1507 $(
1508 $(#[$pub_attr])*
1509 pub $pub_field : $pub_type,
1510 )*
1511 $(
1512 $(#[$pri_attr])*
1513 pub $pri_field : $pri_type,
1514 )*
1515 }
1516 )*
1517 };
1518}
1519
1520i_slint_common::for_each_builtin_structs!(declare_builtin_structs);
1521
1522#[cfg(feature = "ffi")]
1523#[no_mangle]
1524pub unsafe extern "C" fn slint_item_absolute_position(
1525 self_component: &vtable::VRc<crate::item_tree::ItemTreeVTable>,
1526 self_index: u32,
1527) -> LogicalPoint {
1528 let self_rc: ItemRc = ItemRc::new(item_tree:self_component.clone(), self_index);
1529 self_rc.map_to_window(Default::default())
1530}
1531