Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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::IsActive() const { | |
| 429 const Node* start = ComputeVisibleSelectionInDOMTreeDeprecated() | |
| 430 .Start() | |
| 431 .ComputeContainerNode(); | |
| 432 if (!start) | |
| 433 return false; | |
| 434 | |
| 435 // No focused element means document root has focus. | |
| 436 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.
| |
| 437 ? GetDocument().FocusedElement() | |
| 438 : GetDocument().documentElement(); | |
| 439 if (!focus_element) | |
| 440 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
| |
| 441 | |
| 442 if (focus_element->IsTextControl()) | |
| 443 return focus_element->ContainsIncludingHostElements(*start); | |
| 444 | |
| 445 bool has_editable_style = HasEditableStyle(*start); | |
| 446 const Node* current = start; | |
| 447 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
| |
| 448 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
| |
| 449 // We exited an editable sub tree. | |
| 450 // Only range selections can be active in this case. | |
| 451 if (!GetSelectionInDOMTree().IsRange()) { | |
| 452 // Example that triggers this: | |
| 453 // <div tabindex='-1' id='parent'> | |
| 454 // <!-- Place caret within blabla. --> | |
| 455 // <div contenteditable id='ce'>blabla</div> | |
| 456 // </div> | |
| 457 // When focusing the outer <div>, we must hide the inner <div>'s caret. | |
| 458 return false; | |
| 459 } | |
| 460 | |
| 461 // So the selection is a range... | |
| 462 // Only hide the selection if its inside a text control. | |
| 463 const TextControlElement* in_text_control = | |
| 464 EnclosingTextControl(GetSelectionInDOMTree().Base()); | |
| 465 if (in_text_control) { | |
| 466 // Example that triggers this: | |
| 467 // <div tabindex="-1"> | |
| 468 // <input value="hola"> <!-- Select hola --> | |
| 469 // </div> | |
| 470 // When focusing the <div>, we must hide the selection [hola]. | |
| 471 return false; | |
| 472 } | |
| 473 } else { | |
| 474 // Selection is active (= not hidden) if this sub tree got focus. | |
| 475 if (current == focus_element) | |
| 476 return true; | |
| 477 } | |
| 478 current = current->ParentOrShadowHostNode(); | |
| 479 } while (current); | |
| 480 | |
| 481 return true; | |
| 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 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 789 | 825 |
| 790 bool FrameSelection::NeedsLayoutSelectionUpdate() const { | 826 bool FrameSelection::NeedsLayoutSelectionUpdate() const { |
| 791 return layout_selection_->HasPendingSelection(); | 827 return layout_selection_->HasPendingSelection(); |
| 792 } | 828 } |
| 793 | 829 |
| 794 void FrameSelection::CommitAppearanceIfNeeded() { | 830 void FrameSelection::CommitAppearanceIfNeeded() { |
| 795 return layout_selection_->Commit(); | 831 return layout_selection_->Commit(); |
| 796 } | 832 } |
| 797 | 833 |
| 798 void FrameSelection::DidLayout() { | 834 void FrameSelection::DidLayout() { |
| 799 // Upon relayout, a hidden selection must be kept hidden and a visible | 835 UpdateAppearance(); |
| 800 // selection must be kept visible. | |
| 801 UpdateAppearance(LayoutSelection::PaintHint::kKeep); | |
| 802 } | 836 } |
| 803 | 837 |
| 804 void FrameSelection::UpdateAppearance(LayoutSelection::PaintHint hint) { | 838 void FrameSelection::UpdateAppearance() { |
| 805 DCHECK(!frame_->ContentLayoutItem().IsNull()); | 839 DCHECK(!frame_->ContentLayoutItem().IsNull()); |
| 806 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); | 840 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); |
| 807 layout_selection_->SetHasPendingSelection(hint); | 841 layout_selection_->SetHasPendingSelection(); |
| 808 } | 842 } |
| 809 | 843 |
| 810 void FrameSelection::NotifyLayoutObjectOfSelectionChange( | 844 void FrameSelection::NotifyLayoutObjectOfSelectionChange( |
| 811 EUserTriggered user_triggered) { | 845 EUserTriggered user_triggered) { |
| 812 TextControlElement* text_control = | 846 TextControlElement* text_control = |
| 813 EnclosingTextControl(GetSelectionInDOMTree().Base()); | 847 EnclosingTextControl(GetSelectionInDOMTree().Base()); |
| 814 if (!text_control) | 848 if (!text_control) |
| 815 return; | 849 return; |
| 816 text_control->SelectionChanged(user_triggered == kUserTriggered); | 850 text_control->SelectionChanged(user_triggered == kUserTriggered); |
| 817 } | 851 } |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 986 | 1020 |
| 987 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start(); | 1021 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start(); |
| 988 DCHECK(start.AnchorNode()); | 1022 DCHECK(start.AnchorNode()); |
| 989 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) { | 1023 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) { |
| 990 // FIXME: This code only handles scrolling the startContainer's layer, but | 1024 // FIXME: This code only handles scrolling the startContainer's layer, but |
| 991 // the selection rect could intersect more than just that. | 1025 // the selection rect could intersect more than just that. |
| 992 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) | 1026 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) |
| 993 document_loader->GetInitialScrollState().was_scrolled_by_user = true; | 1027 document_loader->GetInitialScrollState().was_scrolled_by_user = true; |
| 994 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( | 1028 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( |
| 995 rect, alignment, alignment)) | 1029 rect, alignment, alignment)) |
| 996 UpdateAppearance(LayoutSelection::PaintHint::kPaint); | 1030 UpdateAppearance(); |
| 997 } | 1031 } |
| 998 } | 1032 } |
| 999 | 1033 |
| 1000 void FrameSelection::SetSelectionFromNone() { | 1034 void FrameSelection::SetSelectionFromNone() { |
| 1001 // Put a caret inside the body if the entire frame is editable (either the | 1035 // 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). | 1036 // entire WebView is editable or designMode is on for this document). |
| 1003 | 1037 |
| 1004 Document* document = frame_->GetDocument(); | 1038 Document* document = frame_->GetDocument(); |
| 1005 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() || | 1039 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() || |
| 1006 !(blink::HasEditableStyle(*document))) | 1040 !(blink::HasEditableStyle(*document))) |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1185 } | 1219 } |
| 1186 | 1220 |
| 1187 void showTree(const blink::FrameSelection* sel) { | 1221 void showTree(const blink::FrameSelection* sel) { |
| 1188 if (sel) | 1222 if (sel) |
| 1189 sel->ShowTreeForThis(); | 1223 sel->ShowTreeForThis(); |
| 1190 else | 1224 else |
| 1191 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; | 1225 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; |
| 1192 } | 1226 } |
| 1193 | 1227 |
| 1194 #endif | 1228 #endif |
| OLD | NEW |