Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Element* rootEditableElement = frame().selection().rootEditableElement(); |
| 583 unsigned underlineEnd = baseOffset + underline.endOffset(); | 619 if (!rootEditableElement) |
| 584 EphemeralRange ephemeralLineRange = EphemeralRange( | 620 return; |
| 585 Position(baseNode, underlineStart), Position(baseNode, underlineEnd)); | 621 |
| 586 if (ephemeralLineRange.isNull()) | 622 PlainTextRange selectionRange = getSelectionOffsets(); |
| 587 continue; | 623 if (selectionRange.isNull()) |
| 588 document().markers().addCompositionMarker( | 624 return; |
| 589 ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(), | 625 |
| 590 underline.color(), underline.thick(), underline.backgroundColor()); | 626 int textStart = selectionRange.start(); |
| 591 } | 627 addCompositionUnderlines(underlines, rootEditableElement, textStart); |
|
rlanday
2016/12/20 20:34:43
There's a bug here: this needs to use the composit
| |
| 592 } | 628 } |
| 593 | 629 |
| 594 PlainTextRange InputMethodController::createSelectionRangeForSetComposition( | 630 PlainTextRange InputMethodController::createSelectionRangeForSetComposition( |
| 595 int selectionStart, | 631 int selectionStart, |
| 596 int selectionEnd, | 632 int selectionEnd, |
| 597 size_t textLength) const { | 633 size_t textLength) const { |
| 598 const int selectionOffsetsStart = | 634 const int selectionOffsetsStart = |
| 599 static_cast<int>(getSelectionOffsets().start()); | 635 static_cast<int>(getSelectionOffsets().start()); |
| 600 const int start = selectionOffsetsStart + selectionStart; | 636 const int start = selectionOffsetsStart + selectionStart; |
| 601 const int end = selectionOffsetsStart + selectionEnd; | 637 const int end = selectionOffsetsStart + selectionEnd; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 620 const Position start = range.startPosition(); | 656 const Position start = range.startPosition(); |
| 621 if (rootEditableElementOf(start) != editable) | 657 if (rootEditableElementOf(start) != editable) |
| 622 return; | 658 return; |
| 623 | 659 |
| 624 const Position end = range.endPosition(); | 660 const Position end = range.endPosition(); |
| 625 if (rootEditableElementOf(end) != editable) | 661 if (rootEditableElementOf(end) != editable) |
| 626 return; | 662 return; |
| 627 | 663 |
| 628 clear(); | 664 clear(); |
| 629 | 665 |
| 630 for (const auto& underline : underlines) { | 666 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 | 667 |
| 642 m_hasComposition = true; | 668 m_hasComposition = true; |
| 643 if (!m_compositionRange) | 669 if (!m_compositionRange) |
| 644 m_compositionRange = Range::create(document()); | 670 m_compositionRange = Range::create(document()); |
| 645 m_compositionRange->setStart(range.startPosition()); | 671 m_compositionRange->setStart(range.startPosition()); |
| 646 m_compositionRange->setEnd(range.endPosition()); | 672 m_compositionRange->setEnd(range.endPosition()); |
| 647 } | 673 } |
| 648 | 674 |
| 649 EphemeralRange InputMethodController::compositionEphemeralRange() const { | 675 EphemeralRange InputMethodController::compositionEphemeralRange() const { |
| 650 if (!hasComposition()) | 676 if (!hasComposition()) |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1063 frame().chromeClient().resetInputMethod(); | 1089 frame().chromeClient().resetInputMethod(); |
| 1064 } | 1090 } |
| 1065 | 1091 |
| 1066 DEFINE_TRACE(InputMethodController) { | 1092 DEFINE_TRACE(InputMethodController) { |
| 1067 visitor->trace(m_frame); | 1093 visitor->trace(m_frame); |
| 1068 visitor->trace(m_compositionRange); | 1094 visitor->trace(m_compositionRange); |
| 1069 SynchronousMutationObserver::trace(visitor); | 1095 SynchronousMutationObserver::trace(visitor); |
| 1070 } | 1096 } |
| 1071 | 1097 |
| 1072 } // namespace blink | 1098 } // namespace blink |
| OLD | NEW |