| 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 LocalFrame* focused = focusedLocalFrameAvailableForIme(); |
| 474 return false; | 499 if (!focused) |
| 500 return false; |
| 501 |
| 502 if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused)) |
| 503 return plugin->setComposition(text, underlines, selectionStart, selectio
nEnd); |
| 504 |
| 505 // The input focus has been moved to another WebWidget object. |
| 506 // We should use this |editor| object only to complete the ongoing |
| 507 // composition. |
| 508 InputMethodController& inputMethodController = focused->inputMethodControlle
r(); |
| 509 if (!focused->editor().canEdit() && !inputMethodController.hasComposition()) |
| 510 return false; |
| 511 |
| 512 // We should verify the parent node of this IME composition node are |
| 513 // editable because JavaScript may delete a parent node of the composition |
| 514 // node. In this case, WebKit crashes while deleting texts from the parent |
| 515 // node, which doesn't exist any longer. |
| 516 const EphemeralRange range = inputMethodController.compositionEphemeralRange
(); |
| 517 if (range.isNotNull()) { |
| 518 Node* node = range.startPosition().computeContainerNode(); |
| 519 if (!node || !node->isContentEditable()) |
| 520 return false; |
| 521 } |
| 522 |
| 523 // A keypress event is canceled. If an ongoing composition exists, then the |
| 524 // keydown event should have arisen from a handled key (e.g., backspace). |
| 525 // In this case we ignore the cancellation and continue; otherwise (no |
| 526 // ongoing composition) we exit and signal success only for attempts to |
| 527 // clear the composition. |
| 528 if (m_suppressNextKeypressEvent && !inputMethodController.hasComposition()) |
| 529 return text.isEmpty(); |
| 530 |
| 531 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); |
| 532 |
| 533 // When the range of composition underlines overlap with the range between |
| 534 // selectionStart and selectionEnd, WebKit somehow won't paint the selection |
| 535 // at all (see InlineTextBox::paint() function in InlineTextBox.cpp). |
| 536 // But the selection range actually takes effect. |
| 537 inputMethodController.setComposition(String(text), |
| 538 CompositionUnderlineVectorBuilder(underlines), |
| 539 selectionStart, selectionEnd); |
| 540 |
| 541 return text.isEmpty() || inputMethodController.hasComposition(); |
| 475 } | 542 } |
| 476 | 543 |
| 477 bool WebFrameWidgetImpl::confirmComposition() | 544 bool WebFrameWidgetImpl::confirmComposition() |
| 478 { | 545 { |
| 479 // FIXME: To be implemented. | 546 return confirmComposition(DoNotKeepSelection); |
| 480 return false; | |
| 481 } | 547 } |
| 482 | 548 |
| 483 bool WebFrameWidgetImpl::confirmComposition(ConfirmCompositionBehavior selection
Behavior) | 549 bool WebFrameWidgetImpl::confirmComposition(ConfirmCompositionBehavior selection
Behavior) |
| 484 { | 550 { |
| 485 // FIXME: To be implemented. | 551 return confirmComposition(WebString(), selectionBehavior); |
| 486 return false; | |
| 487 } | 552 } |
| 488 | 553 |
| 489 bool WebFrameWidgetImpl::confirmComposition(const WebString& text) | 554 bool WebFrameWidgetImpl::confirmComposition(const WebString& text) |
| 490 { | 555 { |
| 491 // FIXME: To be implemented. | 556 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); |
| 492 return false; | 557 return confirmComposition(text, DoNotKeepSelection); |
| 558 } |
| 559 |
| 560 bool WebFrameWidgetImpl::confirmComposition(const WebString& text, ConfirmCompos
itionBehavior selectionBehavior) const |
| 561 { |
| 562 LocalFrame* focused = focusedLocalFrameAvailableForIme(); |
| 563 if (!focused) |
| 564 return false; |
| 565 |
| 566 if (WebPlugin* plugin = focusedPluginIfInputMethodSupported(focused)) |
| 567 return plugin->confirmComposition(text, selectionBehavior); |
| 568 |
| 569 return focused->inputMethodController().confirmCompositionOrInsertText(text,
selectionBehavior == KeepSelection ? InputMethodController::KeepSelection : Inp
utMethodController::DoNotKeepSelection); |
| 493 } | 570 } |
| 494 | 571 |
| 495 bool WebFrameWidgetImpl::compositionRange(size_t* location, size_t* length) | 572 bool WebFrameWidgetImpl::compositionRange(size_t* location, size_t* length) |
| 496 { | 573 { |
| 497 // FIXME: To be implemented. | 574 LocalFrame* focused = focusedLocalFrameAvailableForIme(); |
| 498 return false; | 575 if (!focused) |
| 576 return false; |
| 577 |
| 578 const EphemeralRange range = focused->inputMethodController().compositionEph
emeralRange(); |
| 579 if (range.isNull()) |
| 580 return false; |
| 581 |
| 582 Element* editable = focused->selection().rootEditableElementOrDocumentElemen
t(); |
| 583 DCHECK(editable); |
| 584 PlainTextRange plainTextRange(PlainTextRange::create(*editable, range)); |
| 585 if (plainTextRange.isNull()) |
| 586 return false; |
| 587 *location = plainTextRange.start(); |
| 588 *length = plainTextRange.length(); |
| 589 return true; |
| 499 } | 590 } |
| 500 | 591 |
| 501 WebTextInputInfo WebFrameWidgetImpl::textInputInfo() | 592 WebTextInputInfo WebFrameWidgetImpl::textInputInfo() |
| 502 { | 593 { |
| 503 return view()->textInputInfo(); | 594 WebTextInputInfo info; |
| 595 |
| 596 LocalFrame* focused = focusedLocalFrameInWidget(); |
| 597 if (!focused) |
| 598 return info; |
| 599 |
| 600 FrameSelection& selection = focused->selection(); |
| 601 if (!selection.isAvailable()) { |
| 602 // plugins/mouse-capture-inside-shadow.html reaches here. |
| 603 return info; |
| 604 } |
| 605 Element* element = selection.selection().rootEditableElement(); |
| 606 if (!element) |
| 607 return info; |
| 608 |
| 609 info.inputMode = inputModeOfFocusedElement(); |
| 610 |
| 611 info.type = textInputType(); |
| 612 info.flags = textInputFlags(); |
| 613 if (info.type == WebTextInputTypeNone) |
| 614 return info; |
| 615 |
| 616 if (!focused->editor().canEdit()) |
| 617 return info; |
| 618 |
| 619 // Emits an object replacement character for each replaced element so that |
| 620 // it is exposed to IME and thus could be deleted by IME on android. |
| 621 info.value = plainText(EphemeralRange::rangeOfContents(*element), TextIterat
orEmitsObjectReplacementCharacter); |
| 622 |
| 623 if (info.value.isEmpty()) |
| 624 return info; |
| 625 |
| 626 EphemeralRange firstRange = firstEphemeralRangeOf(selection.selection()); |
| 627 if (firstRange.isNotNull()) { |
| 628 PlainTextRange plainTextRange(PlainTextRange::create(*element, firstRang
e)); |
| 629 if (plainTextRange.isNotNull()) { |
| 630 info.selectionStart = plainTextRange.start(); |
| 631 info.selectionEnd = plainTextRange.end(); |
| 632 } |
| 633 } |
| 634 |
| 635 EphemeralRange range = focused->inputMethodController().compositionEphemeral
Range(); |
| 636 if (range.isNotNull()) { |
| 637 PlainTextRange plainTextRange(PlainTextRange::create(*element, range)); |
| 638 if (plainTextRange.isNotNull()) { |
| 639 info.compositionStart = plainTextRange.start(); |
| 640 info.compositionEnd = plainTextRange.end(); |
| 641 } |
| 642 } |
| 643 |
| 644 return info; |
| 504 } | 645 } |
| 505 | 646 |
| 506 WebTextInputType WebFrameWidgetImpl::textInputType() | 647 WebTextInputType WebFrameWidgetImpl::textInputType() |
| 507 { | 648 { |
| 508 return view()->textInputType(); | 649 LocalFrame* focusedFrame = focusedLocalFrameInWidget(); |
| 650 if (!focusedFrame) |
| 651 return WebTextInputTypeNone; |
| 652 |
| 653 if (!focusedFrame->selection().isAvailable()) { |
| 654 // "mouse-capture-inside-shadow.html" reaches here. |
| 655 return WebTextInputTypeNone; |
| 656 } |
| 657 |
| 658 // It's important to preserve the equivalence of textInputInfo().type and te
xtInputType(), |
| 659 // so perform the same rootEditableElement() existence check here for consis
tency. |
| 660 if (!focusedFrame->selection().selection().rootEditableElement()) |
| 661 return WebTextInputTypeNone; |
| 662 |
| 663 Document* document = focusedFrame->document(); |
| 664 if (!document) |
| 665 return WebTextInputTypeNone; |
| 666 |
| 667 Element* element = document->focusedElement(); |
| 668 if (!element) |
| 669 return WebTextInputTypeNone; |
| 670 |
| 671 if (isHTMLInputElement(*element)) { |
| 672 HTMLInputElement& input = toHTMLInputElement(*element); |
| 673 const AtomicString& type = input.type(); |
| 674 |
| 675 if (input.isDisabledOrReadOnly()) |
| 676 return WebTextInputTypeNone; |
| 677 |
| 678 if (type == InputTypeNames::password) |
| 679 return WebTextInputTypePassword; |
| 680 if (type == InputTypeNames::search) |
| 681 return WebTextInputTypeSearch; |
| 682 if (type == InputTypeNames::email) |
| 683 return WebTextInputTypeEmail; |
| 684 if (type == InputTypeNames::number) |
| 685 return WebTextInputTypeNumber; |
| 686 if (type == InputTypeNames::tel) |
| 687 return WebTextInputTypeTelephone; |
| 688 if (type == InputTypeNames::url) |
| 689 return WebTextInputTypeURL; |
| 690 if (type == InputTypeNames::date) |
| 691 return WebTextInputTypeDate; |
| 692 if (type == InputTypeNames::datetime_local) |
| 693 return WebTextInputTypeDateTimeLocal; |
| 694 if (type == InputTypeNames::month) |
| 695 return WebTextInputTypeMonth; |
| 696 if (type == InputTypeNames::time) |
| 697 return WebTextInputTypeTime; |
| 698 if (type == InputTypeNames::week) |
| 699 return WebTextInputTypeWeek; |
| 700 if (type == InputTypeNames::text) |
| 701 return WebTextInputTypeText; |
| 702 |
| 703 return WebTextInputTypeNone; |
| 704 } |
| 705 |
| 706 if (isHTMLTextAreaElement(*element)) { |
| 707 if (toHTMLTextAreaElement(*element).isDisabledOrReadOnly()) |
| 708 return WebTextInputTypeNone; |
| 709 return WebTextInputTypeTextArea; |
| 710 } |
| 711 |
| 712 if (element->isHTMLElement()) { |
| 713 if (toHTMLElement(element)->isDateTimeFieldElement()) |
| 714 return WebTextInputTypeDateTimeField; |
| 715 } |
| 716 |
| 717 if (element->isContentEditable()) |
| 718 return WebTextInputTypeContentEditable; |
| 719 |
| 720 return WebTextInputTypeNone; |
| 509 } | 721 } |
| 510 | 722 |
| 511 WebColor WebFrameWidgetImpl::backgroundColor() const | 723 WebColor WebFrameWidgetImpl::backgroundColor() const |
| 512 { | 724 { |
| 513 if (isTransparent()) | 725 if (isTransparent()) |
| 514 return Color::transparent; | 726 return Color::transparent; |
| 515 if (!m_localRoot->frameView()) | 727 if (!m_localRoot->frameView()) |
| 516 return m_baseBackgroundColor; | 728 return m_baseBackgroundColor; |
| 517 FrameView* view = m_localRoot->frameView(); | 729 FrameView* view = m_localRoot->frameView(); |
| 518 return view->documentBackgroundColor().rgb(); | 730 return view->documentBackgroundColor().rgb(); |
| 519 } | 731 } |
| 520 | 732 |
| 521 bool WebFrameWidgetImpl::selectionBounds(WebRect& anchor, WebRect& focus) const | 733 bool WebFrameWidgetImpl::selectionBounds(WebRect& anchor, WebRect& focus) const |
| 522 { | 734 { |
| 523 const Frame* frame = focusedCoreFrame(); | 735 const LocalFrame* localFrame = focusedLocalFrameInWidget(); |
| 524 if (!frame || !frame->isLocalFrame()) | 736 if (!localFrame) |
| 525 return false; | 737 return false; |
| 526 | 738 |
| 527 const LocalFrame* localFrame = toLocalFrame(frame); | |
| 528 if (!localFrame) | |
| 529 return false; | |
| 530 FrameSelection& selection = localFrame->selection(); | 739 FrameSelection& selection = localFrame->selection(); |
| 531 | 740 |
| 532 if (selection.isCaret()) { | 741 if (selection.isCaret()) { |
| 533 anchor = focus = selection.absoluteCaretBounds(); | 742 anchor = focus = selection.absoluteCaretBounds(); |
| 534 } else { | 743 } else { |
| 535 const EphemeralRange selectedRange = selection.selection().toNormalizedE
phemeralRange(); | 744 const EphemeralRange selectedRange = selection.selection().toNormalizedE
phemeralRange(); |
| 536 if (selectedRange.isNull()) | 745 if (selectedRange.isNull()) |
| 537 return false; | 746 return false; |
| 538 anchor = localFrame->editor().firstRectForRange(EphemeralRange(selectedR
ange.startPosition())); | 747 anchor = localFrame->editor().firstRectForRange(EphemeralRange(selectedR
ange.startPosition())); |
| 539 focus = localFrame->editor().firstRectForRange(EphemeralRange(selectedRa
nge.endPosition())); | 748 focus = localFrame->editor().firstRectForRange(EphemeralRange(selectedRa
nge.endPosition())); |
| 540 } | 749 } |
| 541 | 750 |
| 542 // FIXME: This doesn't apply page scale. This should probably be contents to
viewport. crbug.com/459293. | 751 // FIXME: This doesn't apply page scale. This should probably be contents to
viewport. crbug.com/459293. |
| 543 IntRect scaledAnchor(localFrame->view()->contentsToRootFrame(anchor)); | 752 IntRect scaledAnchor(localFrame->view()->contentsToRootFrame(anchor)); |
| 544 IntRect scaledFocus(localFrame->view()->contentsToRootFrame(focus)); | 753 IntRect scaledFocus(localFrame->view()->contentsToRootFrame(focus)); |
| 545 | 754 |
| 546 anchor = scaledAnchor; | 755 anchor = scaledAnchor; |
| 547 focus = scaledFocus; | 756 focus = scaledFocus; |
| 548 | 757 |
| 549 if (!selection.selection().isBaseFirst()) | 758 if (!selection.selection().isBaseFirst()) |
| 550 std::swap(anchor, focus); | 759 std::swap(anchor, focus); |
| 551 return true; | 760 return true; |
| 552 } | 761 } |
| 553 | 762 |
| 554 bool WebFrameWidgetImpl::selectionTextDirection(WebTextDirection& start, WebText
Direction& end) const | 763 bool WebFrameWidgetImpl::selectionTextDirection(WebTextDirection& start, WebText
Direction& end) const |
| 555 { | 764 { |
| 556 if (!focusedCoreFrame()->isLocalFrame()) | 765 const LocalFrame* frame = focusedLocalFrameInWidget(); |
| 557 return false; | |
| 558 const LocalFrame* frame = toLocalFrame(focusedCoreFrame()); | |
| 559 if (!frame) | 766 if (!frame) |
| 560 return false; | 767 return false; |
| 768 |
| 561 FrameSelection& selection = frame->selection(); | 769 FrameSelection& selection = frame->selection(); |
| 562 if (selection.selection().toNormalizedEphemeralRange().isNull()) | 770 if (selection.selection().toNormalizedEphemeralRange().isNull()) |
| 563 return false; | 771 return false; |
| 564 start = toWebTextDirection(primaryDirectionOf(*selection.start().anchorNode(
))); | 772 start = toWebTextDirection(primaryDirectionOf(*selection.start().anchorNode(
))); |
| 565 end = toWebTextDirection(primaryDirectionOf(*selection.end().anchorNode())); | 773 end = toWebTextDirection(primaryDirectionOf(*selection.end().anchorNode())); |
| 566 return true; | 774 return true; |
| 567 } | 775 } |
| 568 | 776 |
| 569 bool WebFrameWidgetImpl::isSelectionAnchorFirst() const | 777 bool WebFrameWidgetImpl::isSelectionAnchorFirst() const |
| 570 { | 778 { |
| 571 if (!focusedCoreFrame()->isLocalFrame()) | 779 if (const LocalFrame* frame = focusedLocalFrameInWidget()) |
| 572 return false; | |
| 573 if (const LocalFrame* frame = toLocalFrame(focusedCoreFrame())) | |
| 574 return frame->selection().selection().isBaseFirst(); | 780 return frame->selection().selection().isBaseFirst(); |
| 575 return false; | 781 return false; |
| 576 } | 782 } |
| 577 | 783 |
| 578 bool WebFrameWidgetImpl::caretOrSelectionRange(size_t* location, size_t* length) | 784 bool WebFrameWidgetImpl::caretOrSelectionRange(size_t* location, size_t* length) |
| 579 { | 785 { |
| 580 if (!focusedCoreFrame()->isLocalFrame()) | 786 LocalFrame* focused = focusedLocalFrameInWidget(); |
| 581 return false; | |
| 582 const LocalFrame* focused = toLocalFrame(focusedCoreFrame()); | |
| 583 if (!focused) | 787 if (!focused) |
| 584 return false; | 788 return false; |
| 585 | 789 |
| 586 PlainTextRange selectionOffsets = focused->inputMethodController().getSelect
ionOffsets(); | 790 PlainTextRange selectionOffsets = focused->inputMethodController().getSelect
ionOffsets(); |
| 587 if (selectionOffsets.isNull()) | 791 if (selectionOffsets.isNull()) |
| 588 return false; | 792 return false; |
| 589 | 793 |
| 590 *location = selectionOffsets.start(); | 794 *location = selectionOffsets.start(); |
| 591 *length = selectionOffsets.length(); | 795 *length = selectionOffsets.length(); |
| 592 return true; | 796 return true; |
| 593 } | 797 } |
| 594 | 798 |
| 595 void WebFrameWidgetImpl::setTextDirection(WebTextDirection direction) | 799 void WebFrameWidgetImpl::setTextDirection(WebTextDirection direction) |
| 596 { | 800 { |
| 597 // The Editor::setBaseWritingDirection() function checks if we can change | 801 // The Editor::setBaseWritingDirection() function checks if we can change |
| 598 // the text direction of the selected node and updates its DOM "dir" | 802 // the text direction of the selected node and updates its DOM "dir" |
| 599 // attribute and its CSS "direction" property. | 803 // attribute and its CSS "direction" property. |
| 600 // So, we just call the function as Safari does. | 804 // So, we just call the function as Safari does. |
| 601 if (!focusedCoreFrame()->isLocalFrame()) | 805 const LocalFrame* focused = focusedLocalFrameInWidget(); |
| 602 return; | |
| 603 const LocalFrame* focused = toLocalFrame(focusedCoreFrame()); | |
| 604 if (!focused) | 806 if (!focused) |
| 605 return; | 807 return; |
| 606 | 808 |
| 607 Editor& editor = focused->editor(); | 809 Editor& editor = focused->editor(); |
| 608 if (!editor.canEdit()) | 810 if (!editor.canEdit()) |
| 609 return; | 811 return; |
| 610 | 812 |
| 611 switch (direction) { | 813 switch (direction) { |
| 612 case WebTextDirectionDefault: | 814 case WebTextDirectionDefault: |
| 613 editor.setBaseWritingDirection(NaturalWritingDirection); | 815 editor.setBaseWritingDirection(NaturalWritingDirection); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 void WebFrameWidgetImpl::didNotAcquirePointerLock() | 859 void WebFrameWidgetImpl::didNotAcquirePointerLock() |
| 658 { | 860 { |
| 659 page()->pointerLockController().didNotAcquirePointerLock(); | 861 page()->pointerLockController().didNotAcquirePointerLock(); |
| 660 } | 862 } |
| 661 | 863 |
| 662 void WebFrameWidgetImpl::didLosePointerLock() | 864 void WebFrameWidgetImpl::didLosePointerLock() |
| 663 { | 865 { |
| 664 page()->pointerLockController().didLosePointerLock(); | 866 page()->pointerLockController().didLosePointerLock(); |
| 665 } | 867 } |
| 666 | 868 |
| 869 bool WebFrameWidgetImpl::getCompositionCharacterBounds(WebVector<WebRect>& bound
s) |
| 870 { |
| 871 size_t offset = 0; |
| 872 size_t characterCount = 0; |
| 873 if (!compositionRange(&offset, &characterCount)) |
| 874 return false; |
| 875 |
| 876 if (characterCount == 0) |
| 877 return false; |
| 878 |
| 879 LocalFrame* frame = focusedLocalFrameInWidget(); |
| 880 if (!frame) |
| 881 return false; |
| 882 |
| 883 WebLocalFrameImpl* webLocalFrame = WebLocalFrameImpl::fromFrame(frame); |
| 884 WebVector<WebRect> result(characterCount); |
| 885 WebRect webrect; |
| 886 for (size_t i = 0; i < characterCount; ++i) { |
| 887 if (!webLocalFrame->firstRectForCharacterRange(offset + i, 1, webrect))
{ |
| 888 DLOG(ERROR) << "Could not retrieve character rectangle at " << i; |
| 889 return false; |
| 890 } |
| 891 result[i] = webrect; |
| 892 } |
| 893 bounds.swap(result); |
| 894 return true; |
| 895 } |
| 896 |
| 897 void WebFrameWidgetImpl::applyReplacementRange(int start, int length) |
| 898 { |
| 899 if (LocalFrame* frame = focusedLocalFrameInWidget()) { |
| 900 WebLocalFrameImpl* webLocalFrame = WebLocalFrameImpl::fromFrame(frame); |
| 901 WebRange webrange = WebRange::fromDocumentRange(webLocalFrame, start, le
ngth); |
| 902 if (!webrange.isNull()) |
| 903 webLocalFrame->selectRange(webrange); |
| 904 } |
| 905 } |
| 906 |
| 667 void WebFrameWidgetImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseE
vent& event) | 907 void WebFrameWidgetImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseE
vent& event) |
| 668 { | 908 { |
| 669 // FIXME: WebWidget doesn't have the method below. | 909 // FIXME: WebWidget doesn't have the method below. |
| 670 // m_client->setMouseOverURL(WebURL()); | 910 // m_client->setMouseOverURL(WebURL()); |
| 671 PageWidgetEventHandler::handleMouseLeave(mainFrame, event); | 911 PageWidgetEventHandler::handleMouseLeave(mainFrame, event); |
| 672 } | 912 } |
| 673 | 913 |
| 674 void WebFrameWidgetImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEv
ent& event) | 914 void WebFrameWidgetImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEv
ent& event) |
| 675 { | 915 { |
| 676 // Take capture on a mouse down on a plugin so we can send it mouse events. | 916 // 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 } | 1357 } |
| 1118 | 1358 |
| 1119 HitTestResult WebFrameWidgetImpl::hitTestResultForRootFramePos(const IntPoint& p
osInRootFrame) | 1359 HitTestResult WebFrameWidgetImpl::hitTestResultForRootFramePos(const IntPoint& p
osInRootFrame) |
| 1120 { | 1360 { |
| 1121 IntPoint docPoint(m_localRoot->frame()->view()->rootFrameToContents(posInRoo
tFrame)); | 1361 IntPoint docPoint(m_localRoot->frame()->view()->rootFrameToContents(posInRoo
tFrame)); |
| 1122 HitTestResult result = m_localRoot->frame()->eventHandler().hitTestResultAtP
oint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active); | 1362 HitTestResult result = m_localRoot->frame()->eventHandler().hitTestResultAtP
oint(docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active); |
| 1123 result.setToShadowHostIfInUserAgentShadowRoot(); | 1363 result.setToShadowHostIfInUserAgentShadowRoot(); |
| 1124 return result; | 1364 return result; |
| 1125 } | 1365 } |
| 1126 | 1366 |
| 1367 LocalFrame* WebFrameWidgetImpl::focusedLocalFrameInWidget() const |
| 1368 { |
| 1369 LocalFrame* frame = page()->focusController().focusedFrame(); |
| 1370 return (frame && frame->localFrameRoot() == m_localRoot->frame()) ? frame :
nullptr; |
| 1371 } |
| 1372 |
| 1373 WebPlugin* WebFrameWidgetImpl::focusedPluginIfInputMethodSupported(LocalFrame* f
rame) const |
| 1374 { |
| 1375 WebPluginContainerImpl* container = WebLocalFrameImpl::currentPluginContaine
r(frame); |
| 1376 if (container && container->supportsInputMethod()) |
| 1377 return container->plugin(); |
| 1378 return nullptr; |
| 1379 } |
| 1380 |
| 1381 WebString WebFrameWidgetImpl::inputModeOfFocusedElement() const |
| 1382 { |
| 1383 if (!RuntimeEnabledFeatures::inputModeAttributeEnabled()) |
| 1384 return WebString(); |
| 1385 |
| 1386 Element* element = focusedElement(); |
| 1387 if (!element) |
| 1388 return WebString(); |
| 1389 |
| 1390 if (isHTMLInputElement(*element)) { |
| 1391 const HTMLInputElement& input = toHTMLInputElement(*element); |
| 1392 if (input.supportsInputModeAttribute()) |
| 1393 return input.fastGetAttribute(HTMLNames::inputmodeAttr).lower(); |
| 1394 return WebString(); |
| 1395 } |
| 1396 if (isHTMLTextAreaElement(*element)) { |
| 1397 const HTMLTextAreaElement& textarea = toHTMLTextAreaElement(*element); |
| 1398 return textarea.fastGetAttribute(HTMLNames::inputmodeAttr).lower(); |
| 1399 } |
| 1400 |
| 1401 return WebString(); |
| 1402 } |
| 1403 |
| 1404 int WebFrameWidgetImpl::textInputFlags() const |
| 1405 { |
| 1406 Element* element = focusedElement(); |
| 1407 if (!element) |
| 1408 return WebTextInputFlagNone; |
| 1409 |
| 1410 DEFINE_STATIC_LOCAL(AtomicString, autocompleteString, ("autocomplete")); |
| 1411 DEFINE_STATIC_LOCAL(AtomicString, autocorrectString, ("autocorrect")); |
| 1412 int flags = 0; |
| 1413 |
| 1414 const AtomicString& autocomplete = element->getAttribute(autocompleteString)
; |
| 1415 if (autocomplete == "on") |
| 1416 flags |= WebTextInputFlagAutocompleteOn; |
| 1417 else if (autocomplete == "off") |
| 1418 flags |= WebTextInputFlagAutocompleteOff; |
| 1419 |
| 1420 const AtomicString& autocorrect = element->getAttribute(autocorrectString); |
| 1421 if (autocorrect == "on") |
| 1422 flags |= WebTextInputFlagAutocorrectOn; |
| 1423 else if (autocorrect == "off") |
| 1424 flags |= WebTextInputFlagAutocorrectOff; |
| 1425 |
| 1426 SpellcheckAttributeState spellcheck = element->spellcheckAttributeState(); |
| 1427 if (spellcheck == SpellcheckAttributeTrue) |
| 1428 flags |= WebTextInputFlagSpellcheckOn; |
| 1429 else if (spellcheck == SpellcheckAttributeFalse) |
| 1430 flags |= WebTextInputFlagSpellcheckOff; |
| 1431 |
| 1432 if (isHTMLTextFormControlElement(element)) { |
| 1433 HTMLTextFormControlElement* formElement = static_cast<HTMLTextFormContro
lElement*>(element); |
| 1434 if (formElement->supportsAutocapitalize()) { |
| 1435 DEFINE_STATIC_LOCAL(const AtomicString, none, ("none")); |
| 1436 DEFINE_STATIC_LOCAL(const AtomicString, characters, ("characters")); |
| 1437 DEFINE_STATIC_LOCAL(const AtomicString, words, ("words")); |
| 1438 DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences")); |
| 1439 |
| 1440 const AtomicString& autocapitalize = formElement->autocapitalize(); |
| 1441 if (autocapitalize == none) |
| 1442 flags |= WebTextInputFlagAutocapitalizeNone; |
| 1443 else if (autocapitalize == characters) |
| 1444 flags |= WebTextInputFlagAutocapitalizeCharacters; |
| 1445 else if (autocapitalize == words) |
| 1446 flags |= WebTextInputFlagAutocapitalizeWords; |
| 1447 else if (autocapitalize == sentences) |
| 1448 flags |= WebTextInputFlagAutocapitalizeSentences; |
| 1449 else |
| 1450 NOTREACHED(); |
| 1451 } |
| 1452 } |
| 1453 |
| 1454 return flags; |
| 1455 } |
| 1456 |
| 1457 LocalFrame* WebFrameWidgetImpl::focusedLocalFrameAvailableForIme() const |
| 1458 { |
| 1459 if (!m_imeAcceptEvents) |
| 1460 return nullptr; |
| 1461 return focusedLocalFrameInWidget(); |
| 1462 } |
| 1463 |
| 1127 } // namespace blink | 1464 } // namespace blink |
| OLD | NEW |