| 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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 } | 157 } |
| 158 } | 158 } |
| 159 | 159 |
| 160 // When an event handler has moved the selection outside of a text control | 160 // When an event handler has moved the selection outside of a text control |
| 161 // we should use the target control's selection for this editing operation. | 161 // we should use the target control's selection for this editing operation. |
| 162 VisibleSelection Editor::selectionForCommand(Event* event) { | 162 VisibleSelection Editor::selectionForCommand(Event* event) { |
| 163 frame().selection().updateIfNeeded(); | 163 frame().selection().updateIfNeeded(); |
| 164 VisibleSelection selection = frame().selection().selection(); | 164 VisibleSelection selection = frame().selection().selection(); |
| 165 if (!event) | 165 if (!event) |
| 166 return selection; | 166 return selection; |
| 167 // If the target is a text control, and the current selection is outside of it
s shadow tree, | 167 // If the target is a text control, and the current selection is outside of |
| 168 // then use the saved selection for that text control. | 168 // its shadow tree, then use the saved selection for that text control. |
| 169 HTMLTextFormControlElement* textFormControlOfSelectionStart = | 169 HTMLTextFormControlElement* textFormControlOfSelectionStart = |
| 170 enclosingTextFormControl(selection.start()); | 170 enclosingTextFormControl(selection.start()); |
| 171 HTMLTextFormControlElement* textFromControlOfTarget = | 171 HTMLTextFormControlElement* textFromControlOfTarget = |
| 172 isHTMLTextFormControlElement(*event->target()->toNode()) | 172 isHTMLTextFormControlElement(*event->target()->toNode()) |
| 173 ? toHTMLTextFormControlElement(event->target()->toNode()) | 173 ? toHTMLTextFormControlElement(event->target()->toNode()) |
| 174 : 0; | 174 : 0; |
| 175 if (textFromControlOfTarget && | 175 if (textFromControlOfTarget && |
| 176 (selection.start().isNull() || | 176 (selection.start().isNull() || |
| 177 textFromControlOfTarget != textFormControlOfSelectionStart)) { | 177 textFromControlOfTarget != textFormControlOfSelectionStart)) { |
| 178 if (Range* range = textFromControlOfTarget->selection()) { | 178 if (Range* range = textFromControlOfTarget->selection()) { |
| 179 return createVisibleSelection(EphemeralRange(range), | 179 return createVisibleSelection(EphemeralRange(range), |
| 180 TextAffinity::Downstream, | 180 TextAffinity::Downstream, |
| 181 selection.isDirectional()); | 181 selection.isDirectional()); |
| 182 } | 182 } |
| 183 } | 183 } |
| 184 return selection; | 184 return selection; |
| 185 } | 185 } |
| 186 | 186 |
| 187 // Function considers Mac editing behavior a fallback when Page or Settings is n
ot available. | 187 // Function considers Mac editing behavior a fallback when Page or Settings is |
| 188 // not available. |
| 188 EditingBehavior Editor::behavior() const { | 189 EditingBehavior Editor::behavior() const { |
| 189 if (!frame().settings()) | 190 if (!frame().settings()) |
| 190 return EditingBehavior(EditingMacBehavior); | 191 return EditingBehavior(EditingMacBehavior); |
| 191 | 192 |
| 192 return EditingBehavior(frame().settings()->editingBehaviorType()); | 193 return EditingBehavior(frame().settings()->editingBehaviorType()); |
| 193 } | 194 } |
| 194 | 195 |
| 195 static EditorClient& emptyEditorClient() { | 196 static EditorClient& emptyEditorClient() { |
| 196 DEFINE_STATIC_LOCAL(EmptyEditorClient, client, ()); | 197 DEFINE_STATIC_LOCAL(EmptyEditorClient, client, ()); |
| 197 return client; | 198 return client; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 } | 236 } |
| 236 | 237 |
| 237 bool Editor::canEdit() const { | 238 bool Editor::canEdit() const { |
| 238 return frame().selection().rootEditableElement(); | 239 return frame().selection().rootEditableElement(); |
| 239 } | 240 } |
| 240 | 241 |
| 241 bool Editor::canEditRichly() const { | 242 bool Editor::canEditRichly() const { |
| 242 return frame().selection().isContentRichlyEditable(); | 243 return frame().selection().isContentRichlyEditable(); |
| 243 } | 244 } |
| 244 | 245 |
| 245 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu it
ems. They | 246 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu |
| 246 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the me
nu items. | 247 // items. They also send onbeforecopy, apparently for symmetry, but it doesn't |
| 247 // We need to use onbeforecopy as a real menu enabler because we allow elements
that are not | 248 // affect the menu items. We need to use onbeforecopy as a real menu enabler |
| 248 // normally selectable to implement copy/paste (like divs, or a document body). | 249 // because we allow elements that are not normally selectable to implement |
| 250 // copy/paste (like divs, or a document body). |
| 249 | 251 |
| 250 bool Editor::canDHTMLCut() { | 252 bool Editor::canDHTMLCut() { |
| 251 return !frame().selection().isInPasswordField() && | 253 return !frame().selection().isInPasswordField() && |
| 252 !dispatchCPPEvent(EventTypeNames::beforecut, DataTransferNumb); | 254 !dispatchCPPEvent(EventTypeNames::beforecut, DataTransferNumb); |
| 253 } | 255 } |
| 254 | 256 |
| 255 bool Editor::canDHTMLCopy() { | 257 bool Editor::canDHTMLCopy() { |
| 256 return !frame().selection().isInPasswordField() && | 258 return !frame().selection().isInPasswordField() && |
| 257 !dispatchCPPEvent(EventTypeNames::beforecopy, DataTransferNumb); | 259 !dispatchCPPEvent(EventTypeNames::beforecopy, DataTransferNumb); |
| 258 } | 260 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 case DeleteDirection::Backward: | 352 case DeleteDirection::Backward: |
| 351 DCHECK(frame().document()); | 353 DCHECK(frame().document()); |
| 352 TypingCommand::deleteKeyPressed(*frame().document(), options, | 354 TypingCommand::deleteKeyPressed(*frame().document(), options, |
| 353 granularity); | 355 granularity); |
| 354 break; | 356 break; |
| 355 } | 357 } |
| 356 revealSelectionAfterEditingOperation(); | 358 revealSelectionAfterEditingOperation(); |
| 357 } | 359 } |
| 358 | 360 |
| 359 // FIXME: We should to move this down into deleteKeyPressed. | 361 // FIXME: We should to move this down into deleteKeyPressed. |
| 360 // clear the "start new kill ring sequence" setting, because it was set to tru
e | 362 // clear the "start new kill ring sequence" setting, because it was set to |
| 361 // when the selection was updated by deleting the range | 363 // true when the selection was updated by deleting the range |
| 362 if (killRing) | 364 if (killRing) |
| 363 setStartNewKillRingSequence(false); | 365 setStartNewKillRingSequence(false); |
| 364 | 366 |
| 365 return true; | 367 return true; |
| 366 } | 368 } |
| 367 | 369 |
| 368 void Editor::deleteSelectionWithSmartDelete( | 370 void Editor::deleteSelectionWithSmartDelete( |
| 369 DeleteMode deleteMode, | 371 DeleteMode deleteMode, |
| 370 InputEvent::InputType inputType, | 372 InputEvent::InputType inputType, |
| 371 const Position& referenceMovePosition) { | 373 const Position& referenceMovePosition) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 static void writeImageNodeToPasteboard(Pasteboard* pasteboard, | 495 static void writeImageNodeToPasteboard(Pasteboard* pasteboard, |
| 494 Node* node, | 496 Node* node, |
| 495 const String& title) { | 497 const String& title) { |
| 496 DCHECK(pasteboard); | 498 DCHECK(pasteboard); |
| 497 DCHECK(node); | 499 DCHECK(node); |
| 498 | 500 |
| 499 RefPtr<Image> image = imageFromNode(*node); | 501 RefPtr<Image> image = imageFromNode(*node); |
| 500 if (!image.get()) | 502 if (!image.get()) |
| 501 return; | 503 return; |
| 502 | 504 |
| 503 // FIXME: This should probably be reconciled with HitTestResult::absoluteImage
URL. | 505 // FIXME: This should probably be reconciled with |
| 506 // HitTestResult::absoluteImageURL. |
| 504 AtomicString urlString; | 507 AtomicString urlString; |
| 505 if (isHTMLImageElement(*node) || isHTMLInputElement(*node)) | 508 if (isHTMLImageElement(*node) || isHTMLInputElement(*node)) |
| 506 urlString = toHTMLElement(node)->getAttribute(srcAttr); | 509 urlString = toHTMLElement(node)->getAttribute(srcAttr); |
| 507 else if (isSVGImageElement(*node)) | 510 else if (isSVGImageElement(*node)) |
| 508 urlString = toSVGElement(node)->imageSourceURL(); | 511 urlString = toSVGElement(node)->imageSourceURL(); |
| 509 else if (isHTMLEmbedElement(*node) || isHTMLObjectElement(*node) || | 512 else if (isHTMLEmbedElement(*node) || isHTMLObjectElement(*node) || |
| 510 isHTMLCanvasElement(*node)) | 513 isHTMLCanvasElement(*node)) |
| 511 urlString = toHTMLElement(node)->imageSourceURL(); | 514 urlString = toHTMLElement(node)->imageSourceURL(); |
| 512 KURL url = urlString.isEmpty() | 515 KURL url = urlString.isEmpty() |
| 513 ? KURL() | 516 ? KURL() |
| 514 : node->document().completeURL( | 517 : node->document().completeURL( |
| 515 stripLeadingAndTrailingHTMLSpaces(urlString)); | 518 stripLeadingAndTrailingHTMLSpaces(urlString)); |
| 516 | 519 |
| 517 pasteboard->writeImage(image.get(), url, title); | 520 pasteboard->writeImage(image.get(), url, title); |
| 518 } | 521 } |
| 519 | 522 |
| 520 // Returns whether caller should continue with "the default processing", which i
s the same as | 523 // Returns whether caller should continue with "the default processing", which |
| 521 // the event handler NOT setting the return value to false | 524 // is the same as the event handler NOT setting the return value to false |
| 522 bool Editor::dispatchCPPEvent(const AtomicString& eventType, | 525 bool Editor::dispatchCPPEvent(const AtomicString& eventType, |
| 523 DataTransferAccessPolicy policy, | 526 DataTransferAccessPolicy policy, |
| 524 PasteMode pasteMode) { | 527 PasteMode pasteMode) { |
| 525 Element* target = findEventTargetFromSelection(); | 528 Element* target = findEventTargetFromSelection(); |
| 526 if (!target) | 529 if (!target) |
| 527 return true; | 530 return true; |
| 528 | 531 |
| 529 DataTransfer* dataTransfer = | 532 DataTransfer* dataTransfer = |
| 530 DataTransfer::create(DataTransfer::CopyAndPaste, policy, | 533 DataTransfer::create(DataTransfer::CopyAndPaste, policy, |
| 531 policy == DataTransferWritable | 534 policy == DataTransferWritable |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 DeleteMode deleteMode, | 606 DeleteMode deleteMode, |
| 604 const Position& referenceMovePosition) { | 607 const Position& referenceMovePosition) { |
| 605 if (!dragSource || !dragSource->isConnected()) | 608 if (!dragSource || !dragSource->isConnected()) |
| 606 return true; | 609 return true; |
| 607 | 610 |
| 608 // Dispatch 'beforeinput'. | 611 // Dispatch 'beforeinput'. |
| 609 const bool shouldDelete = dispatchBeforeInputEditorCommand( | 612 const bool shouldDelete = dispatchBeforeInputEditorCommand( |
| 610 dragSource, InputEvent::InputType::DeleteByDrag, | 613 dragSource, InputEvent::InputType::DeleteByDrag, |
| 611 nullptr) == DispatchEventResult::NotCanceled; | 614 nullptr) == DispatchEventResult::NotCanceled; |
| 612 | 615 |
| 613 // 'beforeinput' event handler may destroy frame, return false to cancel remai
ning actions; | 616 // 'beforeinput' event handler may destroy frame, return false to cancel |
| 617 // remaining actions; |
| 614 if (m_frame->document()->frame() != m_frame) | 618 if (m_frame->document()->frame() != m_frame) |
| 615 return false; | 619 return false; |
| 616 | 620 |
| 617 if (shouldDelete && dragSource->isConnected()) { | 621 if (shouldDelete && dragSource->isConnected()) { |
| 618 deleteSelectionWithSmartDelete( | 622 deleteSelectionWithSmartDelete( |
| 619 deleteMode, InputEvent::InputType::DeleteByDrag, referenceMovePosition); | 623 deleteMode, InputEvent::InputType::DeleteByDrag, referenceMovePosition); |
| 620 } | 624 } |
| 621 | 625 |
| 622 return true; | 626 return true; |
| 623 } | 627 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 635 // Dispatch 'beforeinput'. | 639 // Dispatch 'beforeinput'. |
| 636 DataTransfer* dataTransfer = | 640 DataTransfer* dataTransfer = |
| 637 DataTransfer::create(DataTransfer::DragAndDrop, DataTransferReadable, | 641 DataTransfer::create(DataTransfer::DragAndDrop, DataTransferReadable, |
| 638 dragData->platformData()); | 642 dragData->platformData()); |
| 639 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); | 643 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); |
| 640 const bool shouldInsert = | 644 const bool shouldInsert = |
| 641 dispatchBeforeInputDataTransfer( | 645 dispatchBeforeInputDataTransfer( |
| 642 dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, | 646 dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, |
| 643 nullptr) == DispatchEventResult::NotCanceled; | 647 nullptr) == DispatchEventResult::NotCanceled; |
| 644 | 648 |
| 645 // 'beforeinput' event handler may destroy frame, return false to cancel remai
ning actions; | 649 // 'beforeinput' event handler may destroy frame, return false to cancel |
| 650 // remaining actions; |
| 646 if (m_frame->document()->frame() != m_frame) | 651 if (m_frame->document()->frame() != m_frame) |
| 647 return false; | 652 return false; |
| 648 | 653 |
| 649 if (shouldInsert && dropTarget->isConnected()) | 654 if (shouldInsert && dropTarget->isConnected()) |
| 650 replaceSelectionAfterDragging(fragment, insertMode, dragSourceType); | 655 replaceSelectionAfterDragging(fragment, insertMode, dragSourceType); |
| 651 | 656 |
| 652 return true; | 657 return true; |
| 653 } | 658 } |
| 654 | 659 |
| 655 EphemeralRange Editor::selectedRange() { | 660 EphemeralRange Editor::selectedRange() { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 dispatchEditableContentChangedEvents( | 812 dispatchEditableContentChangedEvents( |
| 808 composition->startingRootEditableElement(), | 813 composition->startingRootEditableElement(), |
| 809 composition->endingRootEditableElement()); | 814 composition->endingRootEditableElement()); |
| 810 // TODO(chongz): Filter empty InputType after spec is finalized. | 815 // TODO(chongz): Filter empty InputType after spec is finalized. |
| 811 dispatchInputEventEditableContentChanged( | 816 dispatchInputEventEditableContentChanged( |
| 812 composition->startingRootEditableElement(), | 817 composition->startingRootEditableElement(), |
| 813 composition->endingRootEditableElement(), cmd->inputType(), | 818 composition->endingRootEditableElement(), cmd->inputType(), |
| 814 cmd->textDataForInputEvent(), isComposingFromCommand(cmd)); | 819 cmd->textDataForInputEvent(), isComposingFromCommand(cmd)); |
| 815 VisibleSelection newSelection(cmd->endingSelection()); | 820 VisibleSelection newSelection(cmd->endingSelection()); |
| 816 | 821 |
| 817 // Don't clear the typing style with this selection change. We do those things
elsewhere if necessary. | 822 // Don't clear the typing style with this selection change. We do those things |
| 823 // elsewhere if necessary. |
| 818 changeSelectionAfterCommand(newSelection, 0); | 824 changeSelectionAfterCommand(newSelection, 0); |
| 819 | 825 |
| 820 if (!cmd->preservesTypingStyle()) | 826 if (!cmd->preservesTypingStyle()) |
| 821 frame().selection().clearTypingStyle(); | 827 frame().selection().clearTypingStyle(); |
| 822 | 828 |
| 823 // Command will be equal to last edit command only in the case of typing | 829 // Command will be equal to last edit command only in the case of typing |
| 824 if (m_lastEditCommand.get() == cmd) { | 830 if (m_lastEditCommand.get() == cmd) { |
| 825 DCHECK(cmd->isTypingCommand()); | 831 DCHECK(cmd->isTypingCommand()); |
| 826 } else if (m_lastEditCommand && m_lastEditCommand->isDragAndDropCommand() && | 832 } else if (m_lastEditCommand && m_lastEditCommand->isDragAndDropCommand() && |
| 827 (cmd->inputType() == InputEvent::InputType::DeleteByDrag || | 833 (cmd->inputType() == InputEvent::InputType::DeleteByDrag || |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 | 899 |
| 894 Editor* Editor::create(LocalFrame& frame) { | 900 Editor* Editor::create(LocalFrame& frame) { |
| 895 return new Editor(frame); | 901 return new Editor(frame); |
| 896 } | 902 } |
| 897 | 903 |
| 898 Editor::Editor(LocalFrame& frame) | 904 Editor::Editor(LocalFrame& frame) |
| 899 : m_frame(&frame), | 905 : m_frame(&frame), |
| 900 m_undoStack(UndoStack::create()), | 906 m_undoStack(UndoStack::create()), |
| 901 m_preventRevealSelection(0), | 907 m_preventRevealSelection(0), |
| 902 m_shouldStartNewKillRingSequence(false), | 908 m_shouldStartNewKillRingSequence(false), |
| 903 // This is off by default, since most editors want this behavior (this mat
ches IE but not FF). | 909 // This is off by default, since most editors want this behavior (this |
| 910 // matches IE but not FF). |
| 904 m_shouldStyleWithCSS(false), | 911 m_shouldStyleWithCSS(false), |
| 905 m_killRing(wrapUnique(new KillRing)), | 912 m_killRing(wrapUnique(new KillRing)), |
| 906 m_areMarkedTextMatchesHighlighted(false), | 913 m_areMarkedTextMatchesHighlighted(false), |
| 907 m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv), | 914 m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv), |
| 908 m_overwriteModeEnabled(false) {} | 915 m_overwriteModeEnabled(false) {} |
| 909 | 916 |
| 910 Editor::~Editor() {} | 917 Editor::~Editor() {} |
| 911 | 918 |
| 912 void Editor::clear() { | 919 void Editor::clear() { |
| 913 frame().inputMethodController().clear(); | 920 frame().inputMethodController().clear(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 940 triggeringEvent && triggeringEvent->isComposition() | 947 triggeringEvent && triggeringEvent->isComposition() |
| 941 ? TypingCommand::TextCompositionConfirm | 948 ? TypingCommand::TextCompositionConfirm |
| 942 : TypingCommand::TextCompositionNone); | 949 : TypingCommand::TextCompositionNone); |
| 943 | 950 |
| 944 // Reveal the current selection | 951 // Reveal the current selection |
| 945 if (LocalFrame* editedFrame = selection.start().document()->frame()) { | 952 if (LocalFrame* editedFrame = selection.start().document()->frame()) { |
| 946 if (Page* page = editedFrame->page()) { | 953 if (Page* page = editedFrame->page()) { |
| 947 LocalFrame* focusedOrMainFrame = | 954 LocalFrame* focusedOrMainFrame = |
| 948 toLocalFrame(page->focusController().focusedOrMainFrame()); | 955 toLocalFrame(page->focusController().focusedOrMainFrame()); |
| 949 | 956 |
| 950 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStyleshee
ts | 957 // TODO(xiaochengh): The use of |
| 958 // updateStyleAndLayoutIgnorePendingStylesheets |
| 951 // needs to be audited. See http://crbug.com/590369 for more details. | 959 // needs to be audited. See http://crbug.com/590369 for more details. |
| 952 focusedOrMainFrame->document() | 960 focusedOrMainFrame->document() |
| 953 ->updateStyleAndLayoutIgnorePendingStylesheets(); | 961 ->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 954 | 962 |
| 955 focusedOrMainFrame->selection().revealSelection( | 963 focusedOrMainFrame->selection().revealSelection( |
| 956 ScrollAlignment::alignCenterIfNeeded); | 964 ScrollAlignment::alignCenterIfNeeded); |
| 957 } | 965 } |
| 958 } | 966 } |
| 959 | 967 |
| 960 return true; | 968 return true; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1097 void Editor::performDelete() { | 1105 void Editor::performDelete() { |
| 1098 if (!canDelete()) | 1106 if (!canDelete()) |
| 1099 return; | 1107 return; |
| 1100 addToKillRing(selectedRange()); | 1108 addToKillRing(selectedRange()); |
| 1101 // TODO(chongz): |Editor::performDelete()| has no direction. | 1109 // TODO(chongz): |Editor::performDelete()| has no direction. |
| 1102 // https://github.com/w3c/editing/issues/130 | 1110 // https://github.com/w3c/editing/issues/130 |
| 1103 deleteSelectionWithSmartDelete( | 1111 deleteSelectionWithSmartDelete( |
| 1104 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 1112 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1105 InputEvent::InputType::DeleteContentBackward); | 1113 InputEvent::InputType::DeleteContentBackward); |
| 1106 | 1114 |
| 1107 // clear the "start new kill ring sequence" setting, because it was set to tru
e | 1115 // clear the "start new kill ring sequence" setting, because it was set to |
| 1108 // when the selection was updated by deleting the range | 1116 // true when the selection was updated by deleting the range |
| 1109 setStartNewKillRingSequence(false); | 1117 setStartNewKillRingSequence(false); |
| 1110 } | 1118 } |
| 1111 | 1119 |
| 1112 static void countEditingEvent(ExecutionContext* executionContext, | 1120 static void countEditingEvent(ExecutionContext* executionContext, |
| 1113 const Event* event, | 1121 const Event* event, |
| 1114 UseCounter::Feature featureOnInput, | 1122 UseCounter::Feature featureOnInput, |
| 1115 UseCounter::Feature featureOnTextArea, | 1123 UseCounter::Feature featureOnTextArea, |
| 1116 UseCounter::Feature featureOnContentEditable, | 1124 UseCounter::Feature featureOnContentEditable, |
| 1117 UseCounter::Feature featureOnNonNode) { | 1125 UseCounter::Feature featureOnNonNode) { |
| 1118 EventTarget* eventTarget = event->target(); | 1126 EventTarget* eventTarget = event->target(); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 m_shouldStartNewKillRingSequence = false; | 1292 m_shouldStartNewKillRingSequence = false; |
| 1285 } | 1293 } |
| 1286 | 1294 |
| 1287 void Editor::changeSelectionAfterCommand( | 1295 void Editor::changeSelectionAfterCommand( |
| 1288 const VisibleSelection& newSelection, | 1296 const VisibleSelection& newSelection, |
| 1289 FrameSelection::SetSelectionOptions options) { | 1297 FrameSelection::SetSelectionOptions options) { |
| 1290 // If the new selection is orphaned, then don't update the selection. | 1298 // If the new selection is orphaned, then don't update the selection. |
| 1291 if (newSelection.start().isOrphan() || newSelection.end().isOrphan()) | 1299 if (newSelection.start().isOrphan() || newSelection.end().isOrphan()) |
| 1292 return; | 1300 return; |
| 1293 | 1301 |
| 1294 // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Rang
es for selections that are no longer valid | 1302 // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain |
| 1303 // Ranges for selections that are no longer valid |
| 1295 bool selectionDidNotChangeDOMPosition = | 1304 bool selectionDidNotChangeDOMPosition = |
| 1296 newSelection == frame().selection().selection(); | 1305 newSelection == frame().selection().selection(); |
| 1297 frame().selection().setSelection(newSelection, options); | 1306 frame().selection().setSelection(newSelection, options); |
| 1298 | 1307 |
| 1299 // Some editing operations change the selection visually without affecting its
position within the DOM. | 1308 // Some editing operations change the selection visually without affecting its |
| 1300 // For example when you press return in the following (the caret is marked by
^): | 1309 // position within the DOM. For example when you press return in the following |
| 1310 // (the caret is marked by ^): |
| 1301 // <div contentEditable="true"><div>^Hello</div></div> | 1311 // <div contentEditable="true"><div>^Hello</div></div> |
| 1302 // WebCore inserts <div><br></div> *before* the current block, which correctly
moves the paragraph down but which doesn't | 1312 // WebCore inserts <div><br></div> *before* the current block, which correctly |
| 1303 // change the caret's DOM position (["hello", 0]). In these situations the abo
ve FrameSelection::setSelection call | 1313 // moves the paragraph down but which doesn't change the caret's DOM position |
| 1304 // does not call EditorClient::respondToChangedSelection(), which, on the Mac,
sends selection change notifications and | 1314 // (["hello", 0]). In these situations the above FrameSelection::setSelection |
| 1305 // starts a new kill ring sequence, but we want to do these things (matches Ap
pKit). | 1315 // call does not call EditorClient::respondToChangedSelection(), which, on the |
| 1316 // Mac, sends selection change notifications and starts a new kill ring |
| 1317 // sequence, but we want to do these things (matches AppKit). |
| 1306 if (selectionDidNotChangeDOMPosition) | 1318 if (selectionDidNotChangeDOMPosition) |
| 1307 client().respondToChangedSelection(m_frame, | 1319 client().respondToChangedSelection(m_frame, |
| 1308 frame().selection().getSelectionType()); | 1320 frame().selection().getSelectionType()); |
| 1309 } | 1321 } |
| 1310 | 1322 |
| 1311 IntRect Editor::firstRectForRange(const EphemeralRange& range) const { | 1323 IntRect Editor::firstRectForRange(const EphemeralRange& range) const { |
| 1312 DCHECK(!frame().document()->needsLayoutTreeUpdate()); | 1324 DCHECK(!frame().document()->needsLayoutTreeUpdate()); |
| 1313 DocumentLifecycle::DisallowTransitionScope disallowTransition( | 1325 DocumentLifecycle::DisallowTransitionScope disallowTransition( |
| 1314 frame().document()->lifecycle()); | 1326 frame().document()->lifecycle()); |
| 1315 | 1327 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1333 return IntRect(); | 1345 return IntRect(); |
| 1334 | 1346 |
| 1335 if (startCaretRect.y() == endCaretRect.y()) { | 1347 if (startCaretRect.y() == endCaretRect.y()) { |
| 1336 // start and end are on the same line | 1348 // start and end are on the same line |
| 1337 return IntRect(std::min(startCaretRect.x(), endCaretRect.x()), | 1349 return IntRect(std::min(startCaretRect.x(), endCaretRect.x()), |
| 1338 startCaretRect.y(), | 1350 startCaretRect.y(), |
| 1339 abs(endCaretRect.x() - startCaretRect.x()), | 1351 abs(endCaretRect.x() - startCaretRect.x()), |
| 1340 std::max(startCaretRect.height(), endCaretRect.height())); | 1352 std::max(startCaretRect.height(), endCaretRect.height())); |
| 1341 } | 1353 } |
| 1342 | 1354 |
| 1343 // start and end aren't on the same line, so go from start to the end of its l
ine | 1355 // start and end aren't on the same line, so go from start to the end of its |
| 1356 // line |
| 1344 return IntRect(startCaretRect.x(), startCaretRect.y(), | 1357 return IntRect(startCaretRect.x(), startCaretRect.y(), |
| 1345 (startCaretRect.width() + extraWidthToEndOfLine).toInt(), | 1358 (startCaretRect.width() + extraWidthToEndOfLine).toInt(), |
| 1346 startCaretRect.height()); | 1359 startCaretRect.height()); |
| 1347 } | 1360 } |
| 1348 | 1361 |
| 1349 void Editor::computeAndSetTypingStyle(StylePropertySet* style, | 1362 void Editor::computeAndSetTypingStyle(StylePropertySet* style, |
| 1350 InputEvent::InputType inputType) { | 1363 InputEvent::InputType inputType) { |
| 1351 if (!style || style->isEmpty()) { | 1364 if (!style || style->isEmpty()) { |
| 1352 frame().selection().clearTypingStyle(); | 1365 frame().selection().clearTypingStyle(); |
| 1353 return; | 1366 return; |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 } | 1624 } |
| 1612 | 1625 |
| 1613 DEFINE_TRACE(Editor) { | 1626 DEFINE_TRACE(Editor) { |
| 1614 visitor->trace(m_frame); | 1627 visitor->trace(m_frame); |
| 1615 visitor->trace(m_lastEditCommand); | 1628 visitor->trace(m_lastEditCommand); |
| 1616 visitor->trace(m_undoStack); | 1629 visitor->trace(m_undoStack); |
| 1617 visitor->trace(m_mark); | 1630 visitor->trace(m_mark); |
| 1618 } | 1631 } |
| 1619 | 1632 |
| 1620 } // namespace blink | 1633 } // namespace blink |
| OLD | NEW |