Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: third_party/WebKit/Source/core/editing/Editor.cpp

Issue 2374743002: [InputEvent] Support |deleteByDrag|, |insertFromDrop| and fire in sequential order (Closed)
Patch Set: Yosin's review 2 Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 if (isTypingAction) { 322 if (isTypingAction) {
322 DCHECK(frame().document()); 323 DCHECK(frame().document());
323 TypingCommand::deleteKeyPressed( 324 TypingCommand::deleteKeyPressed(
324 *frame().document(), 325 *frame().document(),
325 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity); 326 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
326 revealSelectionAfterEditingOperation(); 327 revealSelectionAfterEditingOperation();
327 } else { 328 } else {
328 if (killRing) 329 if (killRing)
329 addToKillRing(selectedRange()); 330 addToKillRing(selectedRange());
330 deleteSelectionWithSmartDelete( 331 deleteSelectionWithSmartDelete(
331 canSmartCopyOrDelete(), 332 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple,
332 deletionInputTypeFromTextGranularity(direction, granularity)); 333 deletionInputTypeFromTextGranularity(direction, granularity));
333 // Implicitly calls revealSelectionAfterEditingOperation(). 334 // Implicitly calls revealSelectionAfterEditingOperation().
334 } 335 }
335 } else { 336 } else {
336 TypingCommand::Options options = 0; 337 TypingCommand::Options options = 0;
337 if (canSmartCopyOrDelete()) 338 if (canSmartCopyOrDelete())
338 options |= TypingCommand::SmartDelete; 339 options |= TypingCommand::SmartDelete;
339 if (killRing) 340 if (killRing)
340 options |= TypingCommand::KillRing; 341 options |= TypingCommand::KillRing;
341 switch (direction) { 342 switch (direction) {
(...skipping 15 matching lines...) Expand all
357 358
358 // FIXME: We should to move this down into deleteKeyPressed. 359 // FIXME: We should to move this down into deleteKeyPressed.
359 // clear the "start new kill ring sequence" setting, because it was set to tru e 360 // clear the "start new kill ring sequence" setting, because it was set to tru e
360 // when the selection was updated by deleting the range 361 // when the selection was updated by deleting the range
361 if (killRing) 362 if (killRing)
362 setStartNewKillRingSequence(false); 363 setStartNewKillRingSequence(false);
363 364
364 return true; 365 return true;
365 } 366 }
366 367
367 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, 368 void Editor::deleteSelectionWithSmartDelete(
368 InputEvent::InputType inputType) { 369 DeleteMode deleteMode,
370 InputEvent::InputType inputType,
371 const Position& referenceMovePosition) {
369 if (frame().selection().isNone()) 372 if (frame().selection().isNone())
370 return; 373 return;
371 374
372 const bool kMergeBlocksAfterDelete = true; 375 const bool kMergeBlocksAfterDelete = true;
373 const bool kExpandForSpecialElements = false; 376 const bool kExpandForSpecialElements = false;
374 const bool kSanitizeMarkup = true; 377 const bool kSanitizeMarkup = true;
375 DCHECK(frame().document()); 378 DCHECK(frame().document());
376 DeleteSelectionCommand::create( 379 DeleteSelectionCommand::create(
377 *frame().document(), smartDelete, kMergeBlocksAfterDelete, 380 *frame().document(), deleteMode == DeleteMode::Smart,
378 kExpandForSpecialElements, kSanitizeMarkup, inputType) 381 kMergeBlocksAfterDelete, kExpandForSpecialElements, kSanitizeMarkup,
382 inputType, referenceMovePosition)
379 ->apply(); 383 ->apply();
380 } 384 }
381 385
382 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace) { 386 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace) {
383 Element* target = findEventTargetFromSelection(); 387 Element* target = findEventTargetFromSelection();
384 if (!target) 388 if (!target)
385 return; 389 return;
386 target->dispatchEvent(TextEvent::createForPlainTextPaste( 390 target->dispatchEvent(TextEvent::createForPlainTextPaste(
387 frame().domWindow(), pastingText, smartReplace)); 391 frame().domWindow(), pastingText, smartReplace));
388 } 392 }
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 576
573 void Editor::replaceSelectionWithText(const String& text, 577 void Editor::replaceSelectionWithText(const String& text,
574 bool selectReplacement, 578 bool selectReplacement,
575 bool smartReplace) { 579 bool smartReplace) {
576 replaceSelectionWithFragment(createFragmentFromText(selectedRange(), text), 580 replaceSelectionWithFragment(createFragmentFromText(selectedRange(), text),
577 selectReplacement, smartReplace, true); 581 selectReplacement, smartReplace, true);
578 } 582 }
579 583
580 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. 584 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|.
581 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, 585 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment,
582 bool smartReplace, 586 InsertMode insertMode,
583 bool plainText) { 587 DragSourceType dragSourceType) {
584 ReplaceSelectionCommand::CommandOptions options = 588 ReplaceSelectionCommand::CommandOptions options =
585 ReplaceSelectionCommand::SelectReplacement | 589 ReplaceSelectionCommand::SelectReplacement |
586 ReplaceSelectionCommand::PreventNesting; 590 ReplaceSelectionCommand::PreventNesting;
587 if (smartReplace) 591 if (insertMode == InsertMode::Smart)
588 options |= ReplaceSelectionCommand::SmartReplace; 592 options |= ReplaceSelectionCommand::SmartReplace;
589 if (plainText) 593 if (dragSourceType == DragSourceType::PlainTextSource)
590 options |= ReplaceSelectionCommand::MatchStyle; 594 options |= ReplaceSelectionCommand::MatchStyle;
591 DCHECK(frame().document()); 595 DCHECK(frame().document());
592 ReplaceSelectionCommand::create(*frame().document(), fragment, options, 596 ReplaceSelectionCommand::create(*frame().document(), fragment, options,
593 InputEvent::InputType::Drag) 597 InputEvent::InputType::InsertFromDrop)
594 ->apply(); 598 ->apply();
595 } 599 }
596 600
597 void Editor::moveSelectionAfterDragging(DocumentFragment* fragment, 601 bool Editor::deleteSelectionAfterDraggingWithEvents(
598 const Position& pos, 602 Element* dragSource,
599 bool smartInsert, 603 DeleteMode deleteMode,
600 bool smartDelete) { 604 const Position& referenceMovePosition) {
601 MoveSelectionCommand::create(fragment, pos, smartInsert, smartDelete) 605 if (!dragSource || !dragSource->isConnected())
602 ->apply(); 606 return true;
607
608 // Dispatch 'beforeinput'.
609 const bool shouldDelete = dispatchBeforeInputEditorCommand(
610 dragSource, InputEvent::InputType::DeleteByDrag,
611 nullptr) == DispatchEventResult::NotCanceled;
612
613 // 'beforeinput' event handler may destroy frame, return false to cancel remai ning actions;
614 if (m_frame->document()->frame() != m_frame)
615 return false;
616
617 if (shouldDelete && dragSource->isConnected()) {
618 deleteSelectionWithSmartDelete(
619 deleteMode, InputEvent::InputType::DeleteByDrag, referenceMovePosition);
620 }
621
622 return true;
623 }
624
625 bool Editor::replaceSelectionAfterDraggingWithEvents(
626 Element* dropTarget,
627 DragData* dragData,
628 DocumentFragment* fragment,
629 Range* dropCaretRange,
630 InsertMode insertMode,
631 DragSourceType dragSourceType) {
632 if (!dropTarget || !dropTarget->isConnected())
633 return true;
634
635 // Dispatch 'beforeinput'.
636 DataTransfer* dataTransfer =
637 DataTransfer::create(DataTransfer::DragAndDrop, DataTransferReadable,
638 dragData->platformData());
639 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask());
640 const bool shouldInsert =
641 dispatchBeforeInputDataTransfer(
642 dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer,
643 nullptr) == DispatchEventResult::NotCanceled;
644
645 // 'beforeinput' event handler may destroy frame, return false to cancel remai ning actions;
646 if (m_frame->document()->frame() != m_frame)
647 return false;
648
649 if (shouldInsert && dropTarget->isConnected())
650 replaceSelectionAfterDragging(fragment, insertMode, dragSourceType);
651
652 return true;
603 } 653 }
604 654
605 EphemeralRange Editor::selectedRange() { 655 EphemeralRange Editor::selectedRange() {
606 return frame().selection().selection().toNormalizedEphemeralRange(); 656 return frame().selection().selection().toNormalizedEphemeralRange();
607 } 657 }
608 658
609 bool Editor::canDeleteRange(const EphemeralRange& range) const { 659 bool Editor::canDeleteRange(const EphemeralRange& range) const {
610 if (range.isCollapsed()) 660 if (range.isCollapsed())
611 return false; 661 return false;
612 662
(...skipping 20 matching lines...) Expand all
633 683
634 spellChecker().updateMarkersForWordsAffectedByEditing(true); 684 spellChecker().updateMarkersForWordsAffectedByEditing(true);
635 client().respondToChangedContents(); 685 client().respondToChangedContents();
636 } 686 }
637 687
638 void Editor::removeFormattingAndStyle() { 688 void Editor::removeFormattingAndStyle() {
639 DCHECK(frame().document()); 689 DCHECK(frame().document());
640 RemoveFormatCommand::create(*frame().document())->apply(); 690 RemoveFormatCommand::create(*frame().document())->apply();
641 } 691 }
642 692
693 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) {
694 DCHECK(commandGroupWrapper->isCommandGroupWrapper());
695 m_lastEditCommand = commandGroupWrapper;
696 }
697
643 void Editor::clearLastEditCommand() { 698 void Editor::clearLastEditCommand() {
644 m_lastEditCommand.clear(); 699 m_lastEditCommand.clear();
645 } 700 }
646 701
647 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const { 702 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const {
648 Element* target = associatedElementOf(selection.start()); 703 Element* target = associatedElementOf(selection.start());
649 if (!target) 704 if (!target)
650 target = frame().document()->body(); 705 target = frame().document()->body();
651 706
652 return target; 707 return target;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 Element* endRoot) { 788 Element* endRoot) {
734 if (startRoot) 789 if (startRoot)
735 startRoot->dispatchEvent( 790 startRoot->dispatchEvent(
736 Event::create(EventTypeNames::webkitEditableContentChanged)); 791 Event::create(EventTypeNames::webkitEditableContentChanged));
737 if (endRoot && endRoot != startRoot) 792 if (endRoot && endRoot != startRoot)
738 endRoot->dispatchEvent( 793 endRoot->dispatchEvent(
739 Event::create(EventTypeNames::webkitEditableContentChanged)); 794 Event::create(EventTypeNames::webkitEditableContentChanged));
740 } 795 }
741 796
742 void Editor::appliedEditing(CompositeEditCommand* cmd) { 797 void Editor::appliedEditing(CompositeEditCommand* cmd) {
798 DCHECK(!cmd->isCommandGroupWrapper());
743 EventQueueScope scope; 799 EventQueueScope scope;
744 frame().document()->updateStyleAndLayout(); 800 frame().document()->updateStyleAndLayout();
745 801
746 // Request spell checking before any further DOM change. 802 // Request spell checking before any further DOM change.
747 spellChecker().markMisspellingsAfterApplyingCommand(*cmd); 803 spellChecker().markMisspellingsAfterApplyingCommand(*cmd);
748 804
749 EditCommandComposition* composition = cmd->composition(); 805 EditCommandComposition* composition = cmd->composition();
750 DCHECK(composition); 806 DCHECK(composition);
751 dispatchEditableContentChangedEvents( 807 dispatchEditableContentChangedEvents(
752 composition->startingRootEditableElement(), 808 composition->startingRootEditableElement(),
753 composition->endingRootEditableElement()); 809 composition->endingRootEditableElement());
754 // TODO(chongz): Filter empty InputType after spec is finalized. 810 // TODO(chongz): Filter empty InputType after spec is finalized.
755 dispatchInputEventEditableContentChanged( 811 dispatchInputEventEditableContentChanged(
756 composition->startingRootEditableElement(), 812 composition->startingRootEditableElement(),
757 composition->endingRootEditableElement(), cmd->inputType(), 813 composition->endingRootEditableElement(), cmd->inputType(),
758 cmd->textDataForInputEvent(), isComposingFromCommand(cmd)); 814 cmd->textDataForInputEvent(), isComposingFromCommand(cmd));
759 VisibleSelection newSelection(cmd->endingSelection()); 815 VisibleSelection newSelection(cmd->endingSelection());
760 816
761 // Don't clear the typing style with this selection change. We do those things elsewhere if necessary. 817 // Don't clear the typing style with this selection change. We do those things elsewhere if necessary.
762 changeSelectionAfterCommand(newSelection, 0); 818 changeSelectionAfterCommand(newSelection, 0);
763 819
764 if (!cmd->preservesTypingStyle()) 820 if (!cmd->preservesTypingStyle())
765 frame().selection().clearTypingStyle(); 821 frame().selection().clearTypingStyle();
766 822
767 // Command will be equal to last edit command only in the case of typing 823 // Command will be equal to last edit command only in the case of typing
768 if (m_lastEditCommand.get() == cmd) { 824 if (m_lastEditCommand.get() == cmd) {
769 DCHECK(cmd->isTypingCommand()); 825 DCHECK(cmd->isTypingCommand());
826 } else if (m_lastEditCommand && m_lastEditCommand->isDragAndDropCommand() &&
827 (cmd->inputType() == InputEvent::InputType::DeleteByDrag ||
828 cmd->inputType() == InputEvent::InputType::InsertFromDrop)) {
829 // Only register undo entry when combined with other commands.
830 if (!m_lastEditCommand->composition())
831 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition());
832 m_lastEditCommand->appendCommandToComposite(cmd);
770 } else { 833 } else {
771 // Only register a new undo command if the command passed in is 834 // Only register a new undo command if the command passed in is
772 // different from the last command 835 // different from the last command
773 m_lastEditCommand = cmd; 836 m_lastEditCommand = cmd;
774 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition()); 837 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition());
775 } 838 }
776 839
777 respondToChangedContents(newSelection); 840 respondToChangedContents(newSelection);
778 } 841 }
779 842
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 if (source == CommandFromMenuOrKeyBinding) { 1017 if (source == CommandFromMenuOrKeyBinding) {
955 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), 1018 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(),
956 InputEvent::InputType::DeleteByCut, 1019 InputEvent::InputType::DeleteByCut,
957 nullptr, nullptr) != 1020 nullptr, nullptr) !=
958 DispatchEventResult::NotCanceled) 1021 DispatchEventResult::NotCanceled)
959 return; 1022 return;
960 // 'beforeinput' event handler may destroy target frame. 1023 // 'beforeinput' event handler may destroy target frame.
961 if (m_frame->document()->frame() != m_frame) 1024 if (m_frame->document()->frame() != m_frame)
962 return; 1025 return;
963 } 1026 }
964 deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), 1027 deleteSelectionWithSmartDelete(
965 InputEvent::InputType::DeleteByCut); 1028 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple,
1029 InputEvent::InputType::DeleteByCut);
966 } 1030 }
967 } 1031 }
968 1032
969 void Editor::copy() { 1033 void Editor::copy() {
970 if (tryDHTMLCopy()) 1034 if (tryDHTMLCopy())
971 return; // DHTML did the whole operation 1035 return; // DHTML did the whole operation
972 if (!canCopy()) 1036 if (!canCopy())
973 return; 1037 return;
974 if (enclosingTextFormControl(frame().selection().start())) { 1038 if (enclosingTextFormControl(frame().selection().start())) {
975 Pasteboard::generalPasteboard()->writePlainText( 1039 Pasteboard::generalPasteboard()->writePlainText(
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 spellChecker().updateMarkersForWordsAffectedByEditing(false); 1094 spellChecker().updateMarkersForWordsAffectedByEditing(false);
1031 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); 1095 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
1032 } 1096 }
1033 1097
1034 void Editor::performDelete() { 1098 void Editor::performDelete() {
1035 if (!canDelete()) 1099 if (!canDelete())
1036 return; 1100 return;
1037 addToKillRing(selectedRange()); 1101 addToKillRing(selectedRange());
1038 // TODO(chongz): |Editor::performDelete()| has no direction. 1102 // TODO(chongz): |Editor::performDelete()| has no direction.
1039 // https://github.com/w3c/editing/issues/130 1103 // https://github.com/w3c/editing/issues/130
1040 deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), 1104 deleteSelectionWithSmartDelete(
1041 InputEvent::InputType::DeleteContentBackward); 1105 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple,
1106 InputEvent::InputType::DeleteContentBackward);
1042 1107
1043 // clear the "start new kill ring sequence" setting, because it was set to tru e 1108 // clear the "start new kill ring sequence" setting, because it was set to tru e
1044 // when the selection was updated by deleting the range 1109 // when the selection was updated by deleting the range
1045 setStartNewKillRingSequence(false); 1110 setStartNewKillRingSequence(false);
1046 } 1111 }
1047 1112
1048 static void countEditingEvent(ExecutionContext* executionContext, 1113 static void countEditingEvent(ExecutionContext* executionContext,
1049 const Event* event, 1114 const Event* event,
1050 UseCounter::Feature featureOnInput, 1115 UseCounter::Feature featureOnInput,
1051 UseCounter::Feature featureOnTextArea, 1116 UseCounter::Feature featureOnTextArea,
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 } 1612 }
1548 1613
1549 DEFINE_TRACE(Editor) { 1614 DEFINE_TRACE(Editor) {
1550 visitor->trace(m_frame); 1615 visitor->trace(m_frame);
1551 visitor->trace(m_lastEditCommand); 1616 visitor->trace(m_lastEditCommand);
1552 visitor->trace(m_undoStack); 1617 visitor->trace(m_undoStack);
1553 visitor->trace(m_mark); 1618 visitor->trace(m_mark);
1554 } 1619 }
1555 1620
1556 } // namespace blink 1621 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698