| Index: content/renderer/render_frame_impl.cc
|
| diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
| index 894e553c9e6d2cce2625127ab2104f832ad14df8..3ac32f9104f1aa6699e533c7e7c382c52c4bc332 100644
|
| --- a/content/renderer/render_frame_impl.cc
|
| +++ b/content/renderer/render_frame_impl.cc
|
| @@ -1415,7 +1415,9 @@ void RenderFrameImpl::PepperSelectionChanged(
|
| PepperPluginInstanceImpl* instance) {
|
| if (instance != focused_pepper_plugin_)
|
| return;
|
| - SyncSelectionIfRequired();
|
| + // Keep the original behavior for pepper plugins and handle all selection
|
| + // change as user initiated.
|
| + SyncSelectionIfRequired(true);
|
| }
|
|
|
| RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer(
|
| @@ -2021,7 +2023,9 @@ void RenderFrameImpl::OnReplace(const base::string16& text) {
|
| frame_->SelectWordAroundCaret();
|
|
|
| frame_->ReplaceSelection(WebString::FromUTF16(text));
|
| - SyncSelectionIfRequired();
|
| + // Handle this selection change as user initiated since typically triggered
|
| + // from context menu.
|
| + SyncSelectionIfRequired(true);
|
| }
|
|
|
| void RenderFrameImpl::OnReplaceMisspelling(const base::string16& text) {
|
| @@ -2723,9 +2727,11 @@ void RenderFrameImpl::DetachGuest(int element_instance_id) {
|
|
|
| void RenderFrameImpl::SetSelectedText(const base::string16& selection_text,
|
| size_t offset,
|
| - const gfx::Range& range) {
|
| + const gfx::Range& range,
|
| + bool user_initiated) {
|
| Send(new FrameHostMsg_SelectionChanged(routing_id_, selection_text,
|
| - static_cast<uint32_t>(offset), range));
|
| + static_cast<uint32_t>(offset), range,
|
| + user_initiated));
|
| }
|
|
|
| void RenderFrameImpl::EnsureMojoBuiltinsAreAvailable(
|
| @@ -4104,9 +4110,20 @@ void RenderFrameImpl::AbortClientNavigation() {
|
| }
|
|
|
| void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) {
|
| - if (!GetRenderWidget()->input_handler().handling_input_event() &&
|
| - !handling_select_range_)
|
| - return;
|
| + bool user_initiated =
|
| + GetRenderWidget()->input_handler().handling_input_event() ||
|
| + handling_select_range_;
|
| +
|
| + 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 (GetRenderWidget()->input_handler().ime_composition_replacement())
|
| + return;
|
| + }
|
|
|
| if (is_empty_selection)
|
| selection_text_.clear();
|
| @@ -4117,7 +4134,7 @@ void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) {
|
| // to notify the selection was changed. Focus change should be notified
|
| // before selection change.
|
| GetRenderWidget()->UpdateTextInputState();
|
| - SyncSelectionIfRequired();
|
| + SyncSelectionIfRequired(user_initiated);
|
| }
|
|
|
| bool RenderFrameImpl::HandleCurrentKeyboardEvent() {
|
| @@ -6202,10 +6219,10 @@ void RenderFrameImpl::UpdateEncoding(WebFrame* frame,
|
| Send(new FrameHostMsg_UpdateEncoding(routing_id_, encoding_name));
|
| }
|
|
|
| -void RenderFrameImpl::SyncSelectionIfRequired() {
|
| +void RenderFrameImpl::SyncSelectionIfRequired(bool user_initiated) {
|
| base::string16 text;
|
| - size_t offset;
|
| - gfx::Range range;
|
| + size_t offset = 0;
|
| + gfx::Range range = gfx::Range::InvalidRange();
|
| #if BUILDFLAG(ENABLE_PLUGINS)
|
| if (focused_pepper_plugin_) {
|
| focused_pepper_plugin_->GetSurroundingText(&text, &range);
|
| @@ -6216,32 +6233,37 @@ void RenderFrameImpl::SyncSelectionIfRequired() {
|
| {
|
| WebRange selection =
|
| GetRenderWidget()->GetWebWidget()->CaretOrSelectionRange();
|
| - 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
|
| - // GetWebWidget()->caretOrSelectionRange().
|
| - // 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;
|
| }
|
| }
|
|
|
| @@ -6257,7 +6279,7 @@ void RenderFrameImpl::SyncSelectionIfRequired() {
|
| selection_text_ = text;
|
| selection_text_offset_ = offset;
|
| selection_range_ = range;
|
| - SetSelectedText(text, offset, range);
|
| + SetSelectedText(text, offset, range, user_initiated);
|
| }
|
| GetRenderWidget()->UpdateSelectionBounds();
|
| }
|
|
|