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 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 305 | 305 |
| 306 void InputMethodController::setComposition(const String& text, const Vector<Comp ositionUnderline>& underlines, int selectionStart, int selectionEnd) | 306 void InputMethodController::setComposition(const String& text, const Vector<Comp ositionUnderline>& underlines, int selectionStart, int selectionEnd) |
| 307 { | 307 { |
| 308 Editor::RevealSelectionScope revealSelectionScope(&editor()); | 308 Editor::RevealSelectionScope revealSelectionScope(&editor()); |
| 309 | 309 |
| 310 // Updates styles before setting selection for composition to prevent | 310 // Updates styles before setting selection for composition to prevent |
| 311 // inserting the previous composition text into text nodes oddly. | 311 // inserting the previous composition text into text nodes oddly. |
| 312 // See https://bugs.webkit.org/show_bug.cgi?id=46868 | 312 // See https://bugs.webkit.org/show_bug.cgi?id=46868 |
| 313 frame().document()->updateStyleAndLayoutTree(); | 313 frame().document()->updateStyleAndLayoutTree(); |
| 314 | 314 |
| 315 // When the IME only wants to change a few characters at the end of the | |
| 316 // composition, only touch those characters in order to preserve rich text | |
| 317 // substructure. | |
| 318 String composing = composingText(); | |
| 319 bool appending = composing.length() > 0 && composing == text.left(composing. length()); | |
| 320 bool backspacing = text.length() > 0 && text == composing.left(text.length() ); | |
|
Changwan Ryu
2016/09/07 04:14:39
FYI, this workaround is not going to work for Kore
aelias_OOO_until_Jul13
2016/09/07 05:11:49
OK. It looks like I can just use std::distance an
| |
| 321 if (appending || backspacing) { | |
| 322 const EphemeralRange range = compositionEphemeralRange(); | |
| 323 Element* editable = frame().selection().rootEditableElement(); | |
| 324 if (!editable) | |
| 325 return; | |
| 326 | |
| 327 // Move selection to the end of the composition. | |
| 328 PlainTextRange compositionPlainOffsets = PlainTextRange::create(*editabl e, range); | |
| 329 VisibleSelection selection; | |
| 330 selection.setWithoutValidation(range.endPosition(), range.endPosition()) ; | |
| 331 frame().selection().setSelection(selection, 0); | |
| 332 clear(); | |
| 333 | |
| 334 // Apply the incremental change. | |
| 335 if (appending) | |
| 336 confirmCompositionOrInsertText(text.substring(composing.length()), D oNotKeepSelection); | |
| 337 else if (backspacing) | |
| 338 extendSelectionAndDelete(composing.length() - text.length(), 0); | |
| 339 | |
| 340 // Now recreate the composition starting at its original start, and | |
| 341 // apply the specified final selection offsets. | |
| 342 setCompositionFromExistingText(underlines, compositionPlainOffsets.start (), compositionPlainOffsets.start() + text.length()); | |
| 343 selectComposition(); | |
| 344 setSelectionRangeForSetComposition(selectionStart, selectionEnd); | |
| 345 return; | |
| 346 } | |
| 347 | |
| 315 selectComposition(); | 348 selectComposition(); |
| 316 | 349 |
| 317 if (frame().selection().isNone()) | 350 if (frame().selection().isNone()) |
| 318 return; | 351 return; |
| 319 | 352 |
| 320 Element* target = frame().document()->focusedElement(); | 353 Element* target = frame().document()->focusedElement(); |
| 321 if (!target) | 354 if (!target) |
| 322 return; | 355 return; |
| 323 | 356 |
| 324 // Dispatch an appropriate composition event to the focused node. | 357 // Dispatch an appropriate composition event to the focused node. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 m_isDirty = true; | 416 m_isDirty = true; |
| 384 m_hasComposition = true; | 417 m_hasComposition = true; |
| 385 if (!m_compositionRange) | 418 if (!m_compositionRange) |
| 386 m_compositionRange = Range::create(baseNode->document()); | 419 m_compositionRange = Range::create(baseNode->document()); |
| 387 m_compositionRange->setStart(baseNode, baseOffset); | 420 m_compositionRange->setStart(baseNode, baseOffset); |
| 388 m_compositionRange->setEnd(baseNode, extentOffset); | 421 m_compositionRange->setEnd(baseNode, extentOffset); |
| 389 | 422 |
| 390 if (baseNode->layoutObject()) | 423 if (baseNode->layoutObject()) |
| 391 baseNode->layoutObject()->setShouldDoFullPaintInvalidation(); | 424 baseNode->layoutObject()->setShouldDoFullPaintInvalidation(); |
| 392 | 425 |
| 426 setSelectionRangeForSetComposition(selectionStart, selectionEnd); | |
| 427 | |
| 428 if (underlines.isEmpty()) { | |
| 429 frame().document()->markers().addCompositionMarker(m_compositionRange->s tartPosition(), m_compositionRange->endPosition(), Color::black, false, LayoutTh eme::theme().platformDefaultCompositionBackgroundColor()); | |
| 430 return; | |
| 431 } | |
| 432 for (const auto& underline : underlines) { | |
| 433 unsigned underlineStart = baseOffset + underline.startOffset; | |
| 434 unsigned underlineEnd = baseOffset + underline.endOffset; | |
| 435 EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, un derlineStart), Position(baseNode, underlineEnd)); | |
| 436 if (ephemeralLineRange.isNull()) | |
| 437 continue; | |
| 438 frame().document()->markers().addCompositionMarker(ephemeralLineRange.st artPosition(), ephemeralLineRange.endPosition(), underline.color, underline.thic k, underline.backgroundColor); | |
| 439 } | |
| 440 } | |
| 441 | |
| 442 void InputMethodController::setSelectionRangeForSetComposition(int selectionStar t, int selectionEnd) | |
| 443 { | |
| 393 // In case of exceeding the left boundary. | 444 // In case of exceeding the left boundary. |
| 394 int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start()); | 445 int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start()); |
| 395 int start = std::max(selectionOffsetsStart + selectionStart, 0); | 446 int start = std::max(selectionOffsetsStart + selectionStart, 0); |
| 396 int end = std::max(selectionOffsetsStart + selectionEnd, start); | 447 int end = std::max(selectionOffsetsStart + selectionEnd, start); |
| 397 | 448 |
| 398 Element* rootEditableElement = frame().selection().rootEditableElement(); | 449 Element* rootEditableElement = frame().selection().rootEditableElement(); |
| 399 if (!rootEditableElement) | 450 if (!rootEditableElement) |
| 400 return; | 451 return; |
| 401 | 452 |
| 402 // In case of exceeding the right boundary. | 453 // In case of exceeding the right boundary. |
| 403 // If both |value1| and |value2| exceed right boundary, | 454 // If both |value1| and |value2| exceed right boundary, |
| 404 // PlainTextRange(value1, value2)::createRange() will return a default | 455 // PlainTextRange(value1, value2)::createRange() will return a default |
| 405 // value, which is [0,0]. In order to get the correct Position in that case, | 456 // value, which is [0,0]. In order to get the correct Position in that case, |
| 406 // we should make sure |value1| is within range at least. | 457 // we should make sure |value1| is within range at least. |
| 407 const EphemeralRange& startRange = PlainTextRange(0, start).createRange(*roo tEditableElement); | 458 const EphemeralRange& startRange = PlainTextRange(0, start).createRange(*roo tEditableElement); |
| 408 const EphemeralRange& endRange = PlainTextRange(0, end).createRange(*rootEdi tableElement); | 459 const EphemeralRange& endRange = PlainTextRange(0, end).createRange(*rootEdi tableElement); |
| 409 | 460 |
| 410 // TODO(yabinh): There should be a better way to create |startPosition| and | 461 // TODO(yabinh): There should be a better way to create |startPosition| and |
| 411 // |endPosition|. But for now, since we can't get |anchorNode| and |offset|, | 462 // |endPosition|. But for now, since we can't get |anchorNode| and |offset|, |
| 412 // we can't create the 2 Position objects directly. So we use | 463 // we can't create the 2 Position objects directly. So we use |
| 413 // PlainTextRange::createRange as a workaround. | 464 // PlainTextRange::createRange as a workaround. |
| 414 const Position& startPosition = startRange.endPosition(); | 465 const Position& startPosition = startRange.endPosition(); |
| 415 const Position& endPosition = endRange.endPosition(); | 466 const Position& endPosition = endRange.endPosition(); |
| 416 const EphemeralRange selectedRange(startPosition, endPosition); | 467 const EphemeralRange selectedRange(startPosition, endPosition); |
| 417 frame().selection().setSelectedRange(selectedRange, TextAffinity::Downstream , SelectionDirectionalMode::NonDirectional, NotUserTriggered); | 468 frame().selection().setSelectedRange(selectedRange, TextAffinity::Downstream , SelectionDirectionalMode::NonDirectional, NotUserTriggered); |
| 418 | |
| 419 if (underlines.isEmpty()) { | |
| 420 frame().document()->markers().addCompositionMarker(m_compositionRange->s tartPosition(), m_compositionRange->endPosition(), Color::black, false, LayoutTh eme::theme().platformDefaultCompositionBackgroundColor()); | |
| 421 return; | |
| 422 } | |
| 423 for (const auto& underline : underlines) { | |
| 424 unsigned underlineStart = baseOffset + underline.startOffset; | |
| 425 unsigned underlineEnd = baseOffset + underline.endOffset; | |
| 426 EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, un derlineStart), Position(baseNode, underlineEnd)); | |
| 427 if (ephemeralLineRange.isNull()) | |
| 428 continue; | |
| 429 frame().document()->markers().addCompositionMarker(ephemeralLineRange.st artPosition(), ephemeralLineRange.endPosition(), underline.color, underline.thic k, underline.backgroundColor); | |
| 430 } | |
| 431 } | 469 } |
| 432 | 470 |
| 433 void InputMethodController::setCompositionFromExistingText(const Vector<Composit ionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd) | 471 void InputMethodController::setCompositionFromExistingText(const Vector<Composit ionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd) |
| 434 { | 472 { |
| 435 Element* editable = frame().selection().rootEditableElement(); | 473 Element* editable = frame().selection().rootEditableElement(); |
| 436 if (!editable) | 474 if (!editable) |
| 437 return; | 475 return; |
| 438 | 476 |
| 439 const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd ).createRange(*editable); | 477 const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd ).createRange(*editable); |
| 440 if (range.isNull()) | 478 if (range.isNull()) |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 548 TypingCommand::deleteSelection(*frame().document()); | 586 TypingCommand::deleteSelection(*frame().document()); |
| 549 } | 587 } |
| 550 | 588 |
| 551 DEFINE_TRACE(InputMethodController) | 589 DEFINE_TRACE(InputMethodController) |
| 552 { | 590 { |
| 553 visitor->trace(m_frame); | 591 visitor->trace(m_frame); |
| 554 visitor->trace(m_compositionRange); | 592 visitor->trace(m_compositionRange); |
| 555 } | 593 } |
| 556 | 594 |
| 557 } // namespace blink | 595 } // namespace blink |
| OLD | NEW |