From afa3f4bba27af2a36edec3b023ccc09ec182ec60 Mon Sep 17 00:00:00 2001 From: batu_hoang Date: Fri, 30 May 2025 14:40:24 +0800 Subject: [PATCH] Apply delay when epoch is mismatch for touch events Signed-off-by: batu_hoang --- components/compositing/compositor.rs | 5 ++- components/compositing/webview_renderer.rs | 42 +++++++++++++++++----- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index d174d54ae9c..0cedc54ac76 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -814,13 +814,12 @@ impl IOCompositor { let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) else { return warn!("Could not find WebView for incoming display list"); }; + // epoch is outdated until we receive "NewWebRenderFrameReady" message. webview_renderer.epoch_not_synchronized.set(true); let pipeline_id = display_list_info.pipeline_id; let details = webview_renderer.ensure_pipeline_details(pipeline_id.into()); - details.most_recent_display_list_epoch = Some(display_list_info.epoch); - details.hit_test_items = display_list_info.hit_test_info; details.install_new_scroll_tree(display_list_info.scroll_tree); @@ -1664,7 +1663,7 @@ impl IOCompositor { if found_recomposite_msg { // Process all pending events self.webview_renderers.iter().for_each(|webview| { - webview.dispatch_pending_input_events(); + webview.dispatch_pending_point_input_events(); webview.epoch_not_synchronized.set(false); }); } diff --git a/components/compositing/webview_renderer.rs b/components/compositing/webview_renderer.rs index 19535c7e785..024dd60017d 100644 --- a/components/compositing/webview_renderer.rs +++ b/components/compositing/webview_renderer.rs @@ -99,7 +99,7 @@ pub(crate) struct WebViewRenderer { /// active animations or animation frame callbacks. animating: bool, /// Pending input events queue. Priavte and only this thread pushes events to it. - pending_input_events: RefCell>, + pending_point_input_events: RefCell>, /// Flag to indicate that the epoch has been not synchronized yet. pub epoch_not_synchronized: Cell, } @@ -136,7 +136,7 @@ impl WebViewRenderer { max_viewport_zoom: None, hidpi_scale_factor: Scale::new(hidpi_scale_factor.0), animating: false, - pending_input_events: Default::default(), + pending_point_input_events: Default::default(), epoch_not_synchronized: Cell::default(), } } @@ -323,7 +323,9 @@ impl WebViewRenderer { }; if self.epoch_not_synchronized.get() { - self.pending_input_events.borrow_mut().push_back(event); + self.pending_point_input_events + .borrow_mut() + .push_back(event); return; } @@ -336,7 +338,9 @@ impl WebViewRenderer { { Ok(hit_test_results) => hit_test_results, Err(HitTestError::EpochMismatch) => { - self.pending_input_events.borrow_mut().push_back(event); + self.pending_point_input_events + .borrow_mut() + .push_back(event); return; }, _ => { @@ -353,8 +357,8 @@ impl WebViewRenderer { } } - pub(crate) fn dispatch_pending_input_events(&self) { - while let Some(event) = self.pending_input_events.borrow_mut().pop_front() { + pub(crate) fn dispatch_pending_point_input_events(&self) { + while let Some(event) = self.pending_point_input_events.borrow_mut().pop_front() { // Events that do not need to do hit testing are sent directly to the // constellation to filter down. let Some(point) = event.point() else { @@ -453,13 +457,33 @@ impl WebViewRenderer { } fn send_touch_event(&self, mut event: TouchEvent) -> bool { + if self.epoch_not_synchronized.get() { + // If the epoch is not synchronized, we cannot send the event. + // We will try again later. + self.pending_point_input_events + .borrow_mut() + .push_back(InputEvent::Touch(event)); + return false; + } + let get_pipeline_details = |pipeline_id| self.pipelines.get(&pipeline_id); - let Ok(result) = self + let result = match self .global .borrow() .hit_test_at_point(event.point, get_pipeline_details) - else { - return false; + { + Ok(hit_test_results) => hit_test_results, + Err(HitTestError::EpochMismatch) => { + // If the epoch is not synchronized, we cannot send the event. + // We will try again later. + self.pending_point_input_events + .borrow_mut() + .push_back(InputEvent::Touch(event)); + return false; + }, + _ => { + return false; + }, }; event.init_sequence_id(self.touch_handler.current_sequence_id);