| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 if (event->isIncrementalInsertion()) | 212 if (event->isIncrementalInsertion()) |
| 213 return false; | 213 return false; |
| 214 | 214 |
| 215 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 215 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 216 // needs to be audited. See http://crbug.com/590369 for more details. | 216 // needs to be audited. See http://crbug.com/590369 for more details. |
| 217 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 217 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 218 | 218 |
| 219 if (event->isPaste()) { | 219 if (event->isPaste()) { |
| 220 if (event->pastingFragment()) { | 220 if (event->pastingFragment()) { |
| 221 replaceSelectionWithFragment( | 221 replaceSelectionWithFragment( |
| 222 event->pastingFragment(), false, event->shouldSmartReplace(), | 222 EditCommandSource::kMenuOrKeyBinding, event->pastingFragment(), false, |
| 223 event->shouldMatchStyle(), InputEvent::InputType::InsertFromPaste); | 223 event->shouldSmartReplace(), event->shouldMatchStyle(), |
| 224 InputEvent::InputType::InsertFromPaste); |
| 224 } else { | 225 } else { |
| 225 replaceSelectionWithText(event->data(), false, | 226 replaceSelectionWithText( |
| 226 event->shouldSmartReplace(), | 227 EditCommandSource::kMenuOrKeyBinding, event->data(), false, |
| 227 InputEvent::InputType::InsertFromPaste); | 228 event->shouldSmartReplace(), InputEvent::InputType::InsertFromPaste); |
| 228 } | 229 } |
| 229 return true; | 230 return true; |
| 230 } | 231 } |
| 231 | 232 |
| 232 String data = event->data(); | 233 String data = event->data(); |
| 233 if (data == "\n") { | 234 if (data == "\n") { |
| 234 if (event->isLineBreak()) | 235 if (event->isLineBreak()) |
| 235 return insertLineBreak(); | 236 return insertLineBreak(); |
| 236 return insertParagraphSeparator(); | 237 return insertParagraphSeparator(); |
| 237 } | 238 } |
| 238 | 239 |
| 239 return insertTextWithoutSendingTextEvent(data, false, event); | 240 return insertTextWithoutSendingTextEvent(EditCommandSource::kMenuOrKeyBinding, |
| 241 data, false, event); |
| 240 } | 242 } |
| 241 | 243 |
| 242 bool Editor::canEdit() const { | 244 bool Editor::canEdit() const { |
| 243 return frame().selection().rootEditableElement(); | 245 return frame().selection().rootEditableElement(); |
| 244 } | 246 } |
| 245 | 247 |
| 246 bool Editor::canEditRichly() const { | 248 bool Editor::canEditRichly() const { |
| 247 return frame().selection().isContentRichlyEditable(); | 249 return frame().selection().isContentRichlyEditable(); |
| 248 } | 250 } |
| 249 | 251 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 return smartInsertDeleteEnabled() && | 311 return smartInsertDeleteEnabled() && |
| 310 frame().selection().granularity() == WordGranularity; | 312 frame().selection().granularity() == WordGranularity; |
| 311 } | 313 } |
| 312 | 314 |
| 313 bool Editor::isSelectTrailingWhitespaceEnabled() const { | 315 bool Editor::isSelectTrailingWhitespaceEnabled() const { |
| 314 if (Settings* settings = frame().settings()) | 316 if (Settings* settings = frame().settings()) |
| 315 return settings->selectTrailingWhitespaceEnabled(); | 317 return settings->selectTrailingWhitespaceEnabled(); |
| 316 return false; | 318 return false; |
| 317 } | 319 } |
| 318 | 320 |
| 319 bool Editor::deleteWithDirection(DeleteDirection direction, | 321 bool Editor::deleteWithDirection(EditCommandSource source, |
| 322 DeleteDirection direction, |
| 320 TextGranularity granularity, | 323 TextGranularity granularity, |
| 321 bool killRing, | 324 bool killRing, |
| 322 bool isTypingAction) { | 325 bool isTypingAction) { |
| 323 if (!canEdit()) | 326 if (!canEdit()) |
| 324 return false; | 327 return false; |
| 325 | 328 |
| 326 EditingState editingState; | 329 EditingState editingState; |
| 327 if (frame().selection().isRange()) { | 330 if (frame().selection().isRange()) { |
| 328 if (isTypingAction) { | 331 if (isTypingAction) { |
| 329 DCHECK(frame().document()); | 332 DCHECK(frame().document()); |
| 330 TypingCommand::deleteKeyPressed( | 333 TypingCommand::deleteKeyPressed( |
| 331 *frame().document(), | 334 *frame().document(), |
| 332 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity); | 335 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity); |
| 333 revealSelectionAfterEditingOperation(); | 336 revealSelectionAfterEditingOperation(); |
| 334 } else { | 337 } else { |
| 335 if (killRing) | 338 if (killRing) |
| 336 addToKillRing(selectedRange()); | 339 addToKillRing(selectedRange()); |
| 337 deleteSelectionWithSmartDelete( | 340 deleteSelectionWithSmartDelete( |
| 341 source, |
| 338 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 342 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 339 deletionInputTypeFromTextGranularity(direction, granularity)); | 343 deletionInputTypeFromTextGranularity(direction, granularity)); |
| 340 // Implicitly calls revealSelectionAfterEditingOperation(). | 344 // Implicitly calls revealSelectionAfterEditingOperation(). |
| 341 } | 345 } |
| 342 } else { | 346 } else { |
| 343 TypingCommand::Options options = 0; | 347 TypingCommand::Options options = 0; |
| 344 if (canSmartCopyOrDelete()) | 348 if (canSmartCopyOrDelete()) |
| 345 options |= TypingCommand::SmartDelete; | 349 options |= TypingCommand::SmartDelete; |
| 346 if (killRing) | 350 if (killRing) |
| 347 options |= TypingCommand::KillRing; | 351 options |= TypingCommand::KillRing; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 364 | 368 |
| 365 // FIXME: We should to move this down into deleteKeyPressed. | 369 // FIXME: We should to move this down into deleteKeyPressed. |
| 366 // clear the "start new kill ring sequence" setting, because it was set to | 370 // clear the "start new kill ring sequence" setting, because it was set to |
| 367 // true when the selection was updated by deleting the range | 371 // true when the selection was updated by deleting the range |
| 368 if (killRing) | 372 if (killRing) |
| 369 setStartNewKillRingSequence(false); | 373 setStartNewKillRingSequence(false); |
| 370 | 374 |
| 371 return true; | 375 return true; |
| 372 } | 376 } |
| 373 | 377 |
| 378 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. |
| 374 void Editor::deleteSelectionWithSmartDelete( | 379 void Editor::deleteSelectionWithSmartDelete( |
| 380 EditCommandSource, |
| 375 DeleteMode deleteMode, | 381 DeleteMode deleteMode, |
| 376 InputEvent::InputType inputType, | 382 InputEvent::InputType inputType, |
| 377 const Position& referenceMovePosition) { | 383 const Position& referenceMovePosition) { |
| 378 if (frame().selection().isNone()) | 384 if (frame().selection().isNone()) |
| 379 return; | 385 return; |
| 380 | 386 |
| 381 const bool kMergeBlocksAfterDelete = true; | 387 const bool kMergeBlocksAfterDelete = true; |
| 382 const bool kExpandForSpecialElements = false; | 388 const bool kExpandForSpecialElements = false; |
| 383 const bool kSanitizeMarkup = true; | 389 const bool kSanitizeMarkup = true; |
| 384 DCHECK(frame().document()); | 390 DCHECK(frame().document()); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 // invalidate clipboard here for security | 563 // invalidate clipboard here for security |
| 558 dataTransfer->setAccessPolicy(DataTransferNumb); | 564 dataTransfer->setAccessPolicy(DataTransferNumb); |
| 559 | 565 |
| 560 return !noDefaultProcessing; | 566 return !noDefaultProcessing; |
| 561 } | 567 } |
| 562 | 568 |
| 563 bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard) { | 569 bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard) { |
| 564 return smartInsertDeleteEnabled() && pasteboard->canSmartReplace(); | 570 return smartInsertDeleteEnabled() && pasteboard->canSmartReplace(); |
| 565 } | 571 } |
| 566 | 572 |
| 567 void Editor::replaceSelectionWithFragment(DocumentFragment* fragment, | 573 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. |
| 574 void Editor::replaceSelectionWithFragment(EditCommandSource, |
| 575 DocumentFragment* fragment, |
| 568 bool selectReplacement, | 576 bool selectReplacement, |
| 569 bool smartReplace, | 577 bool smartReplace, |
| 570 bool matchStyle, | 578 bool matchStyle, |
| 571 InputEvent::InputType inputType) { | 579 InputEvent::InputType inputType) { |
| 572 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | 580 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 573 if (frame().selection().isNone() || | 581 if (frame().selection().isNone() || |
| 574 !frame().selection().isContentEditable() || !fragment) | 582 !frame().selection().isContentEditable() || !fragment) |
| 575 return; | 583 return; |
| 576 | 584 |
| 577 ReplaceSelectionCommand::CommandOptions options = | 585 ReplaceSelectionCommand::CommandOptions options = |
| 578 ReplaceSelectionCommand::PreventNesting | | 586 ReplaceSelectionCommand::PreventNesting | |
| 579 ReplaceSelectionCommand::SanitizeFragment; | 587 ReplaceSelectionCommand::SanitizeFragment; |
| 580 if (selectReplacement) | 588 if (selectReplacement) |
| 581 options |= ReplaceSelectionCommand::SelectReplacement; | 589 options |= ReplaceSelectionCommand::SelectReplacement; |
| 582 if (smartReplace) | 590 if (smartReplace) |
| 583 options |= ReplaceSelectionCommand::SmartReplace; | 591 options |= ReplaceSelectionCommand::SmartReplace; |
| 584 if (matchStyle) | 592 if (matchStyle) |
| 585 options |= ReplaceSelectionCommand::MatchStyle; | 593 options |= ReplaceSelectionCommand::MatchStyle; |
| 586 DCHECK(frame().document()); | 594 DCHECK(frame().document()); |
| 587 ReplaceSelectionCommand::create(*frame().document(), fragment, options, | 595 ReplaceSelectionCommand::create(*frame().document(), fragment, options, |
| 588 inputType) | 596 inputType) |
| 589 ->apply(); | 597 ->apply(); |
| 590 revealSelectionAfterEditingOperation(); | 598 revealSelectionAfterEditingOperation(); |
| 591 } | 599 } |
| 592 | 600 |
| 593 void Editor::replaceSelectionWithText(const String& text, | 601 void Editor::replaceSelectionWithText(EditCommandSource source, |
| 602 const String& text, |
| 594 bool selectReplacement, | 603 bool selectReplacement, |
| 595 bool smartReplace, | 604 bool smartReplace, |
| 596 InputEvent::InputType inputType) { | 605 InputEvent::InputType inputType) { |
| 597 replaceSelectionWithFragment(createFragmentFromText(selectedRange(), text), | 606 replaceSelectionWithFragment( |
| 598 selectReplacement, smartReplace, true, | 607 source, createFragmentFromText(selectedRange(), text), selectReplacement, |
| 599 inputType); | 608 smartReplace, true, inputType); |
| 600 } | 609 } |
| 601 | 610 |
| 602 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. | 611 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. |
| 603 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, | 612 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, |
| 604 InsertMode insertMode, | 613 InsertMode insertMode, |
| 605 DragSourceType dragSourceType) { | 614 DragSourceType dragSourceType) { |
| 606 ReplaceSelectionCommand::CommandOptions options = | 615 ReplaceSelectionCommand::CommandOptions options = |
| 607 ReplaceSelectionCommand::SelectReplacement | | 616 ReplaceSelectionCommand::SelectReplacement | |
| 608 ReplaceSelectionCommand::PreventNesting; | 617 ReplaceSelectionCommand::PreventNesting; |
| 609 if (insertMode == InsertMode::Smart) | 618 if (insertMode == InsertMode::Smart) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 628 dragSource, InputEvent::InputType::DeleteByDrag, | 637 dragSource, InputEvent::InputType::DeleteByDrag, |
| 629 nullptr) == DispatchEventResult::NotCanceled; | 638 nullptr) == DispatchEventResult::NotCanceled; |
| 630 | 639 |
| 631 // 'beforeinput' event handler may destroy frame, return false to cancel | 640 // 'beforeinput' event handler may destroy frame, return false to cancel |
| 632 // remaining actions; | 641 // remaining actions; |
| 633 if (m_frame->document()->frame() != m_frame) | 642 if (m_frame->document()->frame() != m_frame) |
| 634 return false; | 643 return false; |
| 635 | 644 |
| 636 if (shouldDelete && dragSource->isConnected()) { | 645 if (shouldDelete && dragSource->isConnected()) { |
| 637 deleteSelectionWithSmartDelete( | 646 deleteSelectionWithSmartDelete( |
| 638 deleteMode, InputEvent::InputType::DeleteByDrag, referenceMovePosition); | 647 EditCommandSource::kMenuOrKeyBinding, deleteMode, |
| 648 InputEvent::InputType::DeleteByDrag, referenceMovePosition); |
| 639 } | 649 } |
| 640 | 650 |
| 641 return true; | 651 return true; |
| 642 } | 652 } |
| 643 | 653 |
| 644 bool Editor::replaceSelectionAfterDraggingWithEvents( | 654 bool Editor::replaceSelectionAfterDraggingWithEvents( |
| 645 Element* dropTarget, | 655 Element* dropTarget, |
| 646 DragData* dragData, | 656 DragData* dragData, |
| 647 DocumentFragment* fragment, | 657 DocumentFragment* fragment, |
| 648 Range* dropCaretRange, | 658 Range* dropCaretRange, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 if (frame().settings() && frame().settings()->accessibilityEnabled()) { | 702 if (frame().settings() && frame().settings()->accessibilityEnabled()) { |
| 693 Node* node = endingSelection.start().anchorNode(); | 703 Node* node = endingSelection.start().anchorNode(); |
| 694 if (AXObjectCache* cache = frame().document()->existingAXObjectCache()) | 704 if (AXObjectCache* cache = frame().document()->existingAXObjectCache()) |
| 695 cache->handleEditableTextContentChanged(node); | 705 cache->handleEditableTextContentChanged(node); |
| 696 } | 706 } |
| 697 | 707 |
| 698 spellChecker().updateMarkersForWordsAffectedByEditing(true); | 708 spellChecker().updateMarkersForWordsAffectedByEditing(true); |
| 699 client().respondToChangedContents(); | 709 client().respondToChangedContents(); |
| 700 } | 710 } |
| 701 | 711 |
| 702 void Editor::removeFormattingAndStyle() { | 712 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. |
| 713 void Editor::removeFormattingAndStyle(EditCommandSource) { |
| 703 DCHECK(frame().document()); | 714 DCHECK(frame().document()); |
| 704 RemoveFormatCommand::create(*frame().document())->apply(); | 715 RemoveFormatCommand::create(*frame().document())->apply(); |
| 705 } | 716 } |
| 706 | 717 |
| 707 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) { | 718 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) { |
| 708 DCHECK(commandGroupWrapper->isCommandGroupWrapper()); | 719 DCHECK(commandGroupWrapper->isCommandGroupWrapper()); |
| 709 m_lastEditCommand = commandGroupWrapper; | 720 m_lastEditCommand = commandGroupWrapper; |
| 710 } | 721 } |
| 711 | 722 |
| 712 void Editor::clearLastEditCommand() { | 723 void Editor::clearLastEditCommand() { |
| 713 m_lastEditCommand.clear(); | 724 m_lastEditCommand.clear(); |
| 714 } | 725 } |
| 715 | 726 |
| 716 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const { | 727 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const { |
| 717 Element* target = associatedElementOf(selection.start()); | 728 Element* target = associatedElementOf(selection.start()); |
| 718 if (!target) | 729 if (!target) |
| 719 target = frame().document()->body(); | 730 target = frame().document()->body(); |
| 720 | 731 |
| 721 return target; | 732 return target; |
| 722 } | 733 } |
| 723 | 734 |
| 724 Element* Editor::findEventTargetFromSelection() const { | 735 Element* Editor::findEventTargetFromSelection() const { |
| 725 return findEventTargetFrom(frame().selection().selection()); | 736 return findEventTargetFrom(frame().selection().selection()); |
| 726 } | 737 } |
| 727 | 738 |
| 728 void Editor::applyStyle(StylePropertySet* style, | 739 void Editor::applyStyle(EditCommandSource source, |
| 740 StylePropertySet* style, |
| 729 InputEvent::InputType inputType) { | 741 InputEvent::InputType inputType) { |
| 730 switch (frame().selection().getSelectionType()) { | 742 switch (frame().selection().getSelectionType()) { |
| 731 case NoSelection: | 743 case NoSelection: |
| 732 // do nothing | 744 // do nothing |
| 733 break; | 745 break; |
| 734 case CaretSelection: | 746 case CaretSelection: |
| 735 computeAndSetTypingStyle(style, inputType); | 747 computeAndSetTypingStyle(source, style, inputType); |
| 736 break; | 748 break; |
| 737 case RangeSelection: | 749 case RangeSelection: |
| 738 if (style) { | 750 if (style) { |
| 739 DCHECK(frame().document()); | 751 DCHECK(frame().document()); |
| 740 ApplyStyleCommand::create(*frame().document(), | 752 ApplyStyleCommand::create(*frame().document(), |
| 741 EditingStyle::create(style), inputType) | 753 EditingStyle::create(style), inputType) |
| 742 ->apply(); | 754 ->apply(); |
| 743 } | 755 } |
| 744 break; | 756 break; |
| 745 } | 757 } |
| 746 } | 758 } |
| 747 | 759 |
| 748 void Editor::applyParagraphStyle(StylePropertySet* style, | 760 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. |
| 761 void Editor::applyParagraphStyle(EditCommandSource, |
| 762 StylePropertySet* style, |
| 749 InputEvent::InputType inputType) { | 763 InputEvent::InputType inputType) { |
| 750 if (frame().selection().isNone() || !style) | 764 if (frame().selection().isNone() || !style) |
| 751 return; | 765 return; |
| 752 DCHECK(frame().document()); | 766 DCHECK(frame().document()); |
| 753 ApplyStyleCommand::create(*frame().document(), EditingStyle::create(style), | 767 ApplyStyleCommand::create(*frame().document(), EditingStyle::create(style), |
| 754 inputType, ApplyStyleCommand::ForceBlockProperties) | 768 inputType, ApplyStyleCommand::ForceBlockProperties) |
| 755 ->apply(); | 769 ->apply(); |
| 756 } | 770 } |
| 757 | 771 |
| 758 void Editor::applyStyleToSelection(StylePropertySet* style, | 772 void Editor::applyStyleToSelection(EditCommandSource source, |
| 773 StylePropertySet* style, |
| 759 InputEvent::InputType inputType) { | 774 InputEvent::InputType inputType) { |
| 760 if (!style || style->isEmpty() || !canEditRichly()) | 775 if (!style || style->isEmpty() || !canEditRichly()) |
| 761 return; | 776 return; |
| 762 | 777 |
| 763 applyStyle(style, inputType); | 778 applyStyle(source, style, inputType); |
| 764 } | 779 } |
| 765 | 780 |
| 766 void Editor::applyParagraphStyleToSelection(StylePropertySet* style, | 781 void Editor::applyParagraphStyleToSelection(EditCommandSource source, |
| 782 StylePropertySet* style, |
| 767 InputEvent::InputType inputType) { | 783 InputEvent::InputType inputType) { |
| 768 if (!style || style->isEmpty() || !canEditRichly()) | 784 if (!style || style->isEmpty() || !canEditRichly()) |
| 769 return; | 785 return; |
| 770 | 786 |
| 771 applyParagraphStyle(style, inputType); | 787 applyParagraphStyle(source, style, inputType); |
| 772 } | 788 } |
| 773 | 789 |
| 774 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, | 790 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, |
| 775 const String& value) const { | 791 const String& value) const { |
| 776 EditingStyle* styleToCheck = EditingStyle::create(propertyID, value); | 792 EditingStyle* styleToCheck = EditingStyle::create(propertyID, value); |
| 777 EditingStyle* styleAtStart = EditingStyle::styleAtSelectionStart( | 793 EditingStyle* styleAtStart = EditingStyle::styleAtSelectionStart( |
| 778 frame().selection().selection(), propertyID == CSSPropertyBackgroundColor, | 794 frame().selection().selection(), propertyID == CSSPropertyBackgroundColor, |
| 779 styleToCheck->style()); | 795 styleToCheck->style()); |
| 780 return styleToCheck->triStateOfStyle(styleAtStart); | 796 return styleToCheck->triStateOfStyle(styleAtStart); |
| 781 } | 797 } |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 frame().inputMethodController().clear(); | 963 frame().inputMethodController().clear(); |
| 948 m_shouldStyleWithCSS = false; | 964 m_shouldStyleWithCSS = false; |
| 949 m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv; | 965 m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv; |
| 950 m_undoStack->clear(); | 966 m_undoStack->clear(); |
| 951 } | 967 } |
| 952 | 968 |
| 953 bool Editor::insertText(const String& text, KeyboardEvent* triggeringEvent) { | 969 bool Editor::insertText(const String& text, KeyboardEvent* triggeringEvent) { |
| 954 return frame().eventHandler().handleTextInputEvent(text, triggeringEvent); | 970 return frame().eventHandler().handleTextInputEvent(text, triggeringEvent); |
| 955 } | 971 } |
| 956 | 972 |
| 957 bool Editor::insertTextWithoutSendingTextEvent(const String& text, | 973 bool Editor::insertTextWithoutSendingTextEvent(EditCommandSource source, |
| 974 const String& text, |
| 958 bool selectInsertedText, | 975 bool selectInsertedText, |
| 959 TextEvent* triggeringEvent) { | 976 TextEvent* triggeringEvent) { |
| 960 if (text.isEmpty()) | 977 if (text.isEmpty()) |
| 961 return false; | 978 return false; |
| 962 | 979 |
| 963 const VisibleSelection& selection = selectionForCommand(triggeringEvent); | 980 const VisibleSelection& selection = selectionForCommand(triggeringEvent); |
| 964 if (!selection.isContentEditable()) | 981 if (!selection.isContentEditable()) |
| 965 return false; | 982 return false; |
| 966 | 983 |
| 967 spellChecker().updateMarkersForWordsAffectedByEditing( | 984 spellChecker().updateMarkersForWordsAffectedByEditing( |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), | 1069 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), |
| 1053 InputEvent::InputType::DeleteByCut, | 1070 InputEvent::InputType::DeleteByCut, |
| 1054 nullptr, nullptr) != | 1071 nullptr, nullptr) != |
| 1055 DispatchEventResult::NotCanceled) | 1072 DispatchEventResult::NotCanceled) |
| 1056 return; | 1073 return; |
| 1057 // 'beforeinput' event handler may destroy target frame. | 1074 // 'beforeinput' event handler may destroy target frame. |
| 1058 if (m_frame->document()->frame() != m_frame) | 1075 if (m_frame->document()->frame() != m_frame) |
| 1059 return; | 1076 return; |
| 1060 } | 1077 } |
| 1061 deleteSelectionWithSmartDelete( | 1078 deleteSelectionWithSmartDelete( |
| 1062 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 1079 source, canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1063 InputEvent::InputType::DeleteByCut); | 1080 InputEvent::InputType::DeleteByCut); |
| 1064 } | 1081 } |
| 1065 } | 1082 } |
| 1066 | 1083 |
| 1067 void Editor::copy() { | 1084 void Editor::copy() { |
| 1068 if (tryDHTMLCopy()) | 1085 if (tryDHTMLCopy()) |
| 1069 return; // DHTML did the whole operation | 1086 return; // DHTML did the whole operation |
| 1070 if (!canCopy()) | 1087 if (!canCopy()) |
| 1071 return; | 1088 return; |
| 1072 | 1089 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 | 1146 |
| 1130 void Editor::pasteAsPlainText(EditCommandSource source) { | 1147 void Editor::pasteAsPlainText(EditCommandSource source) { |
| 1131 if (tryDHTMLPaste(PlainTextOnly)) | 1148 if (tryDHTMLPaste(PlainTextOnly)) |
| 1132 return; | 1149 return; |
| 1133 if (!canPaste()) | 1150 if (!canPaste()) |
| 1134 return; | 1151 return; |
| 1135 spellChecker().updateMarkersForWordsAffectedByEditing(false); | 1152 spellChecker().updateMarkersForWordsAffectedByEditing(false); |
| 1136 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); | 1153 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); |
| 1137 } | 1154 } |
| 1138 | 1155 |
| 1139 void Editor::performDelete() { | 1156 void Editor::performDelete(EditCommandSource source) { |
| 1140 if (!canDelete()) | 1157 if (!canDelete()) |
| 1141 return; | 1158 return; |
| 1142 | 1159 |
| 1143 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 1160 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 1144 // needs to be audited. See http://crbug.com/590369 for more details. | 1161 // needs to be audited. See http://crbug.com/590369 for more details. |
| 1145 // |selectedRange| requires clean layout for visible selection normalization. | 1162 // |selectedRange| requires clean layout for visible selection normalization. |
| 1146 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 1163 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1147 | 1164 |
| 1148 addToKillRing(selectedRange()); | 1165 addToKillRing(selectedRange()); |
| 1149 // TODO(chongz): |Editor::performDelete()| has no direction. | 1166 // TODO(chongz): |Editor::performDelete()| has no direction. |
| 1150 // https://github.com/w3c/editing/issues/130 | 1167 // https://github.com/w3c/editing/issues/130 |
| 1151 deleteSelectionWithSmartDelete( | 1168 deleteSelectionWithSmartDelete( |
| 1152 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 1169 source, canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1153 InputEvent::InputType::DeleteContentBackward); | 1170 InputEvent::InputType::DeleteContentBackward); |
| 1154 | 1171 |
| 1155 // clear the "start new kill ring sequence" setting, because it was set to | 1172 // clear the "start new kill ring sequence" setting, because it was set to |
| 1156 // true when the selection was updated by deleting the range | 1173 // true when the selection was updated by deleting the range |
| 1157 setStartNewKillRingSequence(false); | 1174 setStartNewKillRingSequence(false); |
| 1158 } | 1175 } |
| 1159 | 1176 |
| 1160 static void countEditingEvent(ExecutionContext* executionContext, | 1177 static void countEditingEvent(ExecutionContext* executionContext, |
| 1161 const Event* event, | 1178 const Event* event, |
| 1162 UseCounter::Feature featureOnInput, | 1179 UseCounter::Feature featureOnInput, |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 void Editor::copyImage(const HitTestResult& result) { | 1246 void Editor::copyImage(const HitTestResult& result) { |
| 1230 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), | 1247 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), |
| 1231 result.innerNodeOrImageMapImage(), | 1248 result.innerNodeOrImageMapImage(), |
| 1232 result.altDisplayString()); | 1249 result.altDisplayString()); |
| 1233 } | 1250 } |
| 1234 | 1251 |
| 1235 bool Editor::canUndo() { | 1252 bool Editor::canUndo() { |
| 1236 return m_undoStack->canUndo(); | 1253 return m_undoStack->canUndo(); |
| 1237 } | 1254 } |
| 1238 | 1255 |
| 1239 void Editor::undo() { | 1256 // TODO(chongz): Fire 'beforeinput' for user triggered undo. |
| 1257 void Editor::undo(EditCommandSource) { |
| 1240 m_undoStack->undo(); | 1258 m_undoStack->undo(); |
| 1241 } | 1259 } |
| 1242 | 1260 |
| 1243 bool Editor::canRedo() { | 1261 bool Editor::canRedo() { |
| 1244 return m_undoStack->canRedo(); | 1262 return m_undoStack->canRedo(); |
| 1245 } | 1263 } |
| 1246 | 1264 |
| 1247 void Editor::redo() { | 1265 // TODO(chongz): Fire 'beforeinput' for user triggered redo. |
| 1266 void Editor::redo(EditCommandSource) { |
| 1248 m_undoStack->redo(); | 1267 m_undoStack->redo(); |
| 1249 } | 1268 } |
| 1250 | 1269 |
| 1251 void Editor::setBaseWritingDirection(WritingDirection direction) { | 1270 void Editor::setBaseWritingDirection(WritingDirection direction) { |
| 1252 Element* focusedElement = frame().document()->focusedElement(); | 1271 Element* focusedElement = frame().document()->focusedElement(); |
| 1253 if (isTextControlElement(focusedElement)) { | 1272 if (isTextControlElement(focusedElement)) { |
| 1254 if (direction == NaturalWritingDirection) | 1273 if (direction == NaturalWritingDirection) |
| 1255 return; | 1274 return; |
| 1256 focusedElement->setAttribute( | 1275 focusedElement->setAttribute( |
| 1257 dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl"); | 1276 dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl"); |
| 1258 focusedElement->dispatchInputEvent(); | 1277 focusedElement->dispatchInputEvent(); |
| 1259 return; | 1278 return; |
| 1260 } | 1279 } |
| 1261 | 1280 |
| 1262 MutableStylePropertySet* style = | 1281 MutableStylePropertySet* style = |
| 1263 MutableStylePropertySet::create(HTMLQuirksMode); | 1282 MutableStylePropertySet::create(HTMLQuirksMode); |
| 1264 style->setProperty( | 1283 style->setProperty( |
| 1265 CSSPropertyDirection, | 1284 CSSPropertyDirection, |
| 1266 direction == LeftToRightWritingDirection | 1285 direction == LeftToRightWritingDirection |
| 1267 ? "ltr" | 1286 ? "ltr" |
| 1268 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", | 1287 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", |
| 1269 false); | 1288 false); |
| 1270 applyParagraphStyleToSelection( | 1289 applyParagraphStyleToSelection( |
| 1271 style, InputEvent::InputType::FormatSetBlockTextDirection); | 1290 EditCommandSource::kMenuOrKeyBinding, style, |
| 1291 InputEvent::InputType::FormatSetBlockTextDirection); |
| 1272 } | 1292 } |
| 1273 | 1293 |
| 1274 void Editor::revealSelectionAfterEditingOperation( | 1294 void Editor::revealSelectionAfterEditingOperation( |
| 1275 const ScrollAlignment& alignment, | 1295 const ScrollAlignment& alignment, |
| 1276 RevealExtentOption revealExtentOption) { | 1296 RevealExtentOption revealExtentOption) { |
| 1277 if (m_preventRevealSelection) | 1297 if (m_preventRevealSelection) |
| 1278 return; | 1298 return; |
| 1279 frame().selection().revealSelection(alignment, revealExtentOption); | 1299 frame().selection().revealSelection(alignment, revealExtentOption); |
| 1280 } | 1300 } |
| 1281 | 1301 |
| 1282 void Editor::transpose() { | 1302 void Editor::transpose(EditCommandSource source) { |
| 1283 if (!canEdit()) | 1303 if (!canEdit()) |
| 1284 return; | 1304 return; |
| 1285 | 1305 |
| 1286 VisibleSelection selection = frame().selection().selection(); | 1306 VisibleSelection selection = frame().selection().selection(); |
| 1287 if (!selection.isCaret()) | 1307 if (!selection.isCaret()) |
| 1288 return; | 1308 return; |
| 1289 | 1309 |
| 1290 // Make a selection that goes back one character and forward two characters. | 1310 // Make a selection that goes back one character and forward two characters. |
| 1291 VisiblePosition caret = selection.visibleStart(); | 1311 VisiblePosition caret = selection.visibleStart(); |
| 1292 VisiblePosition next = | 1312 VisiblePosition next = |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1309 return; | 1329 return; |
| 1310 String transposed = text.right(1) + text.left(1); | 1330 String transposed = text.right(1) + text.left(1); |
| 1311 | 1331 |
| 1312 // Select the two characters. | 1332 // Select the two characters. |
| 1313 if (newSelection != frame().selection().selection()) | 1333 if (newSelection != frame().selection().selection()) |
| 1314 frame().selection().setSelection(newSelection); | 1334 frame().selection().setSelection(newSelection); |
| 1315 | 1335 |
| 1316 // Insert the transposed characters. | 1336 // Insert the transposed characters. |
| 1317 // TODO(chongz): Once we add |InsertTranspose| in |InputEvent::InputType|, we | 1337 // TODO(chongz): Once we add |InsertTranspose| in |InputEvent::InputType|, we |
| 1318 // should use it instead of |InsertFromPaste|. | 1338 // should use it instead of |InsertFromPaste|. |
| 1319 replaceSelectionWithText(transposed, false, false, | 1339 replaceSelectionWithText(source, transposed, false, false, |
| 1320 InputEvent::InputType::InsertFromPaste); | 1340 InputEvent::InputType::InsertFromPaste); |
| 1321 } | 1341 } |
| 1322 | 1342 |
| 1323 void Editor::addToKillRing(const EphemeralRange& range) { | 1343 void Editor::addToKillRing(const EphemeralRange& range) { |
| 1324 if (m_shouldStartNewKillRingSequence) | 1344 if (m_shouldStartNewKillRingSequence) |
| 1325 killRing().startNewSequence(); | 1345 killRing().startNewSequence(); |
| 1326 | 1346 |
| 1327 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | 1347 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 1328 String text = plainText(range); | 1348 String text = plainText(range); |
| 1329 killRing().append(text); | 1349 killRing().append(text); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 std::max(startCaretRect.height(), endCaretRect.height())); | 1410 std::max(startCaretRect.height(), endCaretRect.height())); |
| 1391 } | 1411 } |
| 1392 | 1412 |
| 1393 // start and end aren't on the same line, so go from start to the end of its | 1413 // start and end aren't on the same line, so go from start to the end of its |
| 1394 // line | 1414 // line |
| 1395 return IntRect(startCaretRect.x(), startCaretRect.y(), | 1415 return IntRect(startCaretRect.x(), startCaretRect.y(), |
| 1396 (startCaretRect.width() + extraWidthToEndOfLine).toInt(), | 1416 (startCaretRect.width() + extraWidthToEndOfLine).toInt(), |
| 1397 startCaretRect.height()); | 1417 startCaretRect.height()); |
| 1398 } | 1418 } |
| 1399 | 1419 |
| 1400 void Editor::computeAndSetTypingStyle(StylePropertySet* style, | 1420 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. |
| 1421 void Editor::computeAndSetTypingStyle(EditCommandSource, |
| 1422 StylePropertySet* style, |
| 1401 InputEvent::InputType inputType) { | 1423 InputEvent::InputType inputType) { |
| 1402 if (!style || style->isEmpty()) { | 1424 if (!style || style->isEmpty()) { |
| 1403 frame().selection().clearTypingStyle(); | 1425 frame().selection().clearTypingStyle(); |
| 1404 return; | 1426 return; |
| 1405 } | 1427 } |
| 1406 | 1428 |
| 1407 // Calculate the current typing style. | 1429 // Calculate the current typing style. |
| 1408 EditingStyle* typingStyle = nullptr; | 1430 EditingStyle* typingStyle = nullptr; |
| 1409 if (frame().selection().typingStyle()) { | 1431 if (frame().selection().typingStyle()) { |
| 1410 typingStyle = frame().selection().typingStyle()->copy(); | 1432 typingStyle = frame().selection().typingStyle()->copy(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1662 DCHECK(!document.documentElement()); | 1684 DCHECK(!document.documentElement()); |
| 1663 document.appendChild(root); | 1685 document.appendChild(root); |
| 1664 | 1686 |
| 1665 // TODO(tkent): Should we check and move Text node children of <html>? | 1687 // TODO(tkent): Should we check and move Text node children of <html>? |
| 1666 } | 1688 } |
| 1667 | 1689 |
| 1668 void Editor::replaceSelection(const String& text) { | 1690 void Editor::replaceSelection(const String& text) { |
| 1669 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | 1691 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 1670 bool selectReplacement = behavior().shouldSelectReplacement(); | 1692 bool selectReplacement = behavior().shouldSelectReplacement(); |
| 1671 bool smartReplace = true; | 1693 bool smartReplace = true; |
| 1672 replaceSelectionWithText(text, selectReplacement, smartReplace, | 1694 replaceSelectionWithText(EditCommandSource::kMenuOrKeyBinding, text, |
| 1695 selectReplacement, smartReplace, |
| 1673 InputEvent::InputType::InsertReplacementText); | 1696 InputEvent::InputType::InsertReplacementText); |
| 1674 } | 1697 } |
| 1675 | 1698 |
| 1699 void Editor::replaceSelectionForSpellChecker(const String& text) { |
| 1700 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 1701 const bool kSelectReplacement = false; |
| 1702 const bool kSmartReplace = false; |
| 1703 replaceSelectionWithText(EditCommandSource::kMenuOrKeyBinding, text, |
| 1704 kSelectReplacement, kSmartReplace, |
| 1705 InputEvent::InputType::InsertReplacementText); |
| 1706 } |
| 1707 |
| 1676 DEFINE_TRACE(Editor) { | 1708 DEFINE_TRACE(Editor) { |
| 1677 visitor->trace(m_frame); | 1709 visitor->trace(m_frame); |
| 1678 visitor->trace(m_lastEditCommand); | 1710 visitor->trace(m_lastEditCommand); |
| 1679 visitor->trace(m_undoStack); | 1711 visitor->trace(m_undoStack); |
| 1680 visitor->trace(m_mark); | 1712 visitor->trace(m_mark); |
| 1681 } | 1713 } |
| 1682 | 1714 |
| 1683 } // namespace blink | 1715 } // namespace blink |
| OLD | NEW |