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

Side by Side 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: Factor out HasFocus() Created 3 years, 7 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 // "FocusIn", |m_frame| may associate to another document. 243 // "FocusIn", |m_frame| may associate to another document.
244 if (!IsAvailable() || GetDocument() != current_document) { 244 if (!IsAvailable() || GetDocument() != current_document) {
245 // Once we get test case to reach here, we should change this 245 // Once we get test case to reach here, we should change this
246 // if-statement to |DCHECK()|. 246 // if-statement to |DCHECK()|.
247 NOTREACHED(); 247 NOTREACHED();
248 return; 248 return;
249 } 249 }
250 } 250 }
251 251
252 frame_caret_->StopCaretBlinkTimer(); 252 frame_caret_->StopCaretBlinkTimer();
253 UpdateAppearance(LayoutSelection::PaintHint::kPaint); 253 UpdateAppearance();
254 254
255 // Always clear the x position used for vertical arrow navigation. 255 // Always clear the x position used for vertical arrow navigation.
256 // It will be restored by the vertical arrow navigation code if necessary. 256 // It will be restored by the vertical arrow navigation code if necessary.
257 x_pos_for_vertical_arrow_navigation_ = NoXPosForVerticalArrowNavigation(); 257 x_pos_for_vertical_arrow_navigation_ = NoXPosForVerticalArrowNavigation();
258 258
259 // TODO(yosin): Can we move this to at end of this function? 259 // TODO(yosin): Can we move this to at end of this function?
260 // This may dispatch a synchronous focus-related events. 260 // This may dispatch a synchronous focus-related events.
261 if (!(options & kDoNotSetFocus)) { 261 if (!(options & kDoNotSetFocus)) {
262 SelectFrameElementInParentIfFullySelected(); 262 SelectFrameElementInParentIfFullySelected();
263 if (!IsAvailable() || GetDocument() != current_document) { 263 if (!IsAvailable() || GetDocument() != current_document) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to 328 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to
329 // |Editor| class. 329 // |Editor| class.
330 if (!GetDocument().IsRunningExecCommand()) 330 if (!GetDocument().IsRunningExecCommand())
331 TypingCommand::CloseTyping(frame_); 331 TypingCommand::CloseTyping(frame_);
332 } 332 }
333 333
334 void FrameSelection::DidChangeFocus() { 334 void FrameSelection::DidChangeFocus() {
335 // Hits in 335 // Hits in
336 // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disable d.html 336 // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disable d.html
337 DisableCompositingQueryAsserts disabler; 337 DisableCompositingQueryAsserts disabler;
338 338 UpdateAppearance();
339 // No focused element means document root has focus.
340 const Element* const focus = GetDocument().FocusedElement()
341 ? GetDocument().FocusedElement()
342 : GetDocument().documentElement();
343
344 // Protection against LayoutTests/editing/selection/selection-crash.html
345 if (!focus) {
346 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
347 text_control_focused_ = false;
348 return;
349 }
350
351 // Hide the selection when focus goes away from a text-field and into
352 // something that is not a text-field. When focus enters another text-field we
353 // do not need to update appearance; the appearance is updated when the new
354 // selection is set.
355 if (text_control_focused_ && !focus->IsTextControl())
356 UpdateAppearance(LayoutSelection::PaintHint::kHide);
357 text_control_focused_ = focus->IsTextControl();
358 } 339 }
359 340
360 static DispatchEventResult DispatchSelectStart( 341 static DispatchEventResult DispatchSelectStart(
361 const VisibleSelection& selection) { 342 const VisibleSelection& selection) {
362 Node* select_start_target = selection.Extent().ComputeContainerNode(); 343 Node* select_start_target = selection.Extent().ComputeContainerNode();
363 if (!select_start_target) 344 if (!select_start_target)
364 return DispatchEventResult::kNotCanceled; 345 return DispatchEventResult::kNotCanceled;
365 346
366 return select_start_target->DispatchEvent( 347 return select_start_target->DispatchEvent(
367 Event::CreateCancelableBubble(EventTypeNames::selectstart)); 348 Event::CreateCancelableBubble(EventTypeNames::selectstart));
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 return true; 418 return true;
438 } 419 }
439 420
440 void FrameSelection::Clear() { 421 void FrameSelection::Clear() {
441 granularity_ = kCharacterGranularity; 422 granularity_ = kCharacterGranularity;
442 if (granularity_strategy_) 423 if (granularity_strategy_)
443 granularity_strategy_->Clear(); 424 granularity_strategy_->Clear();
444 SetSelection(SelectionInDOMTree()); 425 SetSelection(SelectionInDOMTree());
445 } 426 }
446 427
428 bool FrameSelection::HasFocus() const {
429 const Node* current = ComputeVisibleSelectionInDOMTreeDeprecated()
yosin_UTC9 2017/05/08 05:36:52 nit: Please use |ComputeVisibleSelectionInDOMTree(
hugoh_UTC2 2017/05/08 09:08:13 When I do, I get this crash: $ out/PcDebug/webkit
430 .Start()
431 .ComputeContainerNode();
432 if (!current)
433 return false;
434
435 // No focused element means document root has focus.
436 const Element* const focused_element = GetDocument().FocusedElement()
437 ? GetDocument().FocusedElement()
438 : GetDocument().documentElement();
439 if (!focused_element)
440 return false;
441
442 if (focused_element->IsTextControl())
443 return focused_element->ContainsIncludingHostElements(*current);
444
445 bool has_editable_style = HasEditableStyle(*current);
446 do {
447 // If the selection is within an editable sub tree and that sub tree
448 // doesn't have focus, the selection doesn't have focus either.
449 if (has_editable_style && !HasEditableStyle(*current))
450 return false;
451
452 // Selection has focus if its sub tree has focus.
453 if (current == focused_element)
454 return true;
455 current = current->ParentOrShadowHostNode();
456 } while (current);
457
458 return false;
459 }
460
461 bool FrameSelection::IsHidden() const {
462 if (HasFocus())
463 return false;
464
465 const Node* start = ComputeVisibleSelectionInDOMTreeDeprecated()
yosin_UTC9 2017/05/08 05:36:52 nit: Please use |ComputeVisibleSelectionInDOMTree(
466 .Start()
467 .ComputeContainerNode();
468 if (!start)
469 return true;
470
471 // The selection doesn't have focus, so hide everything but range selections.
472 if (!GetSelectionInDOMTree().IsRange())
473 return true;
474
475 // Here we know we have an unfocused range selection. Let's say that
476 // selection resides inside a text control. Since the selection doesn't have
477 // focus neither does the text control. Meaning, if the selection indeed
478 // resides inside a text control, it should be hidden.
479 return EnclosingTextControl(start);
480 }
481
447 void FrameSelection::DocumentAttached(Document* document) { 482 void FrameSelection::DocumentAttached(Document* document) {
448 DCHECK(document); 483 DCHECK(document);
449 use_secure_keyboard_entry_when_active_ = false; 484 use_secure_keyboard_entry_when_active_ = false;
450 selection_editor_->DocumentAttached(document); 485 selection_editor_->DocumentAttached(document);
451 SetContext(document); 486 SetContext(document);
452 } 487 }
453 488
454 void FrameSelection::ContextDestroyed(Document* document) { 489 void FrameSelection::ContextDestroyed(Document* document) {
455 granularity_ = kCharacterGranularity; 490 granularity_ = kCharacterGranularity;
456 491
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 824
790 bool FrameSelection::NeedsLayoutSelectionUpdate() const { 825 bool FrameSelection::NeedsLayoutSelectionUpdate() const {
791 return layout_selection_->HasPendingSelection(); 826 return layout_selection_->HasPendingSelection();
792 } 827 }
793 828
794 void FrameSelection::CommitAppearanceIfNeeded() { 829 void FrameSelection::CommitAppearanceIfNeeded() {
795 return layout_selection_->Commit(); 830 return layout_selection_->Commit();
796 } 831 }
797 832
798 void FrameSelection::DidLayout() { 833 void FrameSelection::DidLayout() {
799 // Upon relayout, a hidden selection must be kept hidden and a visible 834 UpdateAppearance();
800 // selection must be kept visible.
801 UpdateAppearance(LayoutSelection::PaintHint::kKeep);
802 } 835 }
803 836
804 void FrameSelection::UpdateAppearance(LayoutSelection::PaintHint hint) { 837 void FrameSelection::UpdateAppearance() {
805 DCHECK(!frame_->ContentLayoutItem().IsNull()); 838 DCHECK(!frame_->ContentLayoutItem().IsNull());
806 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); 839 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
807 layout_selection_->SetHasPendingSelection(hint); 840 layout_selection_->SetHasPendingSelection();
808 } 841 }
809 842
810 void FrameSelection::NotifyLayoutObjectOfSelectionChange( 843 void FrameSelection::NotifyLayoutObjectOfSelectionChange(
811 EUserTriggered user_triggered) { 844 EUserTriggered user_triggered) {
812 TextControlElement* text_control = 845 TextControlElement* text_control =
813 EnclosingTextControl(GetSelectionInDOMTree().Base()); 846 EnclosingTextControl(GetSelectionInDOMTree().Base());
814 if (!text_control) 847 if (!text_control)
815 return; 848 return;
816 text_control->SelectionChanged(user_triggered == kUserTriggered); 849 text_control->SelectionChanged(user_triggered == kUserTriggered);
817 } 850 }
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 1019
987 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start(); 1020 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start();
988 DCHECK(start.AnchorNode()); 1021 DCHECK(start.AnchorNode());
989 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) { 1022 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) {
990 // FIXME: This code only handles scrolling the startContainer's layer, but 1023 // FIXME: This code only handles scrolling the startContainer's layer, but
991 // the selection rect could intersect more than just that. 1024 // the selection rect could intersect more than just that.
992 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) 1025 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader())
993 document_loader->GetInitialScrollState().was_scrolled_by_user = true; 1026 document_loader->GetInitialScrollState().was_scrolled_by_user = true;
994 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( 1027 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible(
995 rect, alignment, alignment)) 1028 rect, alignment, alignment))
996 UpdateAppearance(LayoutSelection::PaintHint::kPaint); 1029 UpdateAppearance();
997 } 1030 }
998 } 1031 }
999 1032
1000 void FrameSelection::SetSelectionFromNone() { 1033 void FrameSelection::SetSelectionFromNone() {
1001 // Put a caret inside the body if the entire frame is editable (either the 1034 // Put a caret inside the body if the entire frame is editable (either the
1002 // entire WebView is editable or designMode is on for this document). 1035 // entire WebView is editable or designMode is on for this document).
1003 1036
1004 Document* document = frame_->GetDocument(); 1037 Document* document = frame_->GetDocument();
1005 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() || 1038 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() ||
1006 !(blink::HasEditableStyle(*document))) 1039 !(blink::HasEditableStyle(*document)))
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 } 1218 }
1186 1219
1187 void showTree(const blink::FrameSelection* sel) { 1220 void showTree(const blink::FrameSelection* sel) {
1188 if (sel) 1221 if (sel)
1189 sel->ShowTreeForThis(); 1222 sel->ShowTreeForThis();
1190 else 1223 else
1191 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; 1224 LOG(INFO) << "Cannot showTree for <null> FrameSelection.";
1192 } 1225 }
1193 1226
1194 #endif 1227 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698