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

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: Nit 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::SelectionHasFocus() const {
429 // TODO(editing-dev): Hoist UpdateStyleAndLayoutIgnorePendingStylesheets
430 // to caller. See http://crbug.com/590369 for more details.
431 GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
432 const Node* current =
433 ComputeVisibleSelectionInDOMTree().Start().ComputeContainerNode();
434 if (!current)
435 return false;
436
437 // No focused element means document root has focus.
438 const Element* const focused_element = GetDocument().FocusedElement()
439 ? GetDocument().FocusedElement()
440 : GetDocument().documentElement();
441 if (!focused_element)
442 return false;
443
444 if (focused_element->IsTextControl())
445 return focused_element->ContainsIncludingHostElements(*current);
446
447 bool has_editable_style = HasEditableStyle(*current);
448 do {
449 // If the selection is within an editable sub tree and that sub tree
450 // doesn't have focus, the selection doesn't have focus either.
451 if (has_editable_style && !HasEditableStyle(*current))
452 return false;
453
454 // Selection has focus if its sub tree has focus.
455 if (current == focused_element)
456 return true;
457 current = current->ParentOrShadowHostNode();
458 } while (current);
459
460 return false;
461 }
462
463 bool FrameSelection::IsHidden() const {
464 if (SelectionHasFocus())
465 return false;
466
467 const Node* start =
468 ComputeVisibleSelectionInDOMTree().Start().ComputeContainerNode();
469 if (!start)
470 return true;
471
472 // The selection doesn't have focus, so hide everything but range selections.
473 if (!GetSelectionInDOMTree().IsRange())
474 return true;
475
476 // Here we know we have an unfocused range selection. Let's say that
477 // selection resides inside a text control. Since the selection doesn't have
478 // focus neither does the text control. Meaning, if the selection indeed
479 // resides inside a text control, it should be hidden.
480 return EnclosingTextControl(start);
481 }
482
447 void FrameSelection::DocumentAttached(Document* document) { 483 void FrameSelection::DocumentAttached(Document* document) {
448 DCHECK(document); 484 DCHECK(document);
449 use_secure_keyboard_entry_when_active_ = false; 485 use_secure_keyboard_entry_when_active_ = false;
450 selection_editor_->DocumentAttached(document); 486 selection_editor_->DocumentAttached(document);
451 SetContext(document); 487 SetContext(document);
452 } 488 }
453 489
454 void FrameSelection::ContextDestroyed(Document* document) { 490 void FrameSelection::ContextDestroyed(Document* document) {
455 granularity_ = kCharacterGranularity; 491 granularity_ = kCharacterGranularity;
456 492
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 824
789 bool FrameSelection::NeedsLayoutSelectionUpdate() const { 825 bool FrameSelection::NeedsLayoutSelectionUpdate() const {
790 return layout_selection_->HasPendingSelection(); 826 return layout_selection_->HasPendingSelection();
791 } 827 }
792 828
793 void FrameSelection::CommitAppearanceIfNeeded() { 829 void FrameSelection::CommitAppearanceIfNeeded() {
794 return layout_selection_->Commit(); 830 return layout_selection_->Commit();
795 } 831 }
796 832
797 void FrameSelection::DidLayout() { 833 void FrameSelection::DidLayout() {
798 // Upon relayout, a hidden selection must be kept hidden and a visible 834 UpdateAppearance();
799 // selection must be kept visible.
800 UpdateAppearance(LayoutSelection::PaintHint::kKeep);
801 } 835 }
802 836
803 void FrameSelection::UpdateAppearance(LayoutSelection::PaintHint hint) { 837 void FrameSelection::UpdateAppearance() {
804 DCHECK(!frame_->ContentLayoutItem().IsNull()); 838 DCHECK(!frame_->ContentLayoutItem().IsNull());
805 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); 839 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded();
806 layout_selection_->SetHasPendingSelection(hint); 840 layout_selection_->SetHasPendingSelection();
807 } 841 }
808 842
809 void FrameSelection::NotifyLayoutObjectOfSelectionChange( 843 void FrameSelection::NotifyLayoutObjectOfSelectionChange(
810 EUserTriggered user_triggered) { 844 EUserTriggered user_triggered) {
811 TextControlElement* text_control = 845 TextControlElement* text_control =
812 EnclosingTextControl(GetSelectionInDOMTree().Base()); 846 EnclosingTextControl(GetSelectionInDOMTree().Base());
813 if (!text_control) 847 if (!text_control)
814 return; 848 return;
815 text_control->SelectionChanged(user_triggered == kUserTriggered); 849 text_control->SelectionChanged(user_triggered == kUserTriggered);
816 } 850 }
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 1019
986 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start(); 1020 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start();
987 DCHECK(start.AnchorNode()); 1021 DCHECK(start.AnchorNode());
988 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) { 1022 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) {
989 // FIXME: This code only handles scrolling the startContainer's layer, but 1023 // FIXME: This code only handles scrolling the startContainer's layer, but
990 // the selection rect could intersect more than just that. 1024 // the selection rect could intersect more than just that.
991 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) 1025 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader())
992 document_loader->GetInitialScrollState().was_scrolled_by_user = true; 1026 document_loader->GetInitialScrollState().was_scrolled_by_user = true;
993 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( 1027 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible(
994 rect, alignment, alignment)) 1028 rect, alignment, alignment))
995 UpdateAppearance(LayoutSelection::PaintHint::kPaint); 1029 UpdateAppearance();
996 } 1030 }
997 } 1031 }
998 1032
999 void FrameSelection::SetSelectionFromNone() { 1033 void FrameSelection::SetSelectionFromNone() {
1000 // 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
1001 // entire WebView is editable or designMode is on for this document). 1035 // entire WebView is editable or designMode is on for this document).
1002 1036
1003 Document* document = frame_->GetDocument(); 1037 Document* document = frame_->GetDocument();
1004 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() || 1038 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() ||
1005 !(blink::HasEditableStyle(*document))) 1039 !(blink::HasEditableStyle(*document)))
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 } 1218 }
1185 1219
1186 void showTree(const blink::FrameSelection* sel) { 1220 void showTree(const blink::FrameSelection* sel) {
1187 if (sel) 1221 if (sel)
1188 sel->ShowTreeForThis(); 1222 sel->ShowTreeForThis();
1189 else 1223 else
1190 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; 1224 LOG(INFO) << "Cannot showTree for <null> FrameSelection.";
1191 } 1225 }
1192 1226
1193 #endif 1227 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/FrameSelection.h ('k') | third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698