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

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: Use addCompositionUnderlines() where I said I couldn't Created 3 years, 11 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 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 return insertTextAndMoveCaret(text, relativeCaretPosition, underlines);
285 } 291 }
286 292
287 bool InputMethodController::replaceComposition(const String& text) { 293 bool InputMethodController::replaceComposition(const String& text) {
288 if (!hasComposition()) 294 if (!hasComposition())
289 return false; 295 return false;
290 296
291 // Select the text that will be deleted or replaced. 297 // Select the text that will be deleted or replaced.
292 selectComposition(); 298 selectComposition();
293 299
294 if (frame().selection().isNone()) 300 if (frame().selection().isNone())
(...skipping 22 matching lines...) Expand all
317 return true; 323 return true;
318 } 324 }
319 325
320 // relativeCaretPosition is relative to the end of the text. 326 // relativeCaretPosition is relative to the end of the text.
321 static int computeAbsoluteCaretPosition(size_t textStart, 327 static int computeAbsoluteCaretPosition(size_t textStart,
322 size_t textLength, 328 size_t textLength,
323 int relativeCaretPosition) { 329 int relativeCaretPosition) {
324 return textStart + textLength + relativeCaretPosition; 330 return textStart + textLength + relativeCaretPosition;
325 } 331 }
326 332
333 void InputMethodController::addCompositionUnderlines(
334 const Vector<CompositionUnderline>& underlines,
335 ContainerNode* rootEditableElement,
336 unsigned offset) {
337 for (const auto& underline : underlines) {
338 unsigned underlineStart = offset + underline.startOffset();
339 unsigned underlineEnd = offset + underline.endOffset();
340
341 EphemeralRange ephemeralLineRange =
342 PlainTextRange(underlineStart, underlineEnd)
343 .createRange(*rootEditableElement);
344 if (ephemeralLineRange.isNull())
345 continue;
346
347 document().markers().addCompositionMarker(
348 ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(),
349 underline.color(), underline.thick(), underline.backgroundColor());
350 }
351 }
352
327 bool InputMethodController::replaceCompositionAndMoveCaret( 353 bool InputMethodController::replaceCompositionAndMoveCaret(
328 const String& text, 354 const String& text,
329 int relativeCaretPosition) { 355 int relativeCaretPosition,
356 const Vector<CompositionUnderline>& underlines) {
330 Element* rootEditableElement = frame().selection().rootEditableElement(); 357 Element* rootEditableElement = frame().selection().rootEditableElement();
331 if (!rootEditableElement) 358 if (!rootEditableElement)
332 return false; 359 return false;
333 DCHECK(hasComposition()); 360 DCHECK(hasComposition());
334 PlainTextRange compositionRange = 361 PlainTextRange compositionRange =
335 PlainTextRange::create(*rootEditableElement, *m_compositionRange); 362 PlainTextRange::create(*rootEditableElement, *m_compositionRange);
336 if (compositionRange.isNull()) 363 if (compositionRange.isNull())
337 return false; 364 return false;
338 int textStart = compositionRange.start(); 365 int textStart = compositionRange.start();
339 366
340 if (!replaceComposition(text)) 367 if (!replaceComposition(text))
341 return false; 368 return false;
342 369
370 addCompositionUnderlines(underlines, rootEditableElement, textStart);
371
343 int absoluteCaretPosition = computeAbsoluteCaretPosition( 372 int absoluteCaretPosition = computeAbsoluteCaretPosition(
344 textStart, text.length(), relativeCaretPosition); 373 textStart, text.length(), relativeCaretPosition);
345 if (!moveCaret(absoluteCaretPosition)) 374 if (!moveCaret(absoluteCaretPosition))
346 return false; 375 return false;
347 376
348 // No DOM update after 'compositionend'. 377 // No DOM update after 'compositionend'.
349 dispatchCompositionEndEvent(frame(), text); 378 dispatchCompositionEndEvent(frame(), text);
350 379
351 return true; 380 return true;
352 } 381 }
353 382
354 bool InputMethodController::insertText(const String& text) { 383 bool InputMethodController::insertText(const String& text) {
355 if (dispatchBeforeInputInsertText(document().focusedElement(), text) != 384 if (dispatchBeforeInputInsertText(document().focusedElement(), text) !=
356 DispatchEventResult::NotCanceled) 385 DispatchEventResult::NotCanceled)
357 return false; 386 return false;
358 editor().insertText(text, 0); 387 editor().insertText(text, 0);
359 return true; 388 return true;
360 } 389 }
361 390
362 bool InputMethodController::insertTextAndMoveCaret(const String& text, 391 bool InputMethodController::insertTextAndMoveCaret(
363 int relativeCaretPosition) { 392 const String& text,
393 int relativeCaretPosition,
394 const Vector<CompositionUnderline>& underlines) {
364 PlainTextRange selectionRange = getSelectionOffsets(); 395 PlainTextRange selectionRange = getSelectionOffsets();
365 if (selectionRange.isNull()) 396 if (selectionRange.isNull())
366 return false; 397 return false;
367 int textStart = selectionRange.start(); 398 int textStart = selectionRange.start();
368 399
369 if (text.length()) { 400 if (text.length()) {
370 if (!insertText(text)) 401 if (!insertText(text))
371 return false; 402 return false;
403
404 Element* rootEditableElement = frame().selection().rootEditableElement();
405 if (rootEditableElement) {
406 addCompositionUnderlines(underlines, rootEditableElement, textStart);
407 }
372 } 408 }
373 409
374 int absoluteCaretPosition = computeAbsoluteCaretPosition( 410 int absoluteCaretPosition = computeAbsoluteCaretPosition(
375 textStart, text.length(), relativeCaretPosition); 411 textStart, text.length(), relativeCaretPosition);
376 return moveCaret(absoluteCaretPosition); 412 return moveCaret(absoluteCaretPosition);
377 } 413 }
378 414
379 void InputMethodController::cancelComposition() { 415 void InputMethodController::cancelComposition() {
380 if (!hasComposition()) 416 if (!hasComposition())
381 return; 417 return;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 // We shouldn't close typing in the middle of setComposition. 607 // We shouldn't close typing in the middle of setComposition.
572 setEditableSelectionOffsets(selectedRange, NotUserTriggered); 608 setEditableSelectionOffsets(selectedRange, NotUserTriggered);
573 609
574 if (underlines.isEmpty()) { 610 if (underlines.isEmpty()) {
575 document().markers().addCompositionMarker( 611 document().markers().addCompositionMarker(
576 m_compositionRange->startPosition(), m_compositionRange->endPosition(), 612 m_compositionRange->startPosition(), m_compositionRange->endPosition(),
577 Color::black, false, 613 Color::black, false,
578 LayoutTheme::theme().platformDefaultCompositionBackgroundColor()); 614 LayoutTheme::theme().platformDefaultCompositionBackgroundColor());
579 return; 615 return;
580 } 616 }
581 for (const auto& underline : underlines) { 617
582 unsigned underlineStart = baseOffset + underline.startOffset(); 618 addCompositionUnderlines(underlines, baseNode->parentNode(), 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 } 619 }
593 620
594 PlainTextRange InputMethodController::createSelectionRangeForSetComposition( 621 PlainTextRange InputMethodController::createSelectionRangeForSetComposition(
595 int selectionStart, 622 int selectionStart,
596 int selectionEnd, 623 int selectionEnd,
597 size_t textLength) const { 624 size_t textLength) const {
598 const int selectionOffsetsStart = 625 const int selectionOffsetsStart =
599 static_cast<int>(getSelectionOffsets().start()); 626 static_cast<int>(getSelectionOffsets().start());
600 const int start = selectionOffsetsStart + selectionStart; 627 const int start = selectionOffsetsStart + selectionStart;
601 const int end = selectionOffsetsStart + selectionEnd; 628 const int end = selectionOffsetsStart + selectionEnd;
(...skipping 18 matching lines...) Expand all
620 const Position start = range.startPosition(); 647 const Position start = range.startPosition();
621 if (rootEditableElementOf(start) != editable) 648 if (rootEditableElementOf(start) != editable)
622 return; 649 return;
623 650
624 const Position end = range.endPosition(); 651 const Position end = range.endPosition();
625 if (rootEditableElementOf(end) != editable) 652 if (rootEditableElementOf(end) != editable)
626 return; 653 return;
627 654
628 clear(); 655 clear();
629 656
630 for (const auto& underline : underlines) { 657 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 658
642 m_hasComposition = true; 659 m_hasComposition = true;
643 if (!m_compositionRange) 660 if (!m_compositionRange)
644 m_compositionRange = Range::create(document()); 661 m_compositionRange = Range::create(document());
645 m_compositionRange->setStart(range.startPosition()); 662 m_compositionRange->setStart(range.startPosition());
646 m_compositionRange->setEnd(range.endPosition()); 663 m_compositionRange->setEnd(range.endPosition());
647 } 664 }
648 665
649 EphemeralRange InputMethodController::compositionEphemeralRange() const { 666 EphemeralRange InputMethodController::compositionEphemeralRange() const {
650 if (!hasComposition()) 667 if (!hasComposition())
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 frame().chromeClient().resetInputMethod(); 1080 frame().chromeClient().resetInputMethod();
1064 } 1081 }
1065 1082
1066 DEFINE_TRACE(InputMethodController) { 1083 DEFINE_TRACE(InputMethodController) {
1067 visitor->trace(m_frame); 1084 visitor->trace(m_frame);
1068 visitor->trace(m_compositionRange); 1085 visitor->trace(m_compositionRange);
1069 SynchronousMutationObserver::trace(visitor); 1086 SynchronousMutationObserver::trace(visitor);
1070 } 1087 }
1071 1088
1072 } // namespace blink 1089 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698