[iOS] Native selection views sometimes appear in hidden editable areas after losing...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Mar 2019 21:22:53 +0000 (21:22 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Mar 2019 21:22:53 +0000 (21:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195894
<rdar://problem/48849989>

Reviewed by Tim Horton.

Source/WebKit:

On certain websites, focus is moved away from an editable element while maintaining a selection inside the
editable element. In the case where the editable element is hidden, this currently breaks our text interaction
suppression heuristics, which suppress text selection gestures and overlays inside focused hidden editable
elements. To fix this, we refactor our text interaction suppression heuristics, such that they are not dependent
on an editable element being focused. See changes below for more details.

Test: editing/selection/ios/hide-selection-in-non-focused-element.html

* Shared/EditorState.cpp:
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
* Shared/EditorState.h:

Rename elementIsTransparentOrFullyClipped to editableRootIsTransparentOrFullyClipped, and additionally compute
this flag by checking whether the root editable element containing the selection is transparent or clipped,
instead of using the currently focused element.

* Shared/FocusedElementInformation.cpp:
(WebKit::FocusedElementInformation::encode const):
(WebKit::FocusedElementInformation::decode):
* Shared/FocusedElementInformation.h:

Remove the elementIsTransparentOrFullyClipped flag from FocusedElementInformation (see below for more detail).

* UIProcess/ios/WKContentViewInteraction.h:

Rename FocusedElementIsTransparentOrFullyClipped to EditableRootIsTransparentOrFullyClipped.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _zoomToRevealFocusedElement]):
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):

Remove logic that currently uses state on FocusedElementInformation to determine whether to suppress platform
text interactions; instead, only use EditorState to make this determination. This logic was originally added in
the initial implementation of the text interaction suppression heuristic as a way to begin suppressing text
selection state before zooming to reveal the focused element; however, since we now zoom to reveal the text
selection when focusing editable elements, zooming is deferred until the next complete EditorState update
arrives in the UI process so we don't need to worry about beginning to suppress text interactions prior to this
initial editor state update.

(-[WKContentView _elementDidBlur]):
(-[WKContentView _updateSelectionAssistantSuppressionState]):

Add a helper method that updates text selection suppression state using the current EditorState.

(-[WKContentView _selectionChanged]):
(-[WKContentView _updateChangedSelection:]):

Always update text suppression state when receiving an EditorState, instead of only doing so when processing a
text selection gesture.

(-[WKContentView _startSuppressingSelectionAssistantForReason:]):

Renamed from _beginSuppressingSelectionAssistantForReason:, to better match "start/end" terminology of
_endSuppressingSelectionAssistantForReason:.

(-[WKContentView dropInteraction:performDrop:]):
(-[WKContentView _beginSuppressingSelectionAssistantForReason:]): Deleted.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::editorStateChanged):

Ensure that we run logic to zoom to the focused element *after* updating text selection suppression state, so we
don't erroneously zoom to reveal hidden editable elements.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):
(WebKit::WebPage::getFocusedElementInformation):

LayoutTests:

Add a test to verify that moving focus away from a hidden editable element doesn't cause platform selection
views in the element to appear. See WebKit ChangeLog for more details.

* editing/selection/ios/hide-selection-in-non-focused-element-expected.txt: Added.
* editing/selection/ios/hide-selection-in-non-focused-element.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243102 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/selection/ios/hide-selection-in-non-focused-element-expected.txt [new file with mode: 0644]
LayoutTests/editing/selection/ios/hide-selection-in-non-focused-element.html [new file with mode: 0644]
Source/WebKit/ChangeLog
Source/WebKit/Shared/EditorState.cpp
Source/WebKit/Shared/EditorState.h
Source/WebKit/Shared/FocusedElementInformation.cpp
Source/WebKit/Shared/FocusedElementInformation.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

