Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "web/WebFrameWidgetImpl.h" | 31 #include "web/WebFrameWidgetImpl.h" |
| 32 | 32 |
| 33 #include "core/InputTypeNames.h" | |
| 33 #include "core/editing/EditingUtilities.h" | 34 #include "core/editing/EditingUtilities.h" |
| 34 #include "core/editing/Editor.h" | 35 #include "core/editing/Editor.h" |
| 35 #include "core/editing/FrameSelection.h" | 36 #include "core/editing/FrameSelection.h" |
| 36 #include "core/editing/InputMethodController.h" | 37 #include "core/editing/InputMethodController.h" |
| 37 #include "core/editing/PlainTextRange.h" | 38 #include "core/editing/PlainTextRange.h" |
| 38 #include "core/frame/FrameHost.h" | 39 #include "core/frame/FrameHost.h" |
| 39 #include "core/frame/FrameView.h" | 40 #include "core/frame/FrameView.h" |
| 40 #include "core/frame/RemoteFrame.h" | 41 #include "core/frame/RemoteFrame.h" |
| 41 #include "core/frame/Settings.h" | 42 #include "core/frame/Settings.h" |
| 42 #include "core/frame/VisualViewport.h" | 43 #include "core/frame/VisualViewport.h" |
| 44 #include "core/html/HTMLInputElement.h" | |
| 45 #include "core/html/HTMLTextAreaElement.h" | |
| 43 #include "core/input/EventHandler.h" | 46 #include "core/input/EventHandler.h" |
| 44 #include "core/layout/LayoutView.h" | 47 #include "core/layout/LayoutView.h" |
| 45 #include "core/layout/api/LayoutViewItem.h" | 48 #include "core/layout/api/LayoutViewItem.h" |
| 46 #include "core/layout/compositing/PaintLayerCompositor.h" | 49 #include "core/layout/compositing/PaintLayerCompositor.h" |
| 47 #include "core/page/ContextMenuController.h" | 50 #include "core/page/ContextMenuController.h" |
| 48 #include "core/page/FocusController.h" | 51 #include "core/page/FocusController.h" |
| 49 #include "core/page/Page.h" | 52 #include "core/page/Page.h" |
| 50 #include "core/page/PointerLockController.h" | 53 #include "core/page/PointerLockController.h" |
| 51 #include "platform/KeyboardCodes.h" | 54 #include "platform/KeyboardCodes.h" |
| 52 #include "platform/graphics/CompositorMutatorClient.h" | 55 #include "platform/graphics/CompositorMutatorClient.h" |
| 53 #include "public/platform/WebFrameScheduler.h" | 56 #include "public/platform/WebFrameScheduler.h" |
| 57 #include "public/web/WebAutofillClient.h" | |
| 58 #include "public/web/WebPlugin.h" | |
| 59 #include "public/web/WebRange.h" | |
| 54 #include "public/web/WebWidgetClient.h" | 60 #include "public/web/WebWidgetClient.h" |
| 61 #include "web/CompositionUnderlineVectorBuilder.h" | |
| 55 #include "web/CompositorMutatorImpl.h" | 62 #include "web/CompositorMutatorImpl.h" |
| 56 #include "web/CompositorProxyClientImpl.h" | 63 #include "web/CompositorProxyClientImpl.h" |
| 57 #include "web/ContextMenuAllowedScope.h" | 64 #include "web/ContextMenuAllowedScope.h" |
| 58 #include "web/WebDevToolsAgentImpl.h" | 65 #include "web/WebDevToolsAgentImpl.h" |
| 59 #include "web/WebInputEventConversion.h" | 66 #include "web/WebInputEventConversion.h" |
| 60 #include "web/WebLocalFrameImpl.h" | 67 #include "web/WebLocalFrameImpl.h" |
| 61 #include "web/WebPluginContainerImpl.h" | 68 #include "web/WebPluginContainerImpl.h" |
| 62 #include "web/WebRemoteFrameImpl.h" | 69 #include "web/WebRemoteFrameImpl.h" |
| 63 #include "web/WebViewFrameWidget.h" | 70 #include "web/WebViewFrameWidget.h" |
| 64 #include "wtf/PtrUtil.h" | 71 #include "wtf/PtrUtil.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 , m_localRoot(toWebLocalFrameImpl(localRoot)) | 104 , m_localRoot(toWebLocalFrameImpl(localRoot)) |
| 98 , m_mutator(nullptr) | 105 , m_mutator(nullptr) |
| 99 , m_layerTreeView(nullptr) | 106 , m_layerTreeView(nullptr) |
| 100 , m_rootLayer(nullptr) | 107 , m_rootLayer(nullptr) |
| 101 , m_rootGraphicsLayer(nullptr) | 108 , m_rootGraphicsLayer(nullptr) |
| 102 , m_isAcceleratedCompositingActive(false) | 109 , m_isAcceleratedCompositingActive(false) |
| 103 , m_layerTreeViewClosed(false) | 110 , m_layerTreeViewClosed(false) |
| 104 , m_suppressNextKeypressEvent(false) | 111 , m_suppressNextKeypressEvent(false) |
| 105 , m_ignoreInputEvents(false) | 112 , m_ignoreInputEvents(false) |
| 106 , m_isTransparent(false) | 113 , m_isTransparent(false) |
| 114 , m_imeAcceptEvents(true) | |
| 107 , m_selfKeepAlive(this) | 115 , m_selfKeepAlive(this) |
| 108 { | 116 { |
| 109 DCHECK(m_localRoot->frame()->isLocalRoot()); | 117 DCHECK(m_localRoot->frame()->isLocalRoot()); |
| 110 initializeLayerTreeView(); | 118 initializeLayerTreeView(); |
| 111 m_localRoot->setFrameWidget(this); | 119 m_localRoot->setFrameWidget(this); |
| 112 allInstances().add(this); | 120 allInstances().add(this); |
| 113 | 121 |
| 114 if (localRoot->parent()) | 122 if (localRoot->parent()) |
| 115 setIsTransparent(true); | 123 setIsTransparent(true); |
| 116 } | 124 } |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 } else if (element->isContentEditable()) { | 462 } else if (element->isContentEditable()) { |
| 455 // updateFocusAppearance() selects all the text of | 463 // updateFocusAppearance() selects all the text of |
| 456 // contentseditable DIVs. So we set the selection explicitly | 464 // contentseditable DIVs. So we set the selection explicitly |
| 457 // instead. Note that this has the side effect of moving the | 465 // instead. Note that this has the side effect of moving the |
| 458 // caret back to the beginning of the text. | 466 // caret back to the beginning of the text. |
| 459 Position position(element, 0); | 467 Position position(element, 0); |
| 460 focusedFrame->selection().setSelection(VisibleSelection(posi tion, SelDefaultAffinity)); | 468 focusedFrame->selection().setSelection(VisibleSelection(posi tion, SelDefaultAffinity)); |
| 461 } | 469 } |
| 462 } | 470 } |
| 463 } | 471 } |
| 472 } else { | |
| 473 LocalFrame* focusedFrame = focusedLocalFrameInWidget(); | |
| 474 if (focusedFrame) { | |
| 475 // Finish an ongoing composition to delete the composition node. | |
| 476 if (focusedFrame->inputMethodController().hasComposition()) { | |
| 477 WebAutofillClient* autofillClient = WebLocalFrameImpl::fromFrame (focusedFrame)->autofillClient(); | |
| 478 | |
| 479 if (autofillClient) | |
| 480 autofillClient->setIgnoreTextChanges(true); | |
| 481 | |
| 482 focusedFrame->inputMethodController().confirmComposition(); | |
| 483 | |
| 484 if (autofillClient) | |
| 485 autofillClient->setIgnoreTextChanges(false); | |
| 486 } | |
| 487 m_imeAcceptEvents = false; | |
| 488 } | |
| 464 } | 489 } |
| 465 } | 490 } |
| 466 | 491 |
| 467 bool WebFrameWidgetImpl::setComposition( | 492 bool WebFrameWidgetImpl::setComposition( |
| 468 const WebString& text, | 493 const WebString& text, |
| 469 const WebVector<WebCompositionUnderline>& underlines, | 494 const WebVector<WebCompositionUnderline>& underlines, |
| 470 int selectionStart, | 495 int selectionStart, |
| 471 int selectionEnd) | 496 int selectionEnd) |
| 472 { | 497 { |
| 473 // FIXME: To be implemented. | 498 if (!m_imeAcceptEvents) |
|
dcheng
2016/07/12 14:43:21
I assume this is largely based on the implementati
EhsanK
2016/07/12 15:13:24
Yes. As tested on WebViewImpl itself, we need this
| |
| 474 return false; | 499 return false; |
| 500 | |
| 501 LocalFrame* focused = focusedLocalFrameInWidget(); | |
| 502 | |
| 503 if (!focused) | |
| 504 return false; | |
| 505 | |
| 506 if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused)) | |
| 507 return plugin->setComposition(text, underlines, selectionStart, selectio nEnd); | |
| 508 | |
| 509 // The input focus has been moved to another WebWidget object. | |
| 510 // We should use this |editor| object only to complete the ongoing | |
| 511 // composition. | |
| 512 InputMethodController& inputMethodController = focused->inputMethodControlle r(); | |
| 513 if (!focused->editor().canEdit() && !inputMethodController.hasComposition()) | |
| 514 return false; | |
| 515 | |
| 516 // We should verify the parent node of this IME composition node are | |
| 517 // editable because JavaScript may delete a parent node of the composition | |
| 518 // node. In this case, WebKit crashes while deleting texts from the parent | |
| 519 // node, which doesn't exist any longer. | |
| 520 const EphemeralRange range = inputMethodController.compositionEphemeralRange (); | |
| 521 if (range.isNotNull()) { | |
| 522 Node* node = range.startPosition().computeContainerNode(); | |
| 523 if (!node || !node->isContentEditable()) | |
| 524 return false; | |
| 525 } | |
| 526 | |
| 527 // A keypress event is canceled. If an ongoing composition exists, then the | |
| 528 // keydown event should have arisen from a handled key (e.g., backspace). | |
| 529 // In this case we ignore the cancellation and continue; otherwise (no | |
| 530 // ongoing composition) we exit and signal success only for attempts to | |
| 531 // clear the composition. | |
| 532 if (m_suppressNextKeypressEvent && !inputMethodController.hasComposition()) | |
| 533 return text.isEmpty(); | |
| 534 | |
| 535 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); | |
| 536 | |
| 537 // When the range of composition underlines overlap with the range between | |
| 538 // selectionStart and selectionEnd, WebKit somehow won't paint the selection | |
| 539 // at all (see InlineTextBox::paint() function in InlineTextBox.cpp). | |
| 540 // But the selection range actually takes effect. | |
| 541 inputMethodController.setComposition(String(text), | |
| 542 CompositionUnderlineVectorBuilder(underlines), | |
| 543 selectionStart, selectionEnd); | |
| 544 | |
| 545 return text.isEmpty() || inputMethodController.hasComposition(); | |
| 475 } | 546 } |
| 476 | 547 |
| 477 bool WebFrameWidgetImpl::confirmComposition() | 548 bool WebFrameWidgetImpl::confirmComposition() |
| 478 { | 549 { |
| 479 // FIXME: To be implemented. | 550 return confirmComposition(DoNotKeepSelection); |
| 480 return false; | |
| 481 } | 551 } |
| 482 | 552 |
| 483 bool WebFrameWidgetImpl::confirmComposition(ConfirmCompositionBehavior selection Behavior) | 553 bool WebFrameWidgetImpl::confirmComposition(ConfirmCompositionBehavior selection Behavior) |
| 484 { | 554 { |
| 485 // FIXME: To be implemented. | 555 return confirmComposition(WebString(), selectionBehavior); |
| 486 return false; | |
| 487 } | 556 } |
| 488 | 557 |
| 489 bool WebFrameWidgetImpl::confirmComposition(const WebString& text) | 558 bool WebFrameWidgetImpl::confirmComposition(const WebString& text) |
| 490 { | 559 { |
| 491 // FIXME: To be implemented. | 560 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); |
| 492 return false; | 561 return confirmComposition(text, DoNotKeepSelection); |
| 562 } | |
| 563 | |
| 564 bool WebFrameWidgetImpl::confirmComposition(const WebString& text, ConfirmCompos itionBehavior selectionBehavior) const | |
| 565 { | |
| 566 if (!m_imeAcceptEvents) | |
| 567 return false; | |
| 568 | |
| 569 LocalFrame* focused = focusedLocalFrameInWidget(); | |
| 570 if (!focused) | |
| 571 return false; | |
| 572 | |
| 573 if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused)) | |
| 574 return plugin->confirmComposition(text, selectionBehavior); | |
| 575 | |
| 576 return focused->inputMethodController().confirmCompositionOrInsertText(text, selectionBehavior == KeepSelection ? InputMethodController::KeepSelection : Inp utMethodController::DoNotKeepSelection); | |
| 493 } | 577 } |
| 494 | 578 |
| 495 bool WebFrameWidgetImpl::compositionRange(size_t* location, size_t* length) | 579 bool WebFrameWidgetImpl::compositionRange(size_t* location, size_t* length) |
| 496 { | 580 { |
| 497 // FIXME: To be implemented. | 581 if (!m_imeAcceptEvents) |
| 498 return false; | 582 return false; |
| 583 | |
| 584 LocalFrame* focused = focusedLocalFrameInWidget(); | |
| 585 if (!focused) | |
| 586 return false; | |
| 587 | |
| 588 const EphemeralRange range = focused->inputMethodController().compositionEph emeralRange(); | |
| 589 if (range.isNull()) | |
| 590 return false; | |
| 591 | |
| 592 Element* editable = focused->selection().rootEditableElementOrDocumentElemen t(); | |
| 593 DCHECK(editable); | |
| 594 PlainTextRange plainTextRange(PlainTextRange::create(*editable, range)); | |
| 595 if (plainTextRange.isNull()) | |
| 596 return false; | |
| 597 *location = plainTextRange.start(); | |
| 598 *length = plainTextRange.length(); | |
| 599 return true; | |
| 499 } | 600 } |
| 500 | 601 |
| 501 WebTextInputInfo WebFrameWidgetImpl::textInputInfo() | 602 WebTextInputInfo WebFrameWidgetImpl::textInputInfo() |
| 502 { | 603 { |
| 503 return view()->textInputInfo(); | 604 WebTextInputInfo info; |
| 605 | |
| 606 LocalFrame* focused = focusedLocalFrameInWidget(); | |
| 607 if (!focused) | |
| 608 return info; | |
| 609 | |
| 610 FrameSelection& selection = focused->selection(); | |
| 611 if (!selection.isAvailable()) { | |
| 612 // plugins/mouse-capture-inside-shadow.html reaches here. | |
| 613 return info; | |
| 614 } | |
| 615 Element* element = selection.selection().rootEditableElement(); | |
| 616 if (!element) | |
| 617 return info; | |
| 618 | |
| 619 info.inputMode = inputModeOfFocusedElement(); | |
| 620 | |
| 621 info.type = textInputType(); | |
| 622 info.flags = textInputFlags(); | |
| 623 if (info.type == WebTextInputTypeNone) | |
| 624 return info; | |
| 625 | |
| 626 if (!focused->editor().canEdit()) | |
| 627 return info; | |
| 628 | |
| 629 // Emits an object replacement character for each replaced element so that | |
| 630 // it is exposed to IME and thus could be deleted by IME on android. | |
| 631 info.value = plainText(EphemeralRange::rangeOfContents(*element), TextIterat orEmitsObjectReplacementCharacter); | |
| 632 | |
| 633 if (info.value.isEmpty()) | |
| 634 return info; | |
| 635 | |
| 636 EphemeralRange firstRange = firstEphemeralRangeOf(selection.selection()); | |
| 637 if (firstRange.isNotNull()) { | |
| 638 PlainTextRange plainTextRange(PlainTextRange::create(*element, firstRang e)); | |
| 639 if (plainTextRange.isNotNull()) { | |
| 640 info.selectionStart = plainTextRange.start(); | |
| 641 info.selectionEnd = plainTextRange.end(); | |
| 642 } | |
| 643 } | |
| 644 | |
| 645 EphemeralRange range = focused->inputMethodController().compositionEphemeral Range(); | |
| 646 if (range.isNotNull()) { | |
| 647 PlainTextRange plainTextRange(PlainTextRange::create(*element, range)); | |
| 648 if (plainTextRange.isNotNull()) { | |
| 649 info.compositionStart = plainTextRange.start(); | |
| 650 info.compositionEnd = plainTextRange.end(); | |
| 651 } | |
| 652 } | |
| 653 | |
| 654 return info; | |
| 504 } | 655 } |
| 505 | 656 |
| 506 WebTextInputType WebFrameWidgetImpl::textInputType() | 657 WebTextInputType WebFrameWidgetImpl::textInputType() |
| 507 { | 658 { |
| 508 return view()->textInputType(); | 659 LocalFrame* focusedFrame = focusedLocalFrameInWidget(); |
| 660 if (!focusedFrame) | |
| 661 return WebTextInputTypeNone; | |
| 662 | |
| 663 if (!focusedFrame->selection().isAvailable()) { | |
| 664 // "mouse-capture-inside-shadow.html" reaches here. | |
| 665 return WebTextInputTypeNone; | |
| 666 } | |
| 667 | |
| 668 // It's important to preserve the equivalence of textInputInfo().type and te xtInputType(), | |
| 669 // so perform the same rootEditableElement() existence check here for consis tency. | |
| 670 if (!focusedFrame->selection().selection().rootEditableElement()) | |
| 671 return WebTextInputTypeNone; | |
| 672 | |
| 673 Document* document = focusedFrame->document(); | |
| 674 if (!document) | |
| 675 return WebTextInputTypeNone; | |
| 676 | |
| 677 Element* element = document->focusedElement(); | |
| 678 if (!element) | |
| 679 return WebTextInputTypeNone; | |
| 680 | |
| 681 if (isHTMLInputElement(*element)) { | |
| 682 HTMLInputElement& input = toHTMLInputElement(*element); | |
| 683 const AtomicString& type = input.type(); | |
| 684 | |
| 685 if (input.isDisabledOrReadOnly()) | |
| 686 return WebTextInputTypeNone; | |
| 687 | |
| 688 if (type == InputTypeNames::password) | |
| 689 return WebTextInputTypePassword; | |
| 690 if (type == InputTypeNames::search) | |
| 691 return WebTextInputTypeSearch; | |
| 692 if (type == InputTypeNames::email) | |
| 693 return WebTextInputTypeEmail; | |
| 694 if (type == InputTypeNames::number) | |
| 695 return WebTextInputTypeNumber; | |
| 696 if (type == InputTypeNames::tel) | |
| 697 return WebTextInputTypeTelephone; | |
| 698 if (type == InputTypeNames::url) | |
| 699 return WebTextInputTypeURL; | |
| 700 if (type == InputTypeNames::date) | |
| 701 return WebTextInputTypeDate; | |
| 702 if (type == InputTypeNames::datetime_local) | |
| 703 return WebTextInputTypeDateTimeLocal; | |
| 704 if (type == InputTypeNames::month) | |
| 705 return WebTextInputTypeMonth; | |
| 706 if (type == InputTypeNames::time) | |
| 707 return WebTextInputTypeTime; | |
| 708 if (type == InputTypeNames::week) | |
| 709 return WebTextInputTypeWeek; | |
| 710 if (type == InputTypeNames::text) | |
| 711 return WebTextInputTypeText; | |
| 712 | |
| 713 return WebTextInputTypeNone; | |
| 714 } | |
| 715 | |
| 716 if (isHTMLTextAreaElement(*element)) { | |
| 717 if (toHTMLTextAreaElement(*element).isDisabledOrReadOnly()) | |
| 718 return WebTextInputTypeNone; | |
| 719 return WebTextInputTypeTextArea; | |
| 720 } | |
| 721 | |
| 722 if (element->isHTMLElement()) { | |
| 723 if (toHTMLElement(element)->isDateTimeFieldElement()) | |
| 724 return WebTextInputTypeDateTimeField; | |
| 725 } | |
| 726 | |
| 727 if (element->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) | |
| 728 return WebTextInputTypeContentEditable; | |
| 729 | |
| 730 return WebTextInputTypeNone; | |
| 509 } | 731 } |
| 510 | 732 |
| 511 WebColor WebFrameWidgetImpl::backgroundColor() const | 733 WebColor WebFrameWidgetImpl::backgroundColor() const |
| 512 { | 734 { |
| 513 if (isTransparent()) | 735 if (isTransparent()) |
| 514 return Color::transparent; | 736 return Color::transparent; |
| 515 if (!m_localRoot->frameView()) | 737 if (!m_localRoot->frameView()) |
| 516 return m_baseBackgroundColor; | 738 return m_baseBackgroundColor; |
| 517 FrameView* view = m_localRoot->frameView(); | 739 FrameView* view = m_localRoot->frameView(); |
| 518 return view->documentBackgroundColor().rgb(); | 740 return view->documentBackgroundColor().rgb(); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 void WebFrameWidgetImpl::didNotAcquirePointerLock() | 879 void WebFrameWidgetImpl::didNotAcquirePointerLock() |
| 658 { | 880 { |
| 659 page()->pointerLockController().didNotAcquirePointerLock(); | 881 page()->pointerLockController().didNotAcquirePointerLock(); |
| 660 } | 882 } |
| 661 | 883 |
| 662 void WebFrameWidgetImpl::didLosePointerLock() | 884 void WebFrameWidgetImpl::didLosePointerLock() |
| 663 { | 885 { |
| 664 page()->pointerLockController().didLosePointerLock(); | 886 page()->pointerLockController().didLosePointerLock(); |
| 665 } | 887 } |
| 666 | 888 |
| 889 bool WebFrameWidgetImpl::getCompositionCharacterBounds(WebVector<WebRect>& bound s) | |
| 890 { | |
| 891 size_t offset = 0; | |
| 892 size_t characterCount = 0; | |
| 893 if (!compositionRange(&offset, &characterCount)) | |
| 894 return false; | |
| 895 | |
| 896 if (characterCount == 0) | |
| 897 return false; | |
| 898 | |
| 899 LocalFrame* frame = focusedLocalFrameInWidget(); | |
| 900 if (!frame) | |
| 901 return false; | |
| 902 | |
| 903 WebLocalFrameImpl* webLocalFrame = WebLocalFrameImpl::fromFrame(frame); | |
| 904 WebVector<WebRect> result(characterCount); | |
| 905 WebRect webrect; | |
| 906 for (size_t i = 0; i < characterCount; ++i) { | |
| 907 if (!webLocalFrame->firstRectForCharacterRange(offset + i, 1, webrect)) { | |
| 908 DLOG(ERROR) << "Could not retrieve character rectangle at " << i; | |
| 909 return false; | |
| 910 } | |
| 911 result[i] = webrect; | |
| 912 } | |
| 913 bounds.swap(result); | |
| 914 return true; | |
| 915 } | |
| 916 | |
| 917 void WebFrameWidgetImpl::applyReplacementRange(int start, int length) | |
| 918 { | |
| 919 if (LocalFrame* frame = focusedLocalFrameInWidget()) { | |
| 920 WebLocalFrameImpl* webLocalFrame = WebLocalFrameImpl::fromFrame(frame); | |
| 921 WebRange webrange = WebRange::fromDocumentRange(webLocalFrame, start, le ngth); | |
| 922 if (!webrange.isNull()) | |
| 923 webLocalFrame->selectRange(webrange); | |
| 924 } | |
| 925 } | |
| 926 | |
| 667 void WebFrameWidgetImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseE vent& event) | 927 void WebFrameWidgetImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseE vent& event) |
| 668 { | 928 { |
| 669 // FIXME: WebWidget doesn't have the method below. | 929 // FIXME: WebWidget doesn't have the method below. |
| 670 // m_client->setMouseOverURL(WebURL()); | 930 // m_client->setMouseOverURL(WebURL()); |
| 671 PageWidgetEventHandler::handleMouseLeave(mainFrame, event); | 931 PageWidgetEventHandler::handleMouseLeave(mainFrame, event); |
| 672 } | 932 } |
| 673 | 933 |
| 674 void WebFrameWidgetImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEv ent& event) | 934 void WebFrameWidgetImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEv ent& event) |
| 675 { | 935 { |
| 676 // Take capture on a mouse down on a plugin so we can send it mouse events. | 936 // Take capture on a mouse down on a plugin so we can send it mouse events. |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1117 } | 1377 } |
| 1118 | 1378 |
| 1119 HitTestResult WebFrameWidgetImpl::hitTestResultForRootFramePos(const IntPoint& p osInRootFrame) | 1379 HitTestResult WebFrameWidgetImpl::hitTestResultForRootFramePos(const IntPoint& p osInRootFrame) |
| 1120 { | 1380 { |
| 1121 IntPoint docPoint(m_localRoot->frame()->view()->rootFrameToContents(posInRoo tFrame)); | 1381 IntPoint docPoint(m_localRoot->frame()->view()->rootFrameToContents(posInRoo tFrame)); |
| 1122 HitTestResult result = m_localRoot->frame()->eventHandler().hitTestResultAtP oint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active); | 1382 HitTestResult result = m_localRoot->frame()->eventHandler().hitTestResultAtP oint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active); |
| 1123 result.setToShadowHostIfInUserAgentShadowRoot(); | 1383 result.setToShadowHostIfInUserAgentShadowRoot(); |
| 1124 return result; | 1384 return result; |
| 1125 } | 1385 } |
| 1126 | 1386 |
| 1387 LocalFrame* WebFrameWidgetImpl::focusedLocalFrameInWidget() const | |
| 1388 { | |
| 1389 LocalFrame* frame = page()->focusController().focusedFrame(); | |
| 1390 return (frame && frame->localFrameRoot() == m_localRoot->frame()) ? frame : nullptr; | |
| 1391 } | |
| 1392 | |
| 1393 WebPlugin* WebFrameWidgetImpl::focusedPluginIfInputMethodSupported(LocalFrame* f rame) const | |
| 1394 { | |
| 1395 WebPluginContainerImpl* container = WebLocalFrameImpl::currentPluginContaine r(frame); | |
| 1396 if (container && container->supportsInputMethod()) | |
| 1397 return container->plugin(); | |
| 1398 return nullptr; | |
| 1399 } | |
| 1400 | |
| 1401 WebString WebFrameWidgetImpl::inputModeOfFocusedElement() const | |
| 1402 { | |
| 1403 if (!RuntimeEnabledFeatures::inputModeAttributeEnabled()) | |
| 1404 return WebString(); | |
| 1405 | |
| 1406 Element* element = focusedElement(); | |
| 1407 if (!element) | |
| 1408 return WebString(); | |
| 1409 | |
| 1410 if (isHTMLInputElement(*element)) { | |
| 1411 const HTMLInputElement& input = toHTMLInputElement(*element); | |
| 1412 if (input.supportsInputModeAttribute()) | |
| 1413 return input.fastGetAttribute(HTMLNames::inputmodeAttr).lower(); | |
| 1414 return WebString(); | |
| 1415 } | |
| 1416 if (isHTMLTextAreaElement(*element)) { | |
| 1417 const HTMLTextAreaElement& textarea = toHTMLTextAreaElement(*element); | |
| 1418 return textarea.fastGetAttribute(HTMLNames::inputmodeAttr).lower(); | |
| 1419 } | |
| 1420 | |
| 1421 return WebString(); | |
| 1422 } | |
| 1423 | |
| 1424 int WebFrameWidgetImpl::textInputFlags() const | |
| 1425 { | |
| 1426 Element* element = focusedElement(); | |
| 1427 if (!element) | |
| 1428 return WebTextInputFlagNone; | |
| 1429 | |
| 1430 DEFINE_STATIC_LOCAL(AtomicString, autocompleteString, ("autocomplete")); | |
| 1431 DEFINE_STATIC_LOCAL(AtomicString, autocorrectString, ("autocorrect")); | |
| 1432 int flags = 0; | |
| 1433 | |
| 1434 const AtomicString& autocomplete = element->getAttribute(autocompleteString) ; | |
| 1435 if (autocomplete == "on") | |
| 1436 flags |= WebTextInputFlagAutocompleteOn; | |
| 1437 else if (autocomplete == "off") | |
| 1438 flags |= WebTextInputFlagAutocompleteOff; | |
| 1439 | |
| 1440 const AtomicString& autocorrect = element->getAttribute(autocorrectString); | |
| 1441 if (autocorrect == "on") | |
| 1442 flags |= WebTextInputFlagAutocorrectOn; | |
| 1443 else if (autocorrect == "off") | |
| 1444 flags |= WebTextInputFlagAutocorrectOff; | |
| 1445 | |
| 1446 SpellcheckAttributeState spellcheck = element->spellcheckAttributeState(); | |
| 1447 if (spellcheck == SpellcheckAttributeTrue) | |
| 1448 flags |= WebTextInputFlagSpellcheckOn; | |
| 1449 else if (spellcheck == SpellcheckAttributeFalse) | |
| 1450 flags |= WebTextInputFlagSpellcheckOff; | |
| 1451 | |
| 1452 if (isHTMLTextFormControlElement(element)) { | |
| 1453 HTMLTextFormControlElement* formElement = static_cast<HTMLTextFormContro lElement*>(element); | |
| 1454 if (formElement->supportsAutocapitalize()) { | |
| 1455 DEFINE_STATIC_LOCAL(const AtomicString, none, ("none")); | |
| 1456 DEFINE_STATIC_LOCAL(const AtomicString, characters, ("characters")); | |
| 1457 DEFINE_STATIC_LOCAL(const AtomicString, words, ("words")); | |
| 1458 DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences")); | |
| 1459 | |
| 1460 const AtomicString& autocapitalize = formElement->autocapitalize(); | |
| 1461 if (autocapitalize == none) | |
| 1462 flags |= WebTextInputFlagAutocapitalizeNone; | |
| 1463 else if (autocapitalize == characters) | |
| 1464 flags |= WebTextInputFlagAutocapitalizeCharacters; | |
| 1465 else if (autocapitalize == words) | |
| 1466 flags |= WebTextInputFlagAutocapitalizeWords; | |
| 1467 else if (autocapitalize == sentences) | |
| 1468 flags |= WebTextInputFlagAutocapitalizeSentences; | |
| 1469 else | |
| 1470 NOTREACHED(); | |
| 1471 } | |
| 1472 } | |
| 1473 | |
| 1474 return flags; | |
| 1475 } | |
| 1476 | |
| 1127 } // namespace blink | 1477 } // namespace blink |
| OLD | NEW |