blink: Discard input when render-blocking for SET.
Ensure input events are discarded when rendering is paused for a shared
element transition using the same strategy as paint holding.
Fixed: 1368757
Change-Id: Ief98e2d1a570c5a747e8030e318a02957e1d8b63
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3923394
Commit-Queue: Khushal Sagar <khushalsagar@chromium.org>
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
Reviewed-by: Bo Liu <boliu@chromium.org>
Auto-Submit: Khushal Sagar <khushalsagar@chromium.org>
Reviewed-by: David Bokan <bokan@chromium.org>
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1052556}
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index cac114e8..49ff1e4a 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -423,6 +423,7 @@
bool,
PaintHoldingReason,
absl::optional<PaintHoldingCommitTrigger>) override {}
+ void OnPauseRenderingChanged(bool) override {}
void RecordStartOfFrameMetrics() override {}
void RecordEndOfFrameMetrics(base::TimeTicks,
diff --git a/cc/test/stub_layer_tree_host_client.h b/cc/test/stub_layer_tree_host_client.h
index 0f19a274..23d2a2ee 100644
--- a/cc/test/stub_layer_tree_host_client.h
+++ b/cc/test/stub_layer_tree_host_client.h
@@ -31,6 +31,7 @@
bool,
PaintHoldingReason,
absl::optional<PaintHoldingCommitTrigger>) override {}
+ void OnPauseRenderingChanged(bool) override {}
void RecordStartOfFrameMetrics() override {}
void RecordEndOfFrameMetrics(base::TimeTicks,
ActiveFrameSequenceTrackers) override {}
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index fb69944..3418f6a 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -650,6 +650,11 @@
return std::make_unique<ScopedPauseRendering>(this);
}
+void LayerTreeHost::OnPauseRenderingChanged(bool paused) {
+ DCHECK(IsMainThread());
+ client_->OnPauseRenderingChanged(paused);
+}
+
void LayerTreeHost::OnDeferMainFrameUpdatesChanged(bool defer_status) {
DCHECK(IsMainThread());
client_->OnDeferMainFrameUpdatesChanged(defer_status);
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index fc51c668..d3e9ef7ae 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -315,6 +315,9 @@
// during the main frame) updates are presented before rendering is paused.
[[nodiscard]] std::unique_ptr<ScopedPauseRendering> PauseRendering();
+ // Notification that the proxy paused or resumed rendering.
+ void OnPauseRenderingChanged(bool);
+
// Returns whether main frame updates are deferred. See conditions above.
bool MainFrameUpdatesAreDeferred() const;
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h
index 0383093..17f7e90 100644
--- a/cc/trees/layer_tree_host_client.h
+++ b/cc/trees/layer_tree_host_client.h
@@ -134,6 +134,9 @@
PaintHoldingReason reason,
absl::optional<PaintHoldingCommitTrigger> trigger) = 0;
+ // Notification that rendering has been paused or resumed.
+ virtual void OnPauseRenderingChanged(bool) = 0;
+
// Visual frame-based updates to the state of the LayerTreeHost are expected
// to happen only in calls to LayerTreeHostClient::UpdateLayerTreeHost, which
// should mutate/invalidate the layer tree or other page parameters as
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 63f6d35..ac0d588 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -611,6 +611,8 @@
TRACE_ID_LOCAL(this));
}
+ layer_tree_host_->OnPauseRenderingChanged(pause_rendering_);
+
// The impl thread needs to know that it should not issue BeginFrames.
ImplThreadTaskRunner()->PostTask(
FROM_HERE,
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 050d79a..ad5e3b1 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -362,6 +362,8 @@
"cc", "SingleThreadProxy::SetPauseRendering", TRACE_ID_LOCAL(this));
}
+ layer_tree_host_->OnPauseRenderingChanged(pause_rendering_);
+
// The scheduler needs to know that it should not issue BeginFrame.
DebugScopedSetImplThread impl(task_runner_provider_);
scheduler_on_impl_thread_->SetPauseRendering(pause_rendering_);
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 5952508..2e34173 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -138,6 +138,7 @@
bool,
cc::PaintHoldingReason,
absl::optional<cc::PaintHoldingCommitTrigger>) override {}
+ void OnPauseRenderingChanged(bool) override {}
void BeginMainFrameNotExpectedSoon() override {}
void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override {}
void UpdateLayerTreeHost() override;
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
index b2d9a4f2..8758536 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
@@ -200,6 +200,12 @@
delegate_->OnDeferMainFrameUpdatesChanged(status);
}
+void LayerTreeView::OnPauseRenderingChanged(bool paused) {
+ if (!delegate_)
+ return;
+ delegate_->OnPauseRenderingChanged(paused);
+}
+
void LayerTreeView::OnDeferCommitsChanged(
bool status,
cc::PaintHoldingReason reason,
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
index 883abd7..b9c73329 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
@@ -78,6 +78,7 @@
bool defer_status,
cc::PaintHoldingReason reason,
absl::optional<cc::PaintHoldingCommitTrigger> trigger) override;
+ void OnPauseRenderingChanged(bool) override;
void BeginMainFrameNotExpectedSoon() override;
void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override;
void UpdateLayerTreeHost() override;
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h
index 5fc4149..e881f38 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h
@@ -45,6 +45,7 @@
bool defer_status,
cc::PaintHoldingReason reason,
absl::optional<cc::PaintHoldingCommitTrigger> trigger) = 0;
+ virtual void OnPauseRenderingChanged(bool) = 0;
// Notifies that the layer tree host has completed a call to
// RequestMainFrameUpdate in response to a BeginMainFrame.
diff --git a/third_party/blink/renderer/platform/widget/compositing/test/stub_layer_tree_view_delegate.h b/third_party/blink/renderer/platform/widget/compositing/test/stub_layer_tree_view_delegate.h
index 0bd9d897..e76e8be8 100644
--- a/third_party/blink/renderer/platform/widget/compositing/test/stub_layer_tree_view_delegate.h
+++ b/third_party/blink/renderer/platform/widget/compositing/test/stub_layer_tree_view_delegate.h
@@ -32,6 +32,7 @@
bool defer_status,
cc::PaintHoldingReason reason,
absl::optional<cc::PaintHoldingCommitTrigger> trigger) override {}
+ void OnPauseRenderingChanged(bool) override {}
void DidBeginMainFrame() override {}
void DidCommitAndDrawCompositorFrame() override {}
void WillCommitCompositorFrame() override {}
diff --git a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
index 7530ed0..7c0bd953 100644
--- a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
+++ b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
@@ -766,6 +766,16 @@
}
}
+void WidgetInputHandlerManager::OnPauseRenderingChanged(bool paused) {
+ if (paused) {
+ suppressing_input_events_state_ |=
+ static_cast<uint16_t>(SuppressingInputEventsBits::kRenderingPaused);
+ } else {
+ suppressing_input_events_state_ &=
+ ~static_cast<uint16_t>(SuppressingInputEventsBits::kRenderingPaused);
+ }
+}
+
void WidgetInputHandlerManager::InitOnInputHandlingThread(
const base::WeakPtr<cc::CompositorDelegateForInput>& compositor_delegate,
bool sync_compositing) {
diff --git a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
index 94ed0856..b238849 100644
--- a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
+++ b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
@@ -75,6 +75,9 @@
kDeferCommits = 1 << 1,
// if set, we have not painted a main frame from the current navigation yet
kHasNotPainted = 1 << 2,
+ // if set, suppress events because pipeline has paused rendering (both main
+ // and compositor thread driven updates).
+ kRenderingPaused = 1 << 3,
};
public:
@@ -167,6 +170,9 @@
// Called to inform us when the system starts or stops deferring commits.
void OnDeferCommitsChanged(bool defer_status, cc::PaintHoldingReason reason);
+ // Called to inform us when the system pauses or resumes rendering.
+ void OnPauseRenderingChanged(bool);
+
// Allow tests, headless etc. to have input events processed before the
// compositor is ready to commit frames.
// TODO(schenney): Fix this somehow, forcing all tests to wait for
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index 8589009..c6c278a 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -549,6 +549,10 @@
widget_input_handler_manager_->OnDeferCommitsChanged(defer, reason);
}
+void WidgetBase::OnPauseRenderingChanged(bool paused) {
+ widget_input_handler_manager_->OnPauseRenderingChanged(paused);
+}
+
void WidgetBase::DidBeginMainFrame() {
if (base::FeatureList::IsEnabled(features::kRunTextInputUpdatePostLifecycle))
UpdateTextInputState();
diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h
index 03bbf1d..b73ee82 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.h
+++ b/third_party/blink/renderer/platform/widget/widget_base.h
@@ -157,6 +157,7 @@
bool defer_status,
cc::PaintHoldingReason reason,
absl::optional<cc::PaintHoldingCommitTrigger> trigger) override;
+ void OnPauseRenderingChanged(bool) override;
void DidBeginMainFrame() override;
void RequestNewLayerTreeFrameSink(
LayerTreeFrameSinkCallback callback) override;
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/input-blocked-when-rendering-suppressed.html b/third_party/blink/web_tests/wpt_internal/document-transition/input-blocked-when-rendering-suppressed.html
new file mode 100644
index 0000000..12708f4
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/input-blocked-when-rendering-suppressed.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: ensure input is discarded when rendering is suppressed</title>
+<link rel="help" href="https://github.com/WICG/shared-element-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+async function runTest(resolve, reject) {
+ window.addEventListener('mousedown', (event) => {
+ let point = event.clientX + "," + event.clientY;
+ if (event.clientX == 20 && event.clientY == 20)
+ resolve();
+ else
+ reject(point);
+ });
+
+ let transition = document.createDocumentTransition();
+
+ // Send an event while rendering is suppressed.
+ await transition.start(() => {
+ return new Promise(async (inner_resolve) => {
+ new test_driver.Actions()
+ .setContext(window)
+ .addPointer("finger1", "touch")
+ .pointerMove(10, 10, {origin: "viewport", sourceName: "finger1"})
+ .pointerDown({sourceName: "finger1"})
+ .pointerUp({sourceName: "finger1"})
+ .send();
+
+ // Use a timeout to ensure the input has been queued up. await
+ // times out because the event is discarded.
+ step_timeout(inner_resolve, 1000);
+ });
+ });
+
+ await new test_driver.Actions()
+ .setContext(window)
+ .addPointer("finger1", "touch")
+ .pointerMove(20, 20, {origin: "viewport", sourceName: "finger1"})
+ .pointerDown({sourceName: "finger1"})
+ .pointerUp({sourceName: "finger1"})
+ .send();
+}
+
+promise_test(async t => {
+ return new Promise(async (resolve, reject) => {
+ // Dispatch an event before starting the test to finish init logic in
+ // synthetic input dispatch.
+ await new test_driver.Actions()
+ .setContext(window)
+ .addPointer("finger1", "touch")
+ .pointerMove(0, 0, {origin: "viewport", sourceName: "finger1"})
+ .pointerDown({sourceName: "finger1"})
+ .pointerUp({sourceName: "finger1"})
+ .send();
+ runTest(resolve, reject);
+ });
+}, "Input when rendering suppressed is ignored");
+</script>
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 4cb37cf..ad691e7 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -359,6 +359,7 @@
bool,
cc::PaintHoldingReason,
absl::optional<cc::PaintHoldingCommitTrigger>) override {}
+ void OnPauseRenderingChanged(bool) override {}
void WillUpdateLayers() override {}
void DidUpdateLayers() override;
void BeginMainFrame(const viz::BeginFrameArgs& args) override;