index b7d4c9d..2407576 100644 (file)
@@ -1,3 +1,17 @@
+2019-03-18  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Native selection views sometimes appear in hidden editable areas after losing focus
+        https://bugs.webkit.org/show_bug.cgi?id=195894
+        <rdar://problem/48849989>
+
+        Reviewed by Tim Horton.
+
+        Add a test to verify that moving focus away from a hidden editable element doesn't cause platform selection
+        views in the element to appear. See WebKit ChangeLog for more details.
+
+        * editing/selection/ios/hide-selection-in-non-focused-element-expected.txt: Added.
+        * editing/selection/ios/hide-selection-in-non-focused-element.html: Added.
+
 2019-03-18  Antti Koivisto  <antti@apple.com>
 
         Layer with no backing store should still hit-test over a scroller
diff --git a/LayoutTests/editing/selection/ios/hide-selection-in-non-focused-element-expected.txt b/LayoutTests/editing/selection/ios/hide-selection-in-non-focused-element-expected.txt
new file mode 100644 (file)
index 0000000..b377130
--- /dev/null
@@ -0,0 +1,13 @@
+Hello world
+
+Verifies that text selection is suppressed when the selected content is in a hidden editable root, even when focusing a different element. To manually run the test, tap the editable area in the red box, and then tap the button below it. Platform selection views should not become visible.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS selectionRects.length is 0
+PASS getSelection().toString() is "Hello world"
+PASS document.activeElement is focusTarget
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/selection/ios/hide-selection-in-non-focused-element.html b/LayoutTests/editing/selection/ios/hide-selection-in-non-focused-element.html
new file mode 100644 (file)
index 0000000..3092498
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+<script src="../../../resources/js-test.js"></script>
+<script src="../../../resources/ui-helper.js"></script>
+<style>
+body {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+}
+
+#editor {
+    width: 100%;
+    height: 100%;
+    opacity: 0;
+}
+
+#container {
+    width: 320px;
+    height: 100px;
+    border: 1px solid tomato;
+}
+
+#target {
+    width: 1em;
+    height: 1em;
+}
+
+input {
+    width: 320px;
+    height: 3em;
+}
+</style>
+<script>
+addEventListener("load", runTest);
+jsTestIsAsync = true;
+
+async function runTest() {
+    description("Verifies that text selection is suppressed when the selected content is in a hidden editable root, even when focusing a different element. To manually run the test, tap the editable area in the red box, and then tap the button below it. Platform selection views should not become visible.");
+
+    button = document.querySelector("input");
+    editor = document.getElementById("editor");
+    focusTarget = document.getElementById("focus-target");
+    editor.addEventListener("focus", () => getSelection().selectAllChildren(editor));
+    button.addEventListener("click", () => {
+        event.preventDefault();
+        focusTarget.focus();
+    });
+
+    if (!window.testRunner)
+        return;
+
+    await UIHelper.activateElementAndWaitForInputSession(editor);
+    await UIHelper.activateElement(button);
+    await UIHelper.waitForKeyboardToHide();
+    selectionRects = await UIHelper.getUISelectionViewRects();
+
+    shouldBe("selectionRects.length", "0");
+    shouldBeEqualToString("getSelection().toString()", "Hello world");
+    shouldBe("document.activeElement", "focusTarget");
+
+    finishJSTest();
+}
+</script>
+</head>
+<body>
+<div id="container">
+    <div id="editor" contenteditable>Hello world</div>
+</div>
+<div tabindex="0" id="focus-target"></div>
+<input type="button" value="Press me">
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>
index 3da7f5c..2a985e2 100644 (file)
@@ -1,3 +1,79 @@
+2019-03-18  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Native selection views sometimes appear in hidden editable areas after losing focus
+        https://bugs.webkit.org/show_bug.cgi?id=195894
+        <rdar://problem/48849989>
+
+        Reviewed by Tim Horton.
+
+        On certain websites, focus is moved away from an editable element while maintaining a selection inside the
+        editable element. In the case where the editable element is hidden, this currently breaks our text interaction
+        suppression heuristics, which suppress text selection gestures and overlays inside focused hidden editable
+        elements. To fix this, we refactor our text interaction suppression heuristics, such that they are not dependent
+        on an editable element being focused. See changes below for more details.
+
+        Test: editing/selection/ios/hide-selection-in-non-focused-element.html
+
+        * Shared/EditorState.cpp:
+        (WebKit::EditorState::PostLayoutData::encode const):
+        (WebKit::EditorState::PostLayoutData::decode):
+        * Shared/EditorState.h:
+
+        Rename elementIsTransparentOrFullyClipped to editableRootIsTransparentOrFullyClipped, and additionally compute
+        this flag by checking whether the root editable element containing the selection is transparent or clipped,
+        instead of using the currently focused element.
+
+        * Shared/FocusedElementInformation.cpp:
+        (WebKit::FocusedElementInformation::encode const):
+        (WebKit::FocusedElementInformation::decode):
+        * Shared/FocusedElementInformation.h:
+
+        Remove the elementIsTransparentOrFullyClipped flag from FocusedElementInformation (see below for more detail).
+
+        * UIProcess/ios/WKContentViewInteraction.h:
+
+        Rename FocusedElementIsTransparentOrFullyClipped to EditableRootIsTransparentOrFullyClipped.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _zoomToRevealFocusedElement]):
+        (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
+
+        Remove logic that currently uses state on FocusedElementInformation to determine whether to suppress platform
+        text interactions; instead, only use EditorState to make this determination. This logic was originally added in
+        the initial implementation of the text interaction suppression heuristic as a way to begin suppressing text
+        selection state before zooming to reveal the focused element; however, since we now zoom to reveal the text
+        selection when focusing editable elements, zooming is deferred until the next complete EditorState update
+        arrives in the UI process so we don't need to worry about beginning to suppress text interactions prior to this
+        initial editor state update.
+
+        (-[WKContentView _elementDidBlur]):
+        (-[WKContentView _updateSelectionAssistantSuppressionState]):
+
+        Add a helper method that updates text selection suppression state using the current EditorState.
+
+        (-[WKContentView _selectionChanged]):
+        (-[WKContentView _updateChangedSelection:]):
+
+        Always update text suppression state when receiving an EditorState, instead of only doing so when processing a
+        text selection gesture.
+
+        (-[WKContentView _startSuppressingSelectionAssistantForReason:]):
+
+        Renamed from _beginSuppressingSelectionAssistantForReason:, to better match "start/end" terminology of
+        _endSuppressingSelectionAssistantForReason:.
+
+        (-[WKContentView dropInteraction:performDrop:]):
+        (-[WKContentView _beginSuppressingSelectionAssistantForReason:]): Deleted.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::editorStateChanged):
+
+        Ensure that we run logic to zoom to the focused element *after* updating text selection suppression state, so we
+        don't erroneously zoom to reveal hidden editable elements.
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::platformEditorState const):
+        (WebKit::WebPage::getFocusedElementInformation):
+
 2019-03-18  Chris Dumez  <cdumez@apple.com>
 
         Delay WebProcess launch until a load is triggered in a Web view
