Chromium Code Reviews| Index: third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| index c29027dd0a1dd11bf29fa63735e9e3ee60b32b52..6acb2f467adac08e7de60c5c9ea74cbbff48f81a 100644 |
| --- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| +++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp |
| @@ -250,7 +250,7 @@ void FrameSelection::DidSetSelectionDeprecated(SetSelectionOptions options, |
| } |
| frame_caret_->StopCaretBlinkTimer(); |
| - UpdateAppearance(LayoutSelection::PaintHint::kPaint); |
| + UpdateAppearance(); |
| // Always clear the x position used for vertical arrow navigation. |
| // It will be restored by the vertical arrow navigation code if necessary. |
| @@ -335,26 +335,7 @@ void FrameSelection::DidChangeFocus() { |
| // Hits in |
| // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disabled.html |
| DisableCompositingQueryAsserts disabler; |
| - |
| - // No focused element means document root has focus. |
| - const Element* const focus = GetDocument().FocusedElement() |
| - ? GetDocument().FocusedElement() |
| - : GetDocument().documentElement(); |
| - |
| - // Protection against LayoutTests/editing/selection/selection-crash.html |
| - if (!focus) { |
| - frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); |
| - text_control_focused_ = false; |
| - return; |
| - } |
| - |
| - // Hide the selection when focus goes away from a text-field and into |
| - // something that is not a text-field. When focus enters another text-field we |
| - // do not need to update appearance; the appearance is updated when the new |
| - // selection is set. |
| - if (text_control_focused_ && !focus->IsTextControl()) |
| - UpdateAppearance(LayoutSelection::PaintHint::kHide); |
| - text_control_focused_ = focus->IsTextControl(); |
| + UpdateAppearance(); |
| } |
| static DispatchEventResult DispatchSelectStart( |
| @@ -444,6 +425,61 @@ void FrameSelection::Clear() { |
| SetSelection(SelectionInDOMTree()); |
| } |
| +bool FrameSelection::IsActive() const { |
| + const Node* start = ComputeVisibleSelectionInDOMTreeDeprecated() |
| + .Start() |
| + .ComputeContainerNode(); |
| + if (!start) |
| + return false; |
| + |
| + // No focused element means document root has focus. |
| + const Element* const focus_element = GetDocument().FocusedElement() |
|
Xiaocheng
2017/05/02 20:05:16
nit: s/focus_element/focused_element/g
hugoh_UTC2
2017/05/03 07:18:55
OK, I will change this.
|
| + ? GetDocument().FocusedElement() |
| + : GetDocument().documentElement(); |
| + if (!focus_element) |
| + return false; |
|
Xiaocheng
2017/05/02 20:05:17
Does LayoutTests/editing/selection/selection-crash
hugoh_UTC2
2017/05/03 07:18:55
selection-crash.html doesn't crash right now but s
|
| + |
| + if (focus_element->IsTextControl()) |
| + return focus_element->ContainsIncludingHostElements(*start); |
| + |
| + bool has_editable_style = HasEditableStyle(*start); |
| + const Node* current = start; |
| + do { |
|
Xiaocheng
2017/05/02 20:05:16
nit: A |for| loop seems to have better readability
hugoh_UTC2
2017/05/03 07:18:55
Not sure I agree :) A for-loop would check |curren
Xiaocheng
2017/05/03 15:03:01
Compared to the loop body, an extra nullptr check
|
| + if (has_editable_style && !HasEditableStyle(*current)) { |
|
Xiaocheng
2017/05/02 20:05:16
I can't understand this loop body. There seem to b
hugoh_UTC2
2017/05/03 07:18:55
Yes, we have many cases to think of. This logic is
hugoh_UTC2
2017/05/03 20:31:00
I realized that EnclosingTextControl() and the che
|
| + // We exited an editable sub tree. |
| + // Only range selections can be active in this case. |
| + if (!GetSelectionInDOMTree().IsRange()) { |
| + // Example that triggers this: |
| + // <div tabindex='-1' id='parent'> |
| + // <!-- Place caret within blabla. --> |
| + // <div contenteditable id='ce'>blabla</div> |
| + // </div> |
| + // When focusing the outer <div>, we must hide the inner <div>'s caret. |
| + return false; |
| + } |
| + |
| + // So the selection is a range... |
| + // Only hide the selection if its inside a text control. |
| + const TextControlElement* in_text_control = |
| + EnclosingTextControl(GetSelectionInDOMTree().Base()); |
| + if (in_text_control) { |
| + // Example that triggers this: |
| + // <div tabindex="-1"> |
| + // <input value="hola"> <!-- Select hola --> |
| + // </div> |
| + // When focusing the <div>, we must hide the selection [hola]. |
| + return false; |
| + } |
| + } else { |
| + // Selection is active (= not hidden) if this sub tree got focus. |
| + if (current == focus_element) |
| + return true; |
| + } |
| + current = current->ParentOrShadowHostNode(); |
| + } while (current); |
| + |
| + return true; |
| +} |
| void FrameSelection::DocumentAttached(Document* document) { |
| DCHECK(document); |
| use_secure_keyboard_entry_when_active_ = false; |
| @@ -796,15 +832,13 @@ void FrameSelection::CommitAppearanceIfNeeded() { |
| } |
| void FrameSelection::DidLayout() { |
| - // Upon relayout, a hidden selection must be kept hidden and a visible |
| - // selection must be kept visible. |
| - UpdateAppearance(LayoutSelection::PaintHint::kKeep); |
| + UpdateAppearance(); |
| } |
| -void FrameSelection::UpdateAppearance(LayoutSelection::PaintHint hint) { |
| +void FrameSelection::UpdateAppearance() { |
| DCHECK(!frame_->ContentLayoutItem().IsNull()); |
| frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); |
| - layout_selection_->SetHasPendingSelection(hint); |
| + layout_selection_->SetHasPendingSelection(); |
| } |
| void FrameSelection::NotifyLayoutObjectOfSelectionChange( |
| @@ -993,7 +1027,7 @@ void FrameSelection::RevealSelection(const ScrollAlignment& alignment, |
| document_loader->GetInitialScrollState().was_scrolled_by_user = true; |
| if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( |
| rect, alignment, alignment)) |
| - UpdateAppearance(LayoutSelection::PaintHint::kPaint); |
| + UpdateAppearance(); |
| } |
| } |