use std::rc::Weak;
use super::{RenderRoot, advance_focus_epoch};
use crate::event::{CursorIcon, ImeState, PointerId};
use crate::overlay::{OverlayHit, OverlayInput, OverlayKey, OverlayKeys};
use crate::view::View;
fn store_ime_state_in(slot: &mut Option<ImeState>, generation: &mut u64, next: Option<ImeState>) {
if *slot != next {
*slot = next;
*generation = generation.wrapping_add(1);
}
}
pub(super) fn release_focus_session_in(
focus_active: &mut bool,
ime_slot: &mut Option<ImeState>,
generation: &mut u64,
focus_epoch: &mut u64,
root_identity: u64,
) {
let moved = *focus_active || ime_slot.is_some();
*focus_active = false;
*ime_slot = None;
if moved {
*generation = generation.wrapping_add(1);
*focus_epoch = advance_focus_epoch(*focus_epoch);
crate::widget::set_live_focus_session(root_identity, *focus_epoch, *focus_epoch);
}
}
impl<State: 'static, V: View<State>> RenderRoot<State, V> {
pub fn is_pointer_captured(&self) -> bool {
self.capture_claimant.is_some()
}
pub fn pointer_capture_claimant(&self) -> Option<PointerId> {
self.capture_claimant
}
pub fn pointer_capture_contacts(&self) -> bool {
self.capture_contacts
}
pub fn is_focus_active(&self) -> bool {
self.focus_active
}
pub fn is_hover_active(&self) -> bool {
self.hover_active
}
pub fn cursor(&self) -> CursorIcon {
self.cursor
}
pub fn take_clipboard_write(&mut self) -> Option<String> {
self.pending_clipboard_write.take()
}
pub fn take_paste_request(&mut self) -> bool {
std::mem::take(&mut self.pending_paste_request)
}
pub fn ime_state(&self) -> Option<ImeState> {
self.ime_state.clone()
}
pub fn focus_ime_generation(&self) -> u64 {
self.focus_ime_gen
}
pub fn focus_epoch(&self) -> u64 {
self.focus_epoch
}
pub(super) fn set_focus_active(&mut self, active: bool) {
if self.focus_active != active {
self.focus_active = active;
self.focus_ime_gen = self.focus_ime_gen.wrapping_add(1);
}
}
pub(super) fn store_ime_state(&mut self, ime: Option<ImeState>) {
store_ime_state_in(&mut self.ime_state, &mut self.focus_ime_gen, ime);
}
pub(super) fn release_focus_session(&mut self) {
self.set_keyboard_focus(false);
release_focus_session_in(
&mut self.focus_active,
&mut self.ime_state,
&mut self.focus_ime_gen,
&mut self.focus_epoch,
self.root_identity,
);
self.focus_surface = None;
self.key_forward = None;
if self.selection_toolbar.take().is_some() {
self.selection_toolbar_gen = self.selection_toolbar_gen.wrapping_add(1);
}
}
pub(super) fn trap_modal_focus(&mut self) {
let traps = |hit: &OverlayHit| {
hit.input == OverlayInput::Interactive && hit.keys == OverlayKeys::Modal
};
if !self.focus_active || !self.overlay_hits.iter().any(traps) {
return;
}
self.publish_focus_session();
let floated_holds = self
.overlay_pods
.iter()
.filter_map(Weak::upgrade)
.any(|pod| pod.try_borrow().map_or(true, |pod| pod.holds_live_focus()));
if !floated_holds {
self.release_focus_session();
}
}
pub(super) fn record_key_forward(&mut self, requested: Option<OverlayKey>) {
if let Some(key) = requested.filter(|_| self.focus_active) {
self.key_forward = Some((key, self.focus_epoch));
}
}
pub(super) fn live_key_forward(&self) -> Option<OverlayKey> {
self.key_forward
.filter(|&(_, epoch)| self.focus_active && epoch == self.focus_epoch)
.map(|(key, _)| key)
}
pub(super) fn publish_focus_session(&self) {
crate::widget::set_live_focus_session(
self.root_identity,
self.focus_epoch,
self.focus_epoch,
);
}
pub(super) fn end_hover_link(&mut self) {
self.hover_epoch = self.hover_epoch.wrapping_add(1);
self.hover_active = false;
self.hover_link = None;
crate::event::set_live_hover_link(self.root_identity, 0);
}
}