Chromium Code Reviews

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 review Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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...)
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 24 matching lines...)
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
236 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C onfirmCompositionBehavior confirmBehavior) 236 bool InputMethodController::replaceCompositionAndMoveCaret(const String& text, i nt relativeCaretPosition)
237 { 237 {
238 if (!hasComposition()) { 238 Element* rootEditableElement = frame().selection().rootEditableElement();
239 if (!text.length()) 239 if (!rootEditableElement)
240 return false; 240 return false;
241 PlainTextRange compositionRange = PlainTextRange::create(*rootEditableElemen t, *m_compositionRange);
242 if (compositionRange.isNull())
243 return false;
241 244
242 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled) 245 int absoluteCaretPosition = getAbsoluteCaretPosition(compositionRange.start( ), text.length(), relativeCaretPosition);
243 return false; 246 return replaceComposition(text, DoNotKeepSelection) && moveCaret(absoluteCar etPosition);
247 }
244 248
245 editor().insertText(text, 0); 249 bool InputMethodController::commitComposition(const String& text)
250 {
251 if (!hasComposition())
252 return insertText(text);
253
254 if (text.length()) {
255 replaceComposition(text, KeepSelection);
246 return true; 256 return true;
247 } 257 }
248 258
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); 259 SelectionOffsetsScope selectionOffsetsScope(this);
258 return confirmComposition(); 260 return confirmComposition();
259 } 261 }
260 262
263 bool InputMethodController::commitCompositionAndMoveCaret(const String& text, in t relativeCaretPosition)
264 {
265 if (!hasComposition())
266 return insertTextAndMoveCaret(text, relativeCaretPosition);
267
yosin_UTC9 2016/08/29 07:02:01 nit: no need to have an extra blank line.
yabinh 2016/08/29 08:44:00 Done.
268 if (text.length())
269 return replaceCompositionAndMoveCaret(text, relativeCaretPosition);
270
yosin_UTC9 2016/08/29 07:02:02 nit: no need to have an extra blank line.
yabinh 2016/08/29 08:44:01 Done.
271 return replaceCompositionAndMoveCaret(composingText(), relativeCaretPosition );
272 }
273
274 bool InputMethodController::insertText(const String& text)
275 {
276 if (!text.length())
277 return false;
278
yosin_UTC9 2016/08/29 07:02:02 nit: no need to have an extra blank line.
yabinh 2016/08/29 08:44:01 Done.
279 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text ) != DispatchEventResult::NotCanceled)
280 return false;
281
yosin_UTC9 2016/08/29 07:02:02 nit: no need to have an extra blank line.
yabinh 2016/08/29 08:44:01 Done.
282 editor().insertText(text, 0);
283 return true;
284 }
285
286 bool InputMethodController::insertTextAndMoveCaret(const String& text, int relat iveCaretPosition)
287 {
288 PlainTextRange selectionRange = getSelectionOffsets();
289 if (selectionRange.isNull())
290 return false;
291
yosin_UTC9 2016/08/29 07:02:02 nit: no need to have an extra blank line.
yabinh 2016/08/29 08:44:01 Done.
292 int absoluteCaretPosition = getAbsoluteCaretPosition(selectionRange.start(), text.length(), relativeCaretPosition);
yosin_UTC9 2016/08/29 07:02:01 s/getAbsoluteCaretPosition/computeAbsoluteCaretPos
yabinh 2016/08/29 08:44:01 Done.
293 return insertText(text) && moveCaret(absoluteCaretPosition);
yosin_UTC9 2016/08/29 07:02:02 We should not compute |absoluteCaretPosition| when
yabinh 2016/08/29 08:44:01 Done. BTW, we should restore the selection and com
294 }
295
261 void InputMethodController::cancelComposition() 296 void InputMethodController::cancelComposition()
262 { 297 {
263 if (!hasComposition()) 298 if (!hasComposition())
264 return; 299 return;
265 300
266 Editor::RevealSelectionScope revealSelectionScope(&editor()); 301 Editor::RevealSelectionScope revealSelectionScope(&editor());
267 302
268 if (frame().selection().isNone()) 303 if (frame().selection().isNone())
269 return; 304 return;
270 305
(...skipping 65 matching lines...)
336 // Sending a compositionupdate event at this time ensures that at least o ne 371 // Sending a compositionupdate event at this time ensures that at least o ne
337 // compositionupdate event is dispatched. 372 // compositionupdate event is dispatched.
338 // 2. Updating the existing composition node. 373 // 2. Updating the existing composition node.
339 // Send a compositionupdate event when this function updates the existing composition 374 // Send a compositionupdate event when this function updates the existing composition
340 // node, i.e. hasComposition() && !text.isEmpty(). 375 // node, i.e. hasComposition() && !text.isEmpty().
341 // 3. Canceling the ongoing composition. 376 // 3. Canceling the ongoing composition.
342 // Send a compositionend event when function deletes the existing composi tion node, i.e. 377 // Send a compositionend event when function deletes the existing composi tion node, i.e.
343 // !hasComposition() && test.isEmpty(). 378 // !hasComposition() && test.isEmpty().
344 if (text.isEmpty()) { 379 if (text.isEmpty()) {
345 if (hasComposition()) { 380 if (hasComposition()) {
346 confirmComposition(emptyString()); 381 replaceComposition(emptyString(), KeepSelection);
347 } else { 382 } else {
348 // It's weird to call |setComposition()| with empty text outside com position, however some IME 383 // 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. 384 // (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); 385 TypingCommand::deleteSelection(*frame().document(), TypingCommand::P reventSpellChecking);
351 } 386 }
352 387
353 setEditableSelectionOffsets(selectedRange); 388 setEditableSelectionOffsets(selectedRange);
354 return; 389 return;
355 } 390 }
356 391
(...skipping 179 matching lines...)
536 571
537 rightBoundary += textLength; 572 rightBoundary += textLength;
538 573
539 // In case of exceeding the right boundary. 574 // In case of exceeding the right boundary.
540 start = std::min(start, rightBoundary); 575 start = std::min(start, rightBoundary);
541 end = std::min(end, rightBoundary); 576 end = std::min(end, rightBoundary);
542 577
543 return PlainTextRange(start, end); 578 return PlainTextRange(start, end);
544 } 579 }
545 580
581 int InputMethodController::getAbsoluteCaretPosition(size_t textStart, size_t tex tLength, int relativeCaretPosition) const
yosin_UTC9 2016/08/29 07:02:02 This function should be a local static function in
yabinh 2016/08/29 08:44:00 Done.
582 {
583 // If relativeCaretPosition > 0, it's relative to the end of the text - 1;
yosin_UTC9 2016/08/29 07:02:01 Please put this comment in .h file.
yabinh 2016/08/29 08:44:01 Since this function is not declared in .h file in
584 // if relativeCaretPosition <= 0, it is relative to the start of the text.
585 // This is to match Android behavior. See
586 // https://developer.android.com/reference/android/view/inputmethod/InputCon nection.html#commitText(java.lang.CharSequence, int)
587 if (relativeCaretPosition > 0)
588 relativeCaretPosition += textLength - 1;
589 return textStart + relativeCaretPosition;
590 }
591
592 bool InputMethodController::moveCaret(int newCaretPosition)
593 {
594 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();
595
596 PlainTextRange selectedRange = createRangeForSelection(newCaretPosition, new CaretPosition, 0);
597 if (selectedRange.isNull())
598 return false;
599 return setEditableSelectionOffsets(selectedRange);
600 }
601
546 void InputMethodController::extendSelectionAndDelete(int before, int after) 602 void InputMethodController::extendSelectionAndDelete(int before, int after)
547 { 603 {
548 if (!editor().canEdit()) 604 if (!editor().canEdit())
549 return; 605 return;
550 PlainTextRange selectionOffsets(getSelectionOffsets()); 606 PlainTextRange selectionOffsets(getSelectionOffsets());
551 if (selectionOffsets.isNull()) 607 if (selectionOffsets.isNull())
552 return; 608 return;
553 609
554 // A common call of before=1 and after=0 will fail if the last character 610 // 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 611 // is multi-code-word UTF-16, including both multi-16bit code-points and
(...skipping 19 matching lines...)
575 TypingCommand::deleteSelection(*frame().document()); 631 TypingCommand::deleteSelection(*frame().document());
576 } 632 }
577 633
578 DEFINE_TRACE(InputMethodController) 634 DEFINE_TRACE(InputMethodController)
579 { 635 {
580 visitor->trace(m_frame); 636 visitor->trace(m_frame);
581 visitor->trace(m_compositionRange); 637 visitor->trace(m_compositionRange);
582 } 638 }
583 639
584 } // namespace blink 640 } // namespace blink
OLDNEW

Powered by Google App Engine