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 |