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

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

Issue 2372493002: Workaround for setComposition styling clobber (Closed)
Patch Set: Fix a layout test Created 4 years, 2 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 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 340
341 void InputMethodController::setComposition(const String& text, const Vector<Comp ositionUnderline>& underlines, int selectionStart, int selectionEnd) 341 void InputMethodController::setComposition(const String& text, const Vector<Comp ositionUnderline>& underlines, int selectionStart, int selectionEnd)
342 { 342 {
343 Editor::RevealSelectionScope revealSelectionScope(&editor()); 343 Editor::RevealSelectionScope revealSelectionScope(&editor());
344 344
345 // Updates styles before setting selection for composition to prevent 345 // Updates styles before setting selection for composition to prevent
346 // inserting the previous composition text into text nodes oddly. 346 // inserting the previous composition text into text nodes oddly.
347 // See https://bugs.webkit.org/show_bug.cgi?id=46868 347 // See https://bugs.webkit.org/show_bug.cgi?id=46868
348 frame().document()->updateStyleAndLayoutTree(); 348 frame().document()->updateStyleAndLayoutTree();
349 349
350 // When the IME only wants to change a few characters at the end of the
351 // composition, only touch those characters in order to preserve rich text
352 // substructure.
353 if (hasComposition() && text.length()) {
354 String composing = composingText();
355 size_t commonPrefixLength = 0;
yabinh 2016/09/26 10:10:32 aelias@ suggests to use std::mismatch(): https://c
Changwan Ryu 2016/09/26 13:51:36 std::mismatch accepts not only char* but any Input
yabinh 2016/09/27 04:30:22 Done. Implemented a separate static function.
356 while (commonPrefixLength < composing.length() && commonPrefixLength < t ext.length() && composing[commonPrefixLength] == text[commonPrefixLength])
357 commonPrefixLength++;
358
359 bool appending = text.length() > commonPrefixLength;
360 bool backspacing = composing.length() > commonPrefixLength;
361 if (appending || backspacing) {
362 const EphemeralRange range = compositionEphemeralRange();
363 Element* editable = frame().selection().rootEditableElement();
364 if (!editable)
365 return;
366
367 // Move selection to the end of the composition.
368 PlainTextRange compositionPlainOffsets = PlainTextRange::create(*edi table, range);
369 VisibleSelection selection;
370 selection.setWithoutValidation(range.endPosition(), range.endPositio n());
371 frame().selection().setSelection(selection, 0);
372 clear();
373
374 Element* target = frame().document()->focusedElement();
375 if (!target)
376 return;
377
378 // Apply the incremental change.
379 if (backspacing)
380 extendSelectionAndDelete(composing.length() - commonPrefixLength , 0);
381 if (appending)
382 commitText(text.substring(commonPrefixLength), 0);
383
384 // Now recreate the composition starting at its original start, and
385 // apply the specified final selection offsets.
386 setCompositionFromExistingText(underlines, compositionPlainOffsets.s tart(), compositionPlainOffsets.start() + text.length());
387 selectComposition();
388 PlainTextRange selectedRange = createSelectionRangeForSetComposition (selectionStart, selectionEnd, text.length());
389 // We shouldn't close typing in the middle of setComposition.
390 setEditableSelectionOffsets(selectedRange, NotUserTriggered);
391 m_isDirty = true;
392 return;
393 }
394 }
395
350 selectComposition(); 396 selectComposition();
351 397
352 if (frame().selection().isNone()) 398 if (frame().selection().isNone())
353 return; 399 return;
354 400
355 Element* target = frame().document()->focusedElement(); 401 Element* target = frame().document()->focusedElement();
356 if (!target) 402 if (!target)
357 return; 403 return;
358 404
359 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets 405 PlainTextRange selectedRange = createSelectionRangeForSetComposition(selecti onStart, selectionEnd, text.length());
360 // needs to be audited. see http://crbug.com/590369 for more details.
361 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();
362
363 int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start());
364 int start = selectionOffsetsStart + selectionStart;
365 int end = selectionOffsetsStart + selectionEnd;
366 PlainTextRange selectedRange = createRangeForSelection(start, end, text.leng th());
367 406
368 // Dispatch an appropriate composition event to the focused node. 407 // Dispatch an appropriate composition event to the focused node.
369 // We check the composition status and choose an appropriate composition eve nt since this 408 // We check the composition status and choose an appropriate composition eve nt since this
370 // function is used for three purposes: 409 // function is used for three purposes:
371 // 1. Starting a new composition. 410 // 1. Starting a new composition.
372 // Send a compositionstart and a compositionupdate event when this functi on creates 411 // Send a compositionstart and a compositionupdate event when this functi on creates
373 // a new composition node, i.e. 412 // a new composition node, i.e.
374 // !hasComposition() && !text.isEmpty(). 413 // !hasComposition() && !text.isEmpty().
375 // Sending a compositionupdate event at this time ensures that at least o ne 414 // Sending a compositionupdate event at this time ensures that at least o ne
376 // compositionupdate event is dispatched. 415 // compositionupdate event is dispatched.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 for (const auto& underline : underlines) { 498 for (const auto& underline : underlines) {
460 unsigned underlineStart = baseOffset + underline.startOffset(); 499 unsigned underlineStart = baseOffset + underline.startOffset();
461 unsigned underlineEnd = baseOffset + underline.endOffset(); 500 unsigned underlineEnd = baseOffset + underline.endOffset();
462 EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, un derlineStart), Position(baseNode, underlineEnd)); 501 EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, un derlineStart), Position(baseNode, underlineEnd));
463 if (ephemeralLineRange.isNull()) 502 if (ephemeralLineRange.isNull())
464 continue; 503 continue;
465 frame().document()->markers().addCompositionMarker(ephemeralLineRange.st artPosition(), ephemeralLineRange.endPosition(), underline.color(), underline.th ick(), underline.backgroundColor()); 504 frame().document()->markers().addCompositionMarker(ephemeralLineRange.st artPosition(), ephemeralLineRange.endPosition(), underline.color(), underline.th ick(), underline.backgroundColor());
466 } 505 }
467 } 506 }
468 507
508 PlainTextRange InputMethodController::createSelectionRangeForSetComposition(int selectionStart, int selectionEnd, size_t textLength) const
509 {
510 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
511 // needs to be audited. see http://crbug.com/590369 for more details.
512 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();
513
514 int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start());
515 int start = selectionOffsetsStart + selectionStart;
516 int end = selectionOffsetsStart + selectionEnd;
517 return createRangeForSelection(start, end, textLength);
518 }
519
469 void InputMethodController::setCompositionFromExistingText(const Vector<Composit ionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd) 520 void InputMethodController::setCompositionFromExistingText(const Vector<Composit ionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd)
470 { 521 {
471 Element* editable = frame().selection().rootEditableElement(); 522 Element* editable = frame().selection().rootEditableElement();
472 if (!editable) 523 if (!editable)
473 return; 524 return;
474 525
475 DCHECK(!editable->document().needsLayoutTreeUpdate()); 526 DCHECK(!editable->document().needsLayoutTreeUpdate());
476 527
477 const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd ).createRange(*editable); 528 const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd ).createRange(*editable);
478 if (range.isNull()) 529 if (range.isNull())
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 TypingCommand::deleteSelection(*frame().document()); 680 TypingCommand::deleteSelection(*frame().document());
630 } 681 }
631 682
632 DEFINE_TRACE(InputMethodController) 683 DEFINE_TRACE(InputMethodController)
633 { 684 {
634 visitor->trace(m_frame); 685 visitor->trace(m_frame);
635 visitor->trace(m_compositionRange); 686 visitor->trace(m_compositionRange);
636 } 687 }
637 688
638 } // namespace blink 689 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698