以鼠标点击事件为例:
来自winit的WindowEvent::MouseInput发送到app
WindowEvent::MouseInput { state, button, .. } => {
app.set_navigation_mode(NavigationMode::NotKeyboard);
let event_name = match state {
ElementState::Pressed => "mousedown",
ElementState::Released => "click",
};
app.send_event(FreyaEvent::Mouse {
name: event_name.to_string(),
cursor: cursor_pos,
button: Some(button),
});
}
然后会调用到处理事件:
流程说明:
1.先分发并处理global事件
2.根据dom树的layout和viewports,分发并寻找潜在的事件
3.再根据dom节点,计算转换为dom事件。-- 供后续计算
4.根据dom元素的状态,过滤dom事件,并尝试转换为真实的dom事件。
5.计算获取可以被发射的派生事件。-- 例如移到元素外,会额外产生mouseleave也就是移出事件
6.组合dom和派生的dom事件(也就是第4第5中)并对其进行排序
7.发射dom事件 -- 实际也是入队列 交由真实的事件处理
8.发射global事件
9.清空事件队列
源码如下:
/// Process the events and emit them to the VirtualDOM
pub fn process_events(
dom: &FreyaDOM,
layers: &Layers,
events: &mut EventsQueue,
event_emitter: &EventEmitter,
elements_state: &mut ElementsState,
viewports: &Viewports,
scale_factor: f64,
) {
// 1. Get global events created from the incoming events
let global_events = measure_global_events(events);
// 2. Get potential events that could be emitted based on the elements layout and viewports
let potential_events = measure_potential_event_listeners(layers, events, viewports, dom);
// 3. Get what events can be actually emitted based on what elements are listening
let dom_events = measure_dom_events(potential_events, dom, scale_factor);
// 4. Filter the dom events and get potential derived events, e.g mouseover -> mouseenter
let (potential_colateral_events, mut to_emit_dom_events) =
elements_state.process_events(&dom_events, events);
// 5. Get what derived events can actually be emitted
let to_emit_dom_colateral_events =
measure_dom_events(potential_colateral_events, dom, scale_factor);
// 6. Join both the dom and colateral dom events and sort them
to_emit_dom_events.extend(to_emit_dom_colateral_events);
to_emit_dom_events.sort_unstable();
// 7. Emit the DOM events
for event in to_emit_dom_events {
event_emitter.send(event).unwrap();
}
// 8. Emit the global events
emit_global_events_listeners(global_events, dom, event_emitter, scale_factor);
// 9. Clear the events queue
events.clear();
}