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

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

Issue 2617443002: Implement ThreadedInputConnection.deleteSurroundingTextInCodePoints() (Closed)
Patch Set: Address yosin@'s review 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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 } 193 }
194 194
195 if (!queryAttribute) 195 if (!queryAttribute)
196 return AtomicString(); 196 return AtomicString();
197 197
198 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed 198 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed
199 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016. 199 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016.
200 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower(); 200 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower();
201 } 201 }
202 202
203 bool hasInvalidSurrogatePair(const UChar* text,
204 const int start,
205 const int end) {
206 DCHECK_GE(start, 0);
207 DCHECK_LE(start, end);
208 for (int i = start; i < end; ++i) {
209 if (U_IS_SURROGATE(text[i])) {
210 const bool isValidSurrogatePair =
211 U16_IS_LEAD(text[i]) && i + 1 < end && U16_IS_TRAIL(text[i + 1]);
212 if (!isValidSurrogatePair)
213 return true;
214 ++i;
215 }
216 }
217 return false;
218 }
219
220 std::pair<int, int> invalidDeletionLength() {
221 return std::make_pair(-1, -1);
222 }
223
224 bool isInvalidDeletionLength(const std::pair<int, int>& lengthPair) {
225 return lengthPair.first == -1 && lengthPair.second == -1;
yosin_UTC9 2017/02/10 04:54:11 You could write: return lengthPair == invalidDele
226 }
227
228 std::pair<int, int> calculateDeletionLengthsInCodePoints(
229 const String& text,
230 const int beforeLengthInCodePoints,
231 const int afterLengthInCodePoints,
232 const int selectionStart,
233 const int selectionEnd) {
234 int deletionStart = selectionStart;
235 int deletionEnd = selectionEnd;
236 const int length = static_cast<int>(text.length());
237
238 if (text.is8Bit()) {
239 const LChar* character8s = text.characters8();
240 U8_BACK_N(character8s, 0, deletionStart, beforeLengthInCodePoints);
241 U8_FWD_N(character8s, deletionEnd, length, afterLengthInCodePoints);
242 } else {
243 const UChar* character16s = text.characters16();
244 U16_BACK_N(character16s, 0, deletionStart, beforeLengthInCodePoints);
yosin_UTC9 2017/02/10 04:54:11 Let's avoid U16_BACK_N() and U16_FWD_N() since the
yosin_UTC9 2017/02/10 05:20:19 Refined. Make BackwardCodePointMachine::feed() to
yabinh 2017/02/10 10:49:22 Thanks! Do we need to add a separate file and add
245 // Required by Android's InputConnection spec.
246 if (hasInvalidSurrogatePair(character16s, deletionStart, selectionStart))
247 return invalidDeletionLength();
248
249 U16_FWD_N(character16s, deletionEnd, length, afterLengthInCodePoints);
250 // Required by Android's InputConnection spec.
251 if (hasInvalidSurrogatePair(character16s, selectionEnd, deletionEnd))
252 return invalidDeletionLength();
253 }
254
255 const int beforeLength = selectionStart - deletionStart;
256 const int afterLength = deletionEnd - selectionEnd;
257 DCHECK_GE(beforeLength, 0);
258 DCHECK_GE(afterLength, 0);
259 return std::make_pair(beforeLength, afterLength);
260 }
261
203 } // anonymous namespace 262 } // anonymous namespace
204 263
205 InputMethodController* InputMethodController::create(LocalFrame& frame) { 264 InputMethodController* InputMethodController::create(LocalFrame& frame) {
206 return new InputMethodController(frame); 265 return new InputMethodController(frame);
207 } 266 }
208 267
209 InputMethodController::InputMethodController(LocalFrame& frame) 268 InputMethodController::InputMethodController(LocalFrame& frame)
210 : m_frame(&frame), m_hasComposition(false) {} 269 : m_frame(&frame), m_hasComposition(false) {}
211 270
212 InputMethodController::~InputMethodController() = default; 271 InputMethodController::~InputMethodController() = default;
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 const size_t diff = computeDistanceToRightGraphemeBoundary(position); 943 const size_t diff = computeDistanceToRightGraphemeBoundary(position);
885 const int adjustedEnd = end + static_cast<int>(diff); 944 const int adjustedEnd = end + static_cast<int>(diff);
886 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd))) 945 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd)))
887 return; 946 return;
888 TypingCommand::deleteSelection(document()); 947 TypingCommand::deleteSelection(document());
889 } 948 }
890 949
891 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd)); 950 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
892 } 951 }
893 952
953 void InputMethodController::deleteSurroundingTextInCodePoints(int before,
954 int after) {
955 DCHECK_GE(before, 0);
956 DCHECK_GE(after, 0);
957 if (!editor().canEdit())
958 return;
959 const PlainTextRange selectionOffsets(getSelectionOffsets());
960 if (selectionOffsets.isNull())
961 return;
962 Element* const rootEditableElement =
963 frame().selection().rootEditableElement();
964 if (!rootEditableElement)
965 return;
966
967 const int selectionStart = static_cast<int>(selectionOffsets.start());
968 const int selectionEnd = static_cast<int>(selectionOffsets.end());
969 const TextIteratorBehavior& behavior =
970 TextIteratorBehavior::Builder()
971 .setEmitsObjectReplacementCharacter(true)
972 .build();
973 const String& text = plainText(
974 EphemeralRange::rangeOfContents(*rootEditableElement), behavior);
975 std::pair<int, int> deletionLengthPair = calculateDeletionLengthsInCodePoints(
976 text, before, after, selectionStart, selectionEnd);
977 if (isInvalidDeletionLength(deletionLengthPair))
978 return;
979
980 return deleteSurroundingText(deletionLengthPair.first,
981 deletionLengthPair.second);
982 }
983
894 WebTextInputInfo InputMethodController::textInputInfo() const { 984 WebTextInputInfo InputMethodController::textInputInfo() const {
895 WebTextInputInfo info; 985 WebTextInputInfo info;
896 if (!isAvailable()) 986 if (!isAvailable())
897 return info; 987 return info;
898 988
899 if (!frame().selection().isAvailable()) { 989 if (!frame().selection().isAvailable()) {
900 // plugins/mouse-capture-inside-shadow.html reaches here. 990 // plugins/mouse-capture-inside-shadow.html reaches here.
901 return info; 991 return info;
902 } 992 }
903 Element* element = frame().selection().rootEditableElement(); 993 Element* element = frame().selection().rootEditableElement();
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 frame().chromeClient().resetInputMethod(); 1198 frame().chromeClient().resetInputMethod();
1109 } 1199 }
1110 1200
1111 DEFINE_TRACE(InputMethodController) { 1201 DEFINE_TRACE(InputMethodController) {
1112 visitor->trace(m_frame); 1202 visitor->trace(m_frame);
1113 visitor->trace(m_compositionRange); 1203 visitor->trace(m_compositionRange);
1114 SynchronousMutationObserver::trace(visitor); 1204 SynchronousMutationObserver::trace(visitor);
1115 } 1205 }
1116 1206
1117 } // namespace blink 1207 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698