ferroui_controls/presentation_source/
presentation_source_input.rs1use super::PresentationSource;
2use ferroui_base::input::raw::{IRawInputEventArgs, RawPointerEventArgs};
3use ferroui_base::input::{IInputRoot, InputElement};
4use ferroui_base::logging::{LogArea, LogEventLevel, Logger};
5use ferroui_base::threading::Dispatcher;
6use ferroui_base::Ref;
7use std::rc::Rc;
8
9impl PresentationSource {
10 pub fn input_root(&self) -> Rc<dyn IInputRoot> {
12 self.rc()
13 }
14
15 fn handle_input_core(&self, e: Rc<dyn IRawInputEventArgs>) {
17 if let Some(pointer_args) = e.downcast_ref::<RawPointerEventArgs>() {
18 let hit_test_element = self.root_element().input_hit_test_with(pointer_args.position(), false);
19 let first_enabled_ancestor = first_enabled_ancestor(hit_test_element.clone());
20
21 pointer_args.set_input_hit_test_result(hit_test_element, first_enabled_ancestor);
22 }
23
24 if let Some(input_manager) = &self.input_manager {
25 input_manager.process_input(e);
26 }
27 }
28
29 pub(super) fn handle_input(&self, e: Rc<dyn IRawInputEventArgs>) {
30 if self.platform_impl().is_some() {
31 let this = self.rc();
32 let _ = Dispatcher::ui_thread().invoke_local(move || this.handle_input_core(e));
35 } else if let Some(logger) = Logger::try_get(LogEventLevel::Warning, LogArea::CONTROL) {
36 logger.log(None, "PlatformImpl is null, couldn't handle input.");
37 }
38 }
39
40 pub fn focus_root(&self) -> Ref<InputElement> {
45 self.focus_root.upgrade().expect("the focus root of the presentation source has been dropped")
46 }
47}
48
49fn first_enabled_ancestor(hit_test_element: Option<Ref<InputElement>>) -> Option<Ref<InputElement>> {
50 let mut candidate = hit_test_element;
51 while let Some(element) = &candidate {
52 if element.is_effectively_enabled() {
53 break;
54 }
55 candidate = element.visual_parent().and_then(|parent| parent.downcast::<InputElement>().ok());
56 }
57 candidate
58}