| 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::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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |