aboutsummaryrefslogtreecommitdiffstats
path: root/components/compositing/compositor.rs
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2023-10-04 18:33:18 +0200
committerGitHub <noreply@github.com>2023-10-04 16:33:18 +0000
commitce183d85818e4d9b64f45cc4d7203b1871b3182e (patch)
tree2ecff1ccbdf4f1d995bd44958c9a9f5d5099d9ab /components/compositing/compositor.rs
parent38a325cc1c2a079c42b0511c2e5e5aa88753144d (diff)
downloadservo-ce183d85818e4d9b64f45cc4d7203b1871b3182e.tar.gz
servo-ce183d85818e4d9b64f45cc4d7203b1871b3182e.zip
Only access hit test items for the current epoch in the compositor (#30491)
When display lists update quickly, a hit test result might be returned for a previous display list / list of hit test items. When that happens, ignore the hit test result. This fixes a crash, but there might be situations where we can do something better, such as wait for display list processing to finish before performing the hit test. A future change might do this for events like mouse clicks and touch events that should never be thrown away. Ultimately, the best thing is likely moving hit testing back to layout or script so a valid hit test can always be performed against the current DOM. Fixes #29796.
Diffstat (limited to 'components/compositing/compositor.rs')
-rw-r--r--components/compositing/compositor.rs16
1 files changed, 15 insertions, 1 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 59845759ca0..0f549d50256 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -18,7 +18,7 @@ use crossbeam_channel::Sender;
use embedder_traits::Cursor;
use euclid::{Point2D, Rect, Scale, Transform3D, Vector2D};
use fnv::{FnvHashMap, FnvHashSet};
-use gfx_traits::{Epoch, FontData};
+use gfx_traits::{Epoch, FontData, WebRenderEpochToU16};
#[cfg(feature = "gl")]
use image::{DynamicImage, ImageFormat};
use ipc_channel::ipc;
@@ -283,6 +283,10 @@ struct PipelineDetails {
/// The pipeline associated with this PipelineDetails object.
pipeline: Option<CompositionPipeline>,
+ /// The epoch of the most recent display list for this pipeline. Note that this display
+ /// list might not be displayed, as WebRender processes display lists asynchronously.
+ most_recent_display_list_epoch: Option<WebRenderEpoch>,
+
/// Whether animations are running
animations_running: bool,
@@ -305,6 +309,7 @@ impl PipelineDetails {
fn new() -> PipelineDetails {
PipelineDetails {
pipeline: None,
+ most_recent_display_list_epoch: None,
animations_running: false,
animation_callbacks_running: false,
visible: true,
@@ -696,6 +701,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
let pipeline_id = display_list_info.pipeline_id;
let details = self.pipeline_details(PipelineId::from_webrender(pipeline_id));
+ 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);
@@ -1134,6 +1140,14 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
None => return None,
};
+ // If the epoch in the tag does not match the current epoch of the pipeline,
+ // then the hit test is against an old version of the display list and we
+ // should ignore this hit test for now.
+ match details.most_recent_display_list_epoch {
+ Some(epoch) if epoch.as_u16() == item.tag.1 => {},
+ _ => return None,
+ }
+
let info = &details.hit_test_items[item.tag.0 as usize];
Some(CompositorHitTestResult {
pipeline_id,