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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 if (range.isNull()) | 176 if (range.isNull()) |
177 return; | 177 return; |
178 | 178 |
179 // The composition can start inside a composed character sequence, so we hav e to override checks. | 179 // The composition can start inside a composed character sequence, so we hav e to override checks. |
180 // See <http://bugs.webkit.org/show_bug.cgi?id=15781> | 180 // See <http://bugs.webkit.org/show_bug.cgi?id=15781> |
181 VisibleSelection selection; | 181 VisibleSelection selection; |
182 selection.setWithoutValidation(range.startPosition(), range.endPosition()); | 182 selection.setWithoutValidation(range.startPosition(), range.endPosition()); |
183 frame().selection().setSelection(selection, 0); | 183 frame().selection().setSelection(selection, 0); |
184 } | 184 } |
185 | 185 |
186 bool InputMethodController::confirmComposition() | 186 bool InputMethodController::finishComposingText(ConfirmCompositionBehavior confi rmBehavior) |
187 { | |
188 return confirmComposition(composingText()); | |
189 } | |
190 | |
191 bool InputMethodController::confirmComposition(const String& text, ConfirmCompos itionBehavior confirmBehavior) | |
192 { | 187 { |
193 if (!hasComposition()) | 188 if (!hasComposition()) |
194 return false; | 189 return false; |
190 | |
191 if (confirmBehavior == KeepSelection) { | |
192 SelectionOffsetsScope selectionOffsetsScope(this); | |
193 return replaceComposition(composingText(), KeepSelection); | |
194 } | |
195 | |
196 return replaceCompositionAndMoveCaret(composingText(), 0); | |
197 } | |
198 | |
199 bool InputMethodController::commitText(const String& text, int relativeCaretPosi tion) | |
200 { | |
201 if (!hasComposition()) { | |
202 // We should do nothing in this case, because: | |
203 // 1. No need to insert text when text is empty. | |
204 // 2. Shouldn't move caret when relativeCaretPosition == 0 to avoid | |
205 // duplicate selection change event. | |
206 if (!text.length() && !relativeCaretPosition) | |
207 return false; | |
208 return insertTextAndMoveCaret(text, relativeCaretPosition); | |
209 } | |
210 | |
211 return replaceCompositionAndMoveCaret(text, relativeCaretPosition); | |
yosin_UTC9
2016/09/07 07:19:20
nit: It is better to switch if's condition to redu
yabinh
2016/09/07 10:27:15
Done.
| |
212 } | |
213 | |
214 bool InputMethodController::replaceComposition(const String& text, ConfirmCompos itionBehavior confirmBehavior) | |
215 { | |
216 if (!hasComposition()) | |
217 return false; | |
195 | 218 |
196 Optional<Editor::RevealSelectionScope> revealSelectionScope; | 219 Optional<Editor::RevealSelectionScope> revealSelectionScope; |
197 if (confirmBehavior == KeepSelection) | 220 if (confirmBehavior == KeepSelection) |
198 revealSelectionScope.emplace(&editor()); | 221 revealSelectionScope.emplace(&editor()); |
aelias_OOO_until_Jul13
2016/09/07 05:02:40
Please move this to finishComposingText() and remo
yabinh
2016/09/07 10:27:15
Done.
Note that setComposition() will also be affe
| |
199 | 222 |
200 // If the composition was set from existing text and didn't change, then | 223 // If the composition was set from existing text and didn't change, then |
201 // there's nothing to do here (and we should avoid doing anything as that | 224 // there's nothing to do here (and we should avoid doing anything as that |
202 // may clobber multi-node styled text). | 225 // may clobber multi-node styled text). |
203 if (!m_isDirty && composingText() == text) { | 226 if (!m_isDirty && composingText() == text) { |
204 clear(); | 227 clear(); |
205 return true; | 228 return true; |
206 } | 229 } |
207 | 230 |
208 // Select the text that will be deleted or replaced. | 231 // Select the text that will be deleted or replaced. |
(...skipping 17 matching lines...) Expand all Loading... | |
226 // Event handler might destroy document. | 249 // Event handler might destroy document. |
227 if (!frame().document()) | 250 if (!frame().document()) |
228 return false; | 251 return false; |
229 | 252 |
230 // No DOM update after 'compositionend'. | 253 // No DOM update after 'compositionend'. |
231 dispatchCompositionEndEvent(frame(), text); | 254 dispatchCompositionEndEvent(frame(), text); |
232 | 255 |
233 return true; | 256 return true; |
234 } | 257 } |
235 | 258 |
236 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C onfirmCompositionBehavior confirmBehavior) | 259 // relativeCaretPosition is relative to the end of the text. |
260 static int computeAbsoluteCaretPosition(size_t textStart, size_t textLength, int relativeCaretPosition) | |
237 { | 261 { |
238 if (!hasComposition()) { | 262 return textStart + textLength + relativeCaretPosition; |
239 if (!text.length()) | 263 } |
264 | |
265 bool InputMethodController::replaceCompositionAndMoveCaret(const String& text, i nt relativeCaretPosition) | |
266 { | |
267 Element* rootEditableElement = frame().selection().rootEditableElement(); | |
268 if (!rootEditableElement) | |
269 return false; | |
270 PlainTextRange compositionRange = PlainTextRange::create(*rootEditableElemen t, *m_compositionRange); | |
271 if (compositionRange.isNull()) | |
272 return false; | |
273 int textStart = compositionRange.start(); | |
274 | |
275 if (!replaceComposition(text, DoNotKeepSelection)) | |
276 return false; | |
277 | |
278 int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.len gth(), relativeCaretPosition); | |
279 return moveCaret(absoluteCaretPosition); | |
280 } | |
281 | |
282 bool InputMethodController::insertText(const String& text) | |
283 { | |
284 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text ) != DispatchEventResult::NotCanceled) | |
285 return false; | |
286 editor().insertText(text, 0); | |
287 return true; | |
288 } | |
289 | |
290 bool InputMethodController::insertTextAndMoveCaret(const String& text, int relat iveCaretPosition) | |
291 { | |
292 PlainTextRange selectionRange = getSelectionOffsets(); | |
293 if (selectionRange.isNull()) | |
294 return false; | |
295 int textStart = selectionRange.start(); | |
296 | |
297 if (text.length()) { | |
298 if (!insertText(text)) | |
240 return false; | 299 return false; |
241 | |
242 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled) | |
243 return false; | |
244 | |
245 editor().insertText(text, 0); | |
246 return true; | |
247 } | 300 } |
248 | 301 |
249 if (text.length()) { | 302 int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.len gth(), relativeCaretPosition); |
250 confirmComposition(text); | 303 return moveCaret(absoluteCaretPosition); |
251 return true; | |
252 } | |
253 | |
254 if (confirmBehavior == DoNotKeepSelection) | |
255 return confirmComposition(composingText(), DoNotKeepSelection); | |
256 | |
257 SelectionOffsetsScope selectionOffsetsScope(this); | |
258 return confirmComposition(); | |
259 } | 304 } |
260 | 305 |
261 void InputMethodController::cancelComposition() | 306 void InputMethodController::cancelComposition() |
262 { | 307 { |
263 if (!hasComposition()) | 308 if (!hasComposition()) |
264 return; | 309 return; |
265 | 310 |
266 Editor::RevealSelectionScope revealSelectionScope(&editor()); | 311 Editor::RevealSelectionScope revealSelectionScope(&editor()); |
267 | 312 |
268 if (frame().selection().isNone()) | 313 if (frame().selection().isNone()) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
336 // Sending a compositionupdate event at this time ensures that at least o ne | 381 // Sending a compositionupdate event at this time ensures that at least o ne |
337 // compositionupdate event is dispatched. | 382 // compositionupdate event is dispatched. |
338 // 2. Updating the existing composition node. | 383 // 2. Updating the existing composition node. |
339 // Send a compositionupdate event when this function updates the existing composition | 384 // Send a compositionupdate event when this function updates the existing composition |
340 // node, i.e. hasComposition() && !text.isEmpty(). | 385 // node, i.e. hasComposition() && !text.isEmpty(). |
341 // 3. Canceling the ongoing composition. | 386 // 3. Canceling the ongoing composition. |
342 // Send a compositionend event when function deletes the existing composi tion node, i.e. | 387 // Send a compositionend event when function deletes the existing composi tion node, i.e. |
343 // !hasComposition() && test.isEmpty(). | 388 // !hasComposition() && test.isEmpty(). |
344 if (text.isEmpty()) { | 389 if (text.isEmpty()) { |
345 if (hasComposition()) { | 390 if (hasComposition()) { |
346 confirmComposition(emptyString()); | 391 replaceComposition(emptyString(), KeepSelection); |
347 } else { | 392 } else { |
348 // It's weird to call |setComposition()| with empty text outside com position, however some IME | 393 // It's weird to call |setComposition()| with empty text outside com position, however some IME |
349 // (e.g. Japanese IBus-Anthy) did this, so we simply delete selectio n without sending extra events. | 394 // (e.g. Japanese IBus-Anthy) did this, so we simply delete selectio n without sending extra events. |
350 TypingCommand::deleteSelection(*frame().document(), TypingCommand::P reventSpellChecking); | 395 TypingCommand::deleteSelection(*frame().document(), TypingCommand::P reventSpellChecking); |
351 } | 396 } |
352 | 397 |
353 setEditableSelectionOffsets(selectedRange); | 398 setEditableSelectionOffsets(selectedRange); |
354 return; | 399 return; |
355 } | 400 } |
356 | 401 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
537 | 582 |
538 rightBoundary += textLength; | 583 rightBoundary += textLength; |
539 | 584 |
540 // In case of exceeding the right boundary. | 585 // In case of exceeding the right boundary. |
541 start = std::min(start, rightBoundary); | 586 start = std::min(start, rightBoundary); |
542 end = std::min(end, rightBoundary); | 587 end = std::min(end, rightBoundary); |
543 | 588 |
544 return PlainTextRange(start, end); | 589 return PlainTextRange(start, end); |
545 } | 590 } |
546 | 591 |
592 bool InputMethodController::moveCaret(int newCaretPosition) | |
593 { | |
594 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | |
595 PlainTextRange selectedRange = createRangeForSelection(newCaretPosition, new CaretPosition, 0); | |
596 if (selectedRange.isNull()) | |
597 return false; | |
598 return setEditableSelectionOffsets(selectedRange); | |
599 } | |
600 | |
547 void InputMethodController::extendSelectionAndDelete(int before, int after) | 601 void InputMethodController::extendSelectionAndDelete(int before, int after) |
548 { | 602 { |
549 if (!editor().canEdit()) | 603 if (!editor().canEdit()) |
550 return; | 604 return; |
551 PlainTextRange selectionOffsets(getSelectionOffsets()); | 605 PlainTextRange selectionOffsets(getSelectionOffsets()); |
552 if (selectionOffsets.isNull()) | 606 if (selectionOffsets.isNull()) |
553 return; | 607 return; |
554 | 608 |
555 // A common call of before=1 and after=0 will fail if the last character | 609 // A common call of before=1 and after=0 will fail if the last character |
556 // is multi-code-word UTF-16, including both multi-16bit code-points and | 610 // is multi-code-word UTF-16, including both multi-16bit code-points and |
(...skipping 19 matching lines...) Expand all Loading... | |
576 TypingCommand::deleteSelection(*frame().document()); | 630 TypingCommand::deleteSelection(*frame().document()); |
577 } | 631 } |
578 | 632 |
579 DEFINE_TRACE(InputMethodController) | 633 DEFINE_TRACE(InputMethodController) |
580 { | 634 { |
581 visitor->trace(m_frame); | 635 visitor->trace(m_frame); |
582 visitor->trace(m_compositionRange); | 636 visitor->trace(m_compositionRange); |
583 } | 637 } |
584 | 638 |
585 } // namespace blink | 639 } // namespace blink |
OLD | NEW |