mod config;
mod dispatch;
mod layout;
mod metrics;
mod paint;
mod rebuild;
mod semantics;
mod session;
#[cfg(test)]
mod tests;
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::num::NonZeroU64;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicU64, Ordering};
use kurbo::{Rect, Size};
use crate::event::{CursorIcon, EventOutcome, ImeState, PointerId};
use crate::insets::WindowInsets;
use crate::overlay::{OverlayHit, OverlayKey};
use crate::selection_toolbar::SelectionToolbarRequest;
use crate::shortcuts::{ShortcutHint, ShortcutId, ShortcutTable};
use crate::tree::WidgetTree;
use crate::view::{ChangeFlags, View, WidgetId};
use crate::widget::{ChildPod, PlatformViewFrame};
pub use config::FocusRingPolicy;
use layout::LayoutAudit;
pub use metrics::{Orientation, WindowMetrics};
const MAX_PENDING_RESULT_FLUSH_PASSES: usize = 3;
static NEXT_ROOT_IDENTITY: AtomicU64 = AtomicU64::new(1);
fn advance_focus_epoch(epoch: u64) -> u64 {
match epoch.wrapping_add(1) {
0 => 1,
next => next,
}
}
enum OverlayRoute {
Consumed(EventOutcome),
Continue(EventOutcome),
}
pub struct RenderRoot<State: 'static, V: View<State>> {
tree: WidgetTree,
root_id: Option<WidgetId>,
prev_view: Option<V>,
next_id: u64,
window_size: Size,
capture_claimant: Option<PointerId>,
capture_contacts: bool,
contacts_captor_is_root: bool,
focus_active: bool,
focus_surface: Option<OverlayKey>,
focus_epoch: u64,
key_forward: Option<(OverlayKey, u64)>,
focus_grant: ShortcutId,
keyboard_focus: bool,
focus_ring_policy: FocusRingPolicy,
tab_traversal: bool,
hover_active: bool,
hover_epoch: u64,
root_identity: u64,
cursor: CursorIcon,
pending_clipboard_write: Option<String>,
pending_paste_request: bool,
ime_state: Option<ImeState>,
focus_ime_gen: u64,
platform_view_frames: Vec<PlatformViewFrame>,
input_shields: Vec<Rect>,
pending: ChangeFlags,
theme: Option<Box<dyn Any>>,
insets: WindowInsets,
presented_frames: Option<u64>,
surface_translucent: bool,
semantics_alloc: Cell<u64>,
root_semantics_id: Cell<Option<NonZeroU64>>,
semantics_gen: u64,
deferred_frame: bool,
painted_animating: bool,
overlay_hits: Vec<OverlayHit>,
shortcuts: ShortcutTable,
last_hints: Rc<[ShortcutHint]>,
selection_toolbar: Option<SelectionToolbarRequest>,
selection_toolbar_gen: u64,
layout_epoch: u64,
paint_epoch: u64,
paint_serial: u64,
hover_link: Option<u64>,
painted_links: (Option<u64>, u64),
retained_layers: bool,
retained_ledger: crate::retained::RetainedLedger,
layout_skip: bool,
layout_audit: LayoutAudit,
overlay_pods: Vec<Weak<RefCell<ChildPod>>>,
_state: core::marker::PhantomData<fn(&mut State)>,
}
impl<State: 'static, V: View<State>> RenderRoot<State, V> {
pub fn new() -> Self {
Self {
tree: WidgetTree::new(),
root_id: None,
prev_view: None,
next_id: 0,
window_size: Size::ZERO,
capture_claimant: None,
capture_contacts: false,
contacts_captor_is_root: false,
focus_active: false,
focus_surface: None,
focus_epoch: 1,
key_forward: None,
focus_grant: ShortcutId::next(),
keyboard_focus: false,
focus_ring_policy: FocusRingPolicy::KeyboardOnly,
tab_traversal: true,
hover_active: false,
hover_epoch: 1,
root_identity: NEXT_ROOT_IDENTITY.fetch_add(1, Ordering::Relaxed),
cursor: CursorIcon::Default,
pending_clipboard_write: None,
pending_paste_request: false,
ime_state: None,
focus_ime_gen: 0,
platform_view_frames: Vec::new(),
input_shields: Vec::new(),
pending: ChangeFlags::NONE,
theme: None,
insets: WindowInsets::default(),
presented_frames: None,
surface_translucent: false,
semantics_alloc: Cell::new(2),
root_semantics_id: Cell::new(None),
semantics_gen: 0,
deferred_frame: false,
painted_animating: false,
overlay_hits: Vec::new(),
shortcuts: ShortcutTable::default(),
last_hints: Rc::from(Vec::new()),
selection_toolbar: None,
selection_toolbar_gen: 0,
layout_epoch: 1,
paint_epoch: 1,
paint_serial: 0,
hover_link: None,
painted_links: (None, 1),
retained_layers: true,
retained_ledger: crate::retained::RetainedLedger::empty(),
layout_skip: true,
layout_audit: LayoutAudit::default(),
overlay_pods: Vec::new(),
_state: core::marker::PhantomData,
}
}
pub fn shortcut_hints(
&self,
mut filter: impl FnMut(&ShortcutHint) -> bool,
) -> Vec<ShortcutHint> {
self.last_hints
.iter()
.filter(|hint| filter(hint))
.cloned()
.collect()
}
}
impl<State: 'static, V: View<State>> Default for RenderRoot<State, V> {
fn default() -> Self {
Self::new()
}
}