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

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

Issue 1995333002: Handle newCursorPosition correctly for Android's commitText() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: For yosin@'s 2nd review Created 4 years, 3 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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 178
179 // The composition can start inside a composed character sequence, so we hav e to override checks. 179 // The composition can start inside a composed character sequence, so we hav e to override checks.
180 // See <http://bugs.webkit.org/show_bug.cgi?id=15781> 180 // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
181 VisibleSelection selection; 181 VisibleSelection selection;
182 selection.setWithoutValidation(range.startPosition(), range.endPosition()); 182 selection.setWithoutValidation(range.startPosition(), range.endPosition());
183 frame().selection().setSelection(selection, 0); 183 frame().selection().setSelection(selection, 0);
184 } 184 }
185 185
186 bool InputMethodController::confirmComposition() 186 bool InputMethodController::confirmComposition()
187 { 187 {
188 return confirmComposition(composingText()); 188 return replaceComposition(composingText(), KeepSelection);
189 } 189 }
190 190
191 bool InputMethodController::confirmComposition(const String& text, ConfirmCompos itionBehavior confirmBehavior) 191 bool InputMethodController::replaceComposition(const String& text, ConfirmCompos itionBehavior confirmBehavior)
192 { 192 {
193 if (!hasComposition()) 193 if (!hasComposition())
194 return false; 194 return false;
195 195
196 Optional<Editor::RevealSelectionScope> revealSelectionScope; 196 Optional<Editor::RevealSelectionScope> revealSelectionScope;
197 if (confirmBehavior == KeepSelection) 197 if (confirmBehavior == KeepSelection)
198 revealSelectionScope.emplace(&editor()); 198 revealSelectionScope.emplace(&editor());
199 199
200 // If the composition was set from existing text and didn't change, then 200 // If the composition was set from existing text and didn't change, then
201 // there's nothing to do here (and we should avoid doing anything as that 201 // there's nothing to do here (and we should avoid doing anything as that
(...skipping 23 matching lines...) Expand all
225 insertTextDuringCompositionWithEvents(frame(), text, 0, TypingCommand::TextC ompositionType::TextCompositionConfirm); 225 insertTextDuringCompositionWithEvents(frame(), text, 0, TypingCommand::TextC ompositionType::TextCompositionConfirm);
226 // Event handler might destroy document. 226 // Event handler might destroy document.
227 if (!frame().document()) 227 if (!frame().document())
228 return false; 228 return false;
229 229
230 // No DOM update after 'compositionend'. 230 // No DOM update after 'compositionend'.
231 dispatchCompositionEndEvent(frame(), text); 231 dispatchCompositionEndEvent(frame(), text);
232 232
233 return true; 233 return true;
234 } 234 }
235 235
yabinh 2016/08/29 08:44:01 Move the comments here.
236 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C onfirmCompositionBehavior confirmBehavior) 236 // If > 0, relativeCaretPosition is relative to the end of the text - 1;
237 // if <= 0, its' relative to the start of the text.
238 // This is to match Android behavior. See
239 // https://developer.android.com/reference/android/view/inputmethod/InputConnect ion.html#commitText(java.lang.CharSequence, int)
tkent 2016/08/30 07:47:11 Even though this follows an Android standard API,
yabinh 2016/08/30 12:33:05 Done.
240 static int computeAbsoluteCaretPosition(size_t textStart, size_t textLength, int relativeCaretPosition)
237 { 241 {
238 if (!hasComposition()) { 242 if (relativeCaretPosition > 0)
239 if (!text.length()) 243 relativeCaretPosition += textLength - 1;
240 return false; 244 return textStart + relativeCaretPosition;
245 }
241 246
242 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled) 247 bool InputMethodController::replaceCompositionAndMoveCaret(const String& text, i nt relativeCaretPosition)
243 return false; 248 {
249 Element* rootEditableElement = frame().selection().rootEditableElement();
250 if (!rootEditableElement)
251 return false;
252 PlainTextRange compositionRange = PlainTextRange::create(*rootEditableElemen t, *m_compositionRange);
253 if (compositionRange.isNull())
254 return false;
255 int textStart = compositionRange.start();
244 256
245 editor().insertText(text, 0); 257 if (!replaceComposition(text, DoNotKeepSelection))
258 return false;
259
260 int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.len gth(), relativeCaretPosition);
261 return moveCaret(absoluteCaretPosition);
262 }
263
264 bool InputMethodController::commitComposition(const String& text)
265 {
266 if (!hasComposition())
267 return insertText(text);
268
269 if (text.length()) {
270 replaceComposition(text, KeepSelection);
246 return true; 271 return true;
247 } 272 }
248 273
249 if (text.length()) {
250 confirmComposition(text);
251 return true;
252 }
253
254 if (confirmBehavior == DoNotKeepSelection)
255 return confirmComposition(composingText(), DoNotKeepSelection);
256
257 SelectionOffsetsScope selectionOffsetsScope(this); 274 SelectionOffsetsScope selectionOffsetsScope(this);
258 return confirmComposition(); 275 return confirmComposition();
259 } 276 }
260 277
278 bool InputMethodController::commitCompositionAndMoveCaret(const String& text, in t relativeCaretPosition)
279 {
280 if (!hasComposition())
281 return insertTextAndMoveCaret(text, relativeCaretPosition);
282 if (text.length())
283 return replaceCompositionAndMoveCaret(text, relativeCaretPosition);
284 return replaceCompositionAndMoveCaret(composingText(), relativeCaretPosition );
285 }
286
287 bool InputMethodController::insertText(const String& text)
288 {
289 if (!text.length())
290 return false;
291 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text ) != DispatchEventResult::NotCanceled)
292 return false;
293 editor().insertText(text, 0);
294 return true;
295 }
296
297 bool InputMethodController::insertTextAndMoveCaret(const String& text, int relat iveCaretPosition)
298 {
299 PlainTextRange selectionRange = getSelectionOffsets();
300 if (selectionRange.isNull())
301 return false;
302 int textStart = selectionRange.start();
303
304 if (!insertText(text))
305 return false;
306
307 int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.len gth(), relativeCaretPosition);
308 return moveCaret(absoluteCaretPosition);
309 }
310
261 void InputMethodController::cancelComposition() 311 void InputMethodController::cancelComposition()
262 { 312 {
263 if (!hasComposition()) 313 if (!hasComposition())
264 return; 314 return;
265 315
266 Editor::RevealSelectionScope revealSelectionScope(&editor()); 316 Editor::RevealSelectionScope revealSelectionScope(&editor());
267 317
268 if (frame().selection().isNone()) 318 if (frame().selection().isNone())
269 return; 319 return;
270 320
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 // Sending a compositionupdate event at this time ensures that at least o ne 386 // Sending a compositionupdate event at this time ensures that at least o ne
337 // compositionupdate event is dispatched. 387 // compositionupdate event is dispatched.
338 // 2. Updating the existing composition node. 388 // 2. Updating the existing composition node.
339 // Send a compositionupdate event when this function updates the existing composition 389 // Send a compositionupdate event when this function updates the existing composition
340 // node, i.e. hasComposition() && !text.isEmpty(). 390 // node, i.e. hasComposition() && !text.isEmpty().
341 // 3. Canceling the ongoing composition. 391 // 3. Canceling the ongoing composition.
342 // Send a compositionend event when function deletes the existing composi tion node, i.e. 392 // Send a compositionend event when function deletes the existing composi tion node, i.e.
343 // !hasComposition() && test.isEmpty(). 393 // !hasComposition() && test.isEmpty().
344 if (text.isEmpty()) { 394 if (text.isEmpty()) {
345 if (hasComposition()) { 395 if (hasComposition()) {
346 confirmComposition(emptyString()); 396 replaceComposition(emptyString(), KeepSelection);
347 } else { 397 } else {
348 // It's weird to call |setComposition()| with empty text outside com position, however some IME 398 // It's weird to call |setComposition()| with empty text outside com position, however some IME
349 // (e.g. Japanese IBus-Anthy) did this, so we simply delete selectio n without sending extra events. 399 // (e.g. Japanese IBus-Anthy) did this, so we simply delete selectio n without sending extra events.
350 TypingCommand::deleteSelection(*frame().document(), TypingCommand::P reventSpellChecking); 400 TypingCommand::deleteSelection(*frame().document(), TypingCommand::P reventSpellChecking);
351 } 401 }
352 402
353 setEditableSelectionOffsets(selectedRange); 403 setEditableSelectionOffsets(selectedRange);
354 return; 404 return;
355 } 405 }
356 406
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 586
537 rightBoundary += textLength; 587 rightBoundary += textLength;
538 588
539 // In case of exceeding the right boundary. 589 // In case of exceeding the right boundary.
540 start = std::min(start, rightBoundary); 590 start = std::min(start, rightBoundary);
541 end = std::min(end, rightBoundary); 591 end = std::min(end, rightBoundary);
542 592
543 return PlainTextRange(start, end); 593 return PlainTextRange(start, end);
544 } 594 }
545 595
596 bool InputMethodController::moveCaret(int newCaretPosition)
597 {
598 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();
599
600 PlainTextRange selectedRange = createRangeForSelection(newCaretPosition, new CaretPosition, 0);
601 if (selectedRange.isNull())
602 return false;
603 return setEditableSelectionOffsets(selectedRange);
604 }
605
546 void InputMethodController::extendSelectionAndDelete(int before, int after) 606 void InputMethodController::extendSelectionAndDelete(int before, int after)
547 { 607 {
548 if (!editor().canEdit()) 608 if (!editor().canEdit())
549 return; 609 return;
550 PlainTextRange selectionOffsets(getSelectionOffsets()); 610 PlainTextRange selectionOffsets(getSelectionOffsets());
551 if (selectionOffsets.isNull()) 611 if (selectionOffsets.isNull())
552 return; 612 return;
553 613
554 // A common call of before=1 and after=0 will fail if the last character 614 // A common call of before=1 and after=0 will fail if the last character
555 // is multi-code-word UTF-16, including both multi-16bit code-points and 615 // is multi-code-word UTF-16, including both multi-16bit code-points and
(...skipping 19 matching lines...) Expand all
575 TypingCommand::deleteSelection(*frame().document()); 635 TypingCommand::deleteSelection(*frame().document());
576 } 636 }
577 637
578 DEFINE_TRACE(InputMethodController) 638 DEFINE_TRACE(InputMethodController)
579 { 639 {
580 visitor->trace(m_frame); 640 visitor->trace(m_frame);
581 visitor->trace(m_compositionRange); 641 visitor->trace(m_compositionRange);
582 } 642 }
583 643
584 } // namespace blink 644 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698