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

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

Issue 2617443002: Implement ThreadedInputConnection.deleteSurroundingTextInCodePoints() (Closed)
Patch Set: Address dcheng@'s review Created 3 years, 9 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 17 matching lines...) Expand all
28 28
29 #include "core/InputModeNames.h" 29 #include "core/InputModeNames.h"
30 #include "core/InputTypeNames.h" 30 #include "core/InputTypeNames.h"
31 #include "core/dom/Document.h" 31 #include "core/dom/Document.h"
32 #include "core/dom/Element.h" 32 #include "core/dom/Element.h"
33 #include "core/dom/Text.h" 33 #include "core/dom/Text.h"
34 #include "core/editing/EditingUtilities.h" 34 #include "core/editing/EditingUtilities.h"
35 #include "core/editing/Editor.h" 35 #include "core/editing/Editor.h"
36 #include "core/editing/commands/TypingCommand.h" 36 #include "core/editing/commands/TypingCommand.h"
37 #include "core/editing/markers/DocumentMarkerController.h" 37 #include "core/editing/markers/DocumentMarkerController.h"
38 #include "core/editing/state_machines/BackwardCodePointStateMachine.h"
39 #include "core/editing/state_machines/ForwardCodePointStateMachine.h"
38 #include "core/events/CompositionEvent.h" 40 #include "core/events/CompositionEvent.h"
39 #include "core/frame/LocalFrame.h" 41 #include "core/frame/LocalFrame.h"
40 #include "core/html/HTMLInputElement.h" 42 #include "core/html/HTMLInputElement.h"
41 #include "core/html/HTMLTextAreaElement.h" 43 #include "core/html/HTMLTextAreaElement.h"
42 #include "core/input/EventHandler.h" 44 #include "core/input/EventHandler.h"
43 #include "core/layout/LayoutObject.h" 45 #include "core/layout/LayoutObject.h"
44 #include "core/layout/LayoutTheme.h" 46 #include "core/layout/LayoutTheme.h"
45 #include "core/page/ChromeClient.h" 47 #include "core/page/ChromeClient.h"
46 48
47 namespace blink { 49 namespace blink {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 180 }
179 181
180 if (!queryAttribute) 182 if (!queryAttribute)
181 return AtomicString(); 183 return AtomicString();
182 184
183 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed 185 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed
184 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016. 186 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016.
185 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower(); 187 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower();
186 } 188 }
187 189
190 constexpr int invalidDeletionLength = -1;
191 constexpr bool isInvalidDeletionLength(const int length) {
192 return length == invalidDeletionLength;
193 }
194
195 int calculateBeforeDeletionLengthsInCodePoints(
196 const String& text,
197 const int beforeLengthInCodePoints,
198 const int selectionStart) {
199 DCHECK_GE(beforeLengthInCodePoints, 0);
200 DCHECK_GE(selectionStart, 0);
201 DCHECK_LE(selectionStart, static_cast<int>(text.length()));
202
203 const UChar* uText = text.characters16();
204 BackwardCodePointStateMachine backwardMachine;
205 int counter = beforeLengthInCodePoints;
206 int deletionStart = selectionStart;
207 while (counter > 0 && deletionStart > 0) {
208 const TextSegmentationMachineState state =
209 backwardMachine.feedPrecedingCodeUnit(uText[deletionStart - 1]);
210 // According to Android's InputConnection spec, we should do nothing if
211 // |text| has invalid surrogate pair in the deletion range.
212 if (state == TextSegmentationMachineState::Invalid)
213 return invalidDeletionLength;
214
215 if (backwardMachine.atCodePointBoundary())
216 --counter;
217 --deletionStart;
218 }
219 if (!backwardMachine.atCodePointBoundary())
220 return invalidDeletionLength;
221
222 const int offset = backwardMachine.getBoundaryOffset();
223 DCHECK_EQ(-offset, selectionStart - deletionStart);
224 return -offset;
225 }
226
227 int calculateAfterDeletionLengthsInCodePoints(const String& text,
228 const int afterLengthInCodePoints,
229 const int selectionEnd) {
230 DCHECK_GE(afterLengthInCodePoints, 0);
231 DCHECK_GE(selectionEnd, 0);
232 const int length = text.length();
233 DCHECK_LE(selectionEnd, length);
234
235 const UChar* uText = text.characters16();
236 ForwardCodePointStateMachine forwardMachine;
237 int counter = afterLengthInCodePoints;
238 int deletionEnd = selectionEnd;
239 while (counter > 0 && deletionEnd < length) {
240 const TextSegmentationMachineState state =
241 forwardMachine.feedFollowingCodeUnit(uText[deletionEnd]);
242 // According to Android's InputConnection spec, we should do nothing if
243 // |text| has invalid surrogate pair in the deletion range.
244 if (state == TextSegmentationMachineState::Invalid)
245 return invalidDeletionLength;
246
247 if (forwardMachine.atCodePointBoundary())
248 --counter;
249 ++deletionEnd;
250 }
251 if (!forwardMachine.atCodePointBoundary())
252 return invalidDeletionLength;
253
254 const int offset = forwardMachine.getBoundaryOffset();
255 DCHECK_EQ(offset, deletionEnd - selectionEnd);
256 return offset;
257 }
258
188 } // anonymous namespace 259 } // anonymous namespace
189 260
190 InputMethodController* InputMethodController::create(LocalFrame& frame) { 261 InputMethodController* InputMethodController::create(LocalFrame& frame) {
191 return new InputMethodController(frame); 262 return new InputMethodController(frame);
192 } 263 }
193 264
194 InputMethodController::InputMethodController(LocalFrame& frame) 265 InputMethodController::InputMethodController(LocalFrame& frame)
195 : m_frame(&frame), m_hasComposition(false) {} 266 : m_frame(&frame), m_hasComposition(false) {}
196 267
197 InputMethodController::~InputMethodController() = default; 268 InputMethodController::~InputMethodController() = default;
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 const size_t diff = computeDistanceToRightGraphemeBoundary(position); 968 const size_t diff = computeDistanceToRightGraphemeBoundary(position);
898 const int adjustedEnd = end + static_cast<int>(diff); 969 const int adjustedEnd = end + static_cast<int>(diff);
899 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd))) 970 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd)))
900 return; 971 return;
901 TypingCommand::deleteSelection(document()); 972 TypingCommand::deleteSelection(document());
902 } 973 }
903 974
904 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd)); 975 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
905 } 976 }
906 977
978 void InputMethodController::deleteSurroundingTextInCodePoints(int before,
979 int after) {
980 DCHECK_GE(before, 0);
981 DCHECK_GE(after, 0);
982 if (!editor().canEdit())
983 return;
984 const PlainTextRange selectionOffsets(getSelectionOffsets());
985 if (selectionOffsets.isNull())
986 return;
987 Element* const rootEditableElement =
988 frame().selection().rootEditableElementOrDocumentElement();
989 if (!rootEditableElement)
990 return;
991
992 const TextIteratorBehavior& behavior =
993 TextIteratorBehavior::Builder()
994 .setEmitsObjectReplacementCharacter(true)
995 .build();
996 const String& text = plainText(
997 EphemeralRange::rangeOfContents(*rootEditableElement), behavior);
998
999 // 8-bit characters are Latin-1 characters, so the deletion lengths are
1000 // trivial.
1001 if (text.is8Bit())
1002 return deleteSurroundingText(before, after);
1003
1004 const int selectionStart = static_cast<int>(selectionOffsets.start());
1005 const int selectionEnd = static_cast<int>(selectionOffsets.end());
1006
1007 const int beforeLength =
1008 calculateBeforeDeletionLengthsInCodePoints(text, before, selectionStart);
1009 if (isInvalidDeletionLength(beforeLength))
1010 return;
1011 const int afterLength =
1012 calculateAfterDeletionLengthsInCodePoints(text, after, selectionEnd);
1013 if (isInvalidDeletionLength(afterLength))
1014 return;
1015
1016 return deleteSurroundingText(beforeLength, afterLength);
1017 }
1018
907 WebTextInputInfo InputMethodController::textInputInfo() const { 1019 WebTextInputInfo InputMethodController::textInputInfo() const {
908 WebTextInputInfo info; 1020 WebTextInputInfo info;
909 if (!isAvailable()) 1021 if (!isAvailable())
910 return info; 1022 return info;
911 1023
912 if (!frame().selection().isAvailable()) { 1024 if (!frame().selection().isAvailable()) {
913 // plugins/mouse-capture-inside-shadow.html reaches here. 1025 // plugins/mouse-capture-inside-shadow.html reaches here.
914 return info; 1026 return info;
915 } 1027 }
916 Element* element = frame() 1028 Element* element = frame()
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 finishComposingText(KeepSelection); 1237 finishComposingText(KeepSelection);
1126 } 1238 }
1127 1239
1128 DEFINE_TRACE(InputMethodController) { 1240 DEFINE_TRACE(InputMethodController) {
1129 visitor->trace(m_frame); 1241 visitor->trace(m_frame);
1130 visitor->trace(m_compositionRange); 1242 visitor->trace(m_compositionRange);
1131 SynchronousMutationObserver::trace(visitor); 1243 SynchronousMutationObserver::trace(visitor);
1132 } 1244 }
1133 1245
1134 } // namespace blink 1246 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698