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::IsHidden() { | |
|
yosin_UTC9
2017/04/28 07:57:09
I would like to call this function as |HasFocus()|
| |
| 429 // No focused element means document root has focus. | |
| 430 const Element* const focus_element = GetDocument().FocusedElement() | |
| 431 ? GetDocument().FocusedElement() | |
| 432 : GetDocument().documentElement(); | |
| 433 if (!focus_element) | |
| 434 return true; | |
| 435 | |
| 436 const Node* start = ComputeVisibleSelectionInDOMTreeDeprecated() | |
| 437 .Start() | |
| 438 .ComputeContainerNode(); | |
| 439 if (!start) | |
| 440 return true; | |
| 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 { | |
| 448 if (current == focus_element) | |
| 449 return false; | |
| 450 if (has_editable_style && !HasEditableStyle(*current)) { | |
| 451 // We exited an editable subtree without finding focus. | |
| 452 TextControlElement* in_text_control = | |
| 453 EnclosingTextControl(GetSelectionInDOMTree().Base()); | |
| 454 if (in_text_control || !GetSelectionInDOMTree().IsRange()) { | |
| 455 // Example to trigger this: | |
| 456 // <div style="background: orange; padding: 20%; | |
| 457 // user-select: none" tabindex="-1"> | |
| 458 // <input value="click orange" autofocus></div> | |
| 459 // When clicking (focusing) the orange <div>, <input>'s selection | |
| 460 // looses focus (it should not receive input). | |
| 461 return true; | |
| 462 } | |
| 463 } | |
| 464 current = current->ParentOrShadowHostNode(); | |
| 465 } while (current); | |
| 466 | |
| 467 return false; | |
|
yosin_UTC9
2017/04/28 01:14:33
We also need to handle Range selection case.
We sh
hugoh_UTC2
2017/04/28 06:55:12
The test I made for that case, see TEST_F(FrameSel
yosin_UTC9
2017/04/28 07:57:09
Yes, it is what I expected.
| |
| 468 } | |
| 469 | |
| 447 void FrameSelection::DocumentAttached(Document* document) { | 470 void FrameSelection::DocumentAttached(Document* document) { |
| 448 DCHECK(document); | 471 DCHECK(document); |
| 449 use_secure_keyboard_entry_when_active_ = false; | 472 use_secure_keyboard_entry_when_active_ = false; |
| 450 selection_editor_->DocumentAttached(document); | 473 selection_editor_->DocumentAttached(document); |
| 451 SetContext(document); | 474 SetContext(document); |
| 452 } | 475 } |
| 453 | 476 |
| 454 void FrameSelection::ContextDestroyed(Document* document) { | 477 void FrameSelection::ContextDestroyed(Document* document) { |
| 455 granularity_ = kCharacterGranularity; | 478 granularity_ = kCharacterGranularity; |
| 456 | 479 |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 | 808 |
| 786 bool FrameSelection::NeedsLayoutSelectionUpdate() const { | 809 bool FrameSelection::NeedsLayoutSelectionUpdate() const { |
| 787 return layout_selection_->HasPendingSelection(); | 810 return layout_selection_->HasPendingSelection(); |
| 788 } | 811 } |
| 789 | 812 |
| 790 void FrameSelection::CommitAppearanceIfNeeded() { | 813 void FrameSelection::CommitAppearanceIfNeeded() { |
| 791 return layout_selection_->Commit(); | 814 return layout_selection_->Commit(); |
| 792 } | 815 } |
| 793 | 816 |
| 794 void FrameSelection::DidLayout() { | 817 void FrameSelection::DidLayout() { |
| 795 // Upon relayout, a hidden selection must be kept hidden and a visible | 818 UpdateAppearance(); |
| 796 // selection must be kept visible. | |
| 797 UpdateAppearance(LayoutSelection::PaintHint::kKeep); | |
| 798 } | 819 } |
| 799 | 820 |
| 800 void FrameSelection::UpdateAppearance(LayoutSelection::PaintHint hint) { | 821 void FrameSelection::UpdateAppearance() { |
| 801 DCHECK(!frame_->ContentLayoutItem().IsNull()); | 822 DCHECK(!frame_->ContentLayoutItem().IsNull()); |
| 802 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); | 823 frame_caret_->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); |
| 803 layout_selection_->SetHasPendingSelection(hint); | 824 layout_selection_->SetHasPendingSelection(); |
| 804 } | 825 } |
| 805 | 826 |
| 806 void FrameSelection::NotifyLayoutObjectOfSelectionChange( | 827 void FrameSelection::NotifyLayoutObjectOfSelectionChange( |
| 807 EUserTriggered user_triggered) { | 828 EUserTriggered user_triggered) { |
| 808 TextControlElement* text_control = | 829 TextControlElement* text_control = |
| 809 EnclosingTextControl(GetSelectionInDOMTree().Base()); | 830 EnclosingTextControl(GetSelectionInDOMTree().Base()); |
| 810 if (!text_control) | 831 if (!text_control) |
| 811 return; | 832 return; |
| 812 text_control->SelectionChanged(user_triggered == kUserTriggered); | 833 text_control->SelectionChanged(user_triggered == kUserTriggered); |
| 813 } | 834 } |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 982 | 1003 |
| 983 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start(); | 1004 Position start = ComputeVisibleSelectionInDOMTreeDeprecated().Start(); |
| 984 DCHECK(start.AnchorNode()); | 1005 DCHECK(start.AnchorNode()); |
| 985 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) { | 1006 if (start.AnchorNode() && start.AnchorNode()->GetLayoutObject()) { |
| 986 // FIXME: This code only handles scrolling the startContainer's layer, but | 1007 // FIXME: This code only handles scrolling the startContainer's layer, but |
| 987 // the selection rect could intersect more than just that. | 1008 // the selection rect could intersect more than just that. |
| 988 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) | 1009 if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader()) |
| 989 document_loader->GetInitialScrollState().was_scrolled_by_user = true; | 1010 document_loader->GetInitialScrollState().was_scrolled_by_user = true; |
| 990 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( | 1011 if (start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( |
| 991 rect, alignment, alignment)) | 1012 rect, alignment, alignment)) |
| 992 UpdateAppearance(LayoutSelection::PaintHint::kPaint); | 1013 UpdateAppearance(); |
| 993 } | 1014 } |
| 994 } | 1015 } |
| 995 | 1016 |
| 996 void FrameSelection::SetSelectionFromNone() { | 1017 void FrameSelection::SetSelectionFromNone() { |
| 997 // Put a caret inside the body if the entire frame is editable (either the | 1018 // Put a caret inside the body if the entire frame is editable (either the |
| 998 // entire WebView is editable or designMode is on for this document). | 1019 // entire WebView is editable or designMode is on for this document). |
| 999 | 1020 |
| 1000 Document* document = frame_->GetDocument(); | 1021 Document* document = frame_->GetDocument(); |
| 1001 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() || | 1022 if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() || |
| 1002 !(blink::HasEditableStyle(*document))) | 1023 !(blink::HasEditableStyle(*document))) |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1181 } | 1202 } |
| 1182 | 1203 |
| 1183 void showTree(const blink::FrameSelection* sel) { | 1204 void showTree(const blink::FrameSelection* sel) { |
| 1184 if (sel) | 1205 if (sel) |
| 1185 sel->ShowTreeForThis(); | 1206 sel->ShowTreeForThis(); |
| 1186 else | 1207 else |
| 1187 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; | 1208 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; |
| 1188 } | 1209 } |
| 1189 | 1210 |
| 1190 #endif | 1211 #endif |
| OLD | NEW |