Skip to main content

fission_core/input/
mod.rs

1use crate::env::{
2    Clipboard, ContextMenuState, InteractionStateMap, ScrollStateMap, SelectableTextStateMap,
3    TextEditStateMap,
4};
5use crate::event::InputEvent;
6use crate::{ActionEnvelope, ActionInput};
7use fission_ir::{CoreIR, Op, WidgetId};
8use fission_layout::{LayoutSnapshot, TextMeasurer};
9use std::sync::Arc;
10
11pub mod gesture;
12pub mod hover;
13pub mod selectable_text;
14pub mod slider;
15pub mod text;
16
17pub struct ControllerContext<'a> {
18    pub ir: &'a CoreIR,
19    pub layout: &'a LayoutSnapshot,
20    pub text_edit: &'a mut TextEditStateMap,
21    pub selectable_text: &'a mut SelectableTextStateMap,
22    pub context_menu: &'a mut ContextMenuState,
23    pub interaction: &'a mut InteractionStateMap,
24    pub scroll: &'a mut ScrollStateMap,
25    pub gesture: &'a mut crate::env::GestureState,
26    pub clipboard: Option<&'a Arc<dyn Clipboard>>,
27    pub measurer: Option<&'a Arc<dyn TextMeasurer>>,
28    // We queue actions here instead of dispatching immediately to keep Controller pure logic
29    pub dispatched_actions: Vec<(WidgetId, ActionEnvelope, ActionInput)>,
30}
31
32pub trait InputController {
33    fn handle_event(&mut self, ctx: &mut ControllerContext, event: &InputEvent) -> bool;
34}
35
36pub(crate) fn action_scope_for_node(ir: &CoreIR, node_id: WidgetId) -> Option<u128> {
37    let mut current_id = Some(node_id);
38    while let Some(id) = current_id {
39        let Some(node) = ir.nodes.get(&id) else {
40            break;
41        };
42        if let Op::Semantics(semantics) = &node.op {
43            if let Some(scope_id) = semantics.action_scope_id {
44                return Some(scope_id);
45            }
46        }
47        current_id = node.parent;
48    }
49    None
50}
51
52pub(crate) fn scoped_action_input(
53    ir: &CoreIR,
54    target: WidgetId,
55    input: ActionInput,
56) -> ActionInput {
57    if let Some(scope_id) = action_scope_for_node(ir, target) {
58        ActionInput::scoped_raw(scope_id, target, input)
59    } else {
60        input
61    }
62}