| 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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 if (event->isIncrementalInsertion()) | 222 if (event->isIncrementalInsertion()) |
| 223 return false; | 223 return false; |
| 224 | 224 |
| 225 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 225 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 226 // needs to be audited. See http://crbug.com/590369 for more details. | 226 // needs to be audited. See http://crbug.com/590369 for more details. |
| 227 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 227 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 228 | 228 |
| 229 if (event->isPaste()) { | 229 if (event->isPaste()) { |
| 230 if (event->pastingFragment()) { | 230 if (event->pastingFragment()) { |
| 231 replaceSelectionWithFragment( | 231 replaceSelectionWithFragment( |
| 232 EditCommandSource::kMenuOrKeyBinding, event->pastingFragment(), false, | 232 event->pastingFragment(), false, event->shouldSmartReplace(), |
| 233 event->shouldSmartReplace(), event->shouldMatchStyle(), | 233 event->shouldMatchStyle(), InputEvent::InputType::InsertFromPaste); |
| 234 InputEvent::InputType::InsertFromPaste); | |
| 235 } else { | 234 } else { |
| 236 replaceSelectionWithText( | 235 replaceSelectionWithText(event->data(), false, |
| 237 EditCommandSource::kMenuOrKeyBinding, event->data(), false, | 236 event->shouldSmartReplace(), |
| 238 event->shouldSmartReplace(), InputEvent::InputType::InsertFromPaste); | 237 InputEvent::InputType::InsertFromPaste); |
| 239 } | 238 } |
| 240 return true; | 239 return true; |
| 241 } | 240 } |
| 242 | 241 |
| 243 String data = event->data(); | 242 String data = event->data(); |
| 244 if (data == "\n") { | 243 if (data == "\n") { |
| 245 if (event->isLineBreak()) | 244 if (event->isLineBreak()) |
| 246 return insertLineBreak(); | 245 return insertLineBreak(); |
| 247 return insertParagraphSeparator(); | 246 return insertParagraphSeparator(); |
| 248 } | 247 } |
| 249 | 248 |
| 250 // Typing spaces at the beginning of wrapped line is confusing, because | 249 // Typing spaces at the beginning of wrapped line is confusing, because |
| 251 // inserted spaces would appear in the previous line. | 250 // inserted spaces would appear in the previous line. |
| 252 // Insert a line break automatically so that the spaces appear at the caret. | 251 // Insert a line break automatically so that the spaces appear at the caret. |
| 253 // TODO(kojii): rich editing has the same issue, but has more options and | 252 // TODO(kojii): rich editing has the same issue, but has more options and |
| 254 // needs coordination with JS. Enable for plaintext only for now and collect | 253 // needs coordination with JS. Enable for plaintext only for now and collect |
| 255 // feedback. | 254 // feedback. |
| 256 if (data == " " && !canEditRichly() && | 255 if (data == " " && !canEditRichly() && |
| 257 isCaretAtStartOfWrappedLine(frame().selection())) { | 256 isCaretAtStartOfWrappedLine(frame().selection())) { |
| 258 insertLineBreak(); | 257 insertLineBreak(); |
| 259 } | 258 } |
| 260 | 259 |
| 261 return insertTextWithoutSendingTextEvent(EditCommandSource::kMenuOrKeyBinding, | 260 return insertTextWithoutSendingTextEvent(data, false, event); |
| 262 data, false, event); | |
| 263 } | 261 } |
| 264 | 262 |
| 265 bool Editor::canEdit() const { | 263 bool Editor::canEdit() const { |
| 266 return frame().selection().rootEditableElement(); | 264 return frame().selection().rootEditableElement(); |
| 267 } | 265 } |
| 268 | 266 |
| 269 bool Editor::canEditRichly() const { | 267 bool Editor::canEditRichly() const { |
| 270 return frame().selection().isContentRichlyEditable(); | 268 return frame().selection().isContentRichlyEditable(); |
| 271 } | 269 } |
| 272 | 270 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 return smartInsertDeleteEnabled() && | 330 return smartInsertDeleteEnabled() && |
| 333 frame().selection().granularity() == WordGranularity; | 331 frame().selection().granularity() == WordGranularity; |
| 334 } | 332 } |
| 335 | 333 |
| 336 bool Editor::isSelectTrailingWhitespaceEnabled() const { | 334 bool Editor::isSelectTrailingWhitespaceEnabled() const { |
| 337 if (Settings* settings = frame().settings()) | 335 if (Settings* settings = frame().settings()) |
| 338 return settings->getSelectTrailingWhitespaceEnabled(); | 336 return settings->getSelectTrailingWhitespaceEnabled(); |
| 339 return false; | 337 return false; |
| 340 } | 338 } |
| 341 | 339 |
| 342 bool Editor::deleteWithDirection(EditCommandSource source, | 340 bool Editor::deleteWithDirection(DeleteDirection direction, |
| 343 DeleteDirection direction, | |
| 344 TextGranularity granularity, | 341 TextGranularity granularity, |
| 345 bool killRing, | 342 bool killRing, |
| 346 bool isTypingAction) { | 343 bool isTypingAction) { |
| 347 if (!canEdit()) | 344 if (!canEdit()) |
| 348 return false; | 345 return false; |
| 349 | 346 |
| 350 EditingState editingState; | 347 EditingState editingState; |
| 351 if (frame().selection().isRange()) { | 348 if (frame().selection().isRange()) { |
| 352 if (isTypingAction) { | 349 if (isTypingAction) { |
| 353 DCHECK(frame().document()); | 350 DCHECK(frame().document()); |
| 354 TypingCommand::deleteKeyPressed( | 351 TypingCommand::deleteKeyPressed( |
| 355 *frame().document(), | 352 *frame().document(), |
| 356 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity); | 353 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity); |
| 357 revealSelectionAfterEditingOperation(); | 354 revealSelectionAfterEditingOperation(); |
| 358 } else { | 355 } else { |
| 359 if (killRing) | 356 if (killRing) |
| 360 addToKillRing(selectedRange()); | 357 addToKillRing(selectedRange()); |
| 361 deleteSelectionWithSmartDelete( | 358 deleteSelectionWithSmartDelete( |
| 362 source, | |
| 363 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 359 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 364 deletionInputTypeFromTextGranularity(direction, granularity)); | 360 deletionInputTypeFromTextGranularity(direction, granularity)); |
| 365 // Implicitly calls revealSelectionAfterEditingOperation(). | 361 // Implicitly calls revealSelectionAfterEditingOperation(). |
| 366 } | 362 } |
| 367 } else { | 363 } else { |
| 368 TypingCommand::Options options = 0; | 364 TypingCommand::Options options = 0; |
| 369 if (canSmartCopyOrDelete()) | 365 if (canSmartCopyOrDelete()) |
| 370 options |= TypingCommand::SmartDelete; | 366 options |= TypingCommand::SmartDelete; |
| 371 if (killRing) | 367 if (killRing) |
| 372 options |= TypingCommand::KillRing; | 368 options |= TypingCommand::KillRing; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 389 | 385 |
| 390 // FIXME: We should to move this down into deleteKeyPressed. | 386 // FIXME: We should to move this down into deleteKeyPressed. |
| 391 // clear the "start new kill ring sequence" setting, because it was set to | 387 // clear the "start new kill ring sequence" setting, because it was set to |
| 392 // true when the selection was updated by deleting the range | 388 // true when the selection was updated by deleting the range |
| 393 if (killRing) | 389 if (killRing) |
| 394 setStartNewKillRingSequence(false); | 390 setStartNewKillRingSequence(false); |
| 395 | 391 |
| 396 return true; | 392 return true; |
| 397 } | 393 } |
| 398 | 394 |
| 399 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. | |
| 400 void Editor::deleteSelectionWithSmartDelete( | 395 void Editor::deleteSelectionWithSmartDelete( |
| 401 EditCommandSource, | |
| 402 DeleteMode deleteMode, | 396 DeleteMode deleteMode, |
| 403 InputEvent::InputType inputType, | 397 InputEvent::InputType inputType, |
| 404 const Position& referenceMovePosition) { | 398 const Position& referenceMovePosition) { |
| 405 if (frame().selection().isNone()) | 399 if (frame().selection().isNone()) |
| 406 return; | 400 return; |
| 407 | 401 |
| 408 const bool kMergeBlocksAfterDelete = true; | 402 const bool kMergeBlocksAfterDelete = true; |
| 409 const bool kExpandForSpecialElements = false; | 403 const bool kExpandForSpecialElements = false; |
| 410 const bool kSanitizeMarkup = true; | 404 const bool kSanitizeMarkup = true; |
| 411 DCHECK(frame().document()); | 405 DCHECK(frame().document()); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 // invalidate clipboard here for security | 578 // invalidate clipboard here for security |
| 585 dataTransfer->setAccessPolicy(DataTransferNumb); | 579 dataTransfer->setAccessPolicy(DataTransferNumb); |
| 586 | 580 |
| 587 return !noDefaultProcessing; | 581 return !noDefaultProcessing; |
| 588 } | 582 } |
| 589 | 583 |
| 590 bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard) { | 584 bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard) { |
| 591 return smartInsertDeleteEnabled() && pasteboard->canSmartReplace(); | 585 return smartInsertDeleteEnabled() && pasteboard->canSmartReplace(); |
| 592 } | 586 } |
| 593 | 587 |
| 594 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. | 588 void Editor::replaceSelectionWithFragment(DocumentFragment* fragment, |
| 595 void Editor::replaceSelectionWithFragment(EditCommandSource, | |
| 596 DocumentFragment* fragment, | |
| 597 bool selectReplacement, | 589 bool selectReplacement, |
| 598 bool smartReplace, | 590 bool smartReplace, |
| 599 bool matchStyle, | 591 bool matchStyle, |
| 600 InputEvent::InputType inputType) { | 592 InputEvent::InputType inputType) { |
| 601 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | 593 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 602 if (frame().selection().isNone() || | 594 if (frame().selection().isNone() || |
| 603 !frame().selection().isContentEditable() || !fragment) | 595 !frame().selection().isContentEditable() || !fragment) |
| 604 return; | 596 return; |
| 605 | 597 |
| 606 ReplaceSelectionCommand::CommandOptions options = | 598 ReplaceSelectionCommand::CommandOptions options = |
| 607 ReplaceSelectionCommand::PreventNesting | | 599 ReplaceSelectionCommand::PreventNesting | |
| 608 ReplaceSelectionCommand::SanitizeFragment; | 600 ReplaceSelectionCommand::SanitizeFragment; |
| 609 if (selectReplacement) | 601 if (selectReplacement) |
| 610 options |= ReplaceSelectionCommand::SelectReplacement; | 602 options |= ReplaceSelectionCommand::SelectReplacement; |
| 611 if (smartReplace) | 603 if (smartReplace) |
| 612 options |= ReplaceSelectionCommand::SmartReplace; | 604 options |= ReplaceSelectionCommand::SmartReplace; |
| 613 if (matchStyle) | 605 if (matchStyle) |
| 614 options |= ReplaceSelectionCommand::MatchStyle; | 606 options |= ReplaceSelectionCommand::MatchStyle; |
| 615 DCHECK(frame().document()); | 607 DCHECK(frame().document()); |
| 616 ReplaceSelectionCommand::create(*frame().document(), fragment, options, | 608 ReplaceSelectionCommand::create(*frame().document(), fragment, options, |
| 617 inputType) | 609 inputType) |
| 618 ->apply(); | 610 ->apply(); |
| 619 revealSelectionAfterEditingOperation(); | 611 revealSelectionAfterEditingOperation(); |
| 620 } | 612 } |
| 621 | 613 |
| 622 void Editor::replaceSelectionWithText(EditCommandSource source, | 614 void Editor::replaceSelectionWithText(const String& text, |
| 623 const String& text, | |
| 624 bool selectReplacement, | 615 bool selectReplacement, |
| 625 bool smartReplace, | 616 bool smartReplace, |
| 626 InputEvent::InputType inputType) { | 617 InputEvent::InputType inputType) { |
| 627 replaceSelectionWithFragment( | 618 replaceSelectionWithFragment(createFragmentFromText(selectedRange(), text), |
| 628 source, createFragmentFromText(selectedRange(), text), selectReplacement, | 619 selectReplacement, smartReplace, true, |
| 629 smartReplace, true, inputType); | 620 inputType); |
| 630 } | 621 } |
| 631 | 622 |
| 632 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. | 623 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. |
| 633 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, | 624 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, |
| 634 InsertMode insertMode, | 625 InsertMode insertMode, |
| 635 DragSourceType dragSourceType) { | 626 DragSourceType dragSourceType) { |
| 636 ReplaceSelectionCommand::CommandOptions options = | 627 ReplaceSelectionCommand::CommandOptions options = |
| 637 ReplaceSelectionCommand::SelectReplacement | | 628 ReplaceSelectionCommand::SelectReplacement | |
| 638 ReplaceSelectionCommand::PreventNesting; | 629 ReplaceSelectionCommand::PreventNesting; |
| 639 if (insertMode == InsertMode::Smart) | 630 if (insertMode == InsertMode::Smart) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 658 dragSource, InputEvent::InputType::DeleteByDrag, | 649 dragSource, InputEvent::InputType::DeleteByDrag, |
| 659 nullptr) == DispatchEventResult::NotCanceled; | 650 nullptr) == DispatchEventResult::NotCanceled; |
| 660 | 651 |
| 661 // 'beforeinput' event handler may destroy frame, return false to cancel | 652 // 'beforeinput' event handler may destroy frame, return false to cancel |
| 662 // remaining actions; | 653 // remaining actions; |
| 663 if (m_frame->document()->frame() != m_frame) | 654 if (m_frame->document()->frame() != m_frame) |
| 664 return false; | 655 return false; |
| 665 | 656 |
| 666 if (shouldDelete && dragSource->isConnected()) { | 657 if (shouldDelete && dragSource->isConnected()) { |
| 667 deleteSelectionWithSmartDelete( | 658 deleteSelectionWithSmartDelete( |
| 668 EditCommandSource::kMenuOrKeyBinding, deleteMode, | 659 deleteMode, InputEvent::InputType::DeleteByDrag, referenceMovePosition); |
| 669 InputEvent::InputType::DeleteByDrag, referenceMovePosition); | |
| 670 } | 660 } |
| 671 | 661 |
| 672 return true; | 662 return true; |
| 673 } | 663 } |
| 674 | 664 |
| 675 bool Editor::replaceSelectionAfterDraggingWithEvents( | 665 bool Editor::replaceSelectionAfterDraggingWithEvents( |
| 676 Element* dropTarget, | 666 Element* dropTarget, |
| 677 DragData* dragData, | 667 DragData* dragData, |
| 678 DocumentFragment* fragment, | 668 DocumentFragment* fragment, |
| 679 Range* dropCaretRange, | 669 Range* dropCaretRange, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 if (frame().settings() && frame().settings()->getAccessibilityEnabled()) { | 713 if (frame().settings() && frame().settings()->getAccessibilityEnabled()) { |
| 724 Node* node = endingSelection.start().anchorNode(); | 714 Node* node = endingSelection.start().anchorNode(); |
| 725 if (AXObjectCache* cache = frame().document()->existingAXObjectCache()) | 715 if (AXObjectCache* cache = frame().document()->existingAXObjectCache()) |
| 726 cache->handleEditableTextContentChanged(node); | 716 cache->handleEditableTextContentChanged(node); |
| 727 } | 717 } |
| 728 | 718 |
| 729 spellChecker().updateMarkersForWordsAffectedByEditing(true); | 719 spellChecker().updateMarkersForWordsAffectedByEditing(true); |
| 730 client().respondToChangedContents(); | 720 client().respondToChangedContents(); |
| 731 } | 721 } |
| 732 | 722 |
| 733 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. | 723 void Editor::removeFormattingAndStyle() { |
| 734 void Editor::removeFormattingAndStyle(EditCommandSource) { | |
| 735 DCHECK(frame().document()); | 724 DCHECK(frame().document()); |
| 736 RemoveFormatCommand::create(*frame().document())->apply(); | 725 RemoveFormatCommand::create(*frame().document())->apply(); |
| 737 } | 726 } |
| 738 | 727 |
| 739 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) { | 728 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) { |
| 740 DCHECK(commandGroupWrapper->isCommandGroupWrapper()); | 729 DCHECK(commandGroupWrapper->isCommandGroupWrapper()); |
| 741 m_lastEditCommand = commandGroupWrapper; | 730 m_lastEditCommand = commandGroupWrapper; |
| 742 } | 731 } |
| 743 | 732 |
| 744 void Editor::clearLastEditCommand() { | 733 void Editor::clearLastEditCommand() { |
| 745 m_lastEditCommand.clear(); | 734 m_lastEditCommand.clear(); |
| 746 } | 735 } |
| 747 | 736 |
| 748 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const { | 737 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const { |
| 749 Element* target = associatedElementOf(selection.start()); | 738 Element* target = associatedElementOf(selection.start()); |
| 750 if (!target) | 739 if (!target) |
| 751 target = frame().document()->body(); | 740 target = frame().document()->body(); |
| 752 | 741 |
| 753 return target; | 742 return target; |
| 754 } | 743 } |
| 755 | 744 |
| 756 Element* Editor::findEventTargetFromSelection() const { | 745 Element* Editor::findEventTargetFromSelection() const { |
| 757 return findEventTargetFrom(frame().selection().selection()); | 746 return findEventTargetFrom(frame().selection().selection()); |
| 758 } | 747 } |
| 759 | 748 |
| 760 void Editor::applyStyle(EditCommandSource source, | 749 void Editor::applyStyle(StylePropertySet* style, |
| 761 StylePropertySet* style, | |
| 762 InputEvent::InputType inputType) { | 750 InputEvent::InputType inputType) { |
| 763 switch (frame().selection().getSelectionType()) { | 751 switch (frame().selection().getSelectionType()) { |
| 764 case NoSelection: | 752 case NoSelection: |
| 765 // do nothing | 753 // do nothing |
| 766 break; | 754 break; |
| 767 case CaretSelection: | 755 case CaretSelection: |
| 768 computeAndSetTypingStyle(source, style, inputType); | 756 computeAndSetTypingStyle(style, inputType); |
| 769 break; | 757 break; |
| 770 case RangeSelection: | 758 case RangeSelection: |
| 771 if (style) { | 759 if (style) { |
| 772 DCHECK(frame().document()); | 760 DCHECK(frame().document()); |
| 773 ApplyStyleCommand::create(*frame().document(), | 761 ApplyStyleCommand::create(*frame().document(), |
| 774 EditingStyle::create(style), inputType) | 762 EditingStyle::create(style), inputType) |
| 775 ->apply(); | 763 ->apply(); |
| 776 } | 764 } |
| 777 break; | 765 break; |
| 778 } | 766 } |
| 779 } | 767 } |
| 780 | 768 |
| 781 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. | 769 void Editor::applyParagraphStyle(StylePropertySet* style, |
| 782 void Editor::applyParagraphStyle(EditCommandSource, | |
| 783 StylePropertySet* style, | |
| 784 InputEvent::InputType inputType) { | 770 InputEvent::InputType inputType) { |
| 785 if (frame().selection().isNone() || !style) | 771 if (frame().selection().isNone() || !style) |
| 786 return; | 772 return; |
| 787 DCHECK(frame().document()); | 773 DCHECK(frame().document()); |
| 788 ApplyStyleCommand::create(*frame().document(), EditingStyle::create(style), | 774 ApplyStyleCommand::create(*frame().document(), EditingStyle::create(style), |
| 789 inputType, ApplyStyleCommand::ForceBlockProperties) | 775 inputType, ApplyStyleCommand::ForceBlockProperties) |
| 790 ->apply(); | 776 ->apply(); |
| 791 } | 777 } |
| 792 | 778 |
| 793 void Editor::applyStyleToSelection(EditCommandSource source, | 779 void Editor::applyStyleToSelection(StylePropertySet* style, |
| 794 StylePropertySet* style, | |
| 795 InputEvent::InputType inputType) { | 780 InputEvent::InputType inputType) { |
| 796 if (!style || style->isEmpty() || !canEditRichly()) | 781 if (!style || style->isEmpty() || !canEditRichly()) |
| 797 return; | 782 return; |
| 798 | 783 |
| 799 applyStyle(source, style, inputType); | 784 applyStyle(style, inputType); |
| 800 } | 785 } |
| 801 | 786 |
| 802 void Editor::applyParagraphStyleToSelection(EditCommandSource source, | 787 void Editor::applyParagraphStyleToSelection(StylePropertySet* style, |
| 803 StylePropertySet* style, | |
| 804 InputEvent::InputType inputType) { | 788 InputEvent::InputType inputType) { |
| 805 if (!style || style->isEmpty() || !canEditRichly()) | 789 if (!style || style->isEmpty() || !canEditRichly()) |
| 806 return; | 790 return; |
| 807 | 791 |
| 808 applyParagraphStyle(source, style, inputType); | 792 applyParagraphStyle(style, inputType); |
| 809 } | 793 } |
| 810 | 794 |
| 811 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, | 795 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, |
| 812 const String& value) const { | 796 const String& value) const { |
| 813 EditingStyle* styleToCheck = EditingStyle::create(propertyID, value); | 797 EditingStyle* styleToCheck = EditingStyle::create(propertyID, value); |
| 814 EditingStyle* styleAtStart = EditingStyle::styleAtSelectionStart( | 798 EditingStyle* styleAtStart = EditingStyle::styleAtSelectionStart( |
| 815 frame().selection().selection(), propertyID == CSSPropertyBackgroundColor, | 799 frame().selection().selection(), propertyID == CSSPropertyBackgroundColor, |
| 816 styleToCheck->style()); | 800 styleToCheck->style()); |
| 817 return styleToCheck->triStateOfStyle(styleAtStart); | 801 return styleToCheck->triStateOfStyle(styleAtStart); |
| 818 } | 802 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 frame().inputMethodController().clear(); | 976 frame().inputMethodController().clear(); |
| 993 m_shouldStyleWithCSS = false; | 977 m_shouldStyleWithCSS = false; |
| 994 m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv; | 978 m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv; |
| 995 m_undoStack->clear(); | 979 m_undoStack->clear(); |
| 996 } | 980 } |
| 997 | 981 |
| 998 bool Editor::insertText(const String& text, KeyboardEvent* triggeringEvent) { | 982 bool Editor::insertText(const String& text, KeyboardEvent* triggeringEvent) { |
| 999 return frame().eventHandler().handleTextInputEvent(text, triggeringEvent); | 983 return frame().eventHandler().handleTextInputEvent(text, triggeringEvent); |
| 1000 } | 984 } |
| 1001 | 985 |
| 1002 bool Editor::insertTextWithoutSendingTextEvent(EditCommandSource source, | 986 bool Editor::insertTextWithoutSendingTextEvent(const String& text, |
| 1003 const String& text, | |
| 1004 bool selectInsertedText, | 987 bool selectInsertedText, |
| 1005 TextEvent* triggeringEvent) { | 988 TextEvent* triggeringEvent) { |
| 1006 if (text.isEmpty()) | 989 if (text.isEmpty()) |
| 1007 return false; | 990 return false; |
| 1008 | 991 |
| 1009 const VisibleSelection& selection = selectionForCommand(triggeringEvent); | 992 const VisibleSelection& selection = selectionForCommand(triggeringEvent); |
| 1010 if (!selection.isContentEditable()) | 993 if (!selection.isContentEditable()) |
| 1011 return false; | 994 return false; |
| 1012 | 995 |
| 1013 spellChecker().updateMarkersForWordsAffectedByEditing( | 996 spellChecker().updateMarkersForWordsAffectedByEditing( |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1098 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), | 1081 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), |
| 1099 InputEvent::InputType::DeleteByCut, | 1082 InputEvent::InputType::DeleteByCut, |
| 1100 nullptr, nullptr) != | 1083 nullptr, nullptr) != |
| 1101 DispatchEventResult::NotCanceled) | 1084 DispatchEventResult::NotCanceled) |
| 1102 return; | 1085 return; |
| 1103 // 'beforeinput' event handler may destroy target frame. | 1086 // 'beforeinput' event handler may destroy target frame. |
| 1104 if (m_frame->document()->frame() != m_frame) | 1087 if (m_frame->document()->frame() != m_frame) |
| 1105 return; | 1088 return; |
| 1106 } | 1089 } |
| 1107 deleteSelectionWithSmartDelete( | 1090 deleteSelectionWithSmartDelete( |
| 1108 source, canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 1091 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1109 InputEvent::InputType::DeleteByCut); | 1092 InputEvent::InputType::DeleteByCut); |
| 1110 } | 1093 } |
| 1111 } | 1094 } |
| 1112 | 1095 |
| 1113 void Editor::copy() { | 1096 void Editor::copy() { |
| 1114 if (tryDHTMLCopy()) | 1097 if (tryDHTMLCopy()) |
| 1115 return; // DHTML did the whole operation | 1098 return; // DHTML did the whole operation |
| 1116 if (!canCopy()) | 1099 if (!canCopy()) |
| 1117 return; | 1100 return; |
| 1118 | 1101 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 | 1158 |
| 1176 void Editor::pasteAsPlainText(EditCommandSource source) { | 1159 void Editor::pasteAsPlainText(EditCommandSource source) { |
| 1177 if (tryDHTMLPaste(PlainTextOnly)) | 1160 if (tryDHTMLPaste(PlainTextOnly)) |
| 1178 return; | 1161 return; |
| 1179 if (!canPaste()) | 1162 if (!canPaste()) |
| 1180 return; | 1163 return; |
| 1181 spellChecker().updateMarkersForWordsAffectedByEditing(false); | 1164 spellChecker().updateMarkersForWordsAffectedByEditing(false); |
| 1182 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); | 1165 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); |
| 1183 } | 1166 } |
| 1184 | 1167 |
| 1185 void Editor::performDelete(EditCommandSource source) { | 1168 void Editor::performDelete() { |
| 1186 if (!canDelete()) | 1169 if (!canDelete()) |
| 1187 return; | 1170 return; |
| 1188 | 1171 |
| 1189 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 1172 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 1190 // needs to be audited. See http://crbug.com/590369 for more details. | 1173 // needs to be audited. See http://crbug.com/590369 for more details. |
| 1191 // |selectedRange| requires clean layout for visible selection normalization. | 1174 // |selectedRange| requires clean layout for visible selection normalization. |
| 1192 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 1175 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 1193 | 1176 |
| 1194 addToKillRing(selectedRange()); | 1177 addToKillRing(selectedRange()); |
| 1195 // TODO(chongz): |Editor::performDelete()| has no direction. | 1178 // TODO(chongz): |Editor::performDelete()| has no direction. |
| 1196 // https://github.com/w3c/editing/issues/130 | 1179 // https://github.com/w3c/editing/issues/130 |
| 1197 deleteSelectionWithSmartDelete( | 1180 deleteSelectionWithSmartDelete( |
| 1198 source, canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 1181 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1199 InputEvent::InputType::DeleteContentBackward); | 1182 InputEvent::InputType::DeleteContentBackward); |
| 1200 | 1183 |
| 1201 // clear the "start new kill ring sequence" setting, because it was set to | 1184 // clear the "start new kill ring sequence" setting, because it was set to |
| 1202 // true when the selection was updated by deleting the range | 1185 // true when the selection was updated by deleting the range |
| 1203 setStartNewKillRingSequence(false); | 1186 setStartNewKillRingSequence(false); |
| 1204 } | 1187 } |
| 1205 | 1188 |
| 1206 static void countEditingEvent(ExecutionContext* executionContext, | 1189 static void countEditingEvent(ExecutionContext* executionContext, |
| 1207 const Event* event, | 1190 const Event* event, |
| 1208 UseCounter::Feature featureOnInput, | 1191 UseCounter::Feature featureOnInput, |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 void Editor::copyImage(const HitTestResult& result) { | 1258 void Editor::copyImage(const HitTestResult& result) { |
| 1276 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), | 1259 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), |
| 1277 result.innerNodeOrImageMapImage(), | 1260 result.innerNodeOrImageMapImage(), |
| 1278 result.altDisplayString()); | 1261 result.altDisplayString()); |
| 1279 } | 1262 } |
| 1280 | 1263 |
| 1281 bool Editor::canUndo() { | 1264 bool Editor::canUndo() { |
| 1282 return m_undoStack->canUndo(); | 1265 return m_undoStack->canUndo(); |
| 1283 } | 1266 } |
| 1284 | 1267 |
| 1285 // TODO(chongz): Fire 'beforeinput' for user triggered undo. | 1268 void Editor::undo() { |
| 1286 void Editor::undo(EditCommandSource) { | |
| 1287 m_undoStack->undo(); | 1269 m_undoStack->undo(); |
| 1288 } | 1270 } |
| 1289 | 1271 |
| 1290 bool Editor::canRedo() { | 1272 bool Editor::canRedo() { |
| 1291 return m_undoStack->canRedo(); | 1273 return m_undoStack->canRedo(); |
| 1292 } | 1274 } |
| 1293 | 1275 |
| 1294 // TODO(chongz): Fire 'beforeinput' for user triggered redo. | 1276 void Editor::redo() { |
| 1295 void Editor::redo(EditCommandSource) { | |
| 1296 m_undoStack->redo(); | 1277 m_undoStack->redo(); |
| 1297 } | 1278 } |
| 1298 | 1279 |
| 1299 void Editor::setBaseWritingDirection(WritingDirection direction) { | 1280 void Editor::setBaseWritingDirection(WritingDirection direction) { |
| 1300 Element* focusedElement = frame().document()->focusedElement(); | 1281 Element* focusedElement = frame().document()->focusedElement(); |
| 1301 if (isTextControlElement(focusedElement)) { | 1282 if (isTextControlElement(focusedElement)) { |
| 1302 if (direction == NaturalWritingDirection) | 1283 if (direction == NaturalWritingDirection) |
| 1303 return; | 1284 return; |
| 1304 focusedElement->setAttribute( | 1285 focusedElement->setAttribute( |
| 1305 dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl"); | 1286 dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl"); |
| 1306 focusedElement->dispatchInputEvent(); | 1287 focusedElement->dispatchInputEvent(); |
| 1307 return; | 1288 return; |
| 1308 } | 1289 } |
| 1309 | 1290 |
| 1310 MutableStylePropertySet* style = | 1291 MutableStylePropertySet* style = |
| 1311 MutableStylePropertySet::create(HTMLQuirksMode); | 1292 MutableStylePropertySet::create(HTMLQuirksMode); |
| 1312 style->setProperty( | 1293 style->setProperty( |
| 1313 CSSPropertyDirection, | 1294 CSSPropertyDirection, |
| 1314 direction == LeftToRightWritingDirection | 1295 direction == LeftToRightWritingDirection |
| 1315 ? "ltr" | 1296 ? "ltr" |
| 1316 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", | 1297 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", |
| 1317 false); | 1298 false); |
| 1318 applyParagraphStyleToSelection( | 1299 applyParagraphStyleToSelection( |
| 1319 EditCommandSource::kMenuOrKeyBinding, style, | 1300 style, InputEvent::InputType::FormatSetBlockTextDirection); |
| 1320 InputEvent::InputType::FormatSetBlockTextDirection); | |
| 1321 } | 1301 } |
| 1322 | 1302 |
| 1323 void Editor::revealSelectionAfterEditingOperation( | 1303 void Editor::revealSelectionAfterEditingOperation( |
| 1324 const ScrollAlignment& alignment, | 1304 const ScrollAlignment& alignment, |
| 1325 RevealExtentOption revealExtentOption) { | 1305 RevealExtentOption revealExtentOption) { |
| 1326 if (m_preventRevealSelection) | 1306 if (m_preventRevealSelection) |
| 1327 return; | 1307 return; |
| 1328 frame().selection().revealSelection(alignment, revealExtentOption); | 1308 frame().selection().revealSelection(alignment, revealExtentOption); |
| 1329 } | 1309 } |
| 1330 | 1310 |
| 1331 void Editor::transpose(EditCommandSource source) { | 1311 void Editor::transpose() { |
| 1332 if (!canEdit()) | 1312 if (!canEdit()) |
| 1333 return; | 1313 return; |
| 1334 | 1314 |
| 1335 VisibleSelection selection = frame().selection().selection(); | 1315 VisibleSelection selection = frame().selection().selection(); |
| 1336 if (!selection.isCaret()) | 1316 if (!selection.isCaret()) |
| 1337 return; | 1317 return; |
| 1338 | 1318 |
| 1339 // Make a selection that goes back one character and forward two characters. | 1319 // Make a selection that goes back one character and forward two characters. |
| 1340 VisiblePosition caret = selection.visibleStart(); | 1320 VisiblePosition caret = selection.visibleStart(); |
| 1341 VisiblePosition next = | 1321 VisiblePosition next = |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1358 return; | 1338 return; |
| 1359 String transposed = text.right(1) + text.left(1); | 1339 String transposed = text.right(1) + text.left(1); |
| 1360 | 1340 |
| 1361 // Select the two characters. | 1341 // Select the two characters. |
| 1362 if (newSelection != frame().selection().selection()) | 1342 if (newSelection != frame().selection().selection()) |
| 1363 frame().selection().setSelection(newSelection); | 1343 frame().selection().setSelection(newSelection); |
| 1364 | 1344 |
| 1365 // Insert the transposed characters. | 1345 // Insert the transposed characters. |
| 1366 // TODO(chongz): Once we add |InsertTranspose| in |InputEvent::InputType|, we | 1346 // TODO(chongz): Once we add |InsertTranspose| in |InputEvent::InputType|, we |
| 1367 // should use it instead of |InsertFromPaste|. | 1347 // should use it instead of |InsertFromPaste|. |
| 1368 replaceSelectionWithText(source, transposed, false, false, | 1348 replaceSelectionWithText(transposed, false, false, |
| 1369 InputEvent::InputType::InsertFromPaste); | 1349 InputEvent::InputType::InsertFromPaste); |
| 1370 } | 1350 } |
| 1371 | 1351 |
| 1372 void Editor::addToKillRing(const EphemeralRange& range) { | 1352 void Editor::addToKillRing(const EphemeralRange& range) { |
| 1373 if (m_shouldStartNewKillRingSequence) | 1353 if (m_shouldStartNewKillRingSequence) |
| 1374 killRing().startNewSequence(); | 1354 killRing().startNewSequence(); |
| 1375 | 1355 |
| 1376 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | 1356 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 1377 String text = plainText(range); | 1357 String text = plainText(range); |
| 1378 killRing().append(text); | 1358 killRing().append(text); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 std::max(startCaretRect.height(), endCaretRect.height())); | 1419 std::max(startCaretRect.height(), endCaretRect.height())); |
| 1440 } | 1420 } |
| 1441 | 1421 |
| 1442 // start and end aren't on the same line, so go from start to the end of its | 1422 // start and end aren't on the same line, so go from start to the end of its |
| 1443 // line | 1423 // line |
| 1444 return IntRect(startCaretRect.x(), startCaretRect.y(), | 1424 return IntRect(startCaretRect.x(), startCaretRect.y(), |
| 1445 (startCaretRect.width() + extraWidthToEndOfLine).toInt(), | 1425 (startCaretRect.width() + extraWidthToEndOfLine).toInt(), |
| 1446 startCaretRect.height()); | 1426 startCaretRect.height()); |
| 1447 } | 1427 } |
| 1448 | 1428 |
| 1449 // TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|. | 1429 void Editor::computeAndSetTypingStyle(StylePropertySet* style, |
| 1450 void Editor::computeAndSetTypingStyle(EditCommandSource, | |
| 1451 StylePropertySet* style, | |
| 1452 InputEvent::InputType inputType) { | 1430 InputEvent::InputType inputType) { |
| 1453 if (!style || style->isEmpty()) { | 1431 if (!style || style->isEmpty()) { |
| 1454 frame().selection().clearTypingStyle(); | 1432 frame().selection().clearTypingStyle(); |
| 1455 return; | 1433 return; |
| 1456 } | 1434 } |
| 1457 | 1435 |
| 1458 // Calculate the current typing style. | 1436 // Calculate the current typing style. |
| 1459 EditingStyle* typingStyle = nullptr; | 1437 EditingStyle* typingStyle = nullptr; |
| 1460 if (frame().selection().typingStyle()) { | 1438 if (frame().selection().typingStyle()) { |
| 1461 typingStyle = frame().selection().typingStyle()->copy(); | 1439 typingStyle = frame().selection().typingStyle()->copy(); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 DCHECK(!document.documentElement()); | 1691 DCHECK(!document.documentElement()); |
| 1714 document.appendChild(root); | 1692 document.appendChild(root); |
| 1715 | 1693 |
| 1716 // TODO(tkent): Should we check and move Text node children of <html>? | 1694 // TODO(tkent): Should we check and move Text node children of <html>? |
| 1717 } | 1695 } |
| 1718 | 1696 |
| 1719 void Editor::replaceSelection(const String& text) { | 1697 void Editor::replaceSelection(const String& text) { |
| 1720 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | 1698 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 1721 bool selectReplacement = behavior().shouldSelectReplacement(); | 1699 bool selectReplacement = behavior().shouldSelectReplacement(); |
| 1722 bool smartReplace = true; | 1700 bool smartReplace = true; |
| 1723 replaceSelectionWithText(EditCommandSource::kMenuOrKeyBinding, text, | 1701 replaceSelectionWithText(text, selectReplacement, smartReplace, |
| 1724 selectReplacement, smartReplace, | |
| 1725 InputEvent::InputType::InsertReplacementText); | 1702 InputEvent::InputType::InsertReplacementText); |
| 1726 } | 1703 } |
| 1727 | 1704 |
| 1728 void Editor::replaceSelectionForSpellChecker(const String& text) { | |
| 1729 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | |
| 1730 const bool kSelectReplacement = false; | |
| 1731 const bool kSmartReplace = false; | |
| 1732 replaceSelectionWithText(EditCommandSource::kMenuOrKeyBinding, text, | |
| 1733 kSelectReplacement, kSmartReplace, | |
| 1734 InputEvent::InputType::InsertReplacementText); | |
| 1735 } | |
| 1736 | |
| 1737 DEFINE_TRACE(Editor) { | 1705 DEFINE_TRACE(Editor) { |
| 1738 visitor->trace(m_frame); | 1706 visitor->trace(m_frame); |
| 1739 visitor->trace(m_lastEditCommand); | 1707 visitor->trace(m_lastEditCommand); |
| 1740 visitor->trace(m_undoStack); | 1708 visitor->trace(m_undoStack); |
| 1741 visitor->trace(m_mark); | 1709 visitor->trace(m_mark); |
| 1742 } | 1710 } |
| 1743 | 1711 |
| 1744 } // namespace blink | 1712 } // namespace blink |
| OLD | NEW |