Chromium Code Reviews| 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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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::confirmComposition() |
| 187 { | 187 { |
| 188 return confirmComposition(composingText()); | 188 return replaceComposition(composingText(), KeepSelection); |
| 189 } | 189 } |
| 190 | 190 |
| 191 bool InputMethodController::confirmComposition(const String& text, ConfirmCompos itionBehavior confirmBehavior) | 191 bool InputMethodController::replaceComposition(const String& text, ConfirmCompos itionBehavior confirmBehavior) |
| 192 { | 192 { |
| 193 if (!hasComposition()) | 193 if (!hasComposition()) |
| 194 return false; | 194 return false; |
| 195 | 195 |
| 196 Optional<Editor::RevealSelectionScope> revealSelectionScope; | 196 Optional<Editor::RevealSelectionScope> revealSelectionScope; |
| 197 if (confirmBehavior == KeepSelection) | 197 if (confirmBehavior == KeepSelection) |
| 198 revealSelectionScope.emplace(&editor()); | 198 revealSelectionScope.emplace(&editor()); |
| 199 | 199 |
| 200 // If the composition was set from existing text and didn't change, then | 200 // 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 | 201 // there's nothing to do here (and we should avoid doing anything as that |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 225 insertTextDuringCompositionWithEvents(frame(), text, 0, TypingCommand::TextC ompositionType::TextCompositionConfirm); | 225 insertTextDuringCompositionWithEvents(frame(), text, 0, TypingCommand::TextC ompositionType::TextCompositionConfirm); |
| 226 // Event handler might destroy document. | 226 // Event handler might destroy document. |
| 227 if (!frame().document()) | 227 if (!frame().document()) |
| 228 return false; | 228 return false; |
| 229 | 229 |
| 230 // No DOM update after 'compositionend'. | 230 // No DOM update after 'compositionend'. |
| 231 dispatchCompositionEndEvent(frame(), text); | 231 dispatchCompositionEndEvent(frame(), text); |
| 232 | 232 |
| 233 return true; | 233 return true; |
| 234 } | 234 } |
| 235 | 235 |
|
yabinh
2016/08/29 08:44:01
Move the comments here.
| |
| 236 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C onfirmCompositionBehavior confirmBehavior) | 236 // If > 0, relativeCaretPosition is relative to the end of the text - 1; |
| 237 // if <= 0, its' relative to the start of the text. | |
| 238 // This is to match Android behavior. See | |
| 239 // https://developer.android.com/reference/android/view/inputmethod/InputConnect ion.html#commitText(java.lang.CharSequence, int) | |
|
tkent
2016/08/30 07:47:11
Even though this follows an Android standard API,
yabinh
2016/08/30 12:33:05
Done.
| |
| 240 static int computeAbsoluteCaretPosition(size_t textStart, size_t textLength, int relativeCaretPosition) | |
| 237 { | 241 { |
| 238 if (!hasComposition()) { | 242 if (relativeCaretPosition > 0) |
| 239 if (!text.length()) | 243 relativeCaretPosition += textLength - 1; |
| 240 return false; | 244 return textStart + relativeCaretPosition; |
| 245 } | |
| 241 | 246 |
| 242 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled) | 247 bool InputMethodController::replaceCompositionAndMoveCaret(const String& text, i nt relativeCaretPosition) |
| 243 return false; | 248 { |
| 249 Element* rootEditableElement = frame().selection().rootEditableElement(); | |
| 250 if (!rootEditableElement) | |
| 251 return false; | |
| 252 PlainTextRange compositionRange = PlainTextRange::create(*rootEditableElemen t, *m_compositionRange); | |
| 253 if (compositionRange.isNull()) | |
| 254 return false; | |
| 255 int textStart = compositionRange.start(); | |
| 244 | 256 |
| 245 editor().insertText(text, 0); | 257 if (!replaceComposition(text, DoNotKeepSelection)) |
| 258 return false; | |
| 259 | |
| 260 int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.len gth(), relativeCaretPosition); | |
| 261 return moveCaret(absoluteCaretPosition); | |
| 262 } | |
| 263 | |
| 264 bool InputMethodController::commitComposition(const String& text) | |
| 265 { | |
| 266 if (!hasComposition()) | |
| 267 return insertText(text); | |
| 268 | |
| 269 if (text.length()) { | |
| 270 replaceComposition(text, KeepSelection); | |
| 246 return true; | 271 return true; |
| 247 } | 272 } |
| 248 | 273 |
| 249 if (text.length()) { | |
| 250 confirmComposition(text); | |
| 251 return true; | |
| 252 } | |
| 253 | |
| 254 if (confirmBehavior == DoNotKeepSelection) | |
| 255 return confirmComposition(composingText(), DoNotKeepSelection); | |
| 256 | |
| 257 SelectionOffsetsScope selectionOffsetsScope(this); | 274 SelectionOffsetsScope selectionOffsetsScope(this); |
| 258 return confirmComposition(); | 275 return confirmComposition(); |
| 259 } | 276 } |
| 260 | 277 |
| 278 bool InputMethodController::commitCompositionAndMoveCaret(const String& text, in t relativeCaretPosition) | |
| 279 { | |
| 280 if (!hasComposition()) | |
| 281 return insertTextAndMoveCaret(text, relativeCaretPosition); | |
| 282 if (text.length()) | |
| 283 return replaceCompositionAndMoveCaret(text, relativeCaretPosition); | |
| 284 return replaceCompositionAndMoveCaret(composingText(), relativeCaretPosition ); | |
| 285 } | |
| 286 | |
| 287 bool InputMethodController::insertText(const String& text) | |
| 288 { | |
| 289 if (!text.length()) | |
| 290 return false; | |
| 291 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text ) != DispatchEventResult::NotCanceled) | |
| 292 return false; | |
| 293 editor().insertText(text, 0); | |
| 294 return true; | |
| 295 } | |
| 296 | |
| 297 bool InputMethodController::insertTextAndMoveCaret(const String& text, int relat iveCaretPosition) | |
| 298 { | |
| 299 PlainTextRange selectionRange = getSelectionOffsets(); | |
| 300 if (selectionRange.isNull()) | |
| 301 return false; | |
| 302 int textStart = selectionRange.start(); | |
| 303 | |
| 304 if (!insertText(text)) | |
| 305 return false; | |
| 306 | |
| 307 int absoluteCaretPosition = computeAbsoluteCaretPosition(textStart, text.len gth(), relativeCaretPosition); | |
| 308 return moveCaret(absoluteCaretPosition); | |
| 309 } | |
| 310 | |
| 261 void InputMethodController::cancelComposition() | 311 void InputMethodController::cancelComposition() |
| 262 { | 312 { |
| 263 if (!hasComposition()) | 313 if (!hasComposition()) |
| 264 return; | 314 return; |
| 265 | 315 |
| 266 Editor::RevealSelectionScope revealSelectionScope(&editor()); | 316 Editor::RevealSelectionScope revealSelectionScope(&editor()); |
| 267 | 317 |
| 268 if (frame().selection().isNone()) | 318 if (frame().selection().isNone()) |
| 269 return; | 319 return; |
| 270 | 320 |
| (...skipping 65 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 | 386 // Sending a compositionupdate event at this time ensures that at least o ne |
| 337 // compositionupdate event is dispatched. | 387 // compositionupdate event is dispatched. |
| 338 // 2. Updating the existing composition node. | 388 // 2. Updating the existing composition node. |
| 339 // Send a compositionupdate event when this function updates the existing composition | 389 // Send a compositionupdate event when this function updates the existing composition |
| 340 // node, i.e. hasComposition() && !text.isEmpty(). | 390 // node, i.e. hasComposition() && !text.isEmpty(). |
| 341 // 3. Canceling the ongoing composition. | 391 // 3. Canceling the ongoing composition. |
| 342 // Send a compositionend event when function deletes the existing composi tion node, i.e. | 392 // Send a compositionend event when function deletes the existing composi tion node, i.e. |
| 343 // !hasComposition() && test.isEmpty(). | 393 // !hasComposition() && test.isEmpty(). |
| 344 if (text.isEmpty()) { | 394 if (text.isEmpty()) { |
| 345 if (hasComposition()) { | 395 if (hasComposition()) { |
| 346 confirmComposition(emptyString()); | 396 replaceComposition(emptyString(), KeepSelection); |
| 347 } else { | 397 } else { |
| 348 // It's weird to call |setComposition()| with empty text outside com position, however some IME | 398 // 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. | 399 // (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); | 400 TypingCommand::deleteSelection(*frame().document(), TypingCommand::P reventSpellChecking); |
| 351 } | 401 } |
| 352 | 402 |
| 353 setEditableSelectionOffsets(selectedRange); | 403 setEditableSelectionOffsets(selectedRange); |
| 354 return; | 404 return; |
| 355 } | 405 } |
| 356 | 406 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 | 586 |
| 537 rightBoundary += textLength; | 587 rightBoundary += textLength; |
| 538 | 588 |
| 539 // In case of exceeding the right boundary. | 589 // In case of exceeding the right boundary. |
| 540 start = std::min(start, rightBoundary); | 590 start = std::min(start, rightBoundary); |
| 541 end = std::min(end, rightBoundary); | 591 end = std::min(end, rightBoundary); |
| 542 | 592 |
| 543 return PlainTextRange(start, end); | 593 return PlainTextRange(start, end); |
| 544 } | 594 } |
| 545 | 595 |
| 596 bool InputMethodController::moveCaret(int newCaretPosition) | |
| 597 { | |
| 598 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets(); | |
| 599 | |
| 600 PlainTextRange selectedRange = createRangeForSelection(newCaretPosition, new CaretPosition, 0); | |
| 601 if (selectedRange.isNull()) | |
| 602 return false; | |
| 603 return setEditableSelectionOffsets(selectedRange); | |
| 604 } | |
| 605 | |
| 546 void InputMethodController::extendSelectionAndDelete(int before, int after) | 606 void InputMethodController::extendSelectionAndDelete(int before, int after) |
| 547 { | 607 { |
| 548 if (!editor().canEdit()) | 608 if (!editor().canEdit()) |
| 549 return; | 609 return; |
| 550 PlainTextRange selectionOffsets(getSelectionOffsets()); | 610 PlainTextRange selectionOffsets(getSelectionOffsets()); |
| 551 if (selectionOffsets.isNull()) | 611 if (selectionOffsets.isNull()) |
| 552 return; | 612 return; |
| 553 | 613 |
| 554 // A common call of before=1 and after=0 will fail if the last character | 614 // A common call of before=1 and after=0 will fail if the last character |
| 555 // is multi-code-word UTF-16, including both multi-16bit code-points and | 615 // is multi-code-word UTF-16, including both multi-16bit code-points and |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 575 TypingCommand::deleteSelection(*frame().document()); | 635 TypingCommand::deleteSelection(*frame().document()); |
| 576 } | 636 } |
| 577 | 637 |
| 578 DEFINE_TRACE(InputMethodController) | 638 DEFINE_TRACE(InputMethodController) |
| 579 { | 639 { |
| 580 visitor->trace(m_frame); | 640 visitor->trace(m_frame); |
| 581 visitor->trace(m_compositionRange); | 641 visitor->trace(m_compositionRange); |
| 582 } | 642 } |
| 583 | 643 |
| 584 } // namespace blink | 644 } // namespace blink |
| OLD | NEW |