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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 | 314 |
315 selectComposition(); | 315 selectComposition(); |
316 | 316 |
317 if (frame().selection().isNone()) | 317 if (frame().selection().isNone()) |
318 return; | 318 return; |
319 | 319 |
320 Element* target = frame().document()->focusedElement(); | 320 Element* target = frame().document()->focusedElement(); |
321 if (!target) | 321 if (!target) |
322 return; | 322 return; |
323 | 323 |
324 int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start()); | |
325 int start = selectionOffsetsStart + selectionStart; | |
326 int end = selectionOffsetsStart + selectionEnd; | |
327 | |
324 // Dispatch an appropriate composition event to the focused node. | 328 // Dispatch an appropriate composition event to the focused node. |
325 // We check the composition status and choose an appropriate composition eve nt since this | 329 // We check the composition status and choose an appropriate composition eve nt since this |
326 // function is used for three purposes: | 330 // function is used for three purposes: |
327 // 1. Starting a new composition. | 331 // 1. Starting a new composition. |
328 // Send a compositionstart and a compositionupdate event when this functi on creates | 332 // Send a compositionstart and a compositionupdate event when this functi on creates |
329 // a new composition node, i.e. | 333 // a new composition node, i.e. |
330 // !hasComposition() && !text.isEmpty(). | 334 // !hasComposition() && !text.isEmpty(). |
331 // Sending a compositionupdate event at this time ensures that at least o ne | 335 // Sending a compositionupdate event at this time ensures that at least o ne |
332 // compositionupdate event is dispatched. | 336 // compositionupdate event is dispatched. |
333 // 2. Updating the existing composition node. | 337 // 2. Updating the existing composition node. |
334 // Send a compositionupdate event when this function updates the existing composition | 338 // Send a compositionupdate event when this function updates the existing composition |
335 // node, i.e. hasComposition() && !text.isEmpty(). | 339 // node, i.e. hasComposition() && !text.isEmpty(). |
336 // 3. Canceling the ongoing composition. | 340 // 3. Canceling the ongoing composition. |
337 // Send a compositionend event when function deletes the existing composi tion node, i.e. | 341 // Send a compositionend event when function deletes the existing composi tion node, i.e. |
338 // !hasComposition() && test.isEmpty(). | 342 // !hasComposition() && test.isEmpty(). |
339 if (text.isEmpty()) { | 343 if (text.isEmpty()) { |
340 if (hasComposition()) { | 344 if (hasComposition()) { |
341 confirmComposition(emptyString()); | 345 confirmComposition(emptyString()); |
346 setEditableSelectionOffsetsWithBoundaryCheck(start, end); | |
342 return; | 347 return; |
343 } | 348 } |
344 // It's weird to call |setComposition()| with empty text outside composi tion, however some IME | 349 // It's weird to call |setComposition()| with empty text outside composi tion, however some IME |
345 // (e.g. Japanese IBus-Anthy) did this, so we simply delete selection wi thout sending extra events. | 350 // (e.g. Japanese IBus-Anthy) did this, so we simply delete selection wi thout sending extra events. |
346 TypingCommand::deleteSelection(*frame().document(), TypingCommand::Preve ntSpellChecking); | 351 TypingCommand::deleteSelection(*frame().document(), TypingCommand::Preve ntSpellChecking); |
352 setEditableSelectionOffsetsWithBoundaryCheck(start, end); | |
347 return; | 353 return; |
348 } | 354 } |
349 | 355 |
350 // We should send a 'compositionstart' event only when the given text is not empty because this | 356 // We should send a 'compositionstart' event only when the given text is not empty because this |
351 // function doesn't create a composition node when the text is empty. | 357 // function doesn't create a composition node when the text is empty. |
352 if (!hasComposition()) { | 358 if (!hasComposition()) { |
353 target->dispatchEvent(CompositionEvent::create(EventTypeNames::compositi onstart, frame().domWindow(), frame().selectedText())); | 359 target->dispatchEvent(CompositionEvent::create(EventTypeNames::compositi onstart, frame().domWindow(), frame().selectedText())); |
354 if (!frame().document()) | 360 if (!frame().document()) |
355 return; | 361 return; |
356 } | 362 } |
(...skipping 26 matching lines...) Expand all Loading... | |
383 m_isDirty = true; | 389 m_isDirty = true; |
384 m_hasComposition = true; | 390 m_hasComposition = true; |
385 if (!m_compositionRange) | 391 if (!m_compositionRange) |
386 m_compositionRange = Range::create(baseNode->document()); | 392 m_compositionRange = Range::create(baseNode->document()); |
387 m_compositionRange->setStart(baseNode, baseOffset); | 393 m_compositionRange->setStart(baseNode, baseOffset); |
388 m_compositionRange->setEnd(baseNode, extentOffset); | 394 m_compositionRange->setEnd(baseNode, extentOffset); |
389 | 395 |
390 if (baseNode->layoutObject()) | 396 if (baseNode->layoutObject()) |
391 baseNode->layoutObject()->setShouldDoFullPaintInvalidation(); | 397 baseNode->layoutObject()->setShouldDoFullPaintInvalidation(); |
392 | 398 |
393 // In case of exceeding the left boundary. | 399 setEditableSelectionOffsetsWithBoundaryCheck(start, end); |
394 int selectionOffsetsStart = static_cast<int>(getSelectionOffsets().start()); | |
395 int start = std::max(selectionOffsetsStart + selectionStart, 0); | |
396 int end = std::max(selectionOffsetsStart + selectionEnd, start); | |
397 | |
398 Element* rootEditableElement = frame().selection().rootEditableElement(); | |
399 if (!rootEditableElement) | |
400 return; | |
401 | |
402 // In case of exceeding the right boundary. | |
403 // If both |value1| and |value2| exceed right boundary, | |
404 // PlainTextRange(value1, value2)::createRange() will return a default | |
405 // value, which is [0,0]. In order to get the correct Position in that case, | |
406 // we should make sure |value1| is within range at least. | |
407 const EphemeralRange& startRange = PlainTextRange(0, start).createRange(*roo tEditableElement); | |
408 const EphemeralRange& endRange = PlainTextRange(0, end).createRange(*rootEdi tableElement); | |
409 | |
410 // TODO(yabinh): There should be a better way to create |startPosition| and | |
411 // |endPosition|. But for now, since we can't get |anchorNode| and |offset|, | |
412 // we can't create the 2 Position objects directly. So we use | |
413 // PlainTextRange::createRange as a workaround. | |
414 const Position& startPosition = startRange.endPosition(); | |
415 const Position& endPosition = endRange.endPosition(); | |
416 Range* selectedRange = Range::create(rootEditableElement->document(), startP osition, endPosition); | |
417 frame().selection().setSelectedRange(selectedRange, TextAffinity::Downstream , SelectionDirectionalMode::NonDirectional, NotUserTriggered); | |
418 | 400 |
419 if (underlines.isEmpty()) { | 401 if (underlines.isEmpty()) { |
420 frame().document()->markers().addCompositionMarker(m_compositionRange->s tartPosition(), m_compositionRange->endPosition(), Color::black, false, LayoutTh eme::theme().platformDefaultCompositionBackgroundColor()); | 402 frame().document()->markers().addCompositionMarker(m_compositionRange->s tartPosition(), m_compositionRange->endPosition(), Color::black, false, LayoutTh eme::theme().platformDefaultCompositionBackgroundColor()); |
421 return; | 403 return; |
422 } | 404 } |
423 for (const auto& underline : underlines) { | 405 for (const auto& underline : underlines) { |
424 unsigned underlineStart = baseOffset + underline.startOffset; | 406 unsigned underlineStart = baseOffset + underline.startOffset; |
425 unsigned underlineEnd = baseOffset + underline.endOffset; | 407 unsigned underlineEnd = baseOffset + underline.endOffset; |
426 EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, un derlineStart), Position(baseNode, underlineEnd)); | 408 EphemeralRange ephemeralLineRange = EphemeralRange(Position(baseNode, un derlineStart), Position(baseNode, underlineEnd)); |
427 if (ephemeralLineRange.isNull()) | 409 if (ephemeralLineRange.isNull()) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 return frame().selection().setSelectedRange(range, VP_DEFAULT_AFFINITY, Sele ctionDirectionalMode::NonDirectional, FrameSelection::CloseTyping); | 490 return frame().selection().setSelectedRange(range, VP_DEFAULT_AFFINITY, Sele ctionDirectionalMode::NonDirectional, FrameSelection::CloseTyping); |
509 } | 491 } |
510 | 492 |
511 bool InputMethodController::setEditableSelectionOffsets(const PlainTextRange& se lectionOffsets) | 493 bool InputMethodController::setEditableSelectionOffsets(const PlainTextRange& se lectionOffsets) |
512 { | 494 { |
513 if (!editor().canEdit()) | 495 if (!editor().canEdit()) |
514 return false; | 496 return false; |
515 return setSelectionOffsets(selectionOffsets); | 497 return setSelectionOffsets(selectionOffsets); |
516 } | 498 } |
517 | 499 |
500 bool InputMethodController::setEditableSelectionOffsetsWithBoundaryCheck(int sta rt, int end) | |
Changwan Ryu
2016/05/30 08:18:22
could you check if you can replace setEditableSele
yabinh
2016/05/31 01:53:59
Please see patch set 2.
| |
501 { | |
502 if (!editor().canEdit()) | |
503 return false; | |
504 | |
505 Element* rootEditableElement = frame().selection().rootEditableElement(); | |
506 if (!rootEditableElement) | |
507 return false; | |
508 | |
509 // In case of exceeding the left boundary. | |
510 start = std::max(start, 0); | |
511 end = std::max(end, start); | |
512 | |
513 // In case of exceeding the right boundary. | |
514 // If both |value1| and |value2| exceed right boundary, | |
515 // PlainTextRange(value1, value2)::createRange() will return a default | |
516 // value, which is [0,0]. In order to get the correct Position in that case, | |
517 // we should make sure |value1| is within range at least. | |
518 const EphemeralRange& startRange = PlainTextRange(0, start).createRange(*roo tEditableElement); | |
519 if (startRange.isNull()) | |
520 return false; | |
521 const EphemeralRange& endRange = PlainTextRange(0, end).createRange(*rootEdi tableElement); | |
522 if (endRange.isNull()) | |
523 return false; | |
524 | |
525 // TODO(yabinh): There should be a better way to create |startPosition| and | |
526 // |endPosition|. But for now, since we can't get |anchorNode| and |offset|, | |
527 // we can't create the 2 Position objects directly. So we use | |
528 // PlainTextRange::createRange as a workaround. | |
529 const Position& startPosition = startRange.endPosition(); | |
530 const Position& endPosition = endRange.endPosition(); | |
531 const EphemeralRange& range = EphemeralRange(startPosition, endPosition); | |
532 if (range.isNull()) | |
533 return false; | |
534 | |
535 return frame().selection().setSelectedRange(range, VP_DEFAULT_AFFINITY, Sele ctionDirectionalMode::NonDirectional, FrameSelection::CloseTyping); | |
536 } | |
537 | |
518 void InputMethodController::extendSelectionAndDelete(int before, int after) | 538 void InputMethodController::extendSelectionAndDelete(int before, int after) |
519 { | 539 { |
520 if (!editor().canEdit()) | 540 if (!editor().canEdit()) |
521 return; | 541 return; |
522 PlainTextRange selectionOffsets(getSelectionOffsets()); | 542 PlainTextRange selectionOffsets(getSelectionOffsets()); |
523 if (selectionOffsets.isNull()) | 543 if (selectionOffsets.isNull()) |
524 return; | 544 return; |
525 | 545 |
526 // A common call of before=1 and after=0 will fail if the last character | 546 // A common call of before=1 and after=0 will fail if the last character |
527 // is multi-code-word UTF-16, including both multi-16bit code-points and | 547 // is multi-code-word UTF-16, including both multi-16bit code-points and |
(...skipping 19 matching lines...) Expand all Loading... | |
547 TypingCommand::deleteSelection(*frame().document()); | 567 TypingCommand::deleteSelection(*frame().document()); |
548 } | 568 } |
549 | 569 |
550 DEFINE_TRACE(InputMethodController) | 570 DEFINE_TRACE(InputMethodController) |
551 { | 571 { |
552 visitor->trace(m_frame); | 572 visitor->trace(m_frame); |
553 visitor->trace(m_compositionRange); | 573 visitor->trace(m_compositionRange); |
554 } | 574 } |
555 | 575 |
556 } // namespace blink | 576 } // namespace blink |
OLD | NEW |