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

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

Issue 2073863003: [WIP, not for review] Workaround for setComposition styling clobber (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698