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

Unified Diff: Source/core/editing/InputMethodController.cpp

Issue 1325563002: Avoid style clobbering in setCompositionFromExistingText. (2nd land) (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Use DocumentMarker for underlines Created 5 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: Source/core/editing/InputMethodController.cpp
diff --git a/Source/core/editing/InputMethodController.cpp b/Source/core/editing/InputMethodController.cpp
index 3c695f1e8270c7f1baf763f8e3825d031e9a2993..1d1cb9fcad75f1763510b9546aa0b354e972af02 100644
--- a/Source/core/editing/InputMethodController.cpp
+++ b/Source/core/editing/InputMethodController.cpp
@@ -29,15 +29,17 @@
#include "core/dom/Document.h"
#include "core/dom/Element.h"
-#include "core/dom/Range.h"
#include "core/dom/Text.h"
+#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/commands/TypingCommand.h"
+#include "core/editing/markers/DocumentMarkerController.h"
#include "core/events/CompositionEvent.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLTextAreaElement.h"
#include "core/input/EventHandler.h"
#include "core/layout/LayoutObject.h"
+#include "core/layout/LayoutTheme.h"
#include "core/page/ChromeClient.h"
namespace blink {
@@ -62,8 +64,7 @@ PassOwnPtrWillBeRawPtr<InputMethodController> InputMethodController::create(Loca
InputMethodController::InputMethodController(LocalFrame& frame)
: m_frame(&frame)
- , m_compositionStart(0)
- , m_compositionEnd(0)
+ , m_isDirty(false)
{
}
@@ -73,7 +74,7 @@ InputMethodController::~InputMethodController()
bool InputMethodController::hasComposition() const
{
- return m_compositionNode && m_compositionNode->isContentEditable();
+ return m_compositionRange.get() && m_compositionRange->startContainer() && m_compositionRange->startContainer()->isContentEditable();
}
inline Editor& InputMethodController::editor() const
@@ -83,8 +84,9 @@ inline Editor& InputMethodController::editor() const
void InputMethodController::clear()
{
- m_compositionNode = nullptr;
- m_customCompositionUnderlines.clear();
+ m_compositionRange = nullptr;
+ frame().document()->markers().removeMarkers(DocumentMarker::Composition);
+ m_isDirty = false;
}
bool InputMethodController::insertTextForConfirmedComposition(const String& text)
@@ -109,7 +111,7 @@ bool InputMethodController::confirmComposition()
{
if (!hasComposition())
return false;
- return finishComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), ConfirmComposition);
+ return confirmComposition(plainText(compositionEphemeralRange()));
}
bool InputMethodController::confirmComposition(const String& text)
@@ -149,13 +151,16 @@ void InputMethodController::cancelCompositionIfSelectionIsInvalid()
return;
// Check if selection start and selection end are valid.
- Position start = frame().selection().start();
- Position end = frame().selection().end();
- if (start.computeContainerNode() == m_compositionNode
- && end.computeContainerNode() == m_compositionNode
- && static_cast<unsigned>(start.computeOffsetInContainerNode()) >= m_compositionStart
- && static_cast<unsigned>(end.computeOffsetInContainerNode()) <= m_compositionEnd)
- return;
+ FrameSelection& selection = frame().selection();
+ if (!selection.isNone()) {
+ Position start = selection.start();
+ Position end = selection.end();
+ if (start.anchorNode() && end.anchorNode()) {
+ if (m_compositionRange->isPointInRange(start.computeContainerNode(), start.computeOffsetInContainerNode(), IGNORE_EXCEPTION)
+ && m_compositionRange->isPointInRange(end.computeContainerNode(), end.computeOffsetInContainerNode(), IGNORE_EXCEPTION))
+ return;
+ }
+ }
cancelComposition();
frame().chromeClient().didCancelCompositionOnSelectionChange();
@@ -186,17 +191,19 @@ bool InputMethodController::finishComposition(const String& text, FinishComposit
target->dispatchEvent(event);
}
+ bool dirty = m_isDirty || plainText(compositionEphemeralRange()) != text;
+
// If text is empty, then delete the old composition here. If text is non-empty, InsertTextCommand::input
// will delete the old composition with an optimized replace operation.
- if (text.isEmpty() && mode != CancelComposition) {
+ if (text.isEmpty() && mode != CancelComposition && dirty) {
ASSERT(frame().document());
TypingCommand::deleteSelection(*frame().document(), 0);
}
- m_compositionNode = nullptr;
- m_customCompositionUnderlines.clear();
+ clear();
- insertTextForConfirmedComposition(text);
+ if (dirty)
+ insertTextForConfirmedComposition(text);
if (mode == CancelComposition) {
// An open typing command that disagrees about current selection would cause issues with typing later on.
@@ -227,15 +234,15 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp
// 1. Starting a new composition.
// Send a compositionstart and a compositionupdate event when this function creates
// a new composition node, i.e.
- // m_compositionNode == 0 && !text.isEmpty().
+ // !hasComposition() && !text.isEmpty().
// Sending a compositionupdate event at this time ensures that at least one
// compositionupdate event is dispatched.
// 2. Updating the existing composition node.
// Send a compositionupdate event when this function updates the existing composition
- // node, i.e. m_compositionNode != 0 && !text.isEmpty().
+ // node, i.e. hasComposition() && !text.isEmpty().
// 3. Canceling the ongoing composition.
// Send a compositionend event when function deletes the existing composition node, i.e.
- // m_compositionNode != 0 && test.isEmpty().
+ // !hasComposition() && test.isEmpty().
RefPtrWillBeRawPtr<CompositionEvent> event = nullptr;
if (!hasComposition()) {
// We should send a compositionstart event only when the given text is not empty because this
@@ -261,8 +268,9 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp
TypingCommand::deleteSelection(*frame().document(), TypingCommand::PreventSpellChecking);
}
- m_compositionNode = nullptr;
- m_customCompositionUnderlines.clear();
+ clear();
+
+ m_isDirty = true;
if (text.isEmpty())
return;
@@ -285,14 +293,8 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp
if (baseOffset + text.length() != extentOffset)
return;
- m_compositionNode = toText(baseNode);
- m_compositionStart = baseOffset;
- m_compositionEnd = extentOffset;
- m_customCompositionUnderlines = underlines;
- for (auto& underline : m_customCompositionUnderlines) {
- underline.startOffset += baseOffset;
- underline.endOffset += baseOffset;
- }
+ m_compositionRange = Range::create(baseNode->document(), baseNode, baseOffset, baseNode, extentOffset);
yosin_UTC9 2015/09/04 06:20:42 nit: Please create |Range| object at construction
+
if (baseNode->layoutObject())
baseNode->layoutObject()->setShouldDoFullPaintInvalidation();
@@ -300,61 +302,64 @@ void InputMethodController::setComposition(const String& text, const Vector<Comp
unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOffset);
RefPtrWillBeRawPtr<Range> selectedRange = Range::create(baseNode->document(), baseNode, start, baseNode, end);
frame().selection().setSelectedRange(selectedRange.get(), TextAffinity::Downstream, FrameSelection::NonDirectional, NotUserTriggered);
+
+ if (underlines.size()) {
+ for (size_t i = 0; i < underlines.size(); ++i) {
+ unsigned underlineStart = baseOffset + underlines[i].startOffset;
+ unsigned underlineEnd = baseOffset + underlines[i].endOffset;
+ EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, underlineStart), Position(baseNode, underlineEnd));
+ if (ephemeralLineRange.isNull())
+ continue;
+ frame().document()->markers().addCompositionMarker(ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(), underlines[i].color, underlines[i].thick, underlines[i].backgroundColor);
+ }
+ } else {
+ frame().document()->markers().addCompositionMarker(m_compositionRange->startPosition(), m_compositionRange->endPosition(), Color::black, false, LayoutTheme::theme().platformDefaultCompositionBackgroundColor());
+ }
+
}
void InputMethodController::setCompositionFromExistingText(const Vector<CompositionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd)
{
Element* editable = frame().selection().rootEditableElement();
- Position base = mostForwardCaretPosition(frame().selection().base());
- Node* baseNode = base.anchorNode();
- if (baseNode && editable->firstChild() == baseNode && editable->lastChild() == baseNode && baseNode->isTextNode()) {
- m_compositionNode = nullptr;
- m_customCompositionUnderlines.clear();
+ if (!editable)
+ return;
- if (!base.isOffsetInAnchor())
- return;
- if (baseNode != frame().selection().extent().anchorNode())
- return;
+ EphemeralRange range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
yosin_UTC9 2015/09/04 06:20:42 nit: |const EphemeralRange|
+ if (range.isNull())
+ return;
- m_compositionNode = toText(baseNode);
- const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
- if (range.isNull())
- return;
+ Position start = range.startPosition();
yosin_UTC9 2015/09/04 06:20:42 nit: |const Position|
+ if (!start.anchorNode() || start.anchorNode()->rootEditableElement() != editable)
+ return;
- m_compositionStart = range.startPosition().computeOffsetInContainerNode();
- m_compositionEnd = range.endPosition().computeOffsetInContainerNode();
- m_customCompositionUnderlines = underlines;
- size_t numUnderlines = m_customCompositionUnderlines.size();
- for (size_t i = 0; i < numUnderlines; ++i) {
- m_customCompositionUnderlines[i].startOffset += m_compositionStart;
- m_customCompositionUnderlines[i].endOffset += m_compositionStart;
- }
- if (baseNode->layoutObject())
- baseNode->layoutObject()->setShouldDoFullPaintInvalidation();
+ Position end = range.endPosition();
yosin_UTC9 2015/09/04 06:20:42 nit: |const Position|
+ if (!end.anchorNode() || end.anchorNode()->rootEditableElement() != editable)
return;
+
+ clear();
+
+ for (size_t i = 0; i < underlines.size(); ++i) {
+ unsigned underlineStart = compositionStart + underlines[i].startOffset;
+ unsigned underlineEnd = compositionStart + underlines[i].endOffset;
+ EphemeralRange ephemeralLineRange = PlainTextRange(underlineStart, underlineEnd).createRange(*editable);
+ if (ephemeralLineRange.isNull())
+ continue;
+ frame().document()->markers().addCompositionMarker(ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(), underlines[i].color, underlines[i].thick, underlines[i].backgroundColor);
}
- Editor::RevealSelectionScope revealSelectionScope(&editor());
- SelectionOffsetsScope selectionOffsetsScope(this);
- setSelectionOffsets(PlainTextRange(compositionStart, compositionEnd));
- setComposition(frame().selectedText(), underlines, 0, 0);
+ m_compositionRange = Range::create(range.document(), range.startPosition(), range.endPosition());
yosin_UTC9 2015/09/04 06:20:42 nit: Please reuse |Range| object.
}
EphemeralRange InputMethodController::compositionEphemeralRange() const
{
if (!hasComposition())
return EphemeralRange();
- unsigned length = m_compositionNode->length();
- unsigned start = std::min(m_compositionStart, length);
- unsigned end = std::min(std::max(start, m_compositionEnd), length);
- if (start >= end)
- return EphemeralRange();
- return EphemeralRange(Position(m_compositionNode.get(), start), Position(m_compositionNode.get(), end));
+ return EphemeralRange(m_compositionRange->startPosition(), m_compositionRange->endPosition());
yosin_UTC9 2015/09/04 06:20:42 nit: |return EphemeralRange(m_compositionRange);|
}
PassRefPtrWillBeRawPtr<Range> InputMethodController::compositionRange() const
{
- return createRange(compositionEphemeralRange());
+ return hasComposition() ? m_compositionRange : nullptr;
}
PlainTextRange InputMethodController::getSelectionOffsets() const
@@ -422,7 +427,7 @@ void InputMethodController::extendSelectionAndDelete(int before, int after)
DEFINE_TRACE(InputMethodController)
{
visitor->trace(m_frame);
- visitor->trace(m_compositionNode);
+ visitor->trace(m_compositionRange);
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698