diff options
author | Peter Varga <pvarga@inf.u-szeged.hu> | 2017-04-27 11:23:55 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-11-09 11:47:12 +0100 |
commit | 88b1c5593421af8a966171b5e45bf31d349ad9a2 (patch) | |
tree | 2ed32433dba912cecf68ce68a04aea09ad2452ed | |
parent | 7398e571bd85e39341b1007ae9efe5cf5cd640ce (diff) | |
download | qtwebengine-chromium-88b1c5593421af8a966171b5e45bf31d349ad9a2.tar.gz |
Update TextSelection for non-user initiated events
This makes Chromium Content API to be able to notify about text
selection changes triggered by non-user events (eg. JavaScript, IME,
autofill).
Based on:
https://codereview.chromium.org/2903833002
Corresponding Chromium bug report:
https://bugs.chromium.org/p/chromium/issues/detail?id=671986
Change-Id: I86a7f203d789853199469b301facd06fe5ba54bd
Task-number: QTBUG-53134
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
29 files changed, 144 insertions, 66 deletions
diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.cc b/chromium/content/browser/renderer_host/render_frame_host_impl.cc index d87d5d128c1..7ccfd585c69 100644 --- a/chromium/content/browser/renderer_host/render_frame_host_impl.cc +++ b/chromium/content/browser/renderer_host/render_frame_host_impl.cc @@ -6688,9 +6688,10 @@ void RenderFrameHostImpl::FocusedElementChanged( void RenderFrameHostImpl::TextSelectionChanged(const std::u16string& text, uint32_t offset, - const gfx::Range& range) { + const gfx::Range& range, + bool user_initiated) { has_selection_ = !text.empty(); - GetRenderWidgetHost()->SelectionChanged(text, offset, range); + GetRenderWidgetHost()->SelectionChanged(text, offset, range, user_initiated); } void RenderFrameHostImpl::DidReceiveUserActivation() { diff --git a/chromium/content/browser/renderer_host/render_frame_host_impl.h b/chromium/content/browser/renderer_host/render_frame_host_impl.h index 6aff64db8cc..744233390e3 100644 --- a/chromium/content/browser/renderer_host/render_frame_host_impl.h +++ b/chromium/content/browser/renderer_host/render_frame_host_impl.h @@ -2127,7 +2127,8 @@ class CONTENT_EXPORT RenderFrameHostImpl blink::mojom::FocusType focus_type) override; void TextSelectionChanged(const std::u16string& text, uint32_t offset, - const gfx::Range& range) override; + const gfx::Range& range, + bool user_initiated) override; void ShowPopupMenu( mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client, const gfx::Rect& bounds, diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.cc b/chromium/content/browser/renderer_host/render_widget_host_impl.cc index 311dd906e49..794413a9bb1 100644 --- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc +++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc @@ -2182,9 +2182,12 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser( void RenderWidgetHostImpl::SelectionChanged(const std::u16string& text, uint32_t offset, - const gfx::Range& range) { - if (view_) - view_->SelectionChanged(text, static_cast<size_t>(offset), range); + const gfx::Range& range, + bool user_initiated) { + if (view_) { + view_->SelectionChanged(text, static_cast<size_t>(offset), range, + user_initiated); + } } void RenderWidgetHostImpl::SelectionBoundsChanged( diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.h b/chromium/content/browser/renderer_host/render_widget_host_impl.h index 527463920c3..dcabd2aab5d 100644 --- a/chromium/content/browser/renderer_host/render_widget_host_impl.h +++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h @@ -718,7 +718,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl // Called from a RenderFrameHost when the text selection has changed. void SelectionChanged(const std::u16string& text, uint32_t offset, - const gfx::Range& range); + const gfx::Range& range, + bool user_initiated); size_t in_flight_event_count() const { return in_flight_event_count_; } diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc index 9d1301a55ac..d34f1677ef2 100644 --- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -2741,7 +2741,8 @@ void RenderWidgetHostViewAura::OnTextSelectionChanged( ui::ClipboardBuffer::kSelection)) { const TextInputManager::TextSelection* selection = GetTextInputManager()->GetTextSelection(focused_view); - if (selection->selected_text().length()) { + if (selection->selected_text().length() + && selection->user_initiated()) { // Set the ClipboardBuffer::kSelection to the ui::Clipboard. ui::ScopedClipboardWriter clipboard_writer( ui::ClipboardBuffer::kSelection); diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc index 999eeb6fc81..903327417d3 100644 --- a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc @@ -175,9 +175,11 @@ RenderWidgetHostViewBase* RenderWidgetHostViewBase::GetRootView() { void RenderWidgetHostViewBase::SelectionChanged(const std::u16string& text, size_t offset, - const gfx::Range& range) { + const gfx::Range& range, + bool user_initiated) { if (GetTextInputManager()) - GetTextInputManager()->SelectionChanged(this, text, offset, range); + GetTextInputManager()->SelectionChanged(this, text, offset, range, + user_initiated); } gfx::Size RenderWidgetHostViewBase::GetRequestedRendererSize() { diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.h b/chromium/content/browser/renderer_host/render_widget_host_view_base.h index f3a4f3961b5..b82b4913d48 100644 --- a/chromium/content/browser/renderer_host/render_widget_host_view_base.h +++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.h @@ -199,7 +199,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { // Notifies the View that the renderer text selection has changed. virtual void SelectionChanged(const std::u16string& text, size_t offset, - const gfx::Range& range); + const gfx::Range& range, + bool user_initiated); // The requested size of the renderer. May differ from GetViewBounds().size() // when the view requires additional throttling. diff --git a/chromium/content/browser/renderer_host/text_input_manager.cc b/chromium/content/browser/renderer_host/text_input_manager.cc index a1c6d01a2bb..b2979f3638f 100644 --- a/chromium/content/browser/renderer_host/text_input_manager.cc +++ b/chromium/content/browser/renderer_host/text_input_manager.cc @@ -367,9 +367,10 @@ void TextInputManager::ImeCompositionRangeChanged( void TextInputManager::SelectionChanged(RenderWidgetHostViewBase* view, const std::u16string& text, size_t offset, - const gfx::Range& range) { + const gfx::Range& range, + bool user_initiated) { DCHECK(IsRegistered(view)); - text_selection_map_[view].SetSelection(text, offset, range); + text_selection_map_[view].SetSelection(text, offset, range, user_initiated); for (auto& observer : observer_list_) observer.OnTextSelectionChanged(this, view); } @@ -461,11 +462,13 @@ TextInputManager::TextSelection::~TextSelection() = default; void TextInputManager::TextSelection::SetSelection(const std::u16string& text, size_t offset, - const gfx::Range& range) { + const gfx::Range& range, + bool user_initiated) { text_ = text; range_.set_start(range.start()); range_.set_end(range.end()); offset_ = offset; + user_initiated_ = user_initiated; // Update the selected text. selected_text_.clear(); diff --git a/chromium/content/browser/renderer_host/text_input_manager.h b/chromium/content/browser/renderer_host/text_input_manager.h index 4de99f947c5..28eebb28893 100644 --- a/chromium/content/browser/renderer_host/text_input_manager.h +++ b/chromium/content/browser/renderer_host/text_input_manager.h @@ -111,12 +111,14 @@ class CONTENT_EXPORT TextInputManager { void SetSelection(const std::u16string& text, size_t offset, - const gfx::Range& range); + const gfx::Range& range, + bool user_initiated); const std::u16string& selected_text() const { return selected_text_; } size_t offset() const { return offset_; } const gfx::Range& range() const { return range_; } const std::u16string& text() const { return text_; } + bool user_initiated() const { return user_initiated_; } private: // The offset of the text stored in |text| relative to the start of the web @@ -135,6 +137,10 @@ class CONTENT_EXPORT TextInputManager { // Part of the text on the page which includes the highlighted text plus // possibly several characters before and after it. std::u16string text_; + + // True if text selection is triggered by user input. + bool user_initiated_ = false; + }; explicit TextInputManager(bool should_do_learning); @@ -228,7 +234,8 @@ class CONTENT_EXPORT TextInputManager { void SelectionChanged(RenderWidgetHostViewBase* view, const std::u16string& text, size_t offset, - const gfx::Range& range); + const gfx::Range& range, + bool user_initiated); // Registers the given |view| for tracking its TextInputState. This is called // by any view which has updates in its TextInputState (whether tab's RWHV or diff --git a/chromium/content/public/renderer/render_frame.h b/chromium/content/public/renderer/render_frame.h index f49ce6c83a3..4e32e4c3c31 100644 --- a/chromium/content/public/renderer/render_frame.h +++ b/chromium/content/public/renderer/render_frame.h @@ -205,7 +205,8 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener, // Notifies the browser of text selection changes made. virtual void SetSelectedText(const std::u16string& selection_text, size_t offset, - const gfx::Range& range) = 0; + const gfx::Range& range, + bool user_initiated) = 0; // Adds |message| to the DevTools console. virtual void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level, diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc index ba5ad1fd50f..682365a583d 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc @@ -1248,7 +1248,7 @@ void PepperPluginInstanceImpl::SetSelectedText( selected_text_ = selected_text; gfx::Range range(0, selected_text.length()); - render_frame_->SetSelectedText(selected_text, 0, range); + render_frame_->SetSelectedText(selected_text, 0, range, true); } void PepperPluginInstanceImpl::SetLinkUnderCursor(const std::string& url) { diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc index 5fb905bbd1a..858b437dbe9 100644 --- a/chromium/content/renderer/render_frame_impl.cc +++ b/chromium/content/renderer/render_frame_impl.cc @@ -1998,7 +1998,8 @@ void RenderFrameImpl::PepperSelectionChanged( // We have no reason to believe the locally cached last synced selection is // invalid so we do not need to force the update if it matches our last synced // value. - SyncSelectionIfRequired(blink::SyncCondition::kNotForced, false); + SyncSelectionIfRequired(blink::SyncCondition::kNotForced, false /* is_empty_selection */, + true /* user_initiated */); } #endif // BUILDFLAG(ENABLE_PPAPI) @@ -2381,9 +2382,11 @@ RenderFrameImpl::GetRemoteAssociatedInterfaces() { void RenderFrameImpl::SetSelectedText(const std::u16string& selection_text, size_t offset, - const gfx::Range& range) { + const gfx::Range& range, + bool user_initiated) { GetWebFrame()->TextSelectionChanged(WebString::FromUTF16(selection_text), - static_cast<uint32_t>(offset), range); + static_cast<uint32_t>(offset), range, + user_initiated); } void RenderFrameImpl::AddMessageToConsole( @@ -4084,10 +4087,20 @@ void RenderFrameImpl::AbortClientNavigation() { void RenderFrameImpl::DidChangeSelection(bool is_empty_selection, blink::SyncCondition force_sync) { - if (!GetLocalRootWebFrameWidget()->HandlingInputEvent() && - !GetLocalRootWebFrameWidget()->HandlingSelectRange()) - return; + bool user_initiated = + GetLocalRootWebFrameWidget()->HandlingInputEvent() || + GetLocalRootWebFrameWidget()->HandlingSelectRange(); + + if (!user_initiated) { + // Do not update text input state unnecessarily when text selection remains + // empty. + if (is_empty_selection && selection_text_.empty()) + return; + // Ignore selection change of text replacement triggered by IME composition. + if (GetLocalRootWebFrameWidget()->ImeCompositionReplacement()) + return; + } // UpdateTextInputState should be called before SyncSelectionIfRequired. // UpdateTextInputState may send TextInputStateChanged to notify the focus @@ -4095,7 +4108,7 @@ void RenderFrameImpl::DidChangeSelection(bool is_empty_selection, // to notify the selection was changed. Focus change should be notified // before selection change. GetLocalRootWebFrameWidget()->UpdateTextInputState(); - SyncSelectionIfRequired(force_sync, is_empty_selection); + SyncSelectionIfRequired(force_sync, is_empty_selection, user_initiated); } void RenderFrameImpl::OnMainFrameIntersectionChanged( @@ -5490,10 +5503,12 @@ void RenderFrameImpl::UpdateEncoding(WebFrame* frame, } } -void RenderFrameImpl::SyncSelectionIfRequired(blink::SyncCondition force_sync, bool is_empty_selection) { +void RenderFrameImpl::SyncSelectionIfRequired(blink::SyncCondition force_sync, + bool is_empty_selection, + bool user_initiated) { std::u16string text; size_t offset = 0; - gfx::Range range; + gfx::Range range = gfx::Range::InvalidRange(); #if BUILDFLAG(ENABLE_PPAPI) if (focused_pepper_plugin_) { focused_pepper_plugin_->GetSurroundingText(&text, &range); @@ -5504,31 +5519,37 @@ void RenderFrameImpl::SyncSelectionIfRequired(blink::SyncCondition force_sync, b if (!is_empty_selection) { WebRange selection = frame_->GetInputMethodController()->GetSelectionOffsets(); - if (selection.IsNull()) - return; - - range = gfx::Range(selection.StartOffset(), selection.EndOffset()); - if (frame_->GetInputMethodController()->TextInputType() != - blink::kWebTextInputTypeNone) { - // If current focused element is editable, we will send 100 more chars - // before and after selection. It is for input method surrounding text - // feature. - if (selection.StartOffset() > kExtraCharsBeforeAndAfterSelection) - offset = selection.StartOffset() - kExtraCharsBeforeAndAfterSelection; - else - offset = 0; - size_t length = - selection.EndOffset() - offset + kExtraCharsBeforeAndAfterSelection; - text = frame_->RangeAsText(WebRange(offset, length)).Utf16(); - } else { - offset = selection.StartOffset(); - text = frame_->SelectionAsText().Utf16(); - // http://crbug.com/101435 - // In some case, frame->selectionAsText() returned text's length is not - // equal to the length returned from frame_->GetSelectionOffsets(). So we - // have to set the range according to text.length(). - range.set_end(range.start() + text.length()); + // When clearing text selection from JavaScript the selection range + // might be null but the selected text still have to be updated. + // Do not cancel sync selection if the clear was not user initiated. + if (!selection.IsNull()) { + range = gfx::Range(selection.StartOffset(), selection.EndOffset()); + + if (frame_->GetInputMethodController()->TextInputType() != + blink::kWebTextInputTypeNone) { + // If current focused element is editable, we will send 100 more chars + // before and after selection. It is for input method surrounding text + // feature. + if (selection.StartOffset() > kExtraCharsBeforeAndAfterSelection) + offset = selection.StartOffset() - kExtraCharsBeforeAndAfterSelection; + else + offset = 0; + size_t length = + selection.EndOffset() - offset + kExtraCharsBeforeAndAfterSelection; + text = frame_->RangeAsText(WebRange(offset, length)).Utf16(); + } else { + offset = selection.StartOffset(); + text = frame_->SelectionAsText().Utf16(); + // http://crbug.com/101435 + // In some case, frame->selectionAsText() returned text's length is not + // equal to the length returned from + // GetWebWidget()->caretOrSelectionRange(). + // So we have to set the range according to text.length(). + range.set_end(range.start() + text.length()); + } + } else if (user_initiated) { + return; } } @@ -5544,7 +5565,7 @@ void RenderFrameImpl::SyncSelectionIfRequired(blink::SyncCondition force_sync, b selection_text_ = text; selection_text_offset_ = offset; selection_range_ = range; - SetSelectedText(text, offset, range); + SetSelectedText(text, offset, range, user_initiated); } GetLocalRootWebFrameWidget()->UpdateSelectionBounds(); } diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h index a6ed6eda5c7..a910d12606c 100644 --- a/chromium/content/renderer/render_frame_impl.h +++ b/chromium/content/renderer/render_frame_impl.h @@ -363,7 +363,8 @@ class CONTENT_EXPORT RenderFrameImpl blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override; void SetSelectedText(const std::u16string& selection_text, size_t offset, - const gfx::Range& range) override; + const gfx::Range& range, + bool user_initiated) override; void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level, const std::string& message) override; bool IsPasting() override; @@ -628,7 +629,7 @@ class CONTENT_EXPORT RenderFrameImpl // it has changed or if the forced flag is passed. The forced flag is used // when the browser selection may be out of sync with the renderer due to // incorrect prediction. - void SyncSelectionIfRequired(blink::SyncCondition force_sync, bool is_empty_selection) override; + void SyncSelectionIfRequired(blink::SyncCondition force_sync, bool is_empty_selection, bool user_initiated) override; void CreateAudioInputStream( blink::CrossVariantMojoRemote< blink::mojom::RendererAudioInputStreamFactoryClientInterfaceBase> diff --git a/chromium/third_party/blink/public/mojom/frame/frame.mojom b/chromium/third_party/blink/public/mojom/frame/frame.mojom index cc48c697547..95423a623e9 100644 --- a/chromium/third_party/blink/public/mojom/frame/frame.mojom +++ b/chromium/third_party/blink/public/mojom/frame/frame.mojom @@ -410,7 +410,8 @@ interface LocalFrameHost { // std::u16string text in the document. TextSelectionChanged(mojo_base.mojom.BigString16 text, uint32 offset, - gfx.mojom.Range range); + gfx.mojom.Range range, + bool user_initiated); // Show a popup menu using native controls on Mac or Android. // The popup menu is hidden when the mojo channel is closed. diff --git a/chromium/third_party/blink/public/web/web_local_frame.h b/chromium/third_party/blink/public/web/web_local_frame.h index a7302b18854..82a1f9402a6 100644 --- a/chromium/third_party/blink/public/web/web_local_frame.h +++ b/chromium/third_party/blink/public/web/web_local_frame.h @@ -495,7 +495,8 @@ class WebLocalFrame : public WebFrame { virtual void TextSelectionChanged(const WebString& selection_text, uint32_t offset, - const gfx::Range& range) = 0; + const gfx::Range& range, + bool user_initiated) = 0; // DEPRECATED: Use moveRangeSelection. virtual void SelectRange(const gfx::Point& base, diff --git a/chromium/third_party/blink/public/web/web_local_frame_client.h b/chromium/third_party/blink/public/web/web_local_frame_client.h index f2f36a35ec1..528d1d3fc8e 100644 --- a/chromium/third_party/blink/public/web/web_local_frame_client.h +++ b/chromium/third_party/blink/public/web/web_local_frame_client.h @@ -711,7 +711,7 @@ class BLINK_EXPORT WebLocalFrameClient { // TextInputState may have changed call DidChangeSelection instead. // If the browser selection may not match the last synced // value, SyncCondition::kForced can be passed to force a sync. - virtual void SyncSelectionIfRequired(SyncCondition force_sync, bool is_empty_selection) {} + virtual void SyncSelectionIfRequired(SyncCondition force_sync, bool is_empty_selection, bool user_initiated) {} // TODO(https://crbug.com/787252): Remove the methods below and use the // Supplement mechanism. diff --git a/chromium/third_party/blink/public/web/web_widget.h b/chromium/third_party/blink/public/web/web_widget.h index 34730105cb8..98bbb198083 100644 --- a/chromium/third_party/blink/public/web/web_widget.h +++ b/chromium/third_party/blink/public/web/web_widget.h @@ -139,6 +139,8 @@ class WebWidget { // Set state that the widget is in the process of handling input events. virtual void SetHandlingInputEvent(bool handling) = 0; + virtual bool ImeCompositionReplacement() = 0; + // Process the input event, blocking until complete. virtual void ProcessInputEventSynchronouslyForTesting( const WebCoalescedInputEvent&) = 0; diff --git a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc index 24cbad7f3d2..52e029d20d4 100644 --- a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc +++ b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc @@ -472,6 +472,10 @@ void WebPagePopupImpl::SetHandlingInputEvent(bool handling) { widget_base_->input_handler().set_handling_input_event(handling); } +bool WebPagePopupImpl::ImeCompositionReplacement() { + return widget_base_->input_handler().ime_composition_replacement(); +} + void WebPagePopupImpl::ProcessInputEventSynchronouslyForTesting( const WebCoalescedInputEvent& event) { widget_base_->input_handler().HandleInputEvent(event, nullptr, diff --git a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h index 6a85448100e..3c3debd572d 100644 --- a/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h +++ b/chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h @@ -179,6 +179,7 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup, void SetCursor(const ui::Cursor& cursor) override; bool HandlingInputEvent() override; void SetHandlingInputEvent(bool handling) override; + bool ImeCompositionReplacement() override; void ProcessInputEventSynchronouslyForTesting( const WebCoalescedInputEvent&) override; void UpdateTextInputState() override; diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame.cc b/chromium/third_party/blink/renderer/core/frame/local_frame.cc index 90cf3971e57..bbdb4c393ef 100644 --- a/chromium/third_party/blink/renderer/core/frame/local_frame.cc +++ b/chromium/third_party/blink/renderer/core/frame/local_frame.cc @@ -1435,8 +1435,9 @@ String LocalFrame::SelectedTextForClipboard() const { void LocalFrame::TextSelectionChanged(const WTF::String& selection_text, uint32_t offset, - const gfx::Range& range) const { - GetLocalFrameHostRemote().TextSelectionChanged(selection_text, offset, range); + const gfx::Range& range, + bool user_initiated) const { + GetLocalFrameHostRemote().TextSelectionChanged(selection_text, offset, range, user_initiated); } PositionWithAffinity LocalFrame::PositionForPoint( diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame.h b/chromium/third_party/blink/renderer/core/frame/local_frame.h index d9d877912bd..615ddfd8593 100644 --- a/chromium/third_party/blink/renderer/core/frame/local_frame.h +++ b/chromium/third_party/blink/renderer/core/frame/local_frame.h @@ -395,7 +395,8 @@ class CORE_EXPORT LocalFrame final String SelectedTextForClipboard() const; void TextSelectionChanged(const WTF::String& selection_text, uint32_t offset, - const gfx::Range& range) const; + const gfx::Range& range, + bool user_initiated) const; PositionWithAffinityTemplate<EditingAlgorithm<NodeTraversal>> PositionForPoint(const PhysicalOffset& frame_point); diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 32340926713..e945dc8bc12 100644 --- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc @@ -2491,6 +2491,11 @@ void WebFrameWidgetImpl::SetHandlingInputEvent(bool handling) { widget_base_->input_handler().set_handling_input_event(handling); } +bool WebFrameWidgetImpl::ImeCompositionReplacement() +{ + return widget_base_->input_handler().ime_composition_replacement(); +} + void WebFrameWidgetImpl::ProcessInputEventSynchronouslyForTesting( const WebCoalescedInputEvent& event, WidgetBaseInputHandler::HandledEventCallback callback) { @@ -3769,7 +3774,8 @@ void WebFrameWidgetImpl::Replace(const String& word) { // If the resulting selection is not actually a change in selection, we do not // need to explicitly notify about the selection change. focused_frame->Client()->SyncSelectionIfRequired( - blink::SyncCondition::kNotForced); + blink::SyncCondition::kNotForced, false /* is_empty_selection */, + true /* user_initiated */); } void WebFrameWidgetImpl::ReplaceMisspelling(const String& word) { diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index 5811d255713..3c7d6c697b7 100644 --- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h @@ -377,6 +377,7 @@ class CORE_EXPORT WebFrameWidgetImpl void SetCursor(const ui::Cursor& cursor) override; bool HandlingInputEvent() override; void SetHandlingInputEvent(bool handling) override; + bool ImeCompositionReplacement() override; void ProcessInputEventSynchronouslyForTesting( const WebCoalescedInputEvent&) override; WebInputEventResult DispatchBufferedTouchEvents() override; diff --git a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 26d5f5de0ff..3427e3c8a03 100644 --- a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc @@ -1467,8 +1467,9 @@ WebString WebLocalFrameImpl::SelectionAsMarkup() const { void WebLocalFrameImpl::TextSelectionChanged(const WebString& selection_text, uint32_t offset, - const gfx::Range& range) { - GetFrame()->TextSelectionChanged(selection_text, offset, range); + const gfx::Range& range, + bool user_initiated) { + GetFrame()->TextSelectionChanged(selection_text, offset, range, user_initiated); } bool WebLocalFrameImpl::SelectAroundCaret( diff --git a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h index d4c71836be3..744ab643f4a 100644 --- a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h @@ -217,7 +217,8 @@ class CORE_EXPORT WebLocalFrameImpl final WebString SelectionAsMarkup() const override; void TextSelectionChanged(const WebString& selection_text, uint32_t offset, - const gfx::Range& range) override; + const gfx::Range& range, + bool); bool SelectAroundCaret(mojom::blink::SelectionGranularity granularity, bool should_show_handle, bool should_show_context_menu); diff --git a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc index 8e86168dcc4..d5d36be273d 100644 --- a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc +++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc @@ -164,7 +164,8 @@ void FakeLocalFrameHost::FocusedElementChanged( void FakeLocalFrameHost::TextSelectionChanged(const WTF::String& text, uint32_t offset, - const gfx::Range& range) {} + const gfx::Range& range, + bool user_initiated) {} void FakeLocalFrameHost::ShowPopupMenu( mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client, const gfx::Rect& bounds, diff --git a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h index 81c538d0089..0742fa3cce1 100644 --- a/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h +++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h @@ -105,7 +105,8 @@ class FakeLocalFrameHost : public mojom::blink::LocalFrameHost { blink::mojom::FocusType focus_type) override; void TextSelectionChanged(const WTF::String& text, uint32_t offset, - const gfx::Range& range) override; + const gfx::Range& range, + bool user_initiated) override; void ShowPopupMenu( mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client, const gfx::Rect& bounds, diff --git a/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.h b/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.h index 426cc0e890f..8c083002abc 100644 --- a/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.h +++ b/chromium/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.h @@ -90,6 +90,13 @@ class PLATFORM_EXPORT WidgetBaseInputHandler { // cursor. bool DidChangeCursor(const ui::Cursor& cursor); + bool ime_composition_replacement() const { + return ime_composition_replacement_; + } + void set_ime_composition_replacement(bool ime_composition_replacement) { + ime_composition_replacement_ = ime_composition_replacement; + } + private: class HandlingState; struct InjectScrollGestureParams { @@ -137,6 +144,10 @@ class PLATFORM_EXPORT WidgetBaseInputHandler { const bool supports_buffered_touch_ = false; + // Used to suppress notification about text selection changes triggered by + // IME composition when it replaces text. + bool ime_composition_replacement_ = false; + base::WeakPtrFactory<WidgetBaseInputHandler> weak_ptr_factory_{this}; }; diff --git a/chromium/third_party/blink/renderer/platform/widget/widget_base.cc b/chromium/third_party/blink/renderer/platform/widget/widget_base.cc index 115f0e5774a..259a134a56e 100644 --- a/chromium/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/chromium/third_party/blink/renderer/platform/widget/widget_base.cc @@ -1335,6 +1335,7 @@ void WidgetBase::ImeSetComposition( } ImeEventGuard guard(weak_ptr_factory_.GetWeakPtr()); + input_handler_.set_ime_composition_replacement(replacement_range.IsValid()); if (!frame_widget->SetComposition(text, ime_text_spans, replacement_range, selection_start, selection_end)) { // If we failed to set the composition text, then we need to let the browser @@ -1345,6 +1346,7 @@ void WidgetBase::ImeSetComposition( host->ImeCancelComposition(); } } + input_handler_.set_ime_composition_replacement(false); UpdateCompositionInfo(false /* not an immediate request */); } |