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

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

Issue 1995333002: Handle newCursorPosition correctly for Android's commitText() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: change for aelias@'s review Created 4 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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
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::replaceComposition()
187 { 187 {
188 return confirmComposition(composingText()); 188 return replaceComposition(composingText());
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 24 matching lines...) Expand all
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
236 bool InputMethodController::confirmCompositionOrInsertText(const String& text, C onfirmCompositionBehavior confirmBehavior) 236 bool InputMethodController::confirmComposition(const String& text)
237 { 237 {
238 if (!hasComposition()) { 238 if (!hasComposition()) {
239 if (!text.length()) 239 if (!text.length())
240 return false; 240 return false;
241 241
242 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled) 242 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled)
243 return false; 243 return false;
244 244
245 editor().insertText(text, 0); 245 editor().insertText(text, 0);
246 return true; 246 return true;
247 } 247 }
248 248
249 if (text.length()) { 249 if (text.length()) {
250 confirmComposition(text); 250 replaceComposition(text);
251 return true; 251 return true;
252 } 252 }
253 253
254 if (confirmBehavior == DoNotKeepSelection) 254 SelectionOffsetsScope selectionOffsetsScope(this);
255 return confirmComposition(composingText(), DoNotKeepSelection); 255 return replaceComposition();
256 }
256 257
257 SelectionOffsetsScope selectionOffsetsScope(this); 258 bool InputMethodController::confirmCompositionWithCursor(const String& text, int relativeCursorPosition)
258 return confirmComposition(); 259 {
260 // The relativeCursorPosition is relative to the composing text if any, or
261 // relative to the selection if no composing text.
262 // This is to match Android behavior. See:
263 // https://developer.android.com/reference/android/view/inputmethod/InputCon nection.html#commitText(java.lang.CharSequence, int)
264 int textStart, textLength, absoluteCursorPosition;
265 if (hasComposition()) {
266 Element* rootEditableElement = frame().selection().rootEditableElement() ;
267 if (!rootEditableElement)
268 return false;
269 PlainTextRange compositionRange = PlainTextRange::create(*rootEditableEl ement, *m_compositionRange);
270
271 textStart = compositionRange.start();
272
273 // If |text| is empty, we will confirm the composing text; otherwise, we
274 // will insert the |text|.
275 textLength = text.length() ? text.length() : compositionRange.length();
276 } else {
277 PlainTextRange selectionRange = getSelectionOffsets();
278 if (selectionRange.isNull())
279 return false;
280
281 textStart = getSelectionOffsets().start();
282 textLength = text.length();
283 }
284
285 // If relativeCursorPosition > 0, it's relative to the end of the text - 1;
286 // if relativeCursorPosition <= 0, it is relative to the start of the text.
287 // This is also to match Android behavior.
288 if (relativeCursorPosition > 0)
289 relativeCursorPosition += textLength - 1;
290 absoluteCursorPosition = textStart + relativeCursorPosition;
aelias_OOO_until_Jul13 2016/08/25 03:02:10 Since it isn't used before this line, please decla
yabinh 2016/08/25 10:27:08 Done.
291
292 if (!hasComposition()) {
293 if (!text.length())
aelias_OOO_until_Jul13 2016/08/25 02:50:57 Can you move this duplicate code into a new privat
yabinh 2016/08/25 10:27:08 Done.
294 return false;
295
296 if (dispatchBeforeInputInsertText(frame().document()->focusedElement(), text) != DispatchEventResult::NotCanceled)
297 return false;
298
299 editor().insertText(text, 0);
300 } else if (text.length()) {
301 replaceComposition(text);
aelias_OOO_until_Jul13 2016/08/25 02:50:57 Wouldn't it be simpler/more efficient to use DoNot
yabinh 2016/08/25 10:27:08 Done.
302 } else {
303 if (!replaceComposition(composingText(), DoNotKeepSelection))
304 return false;
aelias_OOO_until_Jul13 2016/08/25 03:02:10 Why do we return false here but not in the clause
yabinh 2016/08/25 10:27:08 It seems it makes no difference to return false or
305 }
306
307 frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();
308
309 PlainTextRange selectedRange = createRangeForSelection(absoluteCursorPositio n, absoluteCursorPosition, 0);
310 if (selectedRange.isNull())
311 return false;
312 return setEditableSelectionOffsets(selectedRange);
259 } 313 }
260 314
261 void InputMethodController::cancelComposition() 315 void InputMethodController::cancelComposition()
262 { 316 {
263 if (!hasComposition()) 317 if (!hasComposition())
264 return; 318 return;
265 319
266 Editor::RevealSelectionScope revealSelectionScope(&editor()); 320 Editor::RevealSelectionScope revealSelectionScope(&editor());
267 321
268 if (frame().selection().isNone()) 322 if (frame().selection().isNone())
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 // Sending a compositionupdate event at this time ensures that at least o ne 390 // Sending a compositionupdate event at this time ensures that at least o ne
337 // compositionupdate event is dispatched. 391 // compositionupdate event is dispatched.
338 // 2. Updating the existing composition node. 392 // 2. Updating the existing composition node.
339 // Send a compositionupdate event when this function updates the existing composition 393 // Send a compositionupdate event when this function updates the existing composition
340 // node, i.e. hasComposition() && !text.isEmpty(). 394 // node, i.e. hasComposition() && !text.isEmpty().
341 // 3. Canceling the ongoing composition. 395 // 3. Canceling the ongoing composition.
342 // Send a compositionend event when function deletes the existing composi tion node, i.e. 396 // Send a compositionend event when function deletes the existing composi tion node, i.e.
343 // !hasComposition() && test.isEmpty(). 397 // !hasComposition() && test.isEmpty().
344 if (text.isEmpty()) { 398 if (text.isEmpty()) {
345 if (hasComposition()) { 399 if (hasComposition()) {
346 confirmComposition(emptyString()); 400 replaceComposition(emptyString());
347 } else { 401 } else {
348 // It's weird to call |setComposition()| with empty text outside com position, however some IME 402 // 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. 403 // (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); 404 TypingCommand::deleteSelection(*frame().document(), TypingCommand::P reventSpellChecking);
351 } 405 }
352 406
353 setEditableSelectionOffsets(selectedRange); 407 setEditableSelectionOffsets(selectedRange);
354 return; 408 return;
355 } 409 }
356 410
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 TypingCommand::deleteSelection(*frame().document()); 629 TypingCommand::deleteSelection(*frame().document());
576 } 630 }
577 631
578 DEFINE_TRACE(InputMethodController) 632 DEFINE_TRACE(InputMethodController)
579 { 633 {
580 visitor->trace(m_frame); 634 visitor->trace(m_frame);
581 visitor->trace(m_compositionRange); 635 visitor->trace(m_compositionRange);
582 } 636 }
583 637
584 } // namespace blink 638 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698