index c1153b2..f3bacf5 100644 (file)
@@ -131,7 +131,7 @@ void EditorState::PostLayoutData::encode(IPC::Encoder& encoder) const
     encoder << isStableStateUpdate;
     encoder << insideFixedPosition;
     encoder << hasPlainText;
-    encoder << elementIsTransparentOrFullyClipped;
+    encoder << editableRootIsTransparentOrFullyClipped;
     encoder << caretColor;
     encoder << atStartOfSentence;
 #endif
@@ -191,7 +191,7 @@ bool EditorState::PostLayoutData::decode(IPC::Decoder& decoder, PostLayoutData&
         return false;
     if (!decoder.decode(result.hasPlainText))
         return false;
-    if (!decoder.decode(result.elementIsTransparentOrFullyClipped))
+    if (!decoder.decode(result.editableRootIsTransparentOrFullyClipped))
         return false;
     if (!decoder.decode(result.caretColor))
         return false;
index 4e1d5a4..ef98d3b 100644 (file)
@@ -109,7 +109,7 @@ struct EditorState {
         bool isStableStateUpdate { false };
         bool insideFixedPosition { false };
         bool hasPlainText { false };
-        bool elementIsTransparentOrFullyClipped { false };
+        bool editableRootIsTransparentOrFullyClipped { false };
         WebCore::Color caretColor;
         bool atStartOfSentence { false };
 #endif
index 4c5b72c..bc2bc33 100644 (file)
@@ -91,7 +91,6 @@ void FocusedElementInformation::encode(IPC::Encoder& encoder) const
     encoder << title;
     encoder << acceptsAutofilledLoginCredentials;
     encoder << isAutofillableUsernameField;
-    encoder << elementIsTransparentOrFullyClipped;
     encoder << representingPageURL;
     encoder.encodeEnum(autofillFieldName);
     encoder << placeholder;
@@ -193,9 +192,6 @@ bool FocusedElementInformation::decode(IPC::Decoder& decoder, FocusedElementInfo
     if (!decoder.decode(result.isAutofillableUsernameField))
         return false;
 
-    if (!decoder.decode(result.elementIsTransparentOrFullyClipped))
-        return false;
-
     if (!decoder.decode(result.representingPageURL))
         return false;
 
index 835a0ca..188d5a7 100644 (file)
@@ -124,7 +124,6 @@ struct FocusedElementInformation {
     String title;
     bool acceptsAutofilledLoginCredentials { false };
     bool isAutofillableUsernameField { false };
-    bool elementIsTransparentOrFullyClipped { false };
     URL representingPageURL;
     WebCore::AutofillFieldName autofillFieldName { WebCore::AutofillFieldName::None };
     String placeholder;
index 44a96f7..49f1637 100644 (file)
@@ -156,7 +156,7 @@ typedef std::pair<WebKit::InteractionInformationRequest, InteractionInformationC
 namespace WebKit {
 
 enum SuppressSelectionAssistantReason : uint8_t {
-    FocusedElementIsTransparentOrFullyClipped = 1 << 0,
+    EditableRootIsTransparentOrFullyClipped = 1 << 0,
     FocusedElementIsTooSmall = 1 << 1,
     DropAnimationIsRunning = 1 << 2
 };
index f19ad18..d807a34 100644 (file)
@@ -1615,7 +1615,7 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
 
 - (void)_zoomToRevealFocusedElement
 {
-    if (_suppressSelectionAssistantReasons.contains(WebKit::FocusedElementIsTransparentOrFullyClipped) || _suppressSelectionAssistantReasons.contains(WebKit::FocusedElementIsTooSmall))
+    if (_suppressSelectionAssistantReasons.contains(WebKit::EditableRootIsTransparentOrFullyClipped) || _suppressSelectionAssistantReasons.contains(WebKit::FocusedElementIsTooSmall))
         return;
 
     SetForScope<BOOL> isZoomingToRevealFocusedElementForScope { _isZoomingToRevealFocusedElement, YES };
@@ -4843,8 +4843,6 @@ static WebCore::FloatRect rectToRevealWhenZoomingToFocusedElement(const WebKit::
     return selectionBoundingRect;
 }
 
-static const double minimumFocusedElementAreaForSuppressingSelectionAssistant = 4;
-
 - (void)_elementDidFocus:(const WebKit::FocusedElementInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode changingActivityState:(BOOL)changingActivityState userObject:(NSObject <NSSecureCoding> *)userObject
 {
     SetForScope<BOOL> isChangingFocusForScope { _isChangingFocus, hasFocusedElement(_focusedElementInformation) };
@@ -4867,17 +4865,6 @@ static const double minimumFocusedElementAreaForSuppressingSelectionAssistant =
     if ([inputDelegate respondsToSelector:@selector(_webView:decidePolicyForFocusedElement:)])
         startInputSessionPolicy = [inputDelegate _webView:_webView decidePolicyForFocusedElement:focusedElementInfo.get()];
 
-    if (information.elementIsTransparentOrFullyClipped)
-        [self _beginSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparentOrFullyClipped];
-    else
-        [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparentOrFullyClipped];
-
-    auto elementArea = information.elementRect.area<RecordOverflow>();
-    if (!elementArea.hasOverflowed() && elementArea < minimumFocusedElementAreaForSuppressingSelectionAssistant)
-        [self _beginSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTooSmall];
-    else
-        [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTooSmall];
-
     BOOL shouldShowInputView = [&] {
         switch (startInputSessionPolicy) {
         case _WKFocusStartsInputSessionPolicyAuto:
@@ -5051,11 +5038,8 @@ static const double minimumFocusedElementAreaForSuppressingSelectionAssistant =
     [_webView didEndFormControlInteraction];
     _page->setIsShowingInputViewForFocusedElement(false);
 
-    if (!_isChangingFocus) {
-        [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparentOrFullyClipped];
-        [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTooSmall];
+    if (!_isChangingFocus)
         _didAccessoryTabInitiateFocus = NO;
-    }
 }
 
 - (void)_didUpdateInputMode:(WebCore::InputMode)mode
@@ -5474,8 +5458,43 @@ static BOOL allPasteboardItemOriginsMatchOrigin(UIPasteboard *pasteboard, const
     [super _wheelChangedWithEvent:event];
 }
 
+- (void)_updateSelectionAssistantSuppressionState
+{
+    static const double minimumFocusedElementAreaForSuppressingSelectionAssistant = 4;
+
+    auto& editorState = _page->editorState();
+    if (editorState.isMissingPostLayoutData)
+        return;
+
+    BOOL editableRootIsTransparentOrFullyClipped = NO;
+    BOOL focusedElementIsTooSmall = NO;
+    if (!editorState.selectionIsNone) {
+        auto& postLayoutData = editorState.postLayoutData();
+        if (postLayoutData.editableRootIsTransparentOrFullyClipped)
+            editableRootIsTransparentOrFullyClipped = YES;
+
+        if (hasFocusedElement(_focusedElementInformation)) {
+            auto elementArea = postLayoutData.focusedElementRect.area<RecordOverflow>();
+            if (!elementArea.hasOverflowed() && elementArea < minimumFocusedElementAreaForSuppressingSelectionAssistant)
+                focusedElementIsTooSmall = YES;
+        }
+    }
+
+    if (editableRootIsTransparentOrFullyClipped)
+        [self _startSuppressingSelectionAssistantForReason:WebKit::EditableRootIsTransparentOrFullyClipped];
+    else
+        [self _stopSuppressingSelectionAssistantForReason:WebKit::EditableRootIsTransparentOrFullyClipped];
+
+    if (focusedElementIsTooSmall)
+        [self _startSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTooSmall];
+    else
+        [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTooSmall];
+}
+
 - (void)_selectionChanged
 {
+    [self _updateSelectionAssistantSuppressionState];
+
     _selectionNeedsUpdate = YES;
     // If we are changing the selection with a gesture there is no need
     // to wait to paint the selection.
@@ -5502,20 +5521,7 @@ static BOOL allPasteboardItemOriginsMatchOrigin(UIPasteboard *pasteboard, const
         return;
 
     auto& postLayoutData = state.postLayoutData();
-    if (!state.selectionIsNone && hasFocusedElement(_focusedElementInformation)) {
-        if (postLayoutData.elementIsTransparentOrFullyClipped)
-            [self _beginSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparentOrFullyClipped];
-        else
-            [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparentOrFullyClipped];
-
-        auto elementArea = postLayoutData.focusedElementRect.area<RecordOverflow>();
-        if (!elementArea.hasOverflowed() && elementArea < minimumFocusedElementAreaForSuppressingSelectionAssistant)
-            [self _beginSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTooSmall];
-        else
-            [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTooSmall];
-    }
-
-    WebKit::WKSelectionDrawingInfo selectionDrawingInfo(_page->editorState());
+    WebKit::WKSelectionDrawingInfo selectionDrawingInfo(state);
     if (force || selectionDrawingInfo != _lastSelectionDrawingInfo) {
         LOG_WITH_STREAM(Selection, stream << "_updateChangedSelection " << selectionDrawingInfo);
 
@@ -5552,7 +5558,7 @@ static BOOL allPasteboardItemOriginsMatchOrigin(UIPasteboard *pasteboard, const
     return !!_suppressSelectionAssistantReasons;
 }
 
-- (void)_beginSuppressingSelectionAssistantForReason:(WebKit::SuppressSelectionAssistantReason)reason
+- (void)_startSuppressingSelectionAssistantForReason:(WebKit::SuppressSelectionAssistantReason)reason
 {
     bool wasSuppressingSelectionAssistant = !!_suppressSelectionAssistantReasons;
     _suppressSelectionAssistantReasons.add(reason);
@@ -6551,7 +6557,7 @@ static NSArray<NSItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
         retainedSelf->_page->performDragOperation(capturedDragData, "data interaction pasteboard", WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionForUpload));
 
         retainedSelf->_visibleContentViewSnapshot = [retainedSelf snapshotViewAfterScreenUpdates:NO];
-        [retainedSelf _beginSuppressingSelectionAssistantForReason:WebKit::DropAnimationIsRunning];
+        [retainedSelf _startSuppressingSelectionAssistantForReason:WebKit::DropAnimationIsRunning];
         [UIView performWithoutAnimation:[retainedSelf] {
             [retainedSelf->_visibleContentViewSnapshot setFrame:[retainedSelf bounds]];
             [retainedSelf addSubview:retainedSelf->_visibleContentViewSnapshot.get()];
index 3ba7e81..56d962b 100644 (file)
@@ -1079,11 +1079,6 @@ void WebPageProxy::editorStateChanged(const EditorState& editorState)
     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
     
     m_editorState = editorState;
-
-    if (m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement && !m_editorState.isMissingPostLayoutData) {
-        pageClient().didReceiveEditorStateUpdateAfterFocus();
-        m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
-    }
     
     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
     if (couldChangeSecureInputState && !editorState.selectionIsNone)
@@ -1096,6 +1091,11 @@ void WebPageProxy::editorStateChanged(const EditorState& editorState)
     // even during composition to support phrase boundary gesture.
     pageClient().selectionDidChange();
     updateFontAttributesAfterEditorStateChange();
+
+    if (m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement && !m_editorState.isMissingPostLayoutData) {
+        pageClient().didReceiveEditorStateUpdateAfterFocus();
+        m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
+    }
 }
 
 void WebPageProxy::showValidationMessage(const IntRect& anchorClientRect, const String& message)
index b19df58..4070f88 100644 (file)
@@ -256,7 +256,11 @@ void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePost
             auto& renderer = *m_focusedElement->renderer();
             postLayoutData.focusedElementRect = view->contentsToRootView(renderer.absoluteBoundingBoxRect());
             postLayoutData.caretColor = renderer.style().caretColor();
-            postLayoutData.elementIsTransparentOrFullyClipped = enclosingLayerIsTransparentOrFullyClipped(renderer);
+        }
+        if (result.isContentEditable) {
+            auto container = makeRefPtr(selection.rootEditableElement());
+            if (container && container->renderer())
+                postLayoutData.editableRootIsTransparentOrFullyClipped = enclosingLayerIsTransparentOrFullyClipped(*container->renderer());
         }
         computeEditableRootHasContentAndPlainText(selection, postLayoutData);
     }
@@ -2535,7 +2539,6 @@ void WebPage::getFocusedElementInformation(FocusedElementInformation& informatio
         auto& elementFrame = m_page->focusController().focusedOrMainFrame();
         information.elementRect = elementRectInRootViewCoordinates(*m_focusedElement, elementFrame);
         information.nodeFontSize = renderer->style().fontDescription().computedSize();
-        information.elementIsTransparentOrFullyClipped = enclosingLayerIsTransparentOrFullyClipped(*renderer);
 
         bool inFixed = false;
         renderer->localToContainerPoint(FloatPoint(), nullptr, UseTransforms, &inFixed);