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

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

Issue 1330233003: Revert of Avoid style clobbering in setCompositionFromExistingText. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 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 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 11 matching lines...) Expand all
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #include "config.h" 27 #include "config.h"
28 #include "core/editing/InputMethodController.h" 28 #include "core/editing/InputMethodController.h"
29 29
30 #include "core/dom/Document.h" 30 #include "core/dom/Document.h"
31 #include "core/dom/Element.h" 31 #include "core/dom/Element.h"
32 #include "core/dom/Range.h"
32 #include "core/dom/Text.h" 33 #include "core/dom/Text.h"
33 #include "core/editing/EditingUtilities.h"
34 #include "core/editing/Editor.h" 34 #include "core/editing/Editor.h"
35 #include "core/editing/commands/TypingCommand.h" 35 #include "core/editing/commands/TypingCommand.h"
36 #include "core/editing/markers/DocumentMarkerController.h"
37 #include "core/events/CompositionEvent.h" 36 #include "core/events/CompositionEvent.h"
38 #include "core/frame/LocalFrame.h" 37 #include "core/frame/LocalFrame.h"
39 #include "core/html/HTMLTextAreaElement.h" 38 #include "core/html/HTMLTextAreaElement.h"
40 #include "core/input/EventHandler.h" 39 #include "core/input/EventHandler.h"
41 #include "core/layout/LayoutObject.h" 40 #include "core/layout/LayoutObject.h"
42 #include "core/layout/LayoutTheme.h"
43 #include "core/page/ChromeClient.h" 41 #include "core/page/ChromeClient.h"
44 42
45 namespace blink { 43 namespace blink {
46 44
47 InputMethodController::SelectionOffsetsScope::SelectionOffsetsScope(InputMethodC ontroller* inputMethodController) 45 InputMethodController::SelectionOffsetsScope::SelectionOffsetsScope(InputMethodC ontroller* inputMethodController)
48 : m_inputMethodController(inputMethodController) 46 : m_inputMethodController(inputMethodController)
49 , m_offsets(inputMethodController->getSelectionOffsets()) 47 , m_offsets(inputMethodController->getSelectionOffsets())
50 { 48 {
51 } 49 }
52 50
53 InputMethodController::SelectionOffsetsScope::~SelectionOffsetsScope() 51 InputMethodController::SelectionOffsetsScope::~SelectionOffsetsScope()
54 { 52 {
55 m_inputMethodController->setSelectionOffsets(m_offsets); 53 m_inputMethodController->setSelectionOffsets(m_offsets);
56 } 54 }
57 55
58 // ---------------------------- 56 // ----------------------------
59 57
60 PassOwnPtrWillBeRawPtr<InputMethodController> InputMethodController::create(Loca lFrame& frame) 58 PassOwnPtrWillBeRawPtr<InputMethodController> InputMethodController::create(Loca lFrame& frame)
61 { 59 {
62 return adoptPtrWillBeNoop(new InputMethodController(frame)); 60 return adoptPtrWillBeNoop(new InputMethodController(frame));
63 } 61 }
64 62
65 InputMethodController::InputMethodController(LocalFrame& frame) 63 InputMethodController::InputMethodController(LocalFrame& frame)
66 : m_frame(&frame) 64 : m_frame(&frame)
67 , m_isDirty(false) 65 , m_compositionStart(0)
68 , m_hasComposition(false) 66 , m_compositionEnd(0)
69 { 67 {
70 } 68 }
71 69
72 InputMethodController::~InputMethodController() 70 InputMethodController::~InputMethodController()
73 { 71 {
74 } 72 }
75 73
76 bool InputMethodController::hasComposition() const 74 bool InputMethodController::hasComposition() const
77 { 75 {
78 return m_hasComposition; 76 return m_compositionNode && m_compositionNode->isContentEditable();
79 } 77 }
80 78
81 inline Editor& InputMethodController::editor() const 79 inline Editor& InputMethodController::editor() const
82 { 80 {
83 return frame().editor(); 81 return frame().editor();
84 } 82 }
85 83
86 void InputMethodController::clear() 84 void InputMethodController::clear()
87 { 85 {
88 m_hasComposition = false; 86 m_compositionNode = nullptr;
89 if (m_compositionRange) { 87 m_customCompositionUnderlines.clear();
90 m_compositionRange->setStart(frame().document(), 0);
91 m_compositionRange->collapse(true);
92 }
93 frame().document()->markers().removeMarkers(DocumentMarker::Composition);
94 m_isDirty = false;
95 } 88 }
96 89
97 bool InputMethodController::insertTextForConfirmedComposition(const String& text ) 90 bool InputMethodController::insertTextForConfirmedComposition(const String& text )
98 { 91 {
99 return frame().eventHandler().handleTextInputEvent(text, 0, TextEventInputCo mposition); 92 return frame().eventHandler().handleTextInputEvent(text, 0, TextEventInputCo mposition);
100 } 93 }
101 94
102 void InputMethodController::selectComposition() const 95 void InputMethodController::selectComposition() const
103 { 96 {
104 const EphemeralRange range = compositionEphemeralRange(); 97 const EphemeralRange range = compositionEphemeralRange();
105 if (range.isNull()) 98 if (range.isNull())
106 return; 99 return;
107 100
108 // The composition can start inside a composed character sequence, so we hav e to override checks. 101 // The composition can start inside a composed character sequence, so we hav e to override checks.
109 // See <http://bugs.webkit.org/show_bug.cgi?id=15781> 102 // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
110 VisibleSelection selection; 103 VisibleSelection selection;
111 selection.setWithoutValidation(range.startPosition(), range.endPosition()); 104 selection.setWithoutValidation(range.startPosition(), range.endPosition());
112 frame().selection().setSelection(selection, 0); 105 frame().selection().setSelection(selection, 0);
113 } 106 }
114 107
115 bool InputMethodController::confirmComposition() 108 bool InputMethodController::confirmComposition()
116 { 109 {
117 if (!hasComposition()) 110 if (!hasComposition())
118 return false; 111 return false;
119 return confirmComposition(plainText(compositionEphemeralRange())); 112 return finishComposition(m_compositionNode->data().substring(m_compositionSt art, m_compositionEnd - m_compositionStart), ConfirmComposition);
120 } 113 }
121 114
122 bool InputMethodController::confirmComposition(const String& text) 115 bool InputMethodController::confirmComposition(const String& text)
123 { 116 {
124 return finishComposition(text, ConfirmComposition); 117 return finishComposition(text, ConfirmComposition);
125 } 118 }
126 119
127 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C onfirmCompositionBehavior confirmBehavior) 120 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C onfirmCompositionBehavior confirmBehavior)
128 { 121 {
129 if (!hasComposition()) { 122 if (!hasComposition()) {
(...skipping 19 matching lines...) Expand all
149 { 142 {
150 finishComposition(emptyString(), CancelComposition); 143 finishComposition(emptyString(), CancelComposition);
151 } 144 }
152 145
153 void InputMethodController::cancelCompositionIfSelectionIsInvalid() 146 void InputMethodController::cancelCompositionIfSelectionIsInvalid()
154 { 147 {
155 if (!hasComposition() || editor().preventRevealSelection()) 148 if (!hasComposition() || editor().preventRevealSelection())
156 return; 149 return;
157 150
158 // Check if selection start and selection end are valid. 151 // Check if selection start and selection end are valid.
159 FrameSelection& selection = frame().selection(); 152 Position start = frame().selection().start();
160 if (!selection.isNone() && !m_compositionRange->collapsed()) { 153 Position end = frame().selection().end();
161 Position start = selection.start(); 154 if (start.computeContainerNode() == m_compositionNode
162 Position end = selection.end(); 155 && end.computeContainerNode() == m_compositionNode
163 if (selection.start().compareTo(m_compositionRange->startPosition()) >= 0 156 && static_cast<unsigned>(start.computeOffsetInContainerNode()) >= m_comp ositionStart
164 && selection.end().compareTo(m_compositionRange->endPosition()) <= 0 ) 157 && static_cast<unsigned>(end.computeOffsetInContainerNode()) <= m_compos itionEnd)
165 return; 158 return;
166 }
167 159
168 cancelComposition(); 160 cancelComposition();
169 frame().chromeClient().didCancelCompositionOnSelectionChange(); 161 frame().chromeClient().didCancelCompositionOnSelectionChange();
170 } 162 }
171 163
172 bool InputMethodController::finishComposition(const String& text, FinishComposit ionMode mode) 164 bool InputMethodController::finishComposition(const String& text, FinishComposit ionMode mode)
173 { 165 {
174 if (!hasComposition()) 166 if (!hasComposition())
175 return false; 167 return false;
176 168
(...skipping 10 matching lines...) Expand all
187 return false; 179 return false;
188 180
189 // Dispatch a compositionend event to the focused node. 181 // Dispatch a compositionend event to the focused node.
190 // We should send this event before sending a TextEvent as written in Sectio n 6.2.2 and 6.2.3 of 182 // We should send this event before sending a TextEvent as written in Sectio n 6.2.2 and 6.2.3 of
191 // the DOM Event specification. 183 // the DOM Event specification.
192 if (Element* target = frame().document()->focusedElement()) { 184 if (Element* target = frame().document()->focusedElement()) {
193 RefPtrWillBeRawPtr<CompositionEvent> event = CompositionEvent::create(Ev entTypeNames::compositionend, frame().domWindow(), text); 185 RefPtrWillBeRawPtr<CompositionEvent> event = CompositionEvent::create(Ev entTypeNames::compositionend, frame().domWindow(), text);
194 target->dispatchEvent(event); 186 target->dispatchEvent(event);
195 } 187 }
196 188
197 bool dirty = m_isDirty || plainText(compositionEphemeralRange()) != text;
198
199 // If text is empty, then delete the old composition here. If text is non-em pty, InsertTextCommand::input 189 // If text is empty, then delete the old composition here. If text is non-em pty, InsertTextCommand::input
200 // will delete the old composition with an optimized replace operation. 190 // will delete the old composition with an optimized replace operation.
201 if (text.isEmpty() && mode != CancelComposition && dirty) { 191 if (text.isEmpty() && mode != CancelComposition) {
202 ASSERT(frame().document()); 192 ASSERT(frame().document());
203 TypingCommand::deleteSelection(*frame().document(), 0); 193 TypingCommand::deleteSelection(*frame().document(), 0);
204 } 194 }
205 195
206 clear(); 196 m_compositionNode = nullptr;
197 m_customCompositionUnderlines.clear();
207 198
208 if (dirty) 199 insertTextForConfirmedComposition(text);
209 insertTextForConfirmedComposition(text);
210 200
211 if (mode == CancelComposition) { 201 if (mode == CancelComposition) {
212 // An open typing command that disagrees about current selection would c ause issues with typing later on. 202 // An open typing command that disagrees about current selection would c ause issues with typing later on.
213 TypingCommand::closeTyping(m_frame); 203 TypingCommand::closeTyping(m_frame);
214 } 204 }
215 205
216 return true; 206 return true;
217 } 207 }
218 208
219 void InputMethodController::setComposition(const String& text, const Vector<Comp ositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd) 209 void InputMethodController::setComposition(const String& text, const Vector<Comp ositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd)
(...skipping 10 matching lines...) Expand all
230 if (frame().selection().isNone()) 220 if (frame().selection().isNone())
231 return; 221 return;
232 222
233 if (Element* target = frame().document()->focusedElement()) { 223 if (Element* target = frame().document()->focusedElement()) {
234 // Dispatch an appropriate composition event to the focused node. 224 // Dispatch an appropriate composition event to the focused node.
235 // We check the composition status and choose an appropriate composition event since this 225 // We check the composition status and choose an appropriate composition event since this
236 // function is used for three purposes: 226 // function is used for three purposes:
237 // 1. Starting a new composition. 227 // 1. Starting a new composition.
238 // Send a compositionstart and a compositionupdate event when this fu nction creates 228 // Send a compositionstart and a compositionupdate event when this fu nction creates
239 // a new composition node, i.e. 229 // a new composition node, i.e.
240 // !hasComposition() && !text.isEmpty(). 230 // m_compositionNode == 0 && !text.isEmpty().
241 // Sending a compositionupdate event at this time ensures that at lea st one 231 // Sending a compositionupdate event at this time ensures that at lea st one
242 // compositionupdate event is dispatched. 232 // compositionupdate event is dispatched.
243 // 2. Updating the existing composition node. 233 // 2. Updating the existing composition node.
244 // Send a compositionupdate event when this function updates the exis ting composition 234 // Send a compositionupdate event when this function updates the exis ting composition
245 // node, i.e. hasComposition() && !text.isEmpty(). 235 // node, i.e. m_compositionNode != 0 && !text.isEmpty().
246 // 3. Canceling the ongoing composition. 236 // 3. Canceling the ongoing composition.
247 // Send a compositionend event when function deletes the existing com position node, i.e. 237 // Send a compositionend event when function deletes the existing com position node, i.e.
248 // !hasComposition() && test.isEmpty(). 238 // m_compositionNode != 0 && test.isEmpty().
249 RefPtrWillBeRawPtr<CompositionEvent> event = nullptr; 239 RefPtrWillBeRawPtr<CompositionEvent> event = nullptr;
250 if (!hasComposition()) { 240 if (!hasComposition()) {
251 // We should send a compositionstart event only when the given text is not empty because this 241 // We should send a compositionstart event only when the given text is not empty because this
252 // function doesn't create a composition node when the text is empty . 242 // function doesn't create a composition node when the text is empty .
253 if (!text.isEmpty()) { 243 if (!text.isEmpty()) {
254 target->dispatchEvent(CompositionEvent::create(EventTypeNames::c ompositionstart, frame().domWindow(), frame().selectedText())); 244 target->dispatchEvent(CompositionEvent::create(EventTypeNames::c ompositionstart, frame().domWindow(), frame().selectedText()));
255 event = CompositionEvent::create(EventTypeNames::compositionupda te, frame().domWindow(), text); 245 event = CompositionEvent::create(EventTypeNames::compositionupda te, frame().domWindow(), text);
256 } 246 }
257 } else { 247 } else {
258 if (!text.isEmpty()) 248 if (!text.isEmpty())
259 event = CompositionEvent::create(EventTypeNames::compositionupda te, frame().domWindow(), text); 249 event = CompositionEvent::create(EventTypeNames::compositionupda te, frame().domWindow(), text);
260 else 250 else
261 event = CompositionEvent::create(EventTypeNames::compositionend, frame().domWindow(), text); 251 event = CompositionEvent::create(EventTypeNames::compositionend, frame().domWindow(), text);
262 } 252 }
263 if (event.get()) 253 if (event.get())
264 target->dispatchEvent(event); 254 target->dispatchEvent(event);
265 } 255 }
266 256
267 // If text is empty, then delete the old composition here. If text is non-em pty, InsertTextCommand::input 257 // If text is empty, then delete the old composition here. If text is non-em pty, InsertTextCommand::input
268 // will delete the old composition with an optimized replace operation. 258 // will delete the old composition with an optimized replace operation.
269 if (text.isEmpty()) { 259 if (text.isEmpty()) {
270 ASSERT(frame().document()); 260 ASSERT(frame().document());
271 TypingCommand::deleteSelection(*frame().document(), TypingCommand::Preve ntSpellChecking); 261 TypingCommand::deleteSelection(*frame().document(), TypingCommand::Preve ntSpellChecking);
272 } 262 }
273 263
274 clear(); 264 m_compositionNode = nullptr;
265 m_customCompositionUnderlines.clear();
275 266
276 if (text.isEmpty()) 267 if (text.isEmpty())
277 return; 268 return;
278 ASSERT(frame().document()); 269 ASSERT(frame().document());
279 TypingCommand::insertText(*frame().document(), text, TypingCommand::SelectIn sertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextComposition Update); 270 TypingCommand::insertText(*frame().document(), text, TypingCommand::SelectIn sertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextComposition Update);
280 271
281 // Find out what node has the composition now. 272 // Find out what node has the composition now.
282 Position base = mostForwardCaretPosition(frame().selection().base()); 273 Position base = mostForwardCaretPosition(frame().selection().base());
283 Node* baseNode = base.anchorNode(); 274 Node* baseNode = base.anchorNode();
284 if (!baseNode || !baseNode->isTextNode()) 275 if (!baseNode || !baseNode->isTextNode())
285 return; 276 return;
286 277
287 Position extent = frame().selection().extent(); 278 Position extent = frame().selection().extent();
288 Node* extentNode = extent.anchorNode(); 279 Node* extentNode = extent.anchorNode();
289 if (baseNode != extentNode) 280 if (baseNode != extentNode)
290 return; 281 return;
291 282
292 unsigned extentOffset = extent.computeOffsetInContainerNode(); 283 unsigned extentOffset = extent.computeOffsetInContainerNode();
293 unsigned baseOffset = base.computeOffsetInContainerNode(); 284 unsigned baseOffset = base.computeOffsetInContainerNode();
294 if (baseOffset + text.length() != extentOffset) 285 if (baseOffset + text.length() != extentOffset)
295 return; 286 return;
296 287
297 m_isDirty = true; 288 m_compositionNode = toText(baseNode);
298 m_hasComposition = true; 289 m_compositionStart = baseOffset;
299 if (!m_compositionRange) 290 m_compositionEnd = extentOffset;
300 m_compositionRange = Range::create(baseNode->document()); 291 m_customCompositionUnderlines = underlines;
301 m_compositionRange->setStart(baseNode, baseOffset); 292 for (auto& underline : m_customCompositionUnderlines) {
302 m_compositionRange->setEnd(baseNode, extentOffset); 293 underline.startOffset += baseOffset;
303 294 underline.endOffset += baseOffset;
295 }
304 if (baseNode->layoutObject()) 296 if (baseNode->layoutObject())
305 baseNode->layoutObject()->setShouldDoFullPaintInvalidation(); 297 baseNode->layoutObject()->setShouldDoFullPaintInvalidation();
306 298
307 unsigned start = std::min(baseOffset + selectionStart, extentOffset); 299 unsigned start = std::min(baseOffset + selectionStart, extentOffset);
308 unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOf fset); 300 unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOf fset);
309 RefPtrWillBeRawPtr<Range> selectedRange = Range::create(baseNode->document() , baseNode, start, baseNode, end); 301 RefPtrWillBeRawPtr<Range> selectedRange = Range::create(baseNode->document() , baseNode, start, baseNode, end);
310 frame().selection().setSelectedRange(selectedRange.get(), TextAffinity::Down stream, FrameSelection::NonDirectional, NotUserTriggered); 302 frame().selection().setSelectedRange(selectedRange.get(), TextAffinity::Down stream, FrameSelection::NonDirectional, NotUserTriggered);
311
312 if (underlines.isEmpty()) {
313 frame().document()->markers().addCompositionMarker(m_compositionRange->s tartPosition(), m_compositionRange->endPosition(), Color::black, false, LayoutTh eme::theme().platformDefaultCompositionBackgroundColor());
314 return;
315 }
316 for (const auto& underline : underlines) {
317 unsigned underlineStart = baseOffset + underline.startOffset;
318 unsigned underlineEnd = baseOffset + underline.endOffset;
319 EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, un derlineStart), Position(baseNode, underlineEnd));
320 if (ephemeralLineRange.isNull())
321 continue;
322 frame().document()->markers().addCompositionMarker(ephemeralLineRange.st artPosition(), ephemeralLineRange.endPosition(), underline.color, underline.thic k, underline.backgroundColor);
323 }
324 } 303 }
325 304
326 void InputMethodController::setCompositionFromExistingText(const Vector<Composit ionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd) 305 void InputMethodController::setCompositionFromExistingText(const Vector<Composit ionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd)
327 { 306 {
328 Element* editable = frame().selection().rootEditableElement(); 307 Element* editable = frame().selection().rootEditableElement();
329 if (!editable) 308 Position base = mostForwardCaretPosition(frame().selection().base());
309 Node* baseNode = base.anchorNode();
310 if (baseNode && editable->firstChild() == baseNode && editable->lastChild() == baseNode && baseNode->isTextNode()) {
311 m_compositionNode = nullptr;
312 m_customCompositionUnderlines.clear();
313
314 if (!base.isOffsetInAnchor())
315 return;
316 if (baseNode != frame().selection().extent().anchorNode())
317 return;
318
319 m_compositionNode = toText(baseNode);
320 const EphemeralRange range = PlainTextRange(compositionStart, compositio nEnd).createRange(*editable);
321 if (range.isNull())
322 return;
323
324 m_compositionStart = range.startPosition().computeOffsetInContainerNode( );
325 m_compositionEnd = range.endPosition().computeOffsetInContainerNode();
326 m_customCompositionUnderlines = underlines;
327 size_t numUnderlines = m_customCompositionUnderlines.size();
328 for (size_t i = 0; i < numUnderlines; ++i) {
329 m_customCompositionUnderlines[i].startOffset += m_compositionStart;
330 m_customCompositionUnderlines[i].endOffset += m_compositionStart;
331 }
332 if (baseNode->layoutObject())
333 baseNode->layoutObject()->setShouldDoFullPaintInvalidation();
330 return; 334 return;
331
332 const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd ).createRange(*editable);
333 if (range.isNull())
334 return;
335
336 const Position start = range.startPosition();
337 if (editableRootForPosition(start) != editable)
338 return;
339
340 const Position end = range.endPosition();
341 if (editableRootForPosition(end) != editable)
342 return;
343
344 clear();
345
346 for (const auto& underline : underlines) {
347 unsigned underlineStart = compositionStart + underline.startOffset;
348 unsigned underlineEnd = compositionStart + underline.endOffset;
349 EphemeralRange ephemeralLineRange = PlainTextRange(underlineStart, under lineEnd).createRange(*editable);
350 if (ephemeralLineRange.isNull())
351 continue;
352 frame().document()->markers().addCompositionMarker(ephemeralLineRange.st artPosition(), ephemeralLineRange.endPosition(), underline.color, underline.thic k, underline.backgroundColor);
353 } 335 }
354 336
355 m_hasComposition = true; 337 Editor::RevealSelectionScope revealSelectionScope(&editor());
356 if (!m_compositionRange) 338 SelectionOffsetsScope selectionOffsetsScope(this);
357 m_compositionRange = Range::create(range.document()); 339 setSelectionOffsets(PlainTextRange(compositionStart, compositionEnd));
358 m_compositionRange->setStart(range.startPosition()); 340 setComposition(frame().selectedText(), underlines, 0, 0);
359 m_compositionRange->setEnd(range.endPosition());
360 } 341 }
361 342
362 EphemeralRange InputMethodController::compositionEphemeralRange() const 343 EphemeralRange InputMethodController::compositionEphemeralRange() const
363 { 344 {
364 if (!hasComposition()) 345 if (!hasComposition())
365 return EphemeralRange(); 346 return EphemeralRange();
366 return EphemeralRange(m_compositionRange.get()); 347 unsigned length = m_compositionNode->length();
348 unsigned start = std::min(m_compositionStart, length);
349 unsigned end = std::min(std::max(start, m_compositionEnd), length);
350 if (start >= end)
351 return EphemeralRange();
352 return EphemeralRange(Position(m_compositionNode.get(), start), Position(m_c ompositionNode.get(), end));
367 } 353 }
368 354
369 PassRefPtrWillBeRawPtr<Range> InputMethodController::compositionRange() const 355 PassRefPtrWillBeRawPtr<Range> InputMethodController::compositionRange() const
370 { 356 {
371 return hasComposition() ? m_compositionRange : nullptr; 357 return createRange(compositionEphemeralRange());
372 } 358 }
373 359
374 PlainTextRange InputMethodController::getSelectionOffsets() const 360 PlainTextRange InputMethodController::getSelectionOffsets() const
375 { 361 {
376 RefPtrWillBeRawPtr<Range> range = firstRangeOf(frame().selection().selection ()); 362 RefPtrWillBeRawPtr<Range> range = firstRangeOf(frame().selection().selection ());
377 if (!range) 363 if (!range)
378 return PlainTextRange(); 364 return PlainTextRange();
379 ContainerNode* editable = frame().selection().rootEditableElementOrTreeScope RootNode(); 365 ContainerNode* editable = frame().selection().rootEditableElementOrTreeScope RootNode();
380 ASSERT(editable); 366 ASSERT(editable);
381 return PlainTextRange::create(*editable, *range.get()); 367 return PlainTextRange::create(*editable, *range.get());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 if (before == 0) 415 if (before == 0)
430 break; 416 break;
431 ++before; 417 ++before;
432 } while (frame().selection().start() == frame().selection().end() && before <= static_cast<int>(selectionOffsets.start())); 418 } while (frame().selection().start() == frame().selection().end() && before <= static_cast<int>(selectionOffsets.start()));
433 TypingCommand::deleteSelection(*frame().document()); 419 TypingCommand::deleteSelection(*frame().document());
434 } 420 }
435 421
436 DEFINE_TRACE(InputMethodController) 422 DEFINE_TRACE(InputMethodController)
437 { 423 {
438 visitor->trace(m_frame); 424 visitor->trace(m_frame);
439 visitor->trace(m_compositionRange); 425 visitor->trace(m_compositionNode);
440 } 426 }
441 427
442 } // namespace blink 428 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/editing/InputMethodController.h ('k') | Source/core/editing/markers/DocumentMarker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698