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

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

Issue 2617443002: Implement ThreadedInputConnection.deleteSurroundingTextInCodePoints() (Closed)
Patch Set: Add some DCHECK Created 3 years, 10 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 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 const size_t diff = computeDistanceToRightGraphemeBoundary(position); 931 const size_t diff = computeDistanceToRightGraphemeBoundary(position);
861 const int adjustedEnd = end + static_cast<int>(diff); 932 const int adjustedEnd = end + static_cast<int>(diff);
862 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd))) 933 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd)))
863 return; 934 return;
864 TypingCommand::deleteSelection(document()); 935 TypingCommand::deleteSelection(document());
865 } 936 }
866 937
867 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd)); 938 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
868 } 939 }
869 940
941 void InputMethodController::deleteSurroundingTextInCodePoints(int before,
942 int after) {
943 DCHECK_GE(before, 0);
944 DCHECK_GE(after, 0);
dcheng 2017/02/25 07:37:04 After int -> size_t -> int in the browser side, it
yabinh 2017/02/27 02:04:33 Done. Replaced size_t with int.
945 if (!editor().canEdit())
946 return;
947 const PlainTextRange selectionOffsets(getSelectionOffsets());
948 if (selectionOffsets.isNull())
949 return;
950 Element* const rootEditableElement =
951 frame().selection().rootEditableElement();
952 if (!rootEditableElement)
953 return;
954
955 const TextIteratorBehavior& behavior =
956 TextIteratorBehavior::Builder()
957 .setEmitsObjectReplacementCharacter(true)
958 .build();
959 const String& text = plainText(
960 EphemeralRange::rangeOfContents(*rootEditableElement), behavior);
961
962 // UTF-8 is only used to encode Latin-1 characters, so the deletion lengths
dcheng 2017/02/25 07:37:03 8-bit characters, not UTF-8
yabinh 2017/02/27 02:04:33 Done.
963 // are trivial.
964 if (text.is8Bit())
965 return deleteSurroundingText(before, after);
966
967 const int selectionStart = static_cast<int>(selectionOffsets.start());
968 const int selectionEnd = static_cast<int>(selectionOffsets.end());
969
970 const int beforeLength =
971 calculateBeforeDeletionLengthsInCodePoints(text, before, selectionStart);
972 if (isInvalidDeletionLength(beforeLength))
973 return;
974 const int afterLength =
975 calculateAfterDeletionLengthsInCodePoints(text, after, selectionEnd);
976 if (isInvalidDeletionLength(afterLength))
977 return;
978
979 return deleteSurroundingText(beforeLength, afterLength);
980 }
981
870 WebTextInputInfo InputMethodController::textInputInfo() const { 982 WebTextInputInfo InputMethodController::textInputInfo() const {
871 WebTextInputInfo info; 983 WebTextInputInfo info;
872 if (!isAvailable()) 984 if (!isAvailable())
873 return info; 985 return info;
874 986
875 if (!frame().selection().isAvailable()) { 987 if (!frame().selection().isAvailable()) {
876 // plugins/mouse-capture-inside-shadow.html reaches here. 988 // plugins/mouse-capture-inside-shadow.html reaches here.
877 return info; 989 return info;
878 } 990 }
879 Element* element = frame().selection().rootEditableElement(); 991 Element* element = frame().selection().rootEditableElement();
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 finishComposingText(DoNotKeepSelection); 1194 finishComposingText(DoNotKeepSelection);
1083 } 1195 }
1084 1196
1085 DEFINE_TRACE(InputMethodController) { 1197 DEFINE_TRACE(InputMethodController) {
1086 visitor->trace(m_frame); 1198 visitor->trace(m_frame);
1087 visitor->trace(m_compositionRange); 1199 visitor->trace(m_compositionRange);
1088 SynchronousMutationObserver::trace(visitor); 1200 SynchronousMutationObserver::trace(visitor);
1089 } 1201 }
1090 1202
1091 } // namespace blink 1203 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698