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 |