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 |