Chromium Code Reviews| Index: content/renderer/render_frame_impl.cc |
| diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc |
| index 901eb2261a0b4512b4db7645600e3a2c2d0b0864..740ca73cfcfce4f54db8d8bb6392b3194ba7a46f 100644 |
| --- a/content/renderer/render_frame_impl.cc |
| +++ b/content/renderer/render_frame_impl.cc |
| @@ -1419,7 +1419,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. |
|
Changwan Ryu
2017/07/14 18:44:03
I'm not too familiar with the pepper and desktop u
Peter Varga
2017/07/17 09:36:06
I'm also not familiar with pepper, that's why I ke
|
| + SyncSelectionIfRequired(true); |
| } |
| RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( |
| @@ -2005,7 +2007,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) { |
| @@ -2707,9 +2711,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( |
| @@ -4087,9 +4093,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()) |
|
Changwan Ryu
2017/07/14 18:44:03
What happens if move the cursor from one position
Peter Varga
2017/07/17 09:36:06
I assume you mean to change cursor position by emp
|
| + return; |
| + |
| + // Ignore selection change of text replacement triggered by IME composition. |
| + if (GetRenderWidget()->input_handler().ime_composition_replacement()) |
|
Changwan Ryu
2017/07/14 18:44:03
Hmm... This approach is quite brittle. SetComposin
EhsanK
2017/07/14 18:55:21
I think this is something worth pursing. The poten
Peter Varga
2017/07/17 09:36:06
I try to handle this in render_widget.cc. Only unn
|
| + return; |
| + } |
| if (is_empty_selection) |
| selection_text_.clear(); |
| @@ -4100,7 +4117,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() { |
| @@ -6210,10 +6227,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); |
| @@ -6224,32 +6241,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; |
| } |
| } |
| @@ -6265,7 +6287,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(); |
| } |