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 } |
617 | |
618 // Can't use addCompositionUnderlines here because the ranges are constructed | |
aelias_OOO_until_Jul13
2017/01/10 01:45:35
Is there a good reason for the difference that you
rlanday
2017/01/10 05:02:17
addCompositionUnderlines() takes a root element an
rlanday
2017/01/10 19:25:10
baseNode is guaranteed to be a text node (there's
| |
619 // differently | |
581 for (const auto& underline : underlines) { | 620 for (const auto& underline : underlines) { |
582 unsigned underlineStart = baseOffset + underline.startOffset(); | 621 unsigned underlineStart = baseOffset + underline.startOffset(); |
583 unsigned underlineEnd = baseOffset + underline.endOffset(); | 622 unsigned underlineEnd = baseOffset + underline.endOffset(); |
584 EphemeralRange ephemeralLineRange = EphemeralRange( | 623 EphemeralRange ephemeralLineRange = EphemeralRange( |
585 Position(baseNode, underlineStart), Position(baseNode, underlineEnd)); | 624 Position(baseNode, underlineStart), Position(baseNode, underlineEnd)); |
586 if (ephemeralLineRange.isNull()) | 625 if (ephemeralLineRange.isNull()) |
587 continue; | 626 continue; |
588 document().markers().addCompositionMarker( | 627 document().markers().addCompositionMarker( |
589 ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(), | 628 ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(), |
590 underline.color(), underline.thick(), underline.backgroundColor()); | 629 underline.color(), underline.thick(), underline.backgroundColor()); |
(...skipping 29 matching lines...) Expand all Loading... | |
620 const Position start = range.startPosition(); | 659 const Position start = range.startPosition(); |
621 if (rootEditableElementOf(start) != editable) | 660 if (rootEditableElementOf(start) != editable) |
622 return; | 661 return; |
623 | 662 |
624 const Position end = range.endPosition(); | 663 const Position end = range.endPosition(); |
625 if (rootEditableElementOf(end) != editable) | 664 if (rootEditableElementOf(end) != editable) |
626 return; | 665 return; |
627 | 666 |
628 clear(); | 667 clear(); |
629 | 668 |
630 for (const auto& underline : underlines) { | 669 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 | 670 |
642 m_hasComposition = true; | 671 m_hasComposition = true; |
643 if (!m_compositionRange) | 672 if (!m_compositionRange) |
644 m_compositionRange = Range::create(document()); | 673 m_compositionRange = Range::create(document()); |
645 m_compositionRange->setStart(range.startPosition()); | 674 m_compositionRange->setStart(range.startPosition()); |
646 m_compositionRange->setEnd(range.endPosition()); | 675 m_compositionRange->setEnd(range.endPosition()); |
647 } | 676 } |
648 | 677 |
649 EphemeralRange InputMethodController::compositionEphemeralRange() const { | 678 EphemeralRange InputMethodController::compositionEphemeralRange() const { |
650 if (!hasComposition()) | 679 if (!hasComposition()) |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1063 frame().chromeClient().resetInputMethod(); | 1092 frame().chromeClient().resetInputMethod(); |
1064 } | 1093 } |
1065 | 1094 |
1066 DEFINE_TRACE(InputMethodController) { | 1095 DEFINE_TRACE(InputMethodController) { |
1067 visitor->trace(m_frame); | 1096 visitor->trace(m_frame); |
1068 visitor->trace(m_compositionRange); | 1097 visitor->trace(m_compositionRange); |
1069 SynchronousMutationObserver::trace(visitor); | 1098 SynchronousMutationObserver::trace(visitor); |
1070 } | 1099 } |
1071 | 1100 |
1072 } // namespace blink | 1101 } // namespace blink |
OLD | NEW |