1#![allow(dead_code)]
2
3#[cfg(not(feature = "std"))]
4use alloc::string::ToString;
5use alloc::{alloc::Layout, boxed::Box, collections::BTreeMap, sync::Arc, vec::Vec};
6use core::{
7 ffi::c_void,
8 fmt,
9 sync::atomic::{AtomicUsize, Ordering as AtomicOrdering},
10};
11#[cfg(feature = "std")]
12use std::hash::Hash;
13
14use azul_css::{
15 css::{CssPath, CssPropertyValue},
16 props::{
17 basic::{
18 AnimationInterpolationFunction, FontRef, InterpolateResolver, LayoutRect, LayoutSize,
19 },
20 property::{CssProperty, CssPropertyType},
21 },
22 system::SystemStyle,
23 AzString,
24};
25use rust_fontconfig::{FcFontCache, FontSource};
26
27use crate::{
28 dom::{DomId, DomNodeId, EventFilter},
29 geom::{LogicalPosition, LogicalRect, LogicalSize, OptionLogicalPosition, PhysicalSize},
30 gl::OptionGlContextPtr,
31 hit_test::OverflowingScrollNode,
32 id::{NodeDataContainer, NodeDataContainerRef, NodeDataContainerRefMut, NodeId},
33 prop_cache::CssPropertyCache,
34 refany::{OptionRefAny, RefAny},
35 resources::{
36 DpiScaleFactor, FontInstanceKey, IdNamespace, ImageCache, ImageMask, ImageRef,
37 RendererResources,
38 },
39 styled_dom::{
40 NodeHierarchyItemId, NodeHierarchyItemVec, OptionStyledDom, StyledDom, StyledNode,
41 StyledNodeVec,
42 },
43 task::{
44 Duration as AzDuration, GetSystemTimeCallback, Instant as AzInstant, Instant,
45 TerminateTimer, ThreadId, ThreadReceiver, ThreadSendMsg, TimerId,
46 },
47 window::{
48 AzStringPair, KeyboardState, MouseState, OptionChar, RawWindowHandle, UpdateFocusWarning,
49 WindowFlags, WindowSize, WindowTheme,
50 },
51 FastBTreeSet, FastHashMap,
52};
53
54#[repr(C)]
56#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
57pub enum Update {
58 DoNothing,
60 RefreshDom,
63 RefreshDomAllWindows,
65}
66
67impl Update {
68 pub fn max_self(&mut self, other: Self) {
69 if *self == Update::DoNothing && other != Update::DoNothing {
70 *self = other;
71 } else if *self == Update::RefreshDom && other == Update::RefreshDomAllWindows {
72 *self = other;
73 }
74 }
75}
76
77pub type LayoutCallbackType = extern "C" fn(RefAny, LayoutCallbackInfo) -> StyledDom;
94
95extern "C" fn default_layout_callback(_: RefAny, _: LayoutCallbackInfo) -> StyledDom {
96 StyledDom::default()
97}
98
99#[repr(C)]
108pub struct LayoutCallback {
109 pub cb: LayoutCallbackType,
110 pub ctx: OptionRefAny,
113}
114
115impl_callback!(LayoutCallback, LayoutCallbackType);
116
117impl LayoutCallback {
118 pub fn create<I: Into<Self>>(cb: I) -> Self {
119 cb.into()
120 }
121}
122
123impl Default for LayoutCallback {
124 fn default() -> Self {
125 Self {
126 cb: default_layout_callback,
127 ctx: OptionRefAny::None,
128 }
129 }
130}
131
132pub type IFrameCallbackType = extern "C" fn(RefAny, IFrameCallbackInfo) -> IFrameCallbackReturn;
135
136#[repr(C)]
139pub struct IFrameCallback {
140 pub cb: IFrameCallbackType,
141 pub ctx: OptionRefAny,
144}
145impl_callback!(IFrameCallback, IFrameCallbackType);
146
147impl IFrameCallback {
148 pub fn create(cb: IFrameCallbackType) -> Self {
149 Self {
150 cb,
151 ctx: OptionRefAny::None,
152 }
153 }
154}
155
156#[derive(Debug, Clone, Copy, PartialEq, Eq)]
160#[repr(C, u8)]
161pub enum IFrameCallbackReason {
162 InitialRender,
164 DomRecreated,
166 BoundsExpanded,
168 EdgeScrolled(EdgeType),
170 ScrollBeyondContent,
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176#[repr(C)]
177pub enum EdgeType {
178 Top,
179 Bottom,
180 Left,
181 Right,
182}
183
184#[derive(Debug)]
185#[repr(C)]
186pub struct IFrameCallbackInfo {
187 pub reason: IFrameCallbackReason,
188 pub system_fonts: *const FcFontCache,
189 pub image_cache: *const ImageCache,
190 pub window_theme: WindowTheme,
191 pub bounds: HidpiAdjustedBounds,
192 pub scroll_size: LogicalSize,
193 pub scroll_offset: LogicalPosition,
194 pub virtual_scroll_size: LogicalSize,
195 pub virtual_scroll_offset: LogicalPosition,
196 callable_ptr: *const OptionRefAny,
199 _abi_mut: *mut c_void,
201}
202
203impl Clone for IFrameCallbackInfo {
204 fn clone(&self) -> Self {
205 Self {
206 reason: self.reason,
207 system_fonts: self.system_fonts,
208 image_cache: self.image_cache,
209 window_theme: self.window_theme,
210 bounds: self.bounds,
211 scroll_size: self.scroll_size,
212 scroll_offset: self.scroll_offset,
213 virtual_scroll_size: self.virtual_scroll_size,
214 virtual_scroll_offset: self.virtual_scroll_offset,
215 callable_ptr: self.callable_ptr,
216 _abi_mut: self._abi_mut,
217 }
218 }
219}
220
221impl IFrameCallbackInfo {
222 pub fn new<'a>(
223 reason: IFrameCallbackReason,
224 system_fonts: &'a FcFontCache,
225 image_cache: &'a ImageCache,
226 window_theme: WindowTheme,
227 bounds: HidpiAdjustedBounds,
228 scroll_size: LogicalSize,
229 scroll_offset: LogicalPosition,
230 virtual_scroll_size: LogicalSize,
231 virtual_scroll_offset: LogicalPosition,
232 ) -> Self {
233 Self {
234 reason,
235 system_fonts: system_fonts as *const FcFontCache,
236 image_cache: image_cache as *const ImageCache,
237 window_theme,
238 bounds,
239 scroll_size,
240 scroll_offset,
241 virtual_scroll_size,
242 virtual_scroll_offset,
243 callable_ptr: core::ptr::null(),
244 _abi_mut: core::ptr::null_mut(),
245 }
246 }
247
248 pub fn set_callable_ptr(&mut self, callable: &OptionRefAny) {
250 self.callable_ptr = callable as *const OptionRefAny;
251 }
252
253 pub fn get_ctx(&self) -> OptionRefAny {
255 if self.callable_ptr.is_null() {
256 OptionRefAny::None
257 } else {
258 unsafe { (*self.callable_ptr).clone() }
259 }
260 }
261
262 pub fn get_bounds(&self) -> HidpiAdjustedBounds {
263 self.bounds
264 }
265
266 fn internal_get_system_fonts<'a>(&'a self) -> &'a FcFontCache {
267 unsafe { &*self.system_fonts }
268 }
269 fn internal_get_image_cache<'a>(&'a self) -> &'a ImageCache {
270 unsafe { &*self.image_cache }
271 }
272}
273
274#[derive(Debug, Clone, PartialEq)]
286#[repr(C)]
287pub struct IFrameCallbackReturn {
288 pub dom: OptionStyledDom,
296
297 pub scroll_size: LogicalSize,
305
306 pub scroll_offset: LogicalPosition,
315
316 pub virtual_scroll_size: LogicalSize,
324
325 pub virtual_scroll_offset: LogicalPosition,
330}
331
332impl Default for IFrameCallbackReturn {
333 fn default() -> IFrameCallbackReturn {
334 IFrameCallbackReturn {
335 dom: OptionStyledDom::None,
336 scroll_size: LogicalSize::zero(),
337 scroll_offset: LogicalPosition::zero(),
338 virtual_scroll_size: LogicalSize::zero(),
339 virtual_scroll_offset: LogicalPosition::zero(),
340 }
341 }
342}
343
344impl IFrameCallbackReturn {
345 pub fn with_dom(
356 dom: StyledDom,
357 scroll_size: LogicalSize,
358 scroll_offset: LogicalPosition,
359 virtual_scroll_size: LogicalSize,
360 virtual_scroll_offset: LogicalPosition,
361 ) -> Self {
362 Self {
363 dom: OptionStyledDom::Some(dom),
364 scroll_size,
365 scroll_offset,
366 virtual_scroll_size,
367 virtual_scroll_offset,
368 }
369 }
370
371 pub fn keep_current(
383 scroll_size: LogicalSize,
384 scroll_offset: LogicalPosition,
385 virtual_scroll_size: LogicalSize,
386 virtual_scroll_offset: LogicalPosition,
387 ) -> Self {
388 Self {
389 dom: OptionStyledDom::None,
390 scroll_size,
391 scroll_offset,
392 virtual_scroll_size,
393 virtual_scroll_offset,
394 }
395 }
396
397 #[deprecated(
402 since = "1.0.0",
403 note = "Use `with_dom()` for new content or `keep_current()` for no update"
404 )]
405 pub fn new(
406 dom: StyledDom,
407 scroll_size: LogicalSize,
408 scroll_offset: LogicalPosition,
409 virtual_scroll_size: LogicalSize,
410 virtual_scroll_offset: LogicalPosition,
411 ) -> Self {
412 Self::with_dom(
413 dom,
414 scroll_size,
415 scroll_offset,
416 virtual_scroll_size,
417 virtual_scroll_offset,
418 )
419 }
420}
421
422#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
427#[repr(C)]
428pub struct TimerCallbackReturn {
429 pub should_update: Update,
430 pub should_terminate: TerminateTimer,
431}
432
433impl TimerCallbackReturn {
434 pub fn create(should_update: Update, should_terminate: TerminateTimer) -> Self {
436 Self {
437 should_update,
438 should_terminate,
439 }
440 }
441
442 pub fn continue_unchanged() -> Self {
444 Self {
445 should_update: Update::DoNothing,
446 should_terminate: TerminateTimer::Continue,
447 }
448 }
449
450 pub fn continue_and_update() -> Self {
452 Self {
453 should_update: Update::RefreshDom,
454 should_terminate: TerminateTimer::Continue,
455 }
456 }
457
458 pub fn terminate_unchanged() -> Self {
460 Self {
461 should_update: Update::DoNothing,
462 should_terminate: TerminateTimer::Terminate,
463 }
464 }
465
466 pub fn terminate_and_update() -> Self {
468 Self {
469 should_update: Update::RefreshDom,
470 should_terminate: TerminateTimer::Terminate,
471 }
472 }
473}
474
475impl Default for TimerCallbackReturn {
476 fn default() -> Self {
477 Self::continue_unchanged()
478 }
479}
480
481#[derive(Debug)]
484#[repr(C)]
485pub struct LayoutCallbackInfoRefData<'a> {
494 pub image_cache: &'a ImageCache,
496 pub gl_context: &'a OptionGlContextPtr,
498 pub system_fonts: &'a FcFontCache,
500 pub system_style: Arc<SystemStyle>,
503}
504
505#[repr(C)]
506pub struct LayoutCallbackInfo {
507 ref_data: *const LayoutCallbackInfoRefData<'static>,
510 pub window_size: WindowSize,
514 pub theme: WindowTheme,
516 callable_ptr: *const OptionRefAny,
519 _abi_mut: *mut core::ffi::c_void,
521}
522
523impl Clone for LayoutCallbackInfo {
524 fn clone(&self) -> Self {
525 Self {
526 ref_data: self.ref_data,
527 window_size: self.window_size,
528 theme: self.theme,
529 callable_ptr: self.callable_ptr,
530 _abi_mut: self._abi_mut,
531 }
532 }
533}
534
535impl core::fmt::Debug for LayoutCallbackInfo {
536 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
537 f.debug_struct("LayoutCallbackInfo")
538 .field("window_size", &self.window_size)
539 .field("theme", &self.theme)
540 .finish_non_exhaustive()
541 }
542}
543
544impl LayoutCallbackInfo {
545 pub fn new<'a>(
546 ref_data: &'a LayoutCallbackInfoRefData<'a>,
547 window_size: WindowSize,
548 theme: WindowTheme,
549 ) -> Self {
550 Self {
551 ref_data: unsafe { core::mem::transmute(ref_data) },
554 window_size,
555 theme,
556 callable_ptr: core::ptr::null(),
557 _abi_mut: core::ptr::null_mut(),
558 }
559 }
560
561 pub fn set_callable_ptr(&mut self, callable: &OptionRefAny) {
563 self.callable_ptr = callable as *const OptionRefAny;
564 }
565
566 pub fn get_ctx(&self) -> OptionRefAny {
568 if self.callable_ptr.is_null() {
569 OptionRefAny::None
570 } else {
571 unsafe { (*self.callable_ptr).clone() }
572 }
573 }
574
575 pub fn get_system_style(&self) -> Arc<SystemStyle> {
577 unsafe { (*self.ref_data).system_style.clone() }
578 }
579
580 fn internal_get_image_cache<'a>(&'a self) -> &'a ImageCache {
581 unsafe { (*self.ref_data).image_cache }
582 }
583 fn internal_get_system_fonts<'a>(&'a self) -> &'a FcFontCache {
584 unsafe { (*self.ref_data).system_fonts }
585 }
586 fn internal_get_gl_context<'a>(&'a self) -> &'a OptionGlContextPtr {
587 unsafe { (*self.ref_data).gl_context }
588 }
589
590 pub fn get_gl_context(&self) -> OptionGlContextPtr {
591 self.internal_get_gl_context().clone()
592 }
593
594 pub fn get_system_fonts(&self) -> Vec<AzStringPair> {
595 let fc_cache = self.internal_get_system_fonts();
596
597 fc_cache
598 .list()
599 .iter()
600 .filter_map(|(pattern, font_id)| {
601 let source = fc_cache.get_font_by_id(font_id)?;
602 match source {
603 FontSource::Memory(f) => None,
604 FontSource::Disk(d) => Some((pattern.name.as_ref()?.clone(), d.path.clone())),
605 }
606 })
607 .map(|(k, v)| AzStringPair {
608 key: k.into(),
609 value: v.into(),
610 })
611 .collect()
612 }
613
614 pub fn get_image(&self, image_id: &AzString) -> Option<ImageRef> {
615 self.internal_get_image_cache()
616 .get_css_image_id(image_id)
617 .cloned()
618 }
619
620 pub fn window_width_less_than(&self, px: f32) -> bool {
623 self.window_size.dimensions.width < px
624 }
625
626 pub fn window_width_greater_than(&self, px: f32) -> bool {
628 self.window_size.dimensions.width > px
629 }
630
631 pub fn window_width_between(&self, min_px: f32, max_px: f32) -> bool {
633 let width = self.window_size.dimensions.width;
634 width >= min_px && width <= max_px
635 }
636
637 pub fn window_height_less_than(&self, px: f32) -> bool {
639 self.window_size.dimensions.height < px
640 }
641
642 pub fn window_height_greater_than(&self, px: f32) -> bool {
644 self.window_size.dimensions.height > px
645 }
646
647 pub fn window_height_between(&self, min_px: f32, max_px: f32) -> bool {
649 let height = self.window_size.dimensions.height;
650 height >= min_px && height <= max_px
651 }
652
653 pub fn get_window_width(&self) -> f32 {
655 self.window_size.dimensions.width
656 }
657
658 pub fn get_window_height(&self) -> f32 {
660 self.window_size.dimensions.height
661 }
662
663 pub fn get_dpi_factor(&self) -> f32 {
665 self.window_size.dpi as f32
666 }
667}
668
669#[derive(Debug, Copy, Clone)]
674#[repr(C)]
675pub struct HidpiAdjustedBounds {
676 pub logical_size: LogicalSize,
677 pub hidpi_factor: DpiScaleFactor,
678}
679
680impl HidpiAdjustedBounds {
681 #[inline(always)]
682 pub fn from_bounds(bounds: LayoutSize, hidpi_factor: DpiScaleFactor) -> Self {
683 let logical_size = LogicalSize::new(bounds.width as f32, bounds.height as f32);
684 Self {
685 logical_size,
686 hidpi_factor,
687 }
688 }
689
690 pub fn get_physical_size(&self) -> PhysicalSize<u32> {
691 self.get_logical_size()
692 .to_physical(self.get_hidpi_factor().inner.get())
693 }
694
695 pub fn get_logical_size(&self) -> LogicalSize {
696 self.logical_size
697 }
698
699 pub fn get_hidpi_factor(&self) -> DpiScaleFactor {
700 self.hidpi_factor.clone()
701 }
702}
703
704#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
706#[repr(C, u8)]
707pub enum FocusTarget {
708 Id(DomNodeId),
709 Path(FocusTargetPath),
710 Previous,
711 Next,
712 First,
713 Last,
714 NoFocus,
715}
716
717#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
718#[repr(C)]
719pub struct FocusTargetPath {
720 pub dom: DomId,
721 pub css_path: CssPath,
722}
723
724pub type CoreCallbackType = usize;
749
750#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
759#[repr(C)]
760pub struct CoreCallback {
761 pub cb: CoreCallbackType,
762 pub ctx: OptionRefAny,
765}
766
767impl From<CoreCallbackType> for CoreCallback {
770 fn from(cb: CoreCallbackType) -> Self {
771 CoreCallback {
772 cb,
773 ctx: OptionRefAny::None,
774 }
775 }
776}
777
778impl_option!(
779 CoreCallback,
780 OptionCoreCallback,
781 [Debug, Eq, Clone, PartialEq, PartialOrd, Ord, Hash]
782);
783
784#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
786#[repr(C)]
787pub struct CoreCallbackData {
788 pub event: EventFilter,
789 pub callback: CoreCallback,
790 pub refany: RefAny,
791}
792
793impl_option!(
794 CoreCallbackData,
795 OptionCoreCallbackData,
796 copy = false,
797 [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
798);
799
800impl_vec!(CoreCallbackData, CoreCallbackDataVec, CoreCallbackDataVecDestructor, CoreCallbackDataVecDestructorType, CoreCallbackDataVecSlice, OptionCoreCallbackData);
801impl_vec_clone!(
802 CoreCallbackData,
803 CoreCallbackDataVec,
804 CoreCallbackDataVecDestructor
805);
806impl_vec_mut!(CoreCallbackData, CoreCallbackDataVec);
807impl_vec_debug!(CoreCallbackData, CoreCallbackDataVec);
808impl_vec_partialord!(CoreCallbackData, CoreCallbackDataVec);
809impl_vec_ord!(CoreCallbackData, CoreCallbackDataVec);
810impl_vec_partialeq!(CoreCallbackData, CoreCallbackDataVec);
811impl_vec_eq!(CoreCallbackData, CoreCallbackDataVec);
812impl_vec_hash!(CoreCallbackData, CoreCallbackDataVec);
813
814impl CoreCallbackDataVec {
815 #[inline]
816 pub fn as_container<'a>(&'a self) -> NodeDataContainerRef<'a, CoreCallbackData> {
817 NodeDataContainerRef {
818 internal: self.as_ref(),
819 }
820 }
821 #[inline]
822 pub fn as_container_mut<'a>(&'a mut self) -> NodeDataContainerRefMut<'a, CoreCallbackData> {
823 NodeDataContainerRefMut {
824 internal: self.as_mut(),
825 }
826 }
827}
828
829pub type CoreRenderImageCallbackType = usize;
833
834#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
836#[repr(C)]
837pub struct CoreRenderImageCallback {
838 pub cb: CoreRenderImageCallbackType,
839 pub ctx: OptionRefAny,
842}
843
844impl From<CoreRenderImageCallbackType> for CoreRenderImageCallback {
847 fn from(cb: CoreRenderImageCallbackType) -> Self {
848 CoreRenderImageCallback {
849 cb,
850 ctx: OptionRefAny::None,
851 }
852 }
853}
854
855#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
857#[repr(C)]
858pub struct CoreImageCallback {
859 pub refany: RefAny,
860 pub callback: CoreRenderImageCallback,
861}
862
863impl_option!(
864 CoreImageCallback,
865 OptionCoreImageCallback,
866 copy = false,
867 [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
868);