Diff
Modified: trunk/Source/WebCore/ChangeLog (242695 => 242696)
--- trunk/Source/WebCore/ChangeLog 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/ChangeLog 2019-03-11 03:32:50 UTC (rev 242696)
@@ -1,3 +1,40 @@
+2019-03-10 Tim Horton <[email protected]>
+
+ Add SPI to retrieve the set of text inputs in a given rect, and later focus one
+ https://bugs.webkit.org/show_bug.cgi?id=195499
+
+ Reviewed by Darin Adler.
+
+ New API tests: WebKit.RequestTextInputContext and WebKit.FocusTextInputContext
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/Document.cpp:
+ (WebCore::Document::identifierForElement):
+ (WebCore::Document::elementWithIdentifier):
+ (WebCore::Document::identifiedElementWasRemovedFromDocument):
+ * dom/Document.h:
+ Add a mechanism where Document will vend an ObjectIdentifier for a given
+ element, and can (if possible) retrieve that element later.
+
+ * dom/Element.cpp:
+ (WebCore::Element::removedFromAncestor):
+ If an Element has an identifier created for it, inform Document to remove
+ it from the identifier map when the element is detached.
+
+ (WebCore::Element::createElementIdentifier):
+ * dom/Element.h:
+ * dom/ElementIdentifier.h: Added.
+ * dom/ElementRareData.cpp:
+ * dom/ElementRareData.h:
+ (WebCore::ElementRareData::hasElementIdentifier const):
+ (WebCore::ElementRareData::setHasElementIdentifier):
+ (WebCore::ElementRareData::ElementRareData):
+ Store a bit indicating if the Element has had a identifier created for it,
+ so that we can avoid a hash lookup on every Element removal.
+
+ * dom/Node.h:
+ * html/HTMLTextFormControlElement.h:
+
2019-03-10 Zalan Bujtas <[email protected]>
[ContentChangeObserver] Fix failing test cases
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (242695 => 242696)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-03-11 03:32:50 UTC (rev 242696)
@@ -748,6 +748,7 @@
2D29ECC6192ECC8300984B78 /* DisplayRefreshMonitorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC2192ECC8300984B78 /* DisplayRefreshMonitorClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D29ECC8192ECC8300984B78 /* DisplayRefreshMonitorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D29ECCA192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC9192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h */; };
+ 2D2BEB312234A335005544CA /* ElementIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2BEB2F2234A334005544CA /* ElementIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D2E34AC21A4E192004598B5 /* EditableImageReference.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2E34A921A4E191004598B5 /* EditableImageReference.h */; };
2D3A0E3613A7D76100E85AF0 /* SVGParsingError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3A0E3513A7D76100E85AF0 /* SVGParsingError.h */; settings = {ATTRIBUTES = (Private, ); }; };
2D3EF4481917915C00034184 /* WebActionDisablingCALayerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3EF4441917915C00034184 /* WebActionDisablingCALayerDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -6697,6 +6698,7 @@
2D29ECC3192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayRefreshMonitorManager.cpp; sourceTree = "<group>"; };
2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorManager.h; sourceTree = "<group>"; };
2D29ECC9192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorIOS.h; sourceTree = "<group>"; };
+ 2D2BEB2F2234A334005544CA /* ElementIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIdentifier.h; sourceTree = "<group>"; };
2D2E34A921A4E191004598B5 /* EditableImageReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditableImageReference.h; sourceTree = "<group>"; };
2D2E34AB21A4E192004598B5 /* EditableImageReference.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditableImageReference.cpp; sourceTree = "<group>"; };
2D2FC0541460CD6F00263633 /* CrossfadeGeneratedImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrossfadeGeneratedImage.cpp; sourceTree = "<group>"; };
@@ -27592,6 +27594,7 @@
B5B7A16F17C1080600E4AA0A /* ElementData.cpp */,
B5B7A16E17C1048000E4AA0A /* ElementData.h */,
ADE11F4A18D8311B0078983B /* ElementDescendantIterator.h */,
+ 2D2BEB2F2234A334005544CA /* ElementIdentifier.h */,
E4AE7C1517D1BB950009FB31 /* ElementIterator.h */,
E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */,
4FAB48641643A66D00F70C07 /* ElementRareData.cpp */,
@@ -29196,6 +29199,7 @@
E46A2B1E17CA76B1000DBCD8 /* ElementChildIterator.h in Headers */,
B5B7A17117C10AC000E4AA0A /* ElementData.h in Headers */,
93D437A11D57B3F400AB85EA /* ElementDescendantIterator.h in Headers */,
+ 2D2BEB312234A335005544CA /* ElementIdentifier.h in Headers */,
E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */,
E401C27517CE53EC00C41A35 /* ElementIteratorAssertions.h in Headers */,
63F5D4F70E8C4B7100C0BD04 /* ElementRareData.h in Headers */,
Modified: trunk/Source/WebCore/dom/Document.cpp (242695 => 242696)
--- trunk/Source/WebCore/dom/Document.cpp 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/dom/Document.cpp 2019-03-11 03:32:50 UTC (rev 242696)
@@ -8612,6 +8612,30 @@
detachFromFrame();
}
+ElementIdentifier Document::identifierForElement(Element& element)
+{
+ ASSERT(&element.document() == this);
+ auto result = m_identifiedElementsMap.ensure(&element, [&] {
+ return element.createElementIdentifier();
+ });
+ return result.iterator->value;
+}
+
+Element* Document::searchForElementByIdentifier(const ElementIdentifier& identifier)
+{
+ for (auto it = m_identifiedElementsMap.begin(); it != m_identifiedElementsMap.end(); ++it) {
+ if (it->value == identifier)
+ return it->key;
+ }
+
+ return nullptr;
+}
+
+void Document::identifiedElementWasRemovedFromDocument(Element& element)
+{
+ m_identifiedElementsMap.remove(&element);
+}
+
#if ENABLE(DEVICE_ORIENTATION)
DeviceOrientationAndMotionAccessController& Document::deviceOrientationAndMotionAccessController()
Modified: trunk/Source/WebCore/dom/Document.h (242695 => 242696)
--- trunk/Source/WebCore/dom/Document.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/dom/Document.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -34,6 +34,7 @@
#include "DocumentEventQueue.h"
#include "DocumentIdentifier.h"
#include "DocumentTiming.h"
+#include "ElementIdentifier.h"
#include "FocusDirection.h"
#include "FontSelectorClient.h"
#include "FrameDestructionObserver.h"
@@ -388,6 +389,10 @@
WEBCORE_EXPORT static DocumentsMap::ValuesIteratorRange allDocuments();
WEBCORE_EXPORT static DocumentsMap& allDocumentsMap();
+ WEBCORE_EXPORT ElementIdentifier identifierForElement(Element&);
+ WEBCORE_EXPORT Element* searchForElementByIdentifier(const ElementIdentifier&);
+ void identifiedElementWasRemovedFromDocument(Element&);
+
MediaQueryMatcher& mediaQueryMatcher();
using ContainerNode::ref;
@@ -2083,6 +2088,8 @@
#if PLATFORM(IOS_FAMILY)
std::unique_ptr<ContentChangeObserver> m_contentChangeObserver;
#endif
+
+ HashMap<Element*, ElementIdentifier> m_identifiedElementsMap;
};
Element* eventTargetElementForDocument(Document*);
Modified: trunk/Source/WebCore/dom/Element.cpp (242695 => 242696)
--- trunk/Source/WebCore/dom/Element.cpp 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/dom/Element.cpp 2019-03-11 03:32:50 UTC (rev 242696)
@@ -2049,6 +2049,11 @@
if (frame && frame->page())
frame->page()->removeLatchingStateForTarget(*this);
#endif
+
+ if (hasRareData() && elementRareData()->hasElementIdentifier()) {
+ document().identifiedElementWasRemovedFromDocument(*this);
+ elementRareData()->setHasElementIdentifier(false);
+ }
}
ShadowRoot* Element::shadowRoot() const
@@ -4157,6 +4162,15 @@
return animations;
}
+ElementIdentifier Element::createElementIdentifier()
+{
+ auto& rareData = ensureElementRareData();
+ ASSERT(!rareData.hasElementIdentifier());
+
+ rareData.setHasElementIdentifier(true);
+ return ElementIdentifier::generate();
+}
+
#if ENABLE(CSS_TYPED_OM)
StylePropertyMap* Element::attributeStyleMap()
{
Modified: trunk/Source/WebCore/dom/Element.h (242695 => 242696)
--- trunk/Source/WebCore/dom/Element.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/dom/Element.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -592,6 +592,8 @@
ExceptionOr<Ref<WebAnimation>> animate(JSC::ExecState&, JSC::Strong<JSC::JSObject>&&, Optional<Variant<double, KeyframeAnimationOptions>>&&);
Vector<RefPtr<WebAnimation>> getAnimations();
+ ElementIdentifier createElementIdentifier();
+
#if ENABLE(POINTER_EVENTS)
OptionSet<TouchAction> computedTouchActions() const;
#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
Added: trunk/Source/WebCore/dom/ElementIdentifier.h (0 => 242696)
--- trunk/Source/WebCore/dom/ElementIdentifier.h (rev 0)
+++ trunk/Source/WebCore/dom/ElementIdentifier.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/ObjectIdentifier.h>
+
+namespace WebCore {
+
+enum ElementIdentifierType { };
+using ElementIdentifier = ObjectIdentifier<ElementIdentifierType>;
+
+}
Modified: trunk/Source/WebCore/dom/ElementRareData.cpp (242695 => 242696)
--- trunk/Source/WebCore/dom/ElementRareData.cpp 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/dom/ElementRareData.cpp 2019-03-11 03:32:50 UTC (rev 242696)
@@ -37,9 +37,9 @@
int tabIndex;
unsigned short childIndex;
#if ENABLE(FULLSCREEN_API)
+ unsigned bitfields : 12;
+#else
unsigned bitfields : 11;
-#else
- unsigned bitfields : 10;
#endif
LayoutSize sizeForResizing;
IntPoint savedLayerScrollPosition;
Modified: trunk/Source/WebCore/dom/ElementRareData.h (242695 => 242696)
--- trunk/Source/WebCore/dom/ElementRareData.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/dom/ElementRareData.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -123,6 +123,9 @@
bool hasCSSAnimation() const { return m_hasCSSAnimation; }
void setHasCSSAnimation(bool value) { m_hasCSSAnimation = value; }
+ bool hasElementIdentifier() const { return m_hasElementIdentifier; }
+ void setHasElementIdentifier(bool value) { m_hasElementIdentifier = value; }
+
#if ENABLE(INTERSECTION_OBSERVER)
IntersectionObserverData* intersectionObserverData() { return m_intersectionObserverData.get(); }
void setIntersectionObserverData(std::unique_ptr<IntersectionObserverData>&& data) { m_intersectionObserverData = WTFMove(data); }
@@ -180,6 +183,7 @@
#endif
unsigned m_hasPendingResources : 1;
unsigned m_hasCSSAnimation : 1;
+ unsigned m_hasElementIdentifier : 1;
unsigned m_childrenAffectedByHover : 1;
unsigned m_childrenAffectedByDrag : 1;
// Bits for dynamic child matching.
@@ -228,6 +232,7 @@
#endif
, m_hasPendingResources(false)
, m_hasCSSAnimation(false)
+ , m_hasElementIdentifier(false)
, m_childrenAffectedByHover(false)
, m_childrenAffectedByDrag(false)
, m_childrenAffectedByLastChildRules(false)
Modified: trunk/Source/WebCore/dom/Node.h (242695 => 242696)
--- trunk/Source/WebCore/dom/Node.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/dom/Node.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -283,7 +283,7 @@
virtual bool canContainRangeEndPoint() const { return false; }
- bool isRootEditableElement() const;
+ WEBCORE_EXPORT bool isRootEditableElement() const;
WEBCORE_EXPORT Element* rootEditableElement() const;
// Called by the parser when this element's close tag is reached,
Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.h (242695 => 242696)
--- trunk/Source/WebCore/html/HTMLTextFormControlElement.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -98,6 +98,8 @@
WEBCORE_EXPORT void showPlaceholderIfNecessary();
#endif
+ WEBCORE_EXPORT virtual bool isInnerTextElementEditable() const;
+
protected:
HTMLTextFormControlElement(const QualifiedName&, Document&, HTMLFormElement*);
bool isPlaceholderEmpty() const;
@@ -107,7 +109,7 @@
void disabledStateChanged() override;
void readOnlyStateChanged() override;
- virtual bool isInnerTextElementEditable() const;
+
void updateInnerTextElementEditability();
void cacheSelection(int start, int end, TextFieldSelectionDirection direction)
Modified: trunk/Source/WebKit/ChangeLog (242695 => 242696)
--- trunk/Source/WebKit/ChangeLog 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/ChangeLog 2019-03-11 03:32:50 UTC (rev 242696)
@@ -1,5 +1,64 @@
2019-03-10 Tim Horton <[email protected]>
+ Add SPI to retrieve the set of text inputs in a given rect, and later focus one
+ https://bugs.webkit.org/show_bug.cgi?id=195499
+
+ Reviewed by Darin Adler.
+
+ * Scripts/webkit/messages.py:
+ * Shared/TextInputContext.cpp: Added.
+ (IPC::ArgumentCoder<WebKit::TextInputContext>::encode):
+ (IPC::ArgumentCoder<WebKit::TextInputContext>::decode):
+ * Shared/TextInputContext.h: Added.
+ (WebKit::TextInputContext::operator== const):
+ Add TextInputContext, which represents a minimal set of information
+ about a text field.
+
+ * Sources.txt:
+ * SourcesCocoa.txt:
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView _requestTextInputContextsInRect:completionHandler:]):
+ (-[WKWebView _focusTextInputContext:completionHandler:]):
+ * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+ Add SPI that allows clients to asynchronously request text input
+ contexts for a given rect, and later focus a given context.
+
+ * UIProcess/API/Cocoa/_WKTextInputContext.h: Added.
+ * UIProcess/API/Cocoa/_WKTextInputContext.mm: Added.
+ (-[_WKTextInputContext _initWithTextInputContext:]):
+ (-[_WKTextInputContext boundingRect]):
+ (-[_WKTextInputContext _textInputContext]):
+ (-[_WKTextInputContext isEqual:]):
+ (-[_WKTextInputContext hash]):
+ (-[_WKTextInputContext copyWithZone:]):
+ * UIProcess/API/Cocoa/_WKTextInputContextInternal.h: Added.
+ Add an SPI object that exposes a read-only window on a TextInputContext to clients.
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::textInputContextsInRect):
+ (WebKit::WebPageProxy::focusTextInputContext):
+ * UIProcess/WebPageProxy.h:
+ Plumbing from WKWebView<->WebPage.
+
+ * WebKit.xcodeproj/project.pbxproj:
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::elementRectInWindowCoordinates):
+ (WebKit::isEditableTextInputElement):
+ (WebKit::WebPage::textInputContextsInRect):
+ Search the DOM for text input contexts: <input type='text'> (or other
+ form fields that fall back on text field behavior), <textarea>, and
+ contenteditable roots. Store the WebPage, Document, and Element identifiers
+ so that we can find the element again later.
+
+ (WebKit::WebPage::focusTextInputContext):
+ Find the element for a given (web page, document, element) triple and focus it,
+ if it's still available.
+
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/WebPage.messages.in:
+
+2019-03-10 Tim Horton <[email protected]>
+
iOS: Using ⌥ to scroll horizontally is no different than arrow key
https://bugs.webkit.org/show_bug.cgi?id=195268
<rdar://problem/48326682>
Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (242695 => 242696)
--- trunk/Source/WebKit/Scripts/webkit/messages.py 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py 2019-03-11 03:32:50 UTC (rev 242696)
@@ -453,6 +453,7 @@
'WebKit::WebMouseEvent': ['"WebEvent.h"'],
'WebKit::WebTouchEvent': ['"WebEvent.h"'],
'WebKit::WebWheelEvent': ['"WebEvent.h"'],
+ 'struct WebKit::TextInputContext': ['"TextInputContext.h"'],
'struct WebKit::WebUserScriptData': ['"WebUserContentControllerDataTypes.h"'],
'struct WebKit::WebUserStyleSheetData': ['"WebUserContentControllerDataTypes.h"'],
'struct WebKit::WebScriptMessageHandlerData': ['"WebUserContentControllerDataTypes.h"'],
Added: trunk/Source/WebKit/Shared/TextInputContext.cpp (0 => 242696)
--- trunk/Source/WebKit/Shared/TextInputContext.cpp (rev 0)
+++ trunk/Source/WebKit/Shared/TextInputContext.cpp 2019-03-11 03:32:50 UTC (rev 242696)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TextInputContext.h"
+
+#include "WebCoreArgumentCoders.h"
+#include <WebCore/Element.h>
+
+namespace WebKit {
+
+TextInputContext::~TextInputContext() = default;
+
+}
+
+namespace IPC {
+
+void ArgumentCoder<WebKit::TextInputContext>::encode(Encoder& encoder, const WebKit::TextInputContext& context)
+{
+ encoder << context.boundingRect;
+ encoder << context.webPageIdentifier;
+ encoder << context.documentIdentifier;
+ encoder << context.elementIdentifier;
+}
+
+Optional<WebKit::TextInputContext> ArgumentCoder<WebKit::TextInputContext>::decode(Decoder& decoder)
+{
+ WebKit::TextInputContext context;
+ if (!decoder.decode(context.boundingRect))
+ return WTF::nullopt;
+ if (!decoder.decode(context.webPageIdentifier))
+ return WTF::nullopt;
+ auto documentIdentifier = WebCore::DocumentIdentifier::decode(decoder);
+ if (!documentIdentifier)
+ return WTF::nullopt;
+ context.documentIdentifier = *documentIdentifier;
+ auto elementIdentifier = WebCore::ElementIdentifier::decode(decoder);
+ if (!elementIdentifier)
+ return WTF::nullopt;
+ context.elementIdentifier = *elementIdentifier;
+
+ return context;
+}
+
+}
Added: trunk/Source/WebKit/Shared/TextInputContext.h (0 => 242696)
--- trunk/Source/WebKit/Shared/TextInputContext.h (rev 0)
+++ trunk/Source/WebKit/Shared/TextInputContext.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ArgumentCoders.h"
+#include <WebCore/DocumentIdentifier.h>
+#include <WebCore/ElementIdentifier.h>
+#include <WebCore/FloatRect.h>
+
+namespace WebKit {
+
+struct TextInputContext {
+ WebCore::FloatRect boundingRect;
+
+ uint64_t webPageIdentifier;
+ WebCore::DocumentIdentifier documentIdentifier;
+ WebCore::ElementIdentifier elementIdentifier;
+
+ ~TextInputContext();
+};
+
+inline bool operator==(const TextInputContext& a, const TextInputContext& b)
+{
+ return a.boundingRect == b.boundingRect
+ && a.webPageIdentifier == b.webPageIdentifier
+ && a.documentIdentifier == b.documentIdentifier
+ && a.elementIdentifier == b.elementIdentifier;
+}
+
+}
+
+namespace IPC {
+template<> struct ArgumentCoder<WebKit::TextInputContext> {
+ static void encode(Encoder&, const WebKit::TextInputContext&);
+ static Optional<WebKit::TextInputContext> decode(Decoder&);
+};
+}
Modified: trunk/Source/WebKit/Sources.txt (242695 => 242696)
--- trunk/Source/WebKit/Sources.txt 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/Sources.txt 2019-03-11 03:32:50 UTC (rev 242696)
@@ -128,6 +128,7 @@
Shared/SharedStringHashTableReadOnly.cpp
Shared/SharedStringHashTable.cpp
Shared/StatisticsData.cpp
+Shared/TextInputContext.cpp
Shared/TouchBarMenuData.cpp
Shared/TouchBarMenuItemData.cpp
Shared/URLSchemeTaskParameters.cpp
Modified: trunk/Source/WebKit/SourcesCocoa.txt (242695 => 242696)
--- trunk/Source/WebKit/SourcesCocoa.txt 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/SourcesCocoa.txt 2019-03-11 03:32:50 UTC (rev 242696)
@@ -254,6 +254,7 @@
UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm
UIProcess/API/Cocoa/_WKSessionState.mm
+UIProcess/API/Cocoa/_WKTextInputContext.mm
UIProcess/API/Cocoa/_WKThumbnailView.mm
UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm
UIProcess/API/Cocoa/_WKUserContentFilter.mm
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (242695 => 242696)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm 2019-03-11 03:32:50 UTC (rev 242696)
@@ -49,6 +49,7 @@
#import "RemoteObjectRegistry.h"
#import "RemoteObjectRegistryMessages.h"
#import "SafeBrowsingWarning.h"
+#import "TextInputContext.h"
#import "UIDelegate.h"
#import "UserMediaProcessManager.h"
#import "VersionChecks.h"
@@ -96,6 +97,7 @@
#import "_WKInspectorInternal.h"
#import "_WKRemoteObjectRegistryInternal.h"
#import "_WKSessionStateInternal.h"
+#import "_WKTextInputContextInternal.h"
#import "_WKVisitedLinkStoreInternal.h"
#import "_WKWebsitePoliciesInternal.h"
#import <WebCore/GraphicsContextCG.h>
@@ -4826,6 +4828,31 @@
}
}
+- (void)_requestTextInputContextsInRect:(CGRect)rect completionHandler:(void(^)(NSArray<_WKTextInputContext *> *))completionHandler
+{
+ _page->textInputContextsInRect(rect, [capturedCompletionHandler = makeBlockPtr(completionHandler)] (const Vector<WebKit::TextInputContext>& contexts) {
+ RetainPtr<NSMutableArray> elements = adoptNS([[NSMutableArray alloc] initWithCapacity:contexts.size()]);
+
+ for (const auto& context : contexts)
+ [elements addObject:adoptNS([[_WKTextInputContext alloc] _initWithTextInputContext:context]).get()];
+
+ capturedCompletionHandler(elements.get());
+ });
+}
+
+- (void)_focusTextInputContext:(_WKTextInputContext *)textInputContext completionHandler:(void(^)(BOOL))completionHandler
+{
+ auto webContext = [textInputContext _textInputContext];
+ if (webContext.webPageIdentifier != _page->pageID())
+ [NSException raise:NSInvalidArgumentException format:@"The provided _WKTextInputContext was not created by this WKWebView."];
+
+ [self becomeFirstResponder];
+
+ _page->focusTextInputContext(webContext, [capturedCompletionHandler = makeBlockPtr(completionHandler)](bool success) {
+ capturedCompletionHandler(success);
+ });
+}
+
#if PLATFORM(MAC)
- (void)_setShouldSuppressFirstResponderChanges:(BOOL)shouldSuppress
{
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (242695 => 242696)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -111,6 +111,7 @@
@class _WKRemoteObjectRegistry;
@class _WKSafeBrowsingWarning;
@class _WKSessionState;
+@class _WKTextInputContext;
@class _WKThumbnailView;
@class _WKWebsitePolicies;
@class _WKWebViewPrintFormatter;
@@ -418,6 +419,10 @@
- (void)_stopAllMediaPlayback;
- (void)_suspendAllMediaPlayback;
- (void)_resumeAllMediaPlayback;
+
+- (void)_requestTextInputContextsInRect:(CGRect)rect completionHandler:(void(^)(NSArray<_WKTextInputContext *> *))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (void)_focusTextInputContext:(_WKTextInputContext *)textInputElement completionHandler:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
@end
#if TARGET_OS_IPHONE
Added: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContext.h (0 => 242696)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContext.h (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContext.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WKFoundation.h>
+
+WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
+@interface _WKTextInputContext : NSObject <NSCopying>
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@property (nonatomic, readonly) CGRect boundingRect;
+
+@end
Added: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContext.mm (0 => 242696)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContext.mm (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContext.mm 2019-03-11 03:32:50 UTC (rev 242696)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "_WKTextInputContext.h"
+
+#import "TextInputContext.h"
+#import "_WKTextInputContextInternal.h"
+
+@implementation _WKTextInputContext {
+ WebKit::TextInputContext _textInputContext;
+}
+
+- (instancetype)init
+{
+ return nil;
+}
+
+- (instancetype)_initWithTextInputContext:(const WebKit::TextInputContext&)context
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _textInputContext = context;
+
+ return self;
+}
+
+- (CGRect)boundingRect
+{
+ return _textInputContext.boundingRect;
+}
+
+- (const WebKit::TextInputContext&)_textInputContext
+{
+ return _textInputContext;
+}
+
+- (BOOL)isEqual:(id)otherObject
+{
+ if (self == otherObject)
+ return YES;
+
+ if (![otherObject isKindOfClass:[_WKTextInputContext class]])
+ return NO;
+
+ _WKTextInputContext *other = (_WKTextInputContext *)otherObject;
+
+ return _textInputContext == other->_textInputContext;
+}
+
+- (NSUInteger)hash
+{
+ return _textInputContext.elementIdentifier.toUInt64();
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ return [self retain];
+}
+
+@end
Added: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContextInternal.h (0 => 242696)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContextInternal.h (rev 0)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextInputContextInternal.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "_WKTextInputContext.h"
+
+namespace WebKit {
+struct TextInputContext;
+}
+
+@interface _WKTextInputContext ()
+
+- (instancetype)_initWithTextInputContext:(const WebKit::TextInputContext&)context;
+
+- (const WebKit::TextInputContext&)_textInputContext;
+
+@end
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (242695 => 242696)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2019-03-11 03:32:50 UTC (rev 242696)
@@ -83,6 +83,7 @@
#include "SharedBufferDataReference.h"
#include "TextChecker.h"
#include "TextCheckerState.h"
+#include "TextInputContext.h"
#include "UIMessagePortChannelProvider.h"
#include "URLSchemeTaskParameters.h"
#include "UndoOrRedo.h"
@@ -8817,6 +8818,26 @@
}
}
+void WebPageProxy::textInputContextsInRect(WebCore::FloatRect rect, CompletionHandler<void(const Vector<WebKit::TextInputContext>&)>&& completionHandler)
+{
+ if (!isValid()) {
+ completionHandler({ });
+ return;
+ }
+
+ m_process->connection()->sendWithAsyncReply(Messages::WebPage::TextInputContextsInRect(rect), WTFMove(completionHandler), m_pageID);
+}
+
+void WebPageProxy::focusTextInputContext(const TextInputContext& context, CompletionHandler<void(bool)>&& completionHandler)
+{
+ if (!isValid()) {
+ completionHandler(false);
+ return;
+ }
+
+ m_process->connection()->sendWithAsyncReply(Messages::WebPage::FocusTextInputContext(context), WTFMove(completionHandler), m_pageID);
+}
+
} // namespace WebKit
#undef MERGE_WHEEL_EVENTS
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (242695 => 242696)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -275,6 +275,7 @@
struct LoadParameters;
struct PlatformPopupMenuData;
struct PrintInfo;
+struct TextInputContext;
struct WebPopupItem;
struct URLSchemeTaskParameters;
@@ -606,6 +607,9 @@
void requestFontAttributesAtSelectionStart(Function<void(const WebCore::FontAttributes&, CallbackBase::Error)>&&);
void fontAttributesCallback(const WebCore::FontAttributes&, CallbackID);
+ void textInputContextsInRect(WebCore::FloatRect, CompletionHandler<void(const Vector<TextInputContext>&)>&&);
+ void focusTextInputContext(const TextInputContext&, CompletionHandler<void(bool)>&&);
+
#if PLATFORM(IOS_FAMILY)
double displayedContentScale() const { return m_lastVisibleContentRectUpdate.scale(); }
const WebCore::FloatRect& exposedContentRect() const { return m_lastVisibleContentRectUpdate.exposedContentRect(); }
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (242695 => 242696)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2019-03-11 03:32:50 UTC (rev 242696)
@@ -726,6 +726,9 @@
2DDF731518E95060004F5A66 /* RemoteLayerBackingStoreCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DDF731318E95060004F5A66 /* RemoteLayerBackingStoreCollection.h */; };
2DE6943D18BD2A68005C15E5 /* SmartMagnificationControllerMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2DE6943B18BD2A68005C15E5 /* SmartMagnificationControllerMessageReceiver.cpp */; };
2DE6943E18BD2A68005C15E5 /* SmartMagnificationControllerMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DE6943C18BD2A68005C15E5 /* SmartMagnificationControllerMessages.h */; };
+ 2DE9B1352231B5B2005287B7 /* TextInputContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DE9B1332231B5B2005287B7 /* TextInputContext.h */; };
+ 2DE9B13A2231F61C005287B7 /* _WKTextInputContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DE9B1382231F61C005287B7 /* _WKTextInputContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 2DE9B13C2231F77C005287B7 /* _WKTextInputContextInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DE9B13B2231F77C005287B7 /* _WKTextInputContextInternal.h */; };
2DEAC5CF1AC368BB00A195D8 /* _WKFindOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DEAC5CE1AC368BB00A195D8 /* _WKFindOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
2DEB1D2E2127473600933906 /* ArgumentCodersCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AAF0C4912B16334008E49E2 /* ArgumentCodersCF.cpp */; };
2DF6FE52212E110900469030 /* WebPage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC963D6A113DD19200574BE2 /* WebPage.cpp */; };
@@ -2785,6 +2788,11 @@
2DDF731418E95060004F5A66 /* RemoteLayerBackingStoreCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteLayerBackingStoreCollection.mm; sourceTree = "<group>"; };
2DE6943B18BD2A68005C15E5 /* SmartMagnificationControllerMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SmartMagnificationControllerMessageReceiver.cpp; path = DerivedSources/WebKit2/SmartMagnificationControllerMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
2DE6943C18BD2A68005C15E5 /* SmartMagnificationControllerMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SmartMagnificationControllerMessages.h; path = DerivedSources/WebKit2/SmartMagnificationControllerMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2DE9B1332231B5B2005287B7 /* TextInputContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextInputContext.h; sourceTree = "<group>"; };
+ 2DE9B1342231B5B2005287B7 /* TextInputContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextInputContext.cpp; sourceTree = "<group>"; };
+ 2DE9B1372231F61C005287B7 /* _WKTextInputContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKTextInputContext.mm; sourceTree = "<group>"; };
+ 2DE9B1382231F61C005287B7 /* _WKTextInputContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKTextInputContext.h; sourceTree = "<group>"; };
+ 2DE9B13B2231F77C005287B7 /* _WKTextInputContextInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKTextInputContextInternal.h; sourceTree = "<group>"; };
2DEAC5CE1AC368BB00A195D8 /* _WKFindOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKFindOptions.h; sourceTree = "<group>"; };
2DF3962A21C8DC50008835E3 /* WKInkPickerView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKInkPickerView.mm; path = ios/WKInkPickerView.mm; sourceTree = "<group>"; };
2DF3962B21C8DC50008835E3 /* WKInkPickerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKInkPickerView.h; path = ios/WKInkPickerView.h; sourceTree = "<group>"; };
@@ -5104,6 +5112,8 @@
5272B2881406985D0096A5D0 /* StatisticsData.cpp */,
5272B2891406985D0096A5D0 /* StatisticsData.h */,
1A5E4DA312D3BD3D0099A2BB /* TextCheckerState.h */,
+ 2DE9B1342231B5B2005287B7 /* TextInputContext.cpp */,
+ 2DE9B1332231B5B2005287B7 /* TextInputContext.h */,
2FD43B921FA006A30083F51C /* TouchBarMenuData.cpp */,
2FD43B911FA006A10083F51C /* TouchBarMenuData.h */,
2F809DD51FBD1BC9005FE63A /* TouchBarMenuItemData.cpp */,
@@ -6077,6 +6087,9 @@
1A002D3F196B329400B9AD44 /* _WKSessionState.h */,
1A002D3E196B329400B9AD44 /* _WKSessionState.mm */,
1A002D42196B337000B9AD44 /* _WKSessionStateInternal.h */,
+ 2DE9B1382231F61C005287B7 /* _WKTextInputContext.h */,
+ 2DE9B1372231F61C005287B7 /* _WKTextInputContext.mm */,
+ 2DE9B13B2231F77C005287B7 /* _WKTextInputContextInternal.h */,
2D6B371918A967AD0042AE80 /* _WKThumbnailView.h */,
2D6B371A18A967AD0042AE80 /* _WKThumbnailView.mm */,
2DACE64D18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h */,
@@ -8934,6 +8947,8 @@
376311FE1A3FB600005A2E51 /* _WKSameDocumentNavigationTypeInternal.h in Headers */,
1A002D44196B338900B9AD44 /* _WKSessionState.h in Headers */,
1A002D43196B337000B9AD44 /* _WKSessionStateInternal.h in Headers */,
+ 2DE9B13A2231F61C005287B7 /* _WKTextInputContext.h in Headers */,
+ 2DE9B13C2231F77C005287B7 /* _WKTextInputContextInternal.h in Headers */,
2D6B371B18A967AD0042AE80 /* _WKThumbnailView.h in Headers */,
2DACE64E18ADBFF000E4CA76 /* _WKThumbnailViewInternal.h in Headers */,
99E7189C21F79D9E0055E975 /* _WKTouchEventGenerator.h in Headers */,
@@ -9401,6 +9416,7 @@
1AA417CB12C00CCA002BE67B /* TextChecker.h in Headers */,
53CFBBC82224D1B500266546 /* TextCheckerCompletion.h in Headers */,
1A5E4DA412D3BD3D0099A2BB /* TextCheckerState.h in Headers */,
+ 2DE9B1352231B5B2005287B7 /* TextInputContext.h in Headers */,
CE1A0BD71A48E6C60054EF74 /* TextInputSPI.h in Headers */,
1AAF263914687C39004A1E8A /* TiledCoreAnimationDrawingArea.h in Headers */,
1AF05D8714688348008B1E81 /* TiledCoreAnimationDrawingAreaProxy.h in Headers */,
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (242695 => 242696)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2019-03-11 03:32:50 UTC (rev 242696)
@@ -6468,6 +6468,94 @@
#endif // !PLATFORM(IOS_FAMILY)
+static IntRect elementRectInWindowCoordinates(const Element& element, const Frame& frame)
+{
+ auto* view = frame.view();
+ if (!view)
+ return { };
+
+ auto* renderer = element.renderer();
+ if (!renderer)
+ return { };
+
+ return view->contentsToWindow(renderer->absoluteBoundingBoxRect());
+}
+
+static bool isEditableTextInputElement(Element& element)
+{
+ if (is<HTMLTextFormControlElement>(element)) {
+ if (!element.isTextField() && !is<HTMLTextAreaElement>(element))
+ return false;
+ return downcast<HTMLTextFormControlElement>(element).isInnerTextElementEditable();
+ }
+
+ return element.isRootEditableElement();
+}
+
+void WebPage::textInputContextsInRect(WebCore::FloatRect searchRect, CompletionHandler<void(const Vector<TextInputContext>&)>&& completionHandler)
+{
+ Vector<WebKit::TextInputContext> textInputContexts;
+
+ for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ Document* document = frame->document();
+ if (!document)
+ continue;
+
+ Deque<Node*> nodesToSearch;
+ nodesToSearch.append(document);
+ while (!nodesToSearch.isEmpty()) {
+ auto node = nodesToSearch.takeFirst();
+
+ // It is possible to have nested text input contexts (e.g. <input type='text'> inside contenteditable) but
+ // in this case we just take the outermost context and skip the rest.
+ if (!is<Element>(*node) || !isEditableTextInputElement(downcast<Element>(*node))) {
+ for (auto* child = node->firstChild(); child; child = child->nextSibling())
+ nodesToSearch.append(child);
+ continue;
+ }
+
+ auto& element = downcast<Element>(*node);
+
+ IntRect elementRect = elementRectInWindowCoordinates(element, *frame);
+ if (!searchRect.intersects(elementRect))
+ continue;
+
+ WebKit::TextInputContext context;
+ context.webPageIdentifier = m_pageID;
+ context.documentIdentifier = document->identifier();
+ context.elementIdentifier = document->identifierForElement(element);
+ context.boundingRect = elementRect;
+
+ textInputContexts.append(context);
+ }
+ }
+
+ completionHandler(textInputContexts);
+}
+
+void WebPage::focusTextInputContext(const TextInputContext& textInputContext, CompletionHandler<void(bool)>&& completionHandler)
+{
+ completionHandler([&] {
+ if (textInputContext.webPageIdentifier != m_pageID)
+ return false;
+
+ auto* document = Document::allDocumentsMap().get(textInputContext.documentIdentifier);
+ if (!document)
+ return false;
+
+ if (document->page() != m_page.get())
+ return false;
+
+ auto* element = document->searchForElementByIdentifier(textInputContext.elementIdentifier);
+ if (!element)
+ return false;
+
+ element->focus();
+
+ return true;
+ }());
+}
+
} // namespace WebKit
#undef RELEASE_LOG_IF_ALLOWED
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (242695 => 242696)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-03-11 03:32:50 UTC (rev 242696)
@@ -251,6 +251,7 @@
struct InteractionInformationRequest;
struct LoadParameters;
struct PrintInfo;
+struct TextInputContext;
struct WebAutocorrectionContext;
struct WebPageCreationParameters;
struct WebPreferencesStore;
@@ -592,6 +593,9 @@
void viewportPropertiesDidChange(const WebCore::ViewportArguments&);
void executeEditCommandWithCallback(const String&, const String& argument, CallbackID);
+ void textInputContextsInRect(WebCore::FloatRect, CompletionHandler<void(const Vector<WebKit::TextInputContext>&)>&&);
+ void focusTextInputContext(const TextInputContext&, CompletionHandler<void(bool)>&&);
+
#if PLATFORM(IOS_FAMILY)
WebCore::FloatSize screenSize() const;
WebCore::FloatSize availableScreenSize() const;
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (242695 => 242696)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2019-03-11 03:32:50 UTC (rev 242696)
@@ -545,4 +545,7 @@
UpdateCurrentModifierState(OptionSet<WebCore::PlatformEvent::Modifier> modifiers)
SimulateDeviceOrientationChange(double alpha, double beta, double gamma)
+
+ TextInputContextsInRect(WebCore::FloatRect rect) -> (Vector<struct WebKit::TextInputContext> contexts) Async
+ FocusTextInputContext(struct WebKit::TextInputContext context) -> (bool success) Async
}
Modified: trunk/Tools/ChangeLog (242695 => 242696)
--- trunk/Tools/ChangeLog 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Tools/ChangeLog 2019-03-11 03:32:50 UTC (rev 242696)
@@ -1,3 +1,19 @@
+2019-03-10 Tim Horton <[email protected]>
+
+ Add SPI to retrieve the set of text inputs in a given rect, and later focus one
+ https://bugs.webkit.org/show_bug.cgi?id=195499
+
+ Reviewed by Darin Adler.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm: Added.
+ (-[WKWebView synchronouslyRequestTextInputContextsInRect:]):
+ (-[WKWebView synchronouslyFocusTextInputContext:]):
+ (applyStyle):
+ (applyIframe):
+ (TEST):
+ Add some tests for this SPI.
+
2019-03-10 Yusuke Suzuki <[email protected]>
[WTF] Align assumption in RunLoopWin to the other platform's RunLoop
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (242695 => 242696)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-03-11 02:54:55 UTC (rev 242695)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2019-03-11 03:32:50 UTC (rev 242696)
@@ -92,6 +92,7 @@
2D1646E21D1862CD00015A1A /* DeferredViewInWindowStateChange.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D1646E11D1862CD00015A1A /* DeferredViewInWindowStateChange.mm */; };
2D1C04A71D76298B000A6816 /* TestNavigationDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D1C04A61D76298B000A6816 /* TestNavigationDelegate.mm */; };
2D21FE591F04642900B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D21FE581F04642800B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm */; };
+ 2D2BEB2D22324E5F005544CA /* RequestTextInputContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2BEB2C22324E5F005544CA /* RequestTextInputContext.mm */; };
2D3CA3A8221DF4B40088E803 /* PageOverlayPlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D3CA3A4221DF2390088E803 /* PageOverlayPlugin.mm */; };
2D4CF8BD1D8360CC0001CE8D /* WKThumbnailView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D4CF8BC1D8360CC0001CE8D /* WKThumbnailView.mm */; };
2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */; };
@@ -1426,6 +1427,7 @@
2D1C04A61D76298B000A6816 /* TestNavigationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestNavigationDelegate.mm; path = cocoa/TestNavigationDelegate.mm; sourceTree = "<group>"; };
2D1FE0AF1AD465C1006CD9E6 /* FixedLayoutSize.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FixedLayoutSize.mm; sourceTree = "<group>"; };
2D21FE581F04642800B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKPDFViewStablePresentationUpdateCallback.mm; sourceTree = "<group>"; };
+ 2D2BEB2C22324E5F005544CA /* RequestTextInputContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RequestTextInputContext.mm; sourceTree = "<group>"; };
2D3CA3A4221DF2390088E803 /* PageOverlayPlugin.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PageOverlayPlugin.mm; sourceTree = "<group>"; };
2D4CF8BC1D8360CC0001CE8D /* WKThumbnailView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WKThumbnailView.mm; path = WebKit/WKThumbnailView.mm; sourceTree = "<group>"; };
2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMHTMLVideoElementWrapper.mm; sourceTree = "<group>"; };
@@ -2586,6 +2588,7 @@
52D5D6BD21B9F1B20046ABA6 /* RenderingProgress.mm */,
52D5D6BE21B9F1B20046ABA6 /* RenderingProgressPlugIn.mm */,
52D5D6BF21B9F1B20046ABA6 /* RenderingProgressProtocol.h */,
+ 2D2BEB2C22324E5F005544CA /* RequestTextInputContext.mm */,
CD9E292B1C90A71F000BB800 /* RequiresUserActionForPlayback.mm */,
51C8E1A41F26AC5400BF731B /* ResourceLoadStatistics.mm */,
5CCB10E02134579D00AC5AF0 /* ResponsivenessTimer.mm */,
@@ -4219,6 +4222,7 @@
A12DDBFB1E836F0700CF6CAE /* RenderedImageWithOptions.mm in Sources */,
52D5D6C021B9F1B30046ABA6 /* RenderingProgress.mm in Sources */,
F464AF9220BB66EA007F9B18 /* RenderingProgressTests.mm in Sources */,
+ 2D2BEB2D22324E5F005544CA /* RequestTextInputContext.mm in Sources */,
7C83E0C41D0A654200FEBCF3 /* RequiresUserActionForPlayback.mm in Sources */,
7CCE7F0E1A411AE600447C4C /* ResizeReversePaginatedWebView.cpp in Sources */,
7CCE7F0F1A411AE600447C4C /* ResizeWindowAfterCrash.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm (0 => 242696)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm 2019-03-11 03:32:50 UTC (rev 242696)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKPreferencesRefPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/_WKTextInputContext.h>
+#import <wtf/RetainPtr.h>
+
+#define EXPECT_RECT_EQ(xExpected, yExpected, widthExpected, heightExpected, rect) \
+ EXPECT_DOUBLE_EQ(xExpected, rect.origin.x); \
+ EXPECT_DOUBLE_EQ(yExpected, rect.origin.y); \
+ EXPECT_DOUBLE_EQ(widthExpected, rect.size.width); \
+ EXPECT_DOUBLE_EQ(heightExpected, rect.size.height);
+
+@implementation WKWebView (SynchronousTextInputContext)
+
+- (NSArray<_WKTextInputContext *> *)synchronouslyRequestTextInputContextsInRect:(CGRect)rect
+{
+ __block bool finished = false;
+ __block RetainPtr<NSArray<_WKTextInputContext *>> result;
+ [self _requestTextInputContextsInRect:rect completionHandler:^(NSArray<_WKTextInputContext *> *contexts) {
+ result = contexts;
+ finished = true;
+ }];
+ TestWebKitAPI::Util::run(&finished);
+ return result.autorelease();
+}
+
+- (BOOL)synchronouslyFocusTextInputContext:(_WKTextInputContext *)context
+{
+ __block bool finished = false;
+ __block bool success = false;
+ [self _focusTextInputContext:context completionHandler:^(BOOL innerSuccess) {
+ success = innerSuccess;
+ finished = true;
+ }];
+ TestWebKitAPI::Util::run(&finished);
+ return success;
+}
+
+@end
+
+static NSString *applyStyle(NSString *HTMLString)
+{
+ return [@"<style>body { margin: 0; } iframe { border: none; }</style>" stringByAppendingString:HTMLString];
+}
+
+static NSString *applyIframe(NSString *HTMLString)
+{
+ return applyStyle([NSString stringWithFormat:@"<iframe src="" style='position: absolute; top: 200px;'>", [applyStyle(HTMLString) stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]]]);
+}
+
+TEST(WebKit, RequestTextInputContext)
+{
+ RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ WKPreferencesSetThreadedScrollingEnabled((WKPreferencesRef)[configuration preferences], false);
+ RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+ NSArray<_WKTextInputContext *> *contexts;
+
+ // Basic inputs.
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;'>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 0, 50, 50, contexts[0].boundingRect);
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<textarea style='width: 100px; height: 100px;'></textarea>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 0, 100, 100, contexts[0].boundingRect);
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<div contenteditable style='width: 100px; height: 100px;'></div>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 0, 100, 100, contexts[0].boundingRect);
+
+ // Basic inputs inside subframe.
+
+ [webView synchronouslyLoadHTMLString:applyIframe(@"<input type='text' style='width: 50px; height: 50px;'>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 200, 50, 50, contexts[0].boundingRect);
+
+ [webView synchronouslyLoadHTMLString:applyIframe(@"<textarea style='width: 100px; height: 100px;'></textarea>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 200, 100, 100, contexts[0].boundingRect);
+
+ [webView synchronouslyLoadHTMLString:applyIframe(@"<div contenteditable style='width: 100px; height: 100px;'></div>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 200, 100, 100, contexts[0].boundingRect);
+
+ // Read only inputs; should not be included.
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;' readonly>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(0UL, contexts.count);
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<textarea style='width: 100px; height: 100px;' readonly>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(0UL, contexts.count);
+
+ // Inputs outside the requested rect; should not be included.
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;'>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:CGRectMake(100, 100, 100, 100)];
+ EXPECT_EQ(0UL, contexts.count);
+
+ // Inputs scrolled outside the requested rect; should not be included.
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;'><br><div style='width: 100px; height: 5000px;'></div>")];
+ [webView objectByEvaluatingJavaScript:@"window.scrollTo(0, 5000);"];
+ [webView waitForNextPresentationUpdate];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(0UL, contexts.count);
+
+ // Inputs scrolled into the requested rect.
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px; position: absolute; top: 5000px;'><br><div style='width: 100px; height: 10000px;'></div>")];
+ [webView objectByEvaluatingJavaScript:@"window.scrollTo(0, 5000);"];
+ [webView waitForNextPresentationUpdate];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 0, 50, 50, contexts[0].boundingRect);
+
+ // Multiple inputs.
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;'><br/><input type='text' style='width: 50px; height: 50px;'><br/><input type='text' style='width: 50px; height: 50px;'>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(3UL, contexts.count);
+ EXPECT_RECT_EQ(0, 0, 50, 50, contexts[0].boundingRect);
+ EXPECT_RECT_EQ(0, 50, 50, 50, contexts[1].boundingRect);
+ EXPECT_RECT_EQ(0, 100, 50, 50, contexts[2].boundingRect);
+
+ // Nested <input>-inside-contenteditable. Only the contenteditable is considered.
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<div contenteditable style='width: 100px; height: 100px;'><input type='text' style='width: 50px; height: 50px;'></div>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ EXPECT_RECT_EQ(0, 0, 100, 100, contexts[0].boundingRect);
+}
+
+TEST(WebKit, FocusTextInputContext)
+{
+ RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ WKPreferencesSetThreadedScrollingEnabled((WKPreferencesRef)[configuration preferences], false);
+ RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+ NSArray<_WKTextInputContext *> *contexts;
+
+ [webView synchronouslyLoadHTMLString:applyStyle(@"<input id='test' type='text' style='width: 50px; height: 50px;'>")];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ RetainPtr<_WKTextInputContext> originalInput = contexts[0];
+ EXPECT_TRUE([webView synchronouslyFocusTextInputContext:originalInput.get()]);
+ EXPECT_WK_STREQ("test", [webView objectByEvaluatingJavaScript:@"document.activeElement.id"]);
+
+ // The _WKTextInputContext should still work even after another request.
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_TRUE([contexts[0] isEqual:originalInput.get()]);
+ EXPECT_TRUE([webView synchronouslyFocusTextInputContext:originalInput.get()]);
+
+ // Replace the <input> with a <textarea> with script; the <input> should no longer be focusable.
+ [webView objectByEvaluatingJavaScript:@"document.body.innerHTML = '<textarea id=\"area\">';"];
+ contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+ EXPECT_EQ(1UL, contexts.count);
+ RetainPtr<_WKTextInputContext> textArea = contexts[0];
+ EXPECT_FALSE([textArea isEqual:originalInput.get()]);
+ EXPECT_FALSE([webView synchronouslyFocusTextInputContext:originalInput.get()]);
+ EXPECT_TRUE([webView synchronouslyFocusTextInputContext:textArea.get()]);
+ EXPECT_WK_STREQ("area", [webView objectByEvaluatingJavaScript:@"document.activeElement.id"]);
+
+ // Destroy the <textarea> by navigating away; we can no longer focus it.
+ [webView synchronouslyLoadHTMLString:@""];
+ EXPECT_FALSE([webView synchronouslyFocusTextInputContext:textArea.get()]);
+}