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

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

Issue 2568093003: Support parsing BackgroundSpans and UnderlineSpans in Android IME's commitText() (Closed)
Patch Set: Fix commitText() logic (I think) Created 4 years 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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 document().updateStyleAndLayoutIgnorePendingStylesheets(); 260 document().updateStyleAndLayoutIgnorePendingStylesheets();
261 261
262 setSelectionOffsets(oldOffsets); 262 setSelectionOffsets(oldOffsets);
263 263
264 // No DOM update after 'compositionend'. 264 // No DOM update after 'compositionend'.
265 dispatchCompositionEndEvent(frame(), composing); 265 dispatchCompositionEndEvent(frame(), composing);
266 266
267 return result; 267 return result;
268 } 268 }
269 269
270 return replaceCompositionAndMoveCaret(composingText(), 0); 270 return replaceCompositionAndMoveCaret(composingText(), 0,
271 Vector<CompositionUnderline>());
271 } 272 }
272 273
273 bool InputMethodController::commitText(const String& text, 274 bool InputMethodController::commitText(
274 int relativeCaretPosition) { 275 const String& text,
275 if (hasComposition()) 276 const Vector<CompositionUnderline>& underlines,
276 return replaceCompositionAndMoveCaret(text, relativeCaretPosition); 277 int relativeCaretPosition) {
278 if (hasComposition()) {
279 return replaceCompositionAndMoveCaret(text, relativeCaretPosition,
280 underlines);
281 }
277 282
278 // We should do nothing in this case, because: 283 // We should do nothing in this case, because:
279 // 1. No need to insert text when text is empty. 284 // 1. No need to insert text when text is empty.
280 // 2. Shouldn't move caret when relativeCaretPosition == 0 to avoid 285 // 2. Shouldn't move caret when relativeCaretPosition == 0 to avoid
281 // duplicate selection change event. 286 // duplicate selection change event.
282 if (!text.length() && !relativeCaretPosition) 287 if (!text.length() && !relativeCaretPosition) {
283 return false; 288 return false;
284 return insertTextAndMoveCaret(text, relativeCaretPosition); 289 }
290
291 return insertTextAndMoveCaret(text, relativeCaretPosition, underlines);
285 } 292 }
286 293
287 bool InputMethodController::replaceComposition(const String& text) { 294 bool InputMethodController::replaceComposition(const String& text) {
288 if (!hasComposition()) 295 if (!hasComposition())
289 return false; 296 return false;
290 297
291 // Select the text that will be deleted or replaced. 298 // Select the text that will be deleted or replaced.
292 selectComposition(); 299 selectComposition();
293 300
294 if (frame().selection().isNone()) 301 if (frame().selection().isNone())
(...skipping 22 matching lines...) Expand all
317 return true; 324 return true;
318 } 325 }
319 326
320 // relativeCaretPosition is relative to the end of the text. 327 // relativeCaretPosition is relative to the end of the text.
321 static int computeAbsoluteCaretPosition(size_t textStart, 328 static int computeAbsoluteCaretPosition(size_t textStart,
322 size_t textLength, 329 size_t textLength,
323 int relativeCaretPosition) { 330 int relativeCaretPosition) {
324 return textStart + textLength + relativeCaretPosition; 331 return textStart + textLength + relativeCaretPosition;
325 } 332 }
326 333
334 void InputMethodController::addCompositionUnderlines(
335 const Vector<CompositionUnderline>& underlines,
336 Node* baseNode,
337 unsigned baseOffset) {
338 for (const auto& underline : underlines) {
339 unsigned underlineStart = baseOffset + underline.startOffset();
340 unsigned underlineEnd = baseOffset + underline.endOffset();
341 EphemeralRange ephemeralLineRange = EphemeralRange(
342 Position(baseNode, underlineStart), Position(baseNode, underlineEnd));
343 if (ephemeralLineRange.isNull())
344 continue;
345 document().markers().addCompositionMarker(
346 ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(),
347 underline.color(), underline.thick(), underline.backgroundColor());
348 }
349 }
350
327 bool InputMethodController::replaceCompositionAndMoveCaret( 351 bool InputMethodController::replaceCompositionAndMoveCaret(
328 const String& text, 352 const String& text,
329 int relativeCaretPosition) { 353 int relativeCaretPosition,
354 const Vector<CompositionUnderline>& underlines) {
330 Element* rootEditableElement = frame().selection().rootEditableElement(); 355 Element* rootEditableElement = frame().selection().rootEditableElement();
331 if (!rootEditableElement) 356 if (!rootEditableElement)
332 return false; 357 return false;
333 DCHECK(hasComposition()); 358 DCHECK(hasComposition());
334 PlainTextRange compositionRange = 359 PlainTextRange compositionRange =
335 PlainTextRange::create(*rootEditableElement, *m_compositionRange); 360 PlainTextRange::create(*rootEditableElement, *m_compositionRange);
336 if (compositionRange.isNull()) 361 if (compositionRange.isNull())
337 return false; 362 return false;
338 int textStart = compositionRange.start(); 363 int textStart = compositionRange.start();
339 364
340 if (!replaceComposition(text)) 365 if (!replaceComposition(text))
341 return false; 366 return false;
342 367
368 addCompositionUnderlines(underlines, rootEditableElement, textStart);
rlanday 2016/12/16 20:55:33 I don't think the Voice IME actually ever replaces
rlanday 2016/12/16 21:01:35 I'm going to try to add a test case to InputMethod
rlanday 2016/12/16 21:01:35 I'm going to try to add a test case to InputMethod
369
343 int absoluteCaretPosition = computeAbsoluteCaretPosition( 370 int absoluteCaretPosition = computeAbsoluteCaretPosition(
344 textStart, text.length(), relativeCaretPosition); 371 textStart, text.length(), relativeCaretPosition);
345 if (!moveCaret(absoluteCaretPosition)) 372 if (!moveCaret(absoluteCaretPosition))
346 return false; 373 return false;
347 374
348 // No DOM update after 'compositionend'. 375 // No DOM update after 'compositionend'.
349 dispatchCompositionEndEvent(frame(), text); 376 dispatchCompositionEndEvent(frame(), text);
350 377
351 return true; 378 return true;
352 } 379 }
353 380
354 bool InputMethodController::insertText(const String& text) { 381 bool InputMethodController::insertText(const String& text) {
355 if (dispatchBeforeInputInsertText(document().focusedElement(), text) != 382 if (dispatchBeforeInputInsertText(document().focusedElement(), text) !=
356 DispatchEventResult::NotCanceled) 383 DispatchEventResult::NotCanceled)
357 return false; 384 return false;
358 editor().insertText(text, 0); 385 editor().insertText(text, 0);
359 return true; 386 return true;
360 } 387 }
361 388
362 bool InputMethodController::insertTextAndMoveCaret(const String& text, 389 bool InputMethodController::insertTextAndMoveCaret(
363 int relativeCaretPosition) { 390 const String& text,
391 int relativeCaretPosition,
392 const Vector<CompositionUnderline>& underlines) {
364 PlainTextRange selectionRange = getSelectionOffsets(); 393 PlainTextRange selectionRange = getSelectionOffsets();
365 if (selectionRange.isNull()) 394 if (selectionRange.isNull())
366 return false; 395 return false;
367 int textStart = selectionRange.start(); 396 int textStart = selectionRange.start();
368 397
369 if (text.length()) { 398 if (text.length()) {
399 Position base = mostForwardCaretPosition(frame().selection().base());
400 Node* baseNode = base.anchorNode();
401
402 if (!baseNode)
rlanday 2016/12/16 20:55:33 Note: if I add the baseNode->isTextNode() check th
403 return false;
404
405 unsigned baseOffset = base.computeOffsetInContainerNode();
406
370 if (!insertText(text)) 407 if (!insertText(text))
371 return false; 408 return false;
409
410 addCompositionUnderlines(underlines, baseNode, baseOffset);
372 } 411 }
373 412
374 int absoluteCaretPosition = computeAbsoluteCaretPosition( 413 int absoluteCaretPosition = computeAbsoluteCaretPosition(
375 textStart, text.length(), relativeCaretPosition); 414 textStart, text.length(), relativeCaretPosition);
376 return moveCaret(absoluteCaretPosition); 415 return moveCaret(absoluteCaretPosition);
377 } 416 }
378 417
379 void InputMethodController::cancelComposition() { 418 void InputMethodController::cancelComposition() {
380 if (!hasComposition()) 419 if (!hasComposition())
381 return; 420 return;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 // We shouldn't close typing in the middle of setComposition. 610 // We shouldn't close typing in the middle of setComposition.
572 setEditableSelectionOffsets(selectedRange, NotUserTriggered); 611 setEditableSelectionOffsets(selectedRange, NotUserTriggered);
573 612
574 if (underlines.isEmpty()) { 613 if (underlines.isEmpty()) {
575 document().markers().addCompositionMarker( 614 document().markers().addCompositionMarker(
576 m_compositionRange->startPosition(), m_compositionRange->endPosition(), 615 m_compositionRange->startPosition(), m_compositionRange->endPosition(),
577 Color::black, false, 616 Color::black, false,
578 LayoutTheme::theme().platformDefaultCompositionBackgroundColor()); 617 LayoutTheme::theme().platformDefaultCompositionBackgroundColor());
579 return; 618 return;
580 } 619 }
581 for (const auto& underline : underlines) { 620
582 unsigned underlineStart = baseOffset + underline.startOffset(); 621 addCompositionUnderlines(underlines, baseNode, baseOffset);
583 unsigned underlineEnd = baseOffset + underline.endOffset();
584 EphemeralRange ephemeralLineRange = EphemeralRange(
585 Position(baseNode, underlineStart), Position(baseNode, underlineEnd));
586 if (ephemeralLineRange.isNull())
587 continue;
588 document().markers().addCompositionMarker(
589 ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(),
590 underline.color(), underline.thick(), underline.backgroundColor());
591 }
592 } 622 }
593 623
594 PlainTextRange InputMethodController::createSelectionRangeForSetComposition( 624 PlainTextRange InputMethodController::createSelectionRangeForSetComposition(
595 int selectionStart, 625 int selectionStart,
596 int selectionEnd, 626 int selectionEnd,
597 size_t textLength) const { 627 size_t textLength) const {
598 const int selectionOffsetsStart = 628 const int selectionOffsetsStart =
599 static_cast<int>(getSelectionOffsets().start()); 629 static_cast<int>(getSelectionOffsets().start());
600 const int start = selectionOffsetsStart + selectionStart; 630 const int start = selectionOffsetsStart + selectionStart;
601 const int end = selectionOffsetsStart + selectionEnd; 631 const int end = selectionOffsetsStart + selectionEnd;
(...skipping 18 matching lines...) Expand all
620 const Position start = range.startPosition(); 650 const Position start = range.startPosition();
621 if (rootEditableElementOf(start) != editable) 651 if (rootEditableElementOf(start) != editable)
622 return; 652 return;
623 653
624 const Position end = range.endPosition(); 654 const Position end = range.endPosition();
625 if (rootEditableElementOf(end) != editable) 655 if (rootEditableElementOf(end) != editable)
626 return; 656 return;
627 657
628 clear(); 658 clear();
629 659
630 for (const auto& underline : underlines) { 660 addCompositionUnderlines(underlines, editable, compositionStart);
631 unsigned underlineStart = compositionStart + underline.startOffset();
632 unsigned underlineEnd = compositionStart + underline.endOffset();
633 EphemeralRange ephemeralLineRange =
634 PlainTextRange(underlineStart, underlineEnd).createRange(*editable);
635 if (ephemeralLineRange.isNull())
636 continue;
637 document().markers().addCompositionMarker(
638 ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(),
639 underline.color(), underline.thick(), underline.backgroundColor());
640 }
641 661
642 m_hasComposition = true; 662 m_hasComposition = true;
643 if (!m_compositionRange) 663 if (!m_compositionRange)
644 m_compositionRange = Range::create(document()); 664 m_compositionRange = Range::create(document());
645 m_compositionRange->setStart(range.startPosition()); 665 m_compositionRange->setStart(range.startPosition());
646 m_compositionRange->setEnd(range.endPosition()); 666 m_compositionRange->setEnd(range.endPosition());
647 } 667 }
648 668
649 EphemeralRange InputMethodController::compositionEphemeralRange() const { 669 EphemeralRange InputMethodController::compositionEphemeralRange() const {
650 if (!hasComposition()) 670 if (!hasComposition())
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 frame().chromeClient().resetInputMethod(); 1083 frame().chromeClient().resetInputMethod();
1064 } 1084 }
1065 1085
1066 DEFINE_TRACE(InputMethodController) { 1086 DEFINE_TRACE(InputMethodController) {
1067 visitor->trace(m_frame); 1087 visitor->trace(m_frame);
1068 visitor->trace(m_compositionRange); 1088 visitor->trace(m_compositionRange);
1069 SynchronousMutationObserver::trace(visitor); 1089 SynchronousMutationObserver::trace(visitor);
1070 } 1090 }
1071 1091
1072 } // namespace blink 1092 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698