Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Unified Diff: third_party/WebKit/Source/core/editing/FrameSelection.cpp

Issue 2841093002: Algorithm for deciding if a frame's selection should be hidden (Closed)
Patch Set: Rebase + cosmetic changes Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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();
}
}

Powered by Google App Engine
This is Rietveld 408576698