commit fc644383f5d49d8c9786c11f6add062b01968c8d
parent 4ca534f021c23fd2a77fcf9844e8d47eb357148b
Author: Hiroyuki Ikezoe <hikezoe.birchill@mozilla.com>
Date: Wed, 15 Oct 2025 08:17:08 +0000
Bug 1994305 - Invoke DesiredAsyncPanZoomState::Update in HideCaretsAndDispatchCaretStateChangedEvent. r=TYLin,layout-reviewers,edgar
While moving the focus from a `user-select: text` element to `user-text:
none` element, no selectionchange event is fired. Rather `blur` event is
fired on the `user-select: text` element.
Differential Revision: https://phabricator.services.mozilla.com/D268616
Diffstat:
5 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
@@ -3055,6 +3055,12 @@ nsDOMWindowUtils::DisableApzForElement(Element* aElement) {
return NS_OK;
}
+NS_IMETHODIMP
+nsDOMWindowUtils::IsApzDisabledForElement(Element* aElement, bool* aOutResult) {
+ *aOutResult = nsLayoutUtils::ShouldDisableApzForElement(aElement);
+ return NS_OK;
+}
+
static nsTArray<ScrollContainerFrame*> CollectScrollableAncestors(
nsIFrame* aStart) {
nsTArray<ScrollContainerFrame*> result;
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1647,6 +1647,11 @@ cenum AsyncEnabledOption : 8 {
void disableApzForElement(in Element aElement);
/**
+ * Returns whether APZ is being disabled on the given |aElement|.
+ */
+ boolean isApzDisabledForElement(in Element aElement);
+
+ /**
* Ask APZ to pan and zoom to the focused input element.
*/
[can_run_script] void zoomToFocusedInput();
diff --git a/layout/base/AccessibleCaretManager.cpp b/layout/base/AccessibleCaretManager.cpp
@@ -181,6 +181,7 @@ void AccessibleCaretManager::HideCaretsAndDispatchCaretStateChangedEvent() {
mCarets.GetFirst()->SetAppearance(Appearance::None);
mCarets.GetSecond()->SetAppearance(Appearance::None);
mIsCaretPositionChanged = false;
+ mDesiredAsyncPanZoomState.Update(*this);
DispatchCaretStateChangedEvent(CaretChangedReason::Visibilitychange);
}
}
diff --git a/layout/base/tests/mochitest.toml b/layout/base/tests/mochitest.toml
@@ -296,6 +296,9 @@ support-files = ["preserve3d_sorting_hit_testing_iframe.html"]
["test_preserve3d_sorting_hit_testing2.html"]
support-files = ["preserve3d_sorting_hit_testing2_iframe.html"]
+["test_re_enable_apz_on_blur.html"]
+skip-if = ["os == 'win'"]
+
["test_refreshDriver_hasPendingTick.html"]
["test_reftests_with_caret.html"]
diff --git a/layout/base/tests/test_re_enable_apz_on_blur.html b/layout/base/tests/test_re_enable_apz_on_blur.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <style>
+ html {
+ user-select: none;
+ }
+ textarea {
+ width: 100%;
+ height: 20px;
+ position: fixed;
+ bottom: 20px;
+ user-select: text;
+ }
+ </style>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<textarea name="name" rows="1" cols="20" inputmode="none">text</textarea>
+</body>
+<script>
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv({
+ set: [
+ ["layout.accessiblecaret.enabled", true],
+ ["layout.accessiblecaret.enabled_on_touch", true],
+ ],
+}, async () => {
+ await SpecialPowers.spawnChrome([], () => {
+ browsingContext.touchEventsOverride = "enabled";
+ });
+
+ const utils = SpecialPowers.DOMWindowUtils;
+ const target = document.querySelector("textarea");
+
+ const selectionchangePromise = new Promise(resolve => {
+ target.addEventListener("selectionchange", () => resolve());
+ });
+ ok(!utils.isApzDisabledForElement(target),
+ "APZ is not disabled on the textarea");
+
+ // Tap on the text area.
+ synthesizeTouch(target, 10, 10, { type: "touchstart" });
+ synthesizeTouch(target, 10, 10, { type: "touchend" });
+
+ await selectionchangePromise;
+
+ ok(utils.isApzDisabledForElement(target),
+ "Now APZ is disabled on the textarea");
+
+ const blurPromise = new Promise(resolve => {
+ target.addEventListener("blur", () => resolve());
+ });
+ target.blur();
+
+ await blurPromise;
+
+ ok(!utils.isApzDisabledForElement(target),
+ "Now APZ is re-enabled on the textarea");
+
+ SimpleTest.finish();
+});
+</script>
+</html>