| 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 #include "core/html/HTMLHtmlElement.h" | 74 #include "core/html/HTMLHtmlElement.h" |
| 75 #include "core/html/HTMLImageElement.h" | 75 #include "core/html/HTMLImageElement.h" |
| 76 #include "core/html/HTMLInputElement.h" | 76 #include "core/html/HTMLInputElement.h" |
| 77 #include "core/html/HTMLTextAreaElement.h" | 77 #include "core/html/HTMLTextAreaElement.h" |
| 78 #include "core/html/parser/HTMLParserIdioms.h" | 78 #include "core/html/parser/HTMLParserIdioms.h" |
| 79 #include "core/input/EventHandler.h" | 79 #include "core/input/EventHandler.h" |
| 80 #include "core/inspector/ConsoleMessage.h" | 80 #include "core/inspector/ConsoleMessage.h" |
| 81 #include "core/layout/HitTestResult.h" | 81 #include "core/layout/HitTestResult.h" |
| 82 #include "core/layout/LayoutImage.h" | 82 #include "core/layout/LayoutImage.h" |
| 83 #include "core/loader/EmptyClients.h" | 83 #include "core/loader/EmptyClients.h" |
| 84 #include "core/page/DragData.h" |
| 84 #include "core/page/EditorClient.h" | 85 #include "core/page/EditorClient.h" |
| 85 #include "core/page/FocusController.h" | 86 #include "core/page/FocusController.h" |
| 86 #include "core/page/Page.h" | 87 #include "core/page/Page.h" |
| 87 #include "core/svg/SVGImageElement.h" | 88 #include "core/svg/SVGImageElement.h" |
| 88 #include "platform/KillRing.h" | 89 #include "platform/KillRing.h" |
| 89 #include "platform/weborigin/KURL.h" | 90 #include "platform/weborigin/KURL.h" |
| 90 #include "wtf/PtrUtil.h" | 91 #include "wtf/PtrUtil.h" |
| 91 #include "wtf/text/CharacterNames.h" | 92 #include "wtf/text/CharacterNames.h" |
| 92 | 93 |
| 93 namespace blink { | 94 namespace blink { |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 | 342 |
| 342 // FIXME: We should to move this down into deleteKeyPressed. | 343 // FIXME: We should to move this down into deleteKeyPressed. |
| 343 // clear the "start new kill ring sequence" setting, because it was set to t
rue | 344 // clear the "start new kill ring sequence" setting, because it was set to t
rue |
| 344 // when the selection was updated by deleting the range | 345 // when the selection was updated by deleting the range |
| 345 if (killRing) | 346 if (killRing) |
| 346 setStartNewKillRingSequence(false); | 347 setStartNewKillRingSequence(false); |
| 347 | 348 |
| 348 return true; | 349 return true; |
| 349 } | 350 } |
| 350 | 351 |
| 351 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, InputEvent::InputT
ype inputType) | 352 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, InputEvent::InputT
ype inputType, const Position& referenceMovePosition) |
| 352 { | 353 { |
| 353 if (frame().selection().isNone()) | 354 if (frame().selection().isNone()) |
| 354 return; | 355 return; |
| 355 | 356 |
| 356 const bool kMergeBlocksAfterDelete = true; | 357 const bool kMergeBlocksAfterDelete = true; |
| 357 const bool kExpandForSpecialElements = false; | 358 const bool kExpandForSpecialElements = false; |
| 358 const bool kSanitizeMarkup = true; | 359 const bool kSanitizeMarkup = true; |
| 359 DCHECK(frame().document()); | 360 DCHECK(frame().document()); |
| 360 DeleteSelectionCommand::create(*frame().document(), smartDelete, kMergeBlock
sAfterDelete, kExpandForSpecialElements, kSanitizeMarkup, inputType)->apply(); | 361 DeleteSelectionCommand::create(*frame().document(), smartDelete, kMergeBlock
sAfterDelete, kExpandForSpecialElements, kSanitizeMarkup, inputType, referenceMo
vePosition)->apply(); |
| 361 } | 362 } |
| 362 | 363 |
| 363 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace) | 364 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace) |
| 364 { | 365 { |
| 365 Element* target = findEventTargetFromSelection(); | 366 Element* target = findEventTargetFromSelection(); |
| 366 if (!target) | 367 if (!target) |
| 367 return; | 368 return; |
| 368 target->dispatchEvent(TextEvent::createForPlainTextPaste(frame().domWindow()
, pastingText, smartReplace)); | 369 target->dispatchEvent(TextEvent::createForPlainTextPaste(frame().domWindow()
, pastingText, smartReplace)); |
| 369 } | 370 } |
| 370 | 371 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 | 545 |
| 545 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. | 546 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. |
| 546 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, bool smar
tReplace, bool plainText) | 547 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, bool smar
tReplace, bool plainText) |
| 547 { | 548 { |
| 548 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::PreventNesting; | 549 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::PreventNesting; |
| 549 if (smartReplace) | 550 if (smartReplace) |
| 550 options |= ReplaceSelectionCommand::SmartReplace; | 551 options |= ReplaceSelectionCommand::SmartReplace; |
| 551 if (plainText) | 552 if (plainText) |
| 552 options |= ReplaceSelectionCommand::MatchStyle; | 553 options |= ReplaceSelectionCommand::MatchStyle; |
| 553 DCHECK(frame().document()); | 554 DCHECK(frame().document()); |
| 554 ReplaceSelectionCommand::create(*frame().document(), fragment, options, Inpu
tEvent::InputType::Drag)->apply(); | 555 ReplaceSelectionCommand::create(*frame().document(), fragment, options, Inpu
tEvent::InputType::InsertFromDrop)->apply(); |
| 555 } | 556 } |
| 556 | 557 |
| 557 void Editor::moveSelectionAfterDragging(DocumentFragment* fragment, const Positi
on& pos, bool smartInsert, bool smartDelete) | 558 bool Editor::deleteSelectionAfterDraggingWithEvents(Element* dragSource, SmartDe
lete smartDelete, const Position& referenceMovePosition) |
| 558 { | 559 { |
| 559 MoveSelectionCommand::create(fragment, pos, smartInsert, smartDelete)->apply
(); | 560 if (!dragSource || !dragSource->isConnected()) |
| 561 return true; |
| 562 |
| 563 // Dispatch 'beforeinput'. |
| 564 const bool shouldDelete = dispatchBeforeInputEditorCommand(dragSource, Input
Event::InputType::DeleteByDrag, nullptr) == DispatchEventResult::NotCanceled; |
| 565 |
| 566 // 'beforeinput' event handler may destroy frame, return false to cancel rem
aining actions; |
| 567 if (m_frame->document()->frame() != m_frame) |
| 568 return false; |
| 569 |
| 570 if (shouldDelete && dragSource->isConnected()) |
| 571 deleteSelectionWithSmartDelete(smartDelete == SmartDelete::Yes, InputEve
nt::InputType::DeleteByDrag, referenceMovePosition); |
| 572 |
| 573 return true; |
| 574 } |
| 575 |
| 576 bool Editor::replaceSelectionAfterDraggingWithEvents(Element* dropTarget, DragDa
ta* dragData, DocumentFragment* fragment, Range* dropCaretRange, SmartInsert sma
rtInsert, ChosePlainText chosePlainText) |
| 577 { |
| 578 if (!dropTarget || !dropTarget->isConnected()) |
| 579 return true; |
| 580 |
| 581 // Dispatch 'beforeinput'. |
| 582 DataTransfer* dataTransfer = DataTransfer::create(DataTransfer::DragAndDrop,
DataTransferReadable, dragData->platformData()); |
| 583 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); |
| 584 const bool shouldInsert = dispatchBeforeInputDataTransfer(dropTarget, InputE
vent::InputType::InsertFromDrop, dataTransfer, nullptr) == DispatchEventResult::
NotCanceled; |
| 585 |
| 586 // 'beforeinput' event handler may destroy frame, return false to cancel rem
aining actions; |
| 587 if (m_frame->document()->frame() != m_frame) |
| 588 return false; |
| 589 |
| 590 if (shouldInsert && dropTarget->isConnected()) |
| 591 replaceSelectionAfterDragging(fragment, smartInsert == SmartInsert::Yes,
chosePlainText == ChosePlainText::Yes); |
| 592 |
| 593 return true; |
| 560 } | 594 } |
| 561 | 595 |
| 562 EphemeralRange Editor::selectedRange() | 596 EphemeralRange Editor::selectedRange() |
| 563 { | 597 { |
| 564 return frame().selection().selection().toNormalizedEphemeralRange(); | 598 return frame().selection().selection().toNormalizedEphemeralRange(); |
| 565 } | 599 } |
| 566 | 600 |
| 567 bool Editor::canDeleteRange(const EphemeralRange& range) const | 601 bool Editor::canDeleteRange(const EphemeralRange& range) const |
| 568 { | 602 { |
| 569 if (range.isCollapsed()) | 603 if (range.isCollapsed()) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 594 spellChecker().updateMarkersForWordsAffectedByEditing(true); | 628 spellChecker().updateMarkersForWordsAffectedByEditing(true); |
| 595 client().respondToChangedContents(); | 629 client().respondToChangedContents(); |
| 596 } | 630 } |
| 597 | 631 |
| 598 void Editor::removeFormattingAndStyle() | 632 void Editor::removeFormattingAndStyle() |
| 599 { | 633 { |
| 600 DCHECK(frame().document()); | 634 DCHECK(frame().document()); |
| 601 RemoveFormatCommand::create(*frame().document())->apply(); | 635 RemoveFormatCommand::create(*frame().document())->apply(); |
| 602 } | 636 } |
| 603 | 637 |
| 638 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) |
| 639 { |
| 640 DCHECK(commandGroupWrapper->isCommandGroupWrapper()); |
| 641 m_lastEditCommand = commandGroupWrapper; |
| 642 } |
| 643 |
| 604 void Editor::clearLastEditCommand() | 644 void Editor::clearLastEditCommand() |
| 605 { | 645 { |
| 606 m_lastEditCommand.clear(); | 646 m_lastEditCommand.clear(); |
| 607 } | 647 } |
| 608 | 648 |
| 609 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const | 649 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const |
| 610 { | 650 { |
| 611 Element* target = associatedElementOf(selection.start()); | 651 Element* target = associatedElementOf(selection.start()); |
| 612 if (!target) | 652 if (!target) |
| 613 target = frame().document()->body(); | 653 target = frame().document()->body(); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 static void dispatchEditableContentChangedEvents(Element* startRoot, Element* en
dRoot) | 730 static void dispatchEditableContentChangedEvents(Element* startRoot, Element* en
dRoot) |
| 691 { | 731 { |
| 692 if (startRoot) | 732 if (startRoot) |
| 693 startRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableCon
tentChanged)); | 733 startRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableCon
tentChanged)); |
| 694 if (endRoot && endRoot != startRoot) | 734 if (endRoot && endRoot != startRoot) |
| 695 endRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableConte
ntChanged)); | 735 endRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableConte
ntChanged)); |
| 696 } | 736 } |
| 697 | 737 |
| 698 void Editor::appliedEditing(CompositeEditCommand* cmd) | 738 void Editor::appliedEditing(CompositeEditCommand* cmd) |
| 699 { | 739 { |
| 740 DCHECK(!cmd->isCommandGroupWrapper()); |
| 700 EventQueueScope scope; | 741 EventQueueScope scope; |
| 701 frame().document()->updateStyleAndLayout(); | 742 frame().document()->updateStyleAndLayout(); |
| 702 | 743 |
| 703 // Request spell checking before any further DOM change. | 744 // Request spell checking before any further DOM change. |
| 704 spellChecker().markMisspellingsAfterApplyingCommand(*cmd); | 745 spellChecker().markMisspellingsAfterApplyingCommand(*cmd); |
| 705 | 746 |
| 706 EditCommandComposition* composition = cmd->composition(); | 747 EditCommandComposition* composition = cmd->composition(); |
| 707 DCHECK(composition); | 748 DCHECK(composition); |
| 708 dispatchEditableContentChangedEvents(composition->startingRootEditableElemen
t(), composition->endingRootEditableElement()); | 749 dispatchEditableContentChangedEvents(composition->startingRootEditableElemen
t(), composition->endingRootEditableElement()); |
| 709 // TODO(chongz): Filter empty InputType after spec is finalized. | 750 // TODO(chongz): Filter empty InputType after spec is finalized. |
| 710 dispatchInputEventEditableContentChanged(composition->startingRootEditableEl
ement(), composition->endingRootEditableElement(), cmd->inputType(), cmd->textDa
taForInputEvent(), isComposingFromCommand(cmd)); | 751 dispatchInputEventEditableContentChanged(composition->startingRootEditableEl
ement(), composition->endingRootEditableElement(), cmd->inputType(), cmd->textDa
taForInputEvent(), isComposingFromCommand(cmd)); |
| 711 VisibleSelection newSelection(cmd->endingSelection()); | 752 VisibleSelection newSelection(cmd->endingSelection()); |
| 712 | 753 |
| 713 // Don't clear the typing style with this selection change. We do those thin
gs elsewhere if necessary. | 754 // Don't clear the typing style with this selection change. We do those thin
gs elsewhere if necessary. |
| 714 changeSelectionAfterCommand(newSelection, 0); | 755 changeSelectionAfterCommand(newSelection, 0); |
| 715 | 756 |
| 716 if (!cmd->preservesTypingStyle()) | 757 if (!cmd->preservesTypingStyle()) |
| 717 frame().selection().clearTypingStyle(); | 758 frame().selection().clearTypingStyle(); |
| 718 | 759 |
| 719 // Command will be equal to last edit command only in the case of typing | 760 // Command will be equal to last edit command only in the case of typing |
| 720 if (m_lastEditCommand.get() == cmd) { | 761 if (m_lastEditCommand.get() == cmd) { |
| 721 DCHECK(cmd->isTypingCommand()); | 762 DCHECK(cmd->isTypingCommand()); |
| 763 } else if (m_lastEditCommand && m_lastEditCommand->isDragAndDropCommand() &&
(cmd->inputType() == InputEvent::InputType::DeleteByDrag || cmd->inputType() ==
InputEvent::InputType::InsertFromDrop)) { |
| 764 // Only register undo entry when combined with other commands. |
| 765 if (!m_lastEditCommand->composition()) |
| 766 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition()
); |
| 767 m_lastEditCommand->appendCommandToComposite(cmd); |
| 722 } else { | 768 } else { |
| 723 // Only register a new undo command if the command passed in is | 769 // Only register a new undo command if the command passed in is |
| 724 // different from the last command | 770 // different from the last command |
| 725 m_lastEditCommand = cmd; | 771 m_lastEditCommand = cmd; |
| 726 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition()); | 772 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition()); |
| 727 } | 773 } |
| 728 | 774 |
| 729 respondToChangedContents(newSelection); | 775 respondToChangedContents(newSelection); |
| 730 } | 776 } |
| 731 | 777 |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 | 1463 |
| 1418 DEFINE_TRACE(Editor) | 1464 DEFINE_TRACE(Editor) |
| 1419 { | 1465 { |
| 1420 visitor->trace(m_frame); | 1466 visitor->trace(m_frame); |
| 1421 visitor->trace(m_lastEditCommand); | 1467 visitor->trace(m_lastEditCommand); |
| 1422 visitor->trace(m_undoStack); | 1468 visitor->trace(m_undoStack); |
| 1423 visitor->trace(m_mark); | 1469 visitor->trace(m_mark); |
| 1424 } | 1470 } |
| 1425 | 1471 |
| 1426 } // namespace blink | 1472 } // namespace blink |
| OLD | NEW |