Diff
Modified: trunk/Source/WebCore/ChangeLog (256863 => 256864)
--- trunk/Source/WebCore/ChangeLog 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebCore/ChangeLog 2020-02-18 23:27:22 UTC (rev 256864)
@@ -1,3 +1,27 @@
+2020-02-18 Daniel Bates <[email protected]>
+
+ Ask the EditorClient whether to reveal the current selection after insertion
+ https://bugs.webkit.org/show_bug.cgi?id=207866
+ <rdar://problem/59553028>
+
+ Reviewed by Wenson Hsieh.
+
+ Adds a new EditorClient function shouldRevealCurrentSelectionAfterInsertion() that returns whether
+ the client wants the engine to reveal the current selection after insertion. The default implementation
+ always returns true. On iOS it returns the result of WebPage::shouldRevealCurrentSelectionAfterInsertion().
+
+ * editing/Editor.cpp:
+ (WebCore::Editor::insertTextWithoutSendingTextEvent): Call EditorClient::shouldRevealCurrentSelectionAfterInsertion().
+ If it returns false then skip the code to reveal the current selection: the UI process will call back
+ into WebPage::setShouldRevealCurrentSelectionAfterInsertion() when it is ready to reveal the current
+ selection. Otherwise, do what we do now.
+ * editing/Editor.h:
+ * page/EditorClient.h:
+ (WebCore::EditorClient::shouldRevealCurrentSelectionAfterInsertion const): Added.
+ * page/Page.cpp:
+ (WebCore::Page::revealCurrentSelection): Added.
+ * page/Page.h:
+
2020-02-18 Wenson Hsieh <[email protected]>
[macOS] Web process may crash under ServicesOverlayController::buildPotentialHighlightsIfNeeded
Modified: trunk/Source/WebCore/editing/Editor.cpp (256863 => 256864)
--- trunk/Source/WebCore/editing/Editor.cpp 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebCore/editing/Editor.cpp 2020-02-18 23:27:22 UTC (rev 256864)
@@ -1292,12 +1292,17 @@
TypingCommand::insertText(document, text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionFinal : TypingCommand::TextCompositionNone);
}
- // Reveal the current selection
- if (Frame* editedFrame = document->frame())
- if (Page* page = editedFrame->page()) {
- SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
- page->focusController().focusedOrMainFrame().selection().revealSelection(revealMode, ScrollAlignment::alignCenterIfNeeded);
+ // Reveal the current selection. Note that focus may have changed after insertion.
+ // FIXME: Selection is allowed even if setIgnoreSelectionChanges(true). Ideally setIgnoreSelectionChanges()
+ // should be moved from Editor to a page-level like object. If it must remain a frame-specific concept
+ // then this code should conditionalize revealing selection on whether the ignoreSelectionChanges() bit
+ // is set for the newly focused frame.
+ if (client() && client()->shouldRevealCurrentSelectionAfterInsertion()) {
+ if (auto* editedFrame = document->frame()) {
+ if (auto* page = editedFrame->page())
+ page->revealCurrentSelection();
}
+ }
}
}
Modified: trunk/Source/WebCore/editing/Editor.h (256863 => 256864)
--- trunk/Source/WebCore/editing/Editor.h 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebCore/editing/Editor.h 2020-02-18 23:27:22 UTC (rev 256864)
@@ -373,6 +373,10 @@
bool compositionUsesCustomHighlights() const { return !m_customCompositionHighlights.isEmpty(); }
const Vector<CompositionHighlight>& customCompositionHighlights() const { return m_customCompositionHighlights; }
+ // FIXME: This should be a page-level concept (i.e. on EditorClient) instead of on the Editor, which
+ // is a frame-specific concept, because executing an editing command can run _javascript_ that can do
+ // anything, including changing the focused frame. That is, it is not enough to set this setting on
+ // one Editor to disallow selection changes in all frames.
enum class RevealSelection { No, Yes };
WEBCORE_EXPORT void setIgnoreSelectionChanges(bool, RevealSelection shouldRevealExistingSelection = RevealSelection::Yes);
bool ignoreSelectionChanges() const { return m_ignoreSelectionChanges; }
Modified: trunk/Source/WebCore/page/EditorClient.h (256863 => 256864)
--- trunk/Source/WebCore/page/EditorClient.h 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebCore/page/EditorClient.h 2020-02-18 23:27:22 UTC (rev 256864)
@@ -70,6 +70,7 @@
virtual bool shouldInsertNode(Node*, Range*, EditorInsertAction) = 0;
virtual bool shouldInsertText(const String&, Range*, EditorInsertAction) = 0;
virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting) = 0;
+ virtual bool shouldRevealCurrentSelectionAfterInsertion() const { return true; };
virtual bool shouldApplyStyle(StyleProperties*, Range*) = 0;
virtual void didApplyStyle() = 0;
Modified: trunk/Source/WebCore/page/Page.cpp (256863 => 256864)
--- trunk/Source/WebCore/page/Page.cpp 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebCore/page/Page.cpp 2020-02-18 23:27:22 UTC (rev 256864)
@@ -3001,4 +3001,9 @@
});
}
+void Page::revealCurrentSelection()
+{
+ focusController().focusedOrMainFrame().selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterIfNeeded);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/page/Page.h (256863 => 256864)
--- trunk/Source/WebCore/page/Page.h 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebCore/page/Page.h 2020-02-18 23:27:22 UTC (rev 256864)
@@ -284,6 +284,8 @@
WEBCORE_EXPORT uint32_t replaceRangesWithText(const Vector<Ref<Range>>& rangesToReplace, const String& replacementText, bool selectionOnly);
WEBCORE_EXPORT uint32_t replaceSelectionWithText(const String& replacementText);
+ WEBCORE_EXPORT void revealCurrentSelection();
+
WEBCORE_EXPORT RefPtr<Range> rangeOfString(const String&, Range*, FindOptions);
WEBCORE_EXPORT unsigned countFindMatches(const String&, FindOptions, unsigned maxMatchCount);
Modified: trunk/Source/WebKit/ChangeLog (256863 => 256864)
--- trunk/Source/WebKit/ChangeLog 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/ChangeLog 2020-02-18 23:27:22 UTC (rev 256864)
@@ -1,3 +1,53 @@
+2020-02-18 Daniel Bates <[email protected]>
+
+ Ask the EditorClient whether to reveal the current selection after insertion
+ https://bugs.webkit.org/show_bug.cgi?id=207866
+ <rdar://problem/59553028>
+
+ Reviewed by Wenson Hsieh.
+
+ On iOS, adds a new WebPage message SetShouldRevealCurrentSelectionAfterInsertion that the
+ UI process can send to toggle whether the current selection should be revealed after a
+ text insertion.
+
+ * UIProcess/WebPageProxy.cpp:
+ * UIProcess/WebPageProxy.h:
+ (WebKit::WebPageProxy::setWaitingForPostLayoutEditorStateUpdateAfterFocusingElement):
+ * UIProcess/ios/WKContentViewInteraction.h:
+ Add some declarations for some functions that I need to make the corresponding Apple Internal fix in <rdar://problem/57608794>.
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
+ If we are not going to zoom to reveal the focused element immediately then call WebPage::setWaitingForPostLayoutEditorStateUpdateAfterFocusingElement(true)
+ so that we schedule a -_didUpdateEditorState callback on the next editor state update so that we can call
+ -_zoomToRevealFocusedElement.
+ (-[WKContentView _elementDidBlur]): Call WebPage::setWaitingForPostLayoutEditorStateUpdateAfterFocusingElement(false)
+ to unschedule an existing -_didUpdateEditorState callback.
+
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::elementDidFocus):
+ (WebKit::WebPageProxy::elementDidBlur):
+ Move the setting of m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement from here to
+ -_elementDidFocus and _elementDidBlur when an element is focused or blurred, respectively.
+
+ (WebKit::WebPageProxy::setShouldRevealCurrentSelectionAfterInsertion): Added.
+ * WebProcess/WebCoreSupport/WebEditorClient.h:
+ * WebProcess/WebCoreSupport/ios/WebEditorClientIOS.mm:
+ (WebKit::WebEditorClient::shouldRevealCurrentSelectionAfterInsertion const): Added.
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::editorState const): Mark the editor state as ignoring selection changes if EditorClient::shouldRevealCurrentSelectionAfterInsertion()
+ returns false.
+ (WebKit::WebPage::didCommitLoad): Reset state.
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::shouldRevealCurrentSelectionAfterInsertion const):
+ * WebProcess/WebPage/WebPage.messages.in:
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::updateSelectionAppearance): Do not send an update if EditorClient::shouldRevealCurrentSelectionAfterInsertion()
+ returns false.
+ (WebKit::WebPage::setShouldRevealCurrentSelectionAfterInsertion): Added. Update state, if needed. If passed
+ false, then reveal the current selection just as we would have done after an insertion and schedule a full
+ editor state update (i.e. an update after layout is performed). The latter will trigger the UI process on iOS
+ to zoom to reveal the newly focused element.
+
2020-02-18 Wenson Hsieh <[email protected]>
[macOS] Web process may crash under ServicesOverlayController::buildPotentialHighlightsIfNeeded
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (256863 => 256864)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2020-02-18 23:27:22 UTC (rev 256864)
@@ -700,6 +700,8 @@
#endif
#if PLATFORM(IOS_FAMILY)
+ void setShouldRevealCurrentSelectionAfterInsertion(bool);
+
double displayedContentScale() const { return m_lastVisibleContentRectUpdate.scale(); }
const WebCore::FloatRect& exposedContentRect() const { return m_lastVisibleContentRectUpdate.exposedContentRect(); }
const WebCore::FloatRect& unobscuredContentRect() const { return m_lastVisibleContentRectUpdate.unobscuredContentRect(); }
@@ -1462,7 +1464,10 @@
#if PLATFORM(IOS_FAMILY)
void setIsKeyboardAnimatingIn(bool isKeyboardAnimatingIn) { m_isKeyboardAnimatingIn = isKeyboardAnimatingIn; }
+
+ void setWaitingForPostLayoutEditorStateUpdateAfterFocusingElement(bool waitingForPostLayoutEditorStateUpdateAfterFocusingElement) { m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = waitingForPostLayoutEditorStateUpdateAfterFocusingElement; }
bool waitingForPostLayoutEditorStateUpdateAfterFocusingElement() const { return m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement; }
+
const Function<bool()>& deviceOrientationUserPermissionHandlerForTesting() const { return m_deviceOrientationUserPermissionHandlerForTesting; };
void setDeviceOrientationUserPermissionHandlerForTesting(Function<bool()>&& handler) { m_deviceOrientationUserPermissionHandlerForTesting = WTFMove(handler); }
#endif
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (256863 => 256864)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2020-02-18 23:27:22 UTC (rev 256864)
@@ -449,6 +449,11 @@
- (void)_selectPositionAtPoint:(CGPoint)point stayingWithinFocusedElement:(BOOL)stayingWithinFocusedElement completionHandler:(void (^)(void))completionHandler;
+- (void)_startSuppressingSelectionAssistantForReason:(WebKit::SuppressSelectionAssistantReason)reason;
+- (void)_stopSuppressingSelectionAssistantForReason:(WebKit::SuppressSelectionAssistantReason)reason;
+
+- (void)_zoomToRevealFocusedElement;
+
#if ENABLE(POINTER_EVENTS)
- (void)cancelPointersForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
- (WTF::Optional<unsigned>)activeTouchIdentifierForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (256863 => 256864)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2020-02-18 23:27:22 UTC (rev 256864)
@@ -5772,7 +5772,9 @@
// selection rect before we can zoom and reveal the selection. Non-selectable elements (e.g. <select>) can be zoomed
// immediately because they have no selection to reveal.
BOOL needsEditorStateUpdate = mayContainSelectableText(_focusedElementInformation.elementType);
- if (!needsEditorStateUpdate)
+ if (needsEditorStateUpdate)
+ _page->setWaitingForPostLayoutEditorStateUpdateAfterFocusingElement(true);
+ else
[self _zoomToRevealFocusedElement];
[self _updateAccessory];
@@ -5845,6 +5847,8 @@
_page->setIsShowingInputViewForFocusedElement(false);
}
+ _page->setWaitingForPostLayoutEditorStateUpdateAfterFocusingElement(false);
+
if (!_isChangingFocus)
_didAccessoryTabInitiateFocus = NO;
}
Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (256863 => 256864)
--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2020-02-18 23:27:22 UTC (rev 256864)
@@ -958,7 +958,6 @@
void WebPageProxy::elementDidFocus(const FocusedElementInformation& information, bool userIsInteracting, bool blurPreviousNode, OptionSet<WebCore::ActivityState::Flag> activityStateChanges, const UserData& userData)
{
m_pendingInputModeChange = WTF::nullopt;
- m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = true;
API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
if (m_editorState.isMissingPostLayoutData) {
@@ -973,7 +972,6 @@
void WebPageProxy::elementDidBlur()
{
m_pendingInputModeChange = WTF::nullopt;
- m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
m_deferredElementDidFocusArguments = nullptr;
pageClient().elementDidBlur();
}
@@ -1514,6 +1512,14 @@
return pageClient().isApplicationVisible();
}
+
+void WebPageProxy::setShouldRevealCurrentSelectionAfterInsertion(bool shouldRevealCurrentSelectionAfterInsertion)
+{
+ if (hasRunningProcess())
+ send(Messages::WebPage::SetShouldRevealCurrentSelectionAfterInsertion(shouldRevealCurrentSelectionAfterInsertion));
+}
+
+
#if PLATFORM(IOS)
void WebPageProxy::grantAccessToAssetServices()
{
Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h (256863 => 256864)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h 2020-02-18 23:27:22 UTC (rev 256864)
@@ -187,6 +187,7 @@
bool performsTwoStepPaste(WebCore::DocumentFragment*) final;
void updateStringForFind(const String&) final;
bool shouldAllowSingleClickToChangeSelection(WebCore::Node&, const WebCore::VisibleSelection&) const final;
+ bool shouldRevealCurrentSelectionAfterInsertion() const final;
#endif
bool performTwoStepDrop(WebCore::DocumentFragment&, WebCore::Range&, bool isMove) final;
Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/ios/WebEditorClientIOS.mm (256863 => 256864)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/ios/WebEditorClientIOS.mm 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/ios/WebEditorClientIOS.mm 2020-02-18 23:27:22 UTC (rev 256864)
@@ -114,6 +114,11 @@
return !editableRoot || editableRoot != targetNode.rootEditableElement() || !m_page->isShowingInputViewForFocusedElement();
}
+bool WebEditorClient::shouldRevealCurrentSelectionAfterInsertion() const
+{
+ return m_page->shouldRevealCurrentSelectionAfterInsertion();
+}
+
} // namespace WebKit
#endif // PLATFORM(IOS_FAMILY)
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (256863 => 256864)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2020-02-18 23:27:22 UTC (rev 256864)
@@ -1070,7 +1070,7 @@
result.isContentRichlyEditable = selection.isContentRichlyEditable();
result.isInPasswordField = selection.isInPasswordField();
result.hasComposition = editor.hasComposition();
- result.shouldIgnoreSelectionChanges = editor.ignoreSelectionChanges();
+ result.shouldIgnoreSelectionChanges = editor.ignoreSelectionChanges() || !editor.client()->shouldRevealCurrentSelectionAfterInsertion();
if (auto* document = frame.document())
result.originIdentifierForPasteboard = document->originIdentifierForPasteboard();
@@ -5865,6 +5865,7 @@
m_scaleWasSetByUIProcess = false;
m_userHasChangedPageScaleFactor = false;
m_estimatedLatency = Seconds(1.0 / 60);
+ m_shouldRevealCurrentSelectionAfterInsertion = true;
#if ENABLE(IOS_TOUCH_EVENTS)
WebProcess::singleton().eventDispatcher().clearQueuedTouchEventsForPage(*this);
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (256863 => 256864)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2020-02-18 23:27:22 UTC (rev 256864)
@@ -636,6 +636,9 @@
void setCanShowPlaceholder(const WebCore::ElementContext&, bool);
#if PLATFORM(IOS_FAMILY)
+ bool shouldRevealCurrentSelectionAfterInsertion() const { return m_shouldRevealCurrentSelectionAfterInsertion; }
+ void setShouldRevealCurrentSelectionAfterInsertion(bool);
+
WebCore::FloatSize screenSize() const;
WebCore::FloatSize availableScreenSize() const;
WebCore::FloatSize overrideScreenSize() const;
@@ -1941,6 +1944,7 @@
bool m_userHasChangedPageScaleFactor { false };
bool m_hasStablePageScaleFactor { true };
bool m_isInStableState { true };
+ bool m_shouldRevealCurrentSelectionAfterInsertion { true };
MonotonicTime m_oldestNonStableUpdateVisibleContentRectsTimestamp;
Seconds m_estimatedLatency { 0 };
WebCore::FloatSize m_screenSize;
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (256863 => 256864)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2020-02-18 23:27:22 UTC (rev 256864)
@@ -118,6 +118,7 @@
UpdateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta) -> () Async
RequestDocumentEditingContext(struct WebKit::DocumentEditingContextRequest request) -> (struct WebKit::DocumentEditingContext response) Async
GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType command)
+ SetShouldRevealCurrentSelectionAfterInsertion(bool shouldRevealCurrentSelectionAfterInsertion)
#endif
SetControlledByAutomation(bool controlled)
Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (256863 => 256864)
--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2020-02-18 23:18:23 UTC (rev 256863)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2020-02-18 23:27:22 UTC (rev 256864)
@@ -72,6 +72,7 @@
#import <WebCore/DragController.h>
#import <WebCore/Editing.h>
#import <WebCore/Editor.h>
+#import <WebCore/EditorClient.h>
#import <WebCore/Element.h>
#import <WebCore/ElementAncestorIterator.h>
#import <WebCore/EventHandler.h>
@@ -590,8 +591,9 @@
void WebPage::updateSelectionAppearance()
{
- Frame& frame = m_page->focusController().focusedOrMainFrame();
- if (!frame.editor().ignoreSelectionChanges() && (frame.editor().hasComposition() || !frame.selection().selection().isNone()))
+ auto& frame = m_page->focusController().focusedOrMainFrame();
+ auto& editor = frame.editor();
+ if (!editor.ignoreSelectionChanges() && editor.client()->shouldRevealCurrentSelectionAfterInsertion() && (editor.hasComposition() || !frame.selection().selection().isNone()))
didChangeSelection();
}
@@ -4206,6 +4208,17 @@
completionHandler(context);
}
+void WebPage::setShouldRevealCurrentSelectionAfterInsertion(bool shouldRevealCurrentSelectionAfterInsertion)
+{
+ if (m_shouldRevealCurrentSelectionAfterInsertion == shouldRevealCurrentSelectionAfterInsertion)
+ return;
+ m_shouldRevealCurrentSelectionAfterInsertion = shouldRevealCurrentSelectionAfterInsertion;
+ if (!shouldRevealCurrentSelectionAfterInsertion)
+ return;
+ m_page->revealCurrentSelection();
+ scheduleFullEditorStateUpdate();
+}
+
#if USE(QUICK_LOOK)
void WebPage::didStartLoadForQuickLookDocumentInMainFrame(const String& fileName, const String& uti)