Title: [235556] trunk/Source
Revision
235556
Author
[email protected]
Date
2018-08-31 09:49:21 -0700 (Fri, 31 Aug 2018)

Log Message

[Datalist][iOS] Add suggestions UI for TextFieldInputTypes
https://bugs.webkit.org/show_bug.cgi?id=186714

Reviewed by Wenson Hsieh.

Source/WebCore:

On iOS, the datalist button should appear as a downward triangle. Furthermore, the
button should only be displayed if the input has focus and there are suggested
values.

* css/html.css:
(input::-webkit-list-button): Draw the triangle using an SVG.
* html/DataListSuggestionInformation.h:
* html/HTMLInputElement.h:
* html/TextFieldInputType.cpp: Added logic to show and hide the datalist button as necessary.
(WebCore::TextFieldInputType::handleFocusEvent):
(WebCore::TextFieldInputType::handleBlurEvent):
(WebCore::TextFieldInputType::didSetValueByUserEdit):
(WebCore::TextFieldInputType::listAttributeTargetChanged):
(WebCore::TextFieldInputType::displaySuggestions):

Source/WebKit:

On iOS, we have less space to display suggestions from a datalist element compared
to macOS. Furthermore, iPhones and iPads have different form factors, leading to a
different approach on each device. The commonalities of the two implementations
can be found in WKDataListSuggestionsControl. This class is subclassed by the
device specific implementations.

On iPhone, we display the suggestions in a UIPickerView. This view is accessible
only after tapping on the datalist button element to the side of the input field.
This approach was chosen in order to avoid tricking the user into thinking that
the values displayed in the picker are the only accepted values.
WKDataListSuggestionsPicker is responsible for managing the interface shown on
iPhones.

On iPad, we display the suggestions in a popover, that is visible alongside the
keyboard. The suggestions in the popover update as the user types.
WKDataListSuggestionsPopover is responsible for managing the interface shown on
iPads.

Both devices display predictive text suggestions, taking the first three values
from the filtered suggestions list. In order to prevent other clients from
overwriting the suggestions provided by the datalist element, we prevent writing
to the predictive text bar if an input with the list attribute is the currently
assisted node.

* Shared/AssistedNodeInformation.cpp:
(WebKit::AssistedNodeInformation::encode const):
(WebKit::AssistedNodeInformation::decode):
* Shared/AssistedNodeInformation.h:
* Shared/ios/InteractionInformationAtPosition.h:
* Shared/ios/InteractionInformationAtPosition.mm:
(WebKit::InteractionInformationAtPosition::encode const):
(WebKit::InteractionInformationAtPosition::decode):
* SourcesCocoa.txt:
* UIProcess/WebDataListSuggestionsDropdownIOS.h: Added.
* UIProcess/WebDataListSuggestionsDropdownIOS.mm: Added.
(WebKit::WebDataListSuggestionsDropdownIOS::create):
(WebKit::WebDataListSuggestionsDropdownIOS::WebDataListSuggestionsDropdownIOS):
(WebKit::WebDataListSuggestionsDropdownIOS::show):
(WebKit::WebDataListSuggestionsDropdownIOS::handleKeydownWithIdentifier):
(WebKit::WebDataListSuggestionsDropdownIOS::close):
(WebKit::WebDataListSuggestionsDropdownIOS::didSelectOption):
(-[WKDataListSuggestionsControl initWithInformation:inView:]):
(-[WKDataListSuggestionsControl updateWithInformation:]):
(-[WKDataListSuggestionsControl showSuggestionsDropdown:activationType:]):
(-[WKDataListSuggestionsControl didSelectOptionAtIndex:]):
(-[WKDataListSuggestionsControl invalidate]):
(-[WKDataListSuggestionsControl textSuggestions]):
(-[WKDataListSuggestionsControl suggestionsCount]):
(-[WKDataListSuggestionsControl suggestionAtIndex:]):
(-[WKDataListSuggestionsControl textAlignment]):
(-[WKDataListSuggestionsPicker initWithInformation:inView:]):
(-[WKDataListSuggestionsPicker updateWithInformation:]):
(-[WKDataListSuggestionsPicker showSuggestionsDropdown:activationType:]):
(-[WKDataListSuggestionsPicker numberOfComponentsInPickerView:]):
(-[WKDataListSuggestionsPicker pickerView:numberOfRowsInComponent:]):
(-[WKDataListSuggestionsPicker pickerView:titleForRow:forComponent:]):
(-[WKDataListSuggestionsPicker invalidate]):
(-[WKDataListSuggestionsPickerView controlView]):
(-[WKDataListSuggestionsPickerView controlBeginEditing]):
(-[WKDataListSuggestionsPickerView controlEndEditing]):
(-[WKDataListSuggestionsPopover initWithInformation:inView:]):
(-[WKDataListSuggestionsPopover updateWithInformation:]):
(-[WKDataListSuggestionsPopover showSuggestionsDropdown:activationType:]):
(-[WKDataListSuggestionsPopover invalidate]):
(-[WKDataListSuggestionsPopover didSelectOptionAtIndex:]):
(-[WKDataListSuggestionsViewController reloadData]):
(-[WKDataListSuggestionsViewController tableView:numberOfRowsInSection:]):
(-[WKDataListSuggestionsViewController tableView:cellForRowAtIndexPath:]):
(-[WKDataListSuggestionsViewController tableView:didSelectRowAtIndexPath:]):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::pageDidScroll):
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::createDataListSuggestionsDropdown):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKFormInputSession endEditing]):
(-[WKFormInputSession setSuggestions:]):
(-[WKContentView _formInputSession]):
(-[WKContentView resignFirstResponderForWebView]):
(-[WKContentView textInteractionGesture:shouldBeginAtPoint:]):
(-[WKContentView accessoryTab:]):
(-[WKContentView insertTextSuggestion:]):
* UIProcess/mac/WebDataListSuggestionsDropdownMac.h:
* UIProcess/mac/WebDataListSuggestionsDropdownMac.mm:
(WebKit::WebDataListSuggestionsDropdownMac::didSelectOption):
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::didCloseSuggestions):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPositionInformation):
(WebKit::WebPage::getAssistedNodeInformation):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (235555 => 235556)


--- trunk/Source/WebCore/ChangeLog	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebCore/ChangeLog	2018-08-31 16:49:21 UTC (rev 235556)
@@ -1,3 +1,25 @@
+2018-08-31  Aditya Keerthi  <[email protected]>
+
+        [Datalist][iOS] Add suggestions UI for TextFieldInputTypes
+        https://bugs.webkit.org/show_bug.cgi?id=186714
+
+        Reviewed by Wenson Hsieh.
+
+        On iOS, the datalist button should appear as a downward triangle. Furthermore, the
+        button should only be displayed if the input has focus and there are suggested
+        values.
+
+        * css/html.css:
+        (input::-webkit-list-button): Draw the triangle using an SVG.
+        * html/DataListSuggestionInformation.h:
+        * html/HTMLInputElement.h:
+        * html/TextFieldInputType.cpp: Added logic to show and hide the datalist button as necessary.
+        (WebCore::TextFieldInputType::handleFocusEvent):
+        (WebCore::TextFieldInputType::handleBlurEvent):
+        (WebCore::TextFieldInputType::didSetValueByUserEdit):
+        (WebCore::TextFieldInputType::listAttributeTargetChanged):
+        (WebCore::TextFieldInputType::displaySuggestions):
+
 2018-08-31  Youenn Fablet  <[email protected]>
 
         Move LibWebRTCMediaEndpoint data channel code to LibWebRTCDataChannelHandler

Modified: trunk/Source/WebCore/css/html.css (235555 => 235556)


--- trunk/Source/WebCore/css/html.css	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebCore/css/html.css	2018-08-31 16:49:21 UTC (rev 235556)
@@ -626,7 +626,14 @@
     flex: none;
     -webkit-user-select: none;
     width: 16px;
+#if defined(WTF_PLATFORM_IOS) && WTF_PLATFORM_IOS
+    content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" stroke="black" fill="black" width="16" height="16"><polygon points="8 11.031, 4.5 4.969, 11.5 4.969"/></svg>');
+    /* Make it easier to hit the button on iOS */
+    padding: 7px;
+    margin: -7px;
+#else
     height: 100%;
+#endif
 }
 #endif
 

Modified: trunk/Source/WebCore/html/DataListSuggestionInformation.h (235555 => 235556)


--- trunk/Source/WebCore/html/DataListSuggestionInformation.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebCore/html/DataListSuggestionInformation.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "IntRect.h"
+#include <wtf/Vector.h>
 
 #if ENABLE(DATALIST_ELEMENT)
 namespace WebCore {

Modified: trunk/Source/WebCore/html/HTMLInputElement.h (235555 => 235556)


--- trunk/Source/WebCore/html/HTMLInputElement.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebCore/html/HTMLInputElement.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -151,7 +151,7 @@
     HTMLElement* placeholderElement() const final;
     WEBCORE_EXPORT HTMLElement* autoFillButtonElement() const;
 #if ENABLE(DATALIST_ELEMENT)
-    HTMLElement* dataListButtonElement() const;
+    WEBCORE_EXPORT HTMLElement* dataListButtonElement() const;
 #endif
 
     bool checked() const { return m_isChecked; }

Modified: trunk/Source/WebCore/html/TextFieldInputType.cpp (235555 => 235556)


--- trunk/Source/WebCore/html/TextFieldInputType.cpp	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebCore/html/TextFieldInputType.cpp	2018-08-31 16:49:21 UTC (rev 235556)
@@ -260,8 +260,13 @@
 {
     ASSERT(element());
     ASSERT_UNUSED(oldFocusedNode, oldFocusedNode != element());
-    if (RefPtr<Frame> frame = element()->document().frame())
+    if (RefPtr<Frame> frame = element()->document().frame()) {
         frame->editor().textFieldDidBeginEditing(element());
+#if ENABLE(DATALIST_ELEMENT) && PLATFORM(IOS)
+        if (element()->list() && m_dataListDropdownIndicator)
+            m_dataListDropdownIndicator->setInlineStyleProperty(CSSPropertyDisplay, suggestions().size() ? CSSValueBlock : CSSValueNone, true);
+#endif
+    }
 }
 
 void TextFieldInputType::handleBlurEvent()
@@ -269,6 +274,10 @@
     InputType::handleBlurEvent();
     ASSERT(element());
     element()->endEditing();
+#if ENABLE(DATALIST_ELEMENT) && PLATFORM(IOS)
+    if (element()->list() && m_dataListDropdownIndicator)
+        m_dataListDropdownIndicator->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone, true);
+#endif
 }
 
 bool TextFieldInputType::shouldSubmitImplicitly(Event& event)
@@ -648,6 +657,10 @@
     if (RefPtr<Frame> frame = element()->document().frame())
         frame->editor().textDidChangeInTextField(element());
 #if ENABLE(DATALIST_ELEMENT)
+#if PLATFORM(IOS)
+    if (element()->list() && m_dataListDropdownIndicator)
+        m_dataListDropdownIndicator->setInlineStyleProperty(CSSPropertyDisplay, suggestions().size() ? CSSValueBlock : CSSValueNone, true);
+#endif
     if (element()->list())
         displaySuggestions(DataListSuggestionActivationType::TextChanged);
 #endif
@@ -804,7 +817,9 @@
     if (!m_dataListDropdownIndicator)
         return;
 
+#if !PLATFORM(IOS)
     m_dataListDropdownIndicator->setInlineStyleProperty(CSSPropertyDisplay, element()->list() ? CSSValueBlock : CSSValueNone, true);
+#endif
 }
 
 HTMLElement* TextFieldInputType::dataListButtonElement() const
@@ -875,7 +890,7 @@
     if (element()->isDisabledFormControl() || !element()->renderer())
         return;
 
-    if (!UserGestureIndicator::processingUserGesture())
+    if (!UserGestureIndicator::processingUserGesture() && type != DataListSuggestionActivationType::TextChanged)
         return;
 
     if (!m_suggestionPicker && suggestions().size() > 0)

Modified: trunk/Source/WebKit/ChangeLog (235555 => 235556)


--- trunk/Source/WebKit/ChangeLog	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/ChangeLog	2018-08-31 16:49:21 UTC (rev 235556)
@@ -1,3 +1,102 @@
+2018-08-31  Aditya Keerthi  <[email protected]>
+
+        [Datalist][iOS] Add suggestions UI for TextFieldInputTypes
+        https://bugs.webkit.org/show_bug.cgi?id=186714
+
+        Reviewed by Wenson Hsieh.
+
+        On iOS, we have less space to display suggestions from a datalist element compared
+        to macOS. Furthermore, iPhones and iPads have different form factors, leading to a
+        different approach on each device. The commonalities of the two implementations
+        can be found in WKDataListSuggestionsControl. This class is subclassed by the
+        device specific implementations.
+
+        On iPhone, we display the suggestions in a UIPickerView. This view is accessible
+        only after tapping on the datalist button element to the side of the input field.
+        This approach was chosen in order to avoid tricking the user into thinking that
+        the values displayed in the picker are the only accepted values.
+        WKDataListSuggestionsPicker is responsible for managing the interface shown on
+        iPhones.
+
+        On iPad, we display the suggestions in a popover, that is visible alongside the
+        keyboard. The suggestions in the popover update as the user types.
+        WKDataListSuggestionsPopover is responsible for managing the interface shown on
+        iPads.
+
+        Both devices display predictive text suggestions, taking the first three values
+        from the filtered suggestions list. In order to prevent other clients from
+        overwriting the suggestions provided by the datalist element, we prevent writing
+        to the predictive text bar if an input with the list attribute is the currently
+        assisted node.
+
+        * Shared/AssistedNodeInformation.cpp:
+        (WebKit::AssistedNodeInformation::encode const):
+        (WebKit::AssistedNodeInformation::decode):
+        * Shared/AssistedNodeInformation.h:
+        * Shared/ios/InteractionInformationAtPosition.h:
+        * Shared/ios/InteractionInformationAtPosition.mm:
+        (WebKit::InteractionInformationAtPosition::encode const):
+        (WebKit::InteractionInformationAtPosition::decode):
+        * SourcesCocoa.txt:
+        * UIProcess/WebDataListSuggestionsDropdownIOS.h: Added.
+        * UIProcess/WebDataListSuggestionsDropdownIOS.mm: Added.
+        (WebKit::WebDataListSuggestionsDropdownIOS::create):
+        (WebKit::WebDataListSuggestionsDropdownIOS::WebDataListSuggestionsDropdownIOS):
+        (WebKit::WebDataListSuggestionsDropdownIOS::show):
+        (WebKit::WebDataListSuggestionsDropdownIOS::handleKeydownWithIdentifier):
+        (WebKit::WebDataListSuggestionsDropdownIOS::close):
+        (WebKit::WebDataListSuggestionsDropdownIOS::didSelectOption):
+        (-[WKDataListSuggestionsControl initWithInformation:inView:]):
+        (-[WKDataListSuggestionsControl updateWithInformation:]):
+        (-[WKDataListSuggestionsControl showSuggestionsDropdown:activationType:]):
+        (-[WKDataListSuggestionsControl didSelectOptionAtIndex:]):
+        (-[WKDataListSuggestionsControl invalidate]):
+        (-[WKDataListSuggestionsControl textSuggestions]):
+        (-[WKDataListSuggestionsControl suggestionsCount]):
+        (-[WKDataListSuggestionsControl suggestionAtIndex:]):
+        (-[WKDataListSuggestionsControl textAlignment]):
+        (-[WKDataListSuggestionsPicker initWithInformation:inView:]):
+        (-[WKDataListSuggestionsPicker updateWithInformation:]):
+        (-[WKDataListSuggestionsPicker showSuggestionsDropdown:activationType:]):
+        (-[WKDataListSuggestionsPicker numberOfComponentsInPickerView:]):
+        (-[WKDataListSuggestionsPicker pickerView:numberOfRowsInComponent:]):
+        (-[WKDataListSuggestionsPicker pickerView:titleForRow:forComponent:]):
+        (-[WKDataListSuggestionsPicker invalidate]):
+        (-[WKDataListSuggestionsPickerView controlView]):
+        (-[WKDataListSuggestionsPickerView controlBeginEditing]):
+        (-[WKDataListSuggestionsPickerView controlEndEditing]):
+        (-[WKDataListSuggestionsPopover initWithInformation:inView:]):
+        (-[WKDataListSuggestionsPopover updateWithInformation:]):
+        (-[WKDataListSuggestionsPopover showSuggestionsDropdown:activationType:]):
+        (-[WKDataListSuggestionsPopover invalidate]):
+        (-[WKDataListSuggestionsPopover didSelectOptionAtIndex:]):
+        (-[WKDataListSuggestionsViewController reloadData]):
+        (-[WKDataListSuggestionsViewController tableView:numberOfRowsInSection:]):
+        (-[WKDataListSuggestionsViewController tableView:cellForRowAtIndexPath:]):
+        (-[WKDataListSuggestionsViewController tableView:didSelectRowAtIndexPath:]):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::pageDidScroll):
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::createDataListSuggestionsDropdown):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKFormInputSession endEditing]):
+        (-[WKFormInputSession setSuggestions:]):
+        (-[WKContentView _formInputSession]):
+        (-[WKContentView resignFirstResponderForWebView]):
+        (-[WKContentView textInteractionGesture:shouldBeginAtPoint:]):
+        (-[WKContentView accessoryTab:]):
+        (-[WKContentView insertTextSuggestion:]):
+        * UIProcess/mac/WebDataListSuggestionsDropdownMac.h:
+        * UIProcess/mac/WebDataListSuggestionsDropdownMac.mm:
+        (WebKit::WebDataListSuggestionsDropdownMac::didSelectOption):
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::didCloseSuggestions):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::getPositionInformation):
+        (WebKit::WebPage::getAssistedNodeInformation):
+
 2018-08-31  Frederic Wang  <[email protected]>
 
         REGRESSION(r235484) _WKPreferencesGetWebRTCLegacyAPIEnabled symbol not found when running Safari with external SDK build

Modified: trunk/Source/WebKit/Shared/AssistedNodeInformation.cpp (235555 => 235556)


--- trunk/Source/WebKit/Shared/AssistedNodeInformation.cpp	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/Shared/AssistedNodeInformation.cpp	2018-08-31 16:49:21 UTC (rev 235556)
@@ -97,9 +97,12 @@
     encoder << label;
     encoder << ariaLabel;
     encoder << assistedNodeIdentifier;
-#if ENABLE(INPUT_TYPE_COLOR) && ENABLE(DATALIST_ELEMENT)
+#if ENABLE(DATALIST_ELEMENT)
+    encoder << hasSuggestions;
+#if ENABLE(INPUT_TYPE_COLOR)
     encoder << suggestedColors;
 #endif
+#endif
 }
 
 bool AssistedNodeInformation::decode(IPC::Decoder& decoder, AssistedNodeInformation& result)
@@ -206,10 +209,15 @@
     if (!decoder.decode(result.assistedNodeIdentifier))
         return false;
 
-#if ENABLE(INPUT_TYPE_COLOR) && ENABLE(DATALIST_ELEMENT)
+#if ENABLE(DATALIST_ELEMENT)
+    if (!decoder.decode(result.hasSuggestions))
+        return false;
+
+#if ENABLE(INPUT_TYPE_COLOR)
     if (!decoder.decode(result.suggestedColors))
         return false;
 #endif
+#endif
 
     return true;
 }

Modified: trunk/Source/WebKit/Shared/AssistedNodeInformation.h (235555 => 235556)


--- trunk/Source/WebKit/Shared/AssistedNodeInformation.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/Shared/AssistedNodeInformation.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -125,9 +125,12 @@
     String placeholder;
     String label;
     String ariaLabel;
-#if ENABLE(INPUT_TYPE_COLOR) && ENABLE(DATALIST_ELEMENT)
+#if ENABLE(DATALIST_ELEMENT)
+    bool hasSuggestions { false };
+#if ENABLE(INPUT_TYPE_COLOR)
     Vector<WebCore::Color> suggestedColors;
 #endif
+#endif
 
     uint64_t assistedNodeIdentifier { 0 };
 

Modified: trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h (235555 => 235556)


--- trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -56,6 +56,9 @@
 #if ENABLE(DATA_DETECTION)
     bool isDataDetectorLink { false };
 #endif
+#if ENABLE(DATALIST_ELEMENT)
+    bool preventTextInteraction { false };
+#endif
     WebCore::FloatPoint adjustedPointForNodeRespondingToClickEvents;
     WebCore::URL url;
     WebCore::URL imageURL;

Modified: trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm (235555 => 235556)


--- trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm	2018-08-31 16:49:21 UTC (rev 235556)
@@ -82,6 +82,9 @@
         IPC::encode(encoder, reinterpret_cast<CFDataRef>(archiver.get().encodedData));
     }
 #endif
+#if ENABLE(DATALIST_ELEMENT)
+    encoder << preventTextInteraction;
+#endif
 }
 
 bool InteractionInformationAtPosition::decode(IPC::Decoder& decoder, InteractionInformationAtPosition& result)
@@ -186,6 +189,11 @@
     }
 #endif
 
+#if ENABLE(DATALIST_ELEMENT)
+    if (!decoder.decode(result.preventTextInteraction))
+        return false;
+#endif
+
     return true;
 }
 

Modified: trunk/Source/WebKit/SourcesCocoa.txt (235555 => 235556)


--- trunk/Source/WebKit/SourcesCocoa.txt	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/SourcesCocoa.txt	2018-08-31 16:49:21 UTC (rev 235556)
@@ -349,6 +349,7 @@
 UIProcess/Gamepad/mac/UIGamepadProviderMac.mm
 
 UIProcess/ios/DragDropInteractionState.mm
+UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm
 
 UIProcess/ios/forms/WKAirPlayRoutePicker.mm
 UIProcess/ios/forms/WKDatePickerViewController.mm

Modified: trunk/Source/WebKit/UIProcess/WebDataListSuggestionsDropdown.h (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/WebDataListSuggestionsDropdown.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/WebDataListSuggestionsDropdown.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -40,7 +40,7 @@
         virtual ~Client() { }
 
     public:
-        virtual void didSelectOption(String&) = 0;
+        virtual void didSelectOption(const String&) = 0;
         virtual void didCloseSuggestions() = 0;
     };
 

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-08-31 16:49:21 UTC (rev 235556)
@@ -4556,7 +4556,10 @@
     if (m_isKeyboardAnimatingIn)
         return;
 #endif
+
+#if !PLATFORM(IOS)
     closeOverlayedViews();
+#endif
 }
 
 void WebPageProxy::runOpenPanel(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, const FileChooserSettings& settings)
@@ -4783,7 +4786,7 @@
     m_process->send(Messages::WebPage::DidCloseSuggestions(), m_pageID);
 }
 
-void WebPageProxy::didSelectOption(String& selectedOption)
+void WebPageProxy::didSelectOption(const String& selectedOption)
 {
     if (!isValid())
         return;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -1526,7 +1526,7 @@
     void showDataListSuggestions(WebCore::DataListSuggestionInformation&&);
     void handleKeydownInDataList(const String&);
     void endDataListSuggestions();
-    void didSelectOption(String&) final;
+    void didSelectOption(const String&) final;
     void didCloseSuggestions() final;
 #endif
 

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2018-08-31 16:49:21 UTC (rev 235556)
@@ -48,6 +48,7 @@
 #import "WKWebViewContentProviderRegistry.h"
 #import "WKWebViewInternal.h"
 #import "WebContextMenuProxy.h"
+#import "WebDataListSuggestionsDropdownIOS.h"
 #import "WebEditCommandProxy.h"
 #import "WebProcessProxy.h"
 #import "_WKDownloadInternal.h"
@@ -780,7 +781,7 @@
 #if ENABLE(DATALIST_ELEMENT)
 RefPtr<WebDataListSuggestionsDropdown> PageClientImpl::createDataListSuggestionsDropdown(WebPageProxy& page)
 {
-    return nullptr;
+    return WebDataListSuggestionsDropdownIOS::create(page, m_contentView);
 }
 #endif
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -44,6 +44,7 @@
 #import "WKKeyboardScrollingAnimator.h"
 #import "WKShareSheet.h"
 #import "WKSyntheticClickTapGestureRecognizer.h"
+#import "_WKFormInputSession.h"
 #import <UIKit/UIView.h>
 #import <WebCore/Color.h>
 #import <WebCore/FloatQuad.h>
@@ -147,6 +148,16 @@
 
 }
 
+@class WKFocusedElementInfo;
+
+@interface WKFormInputSession : NSObject <_WKFormInputSession>
+
+- (instancetype)initWithContentView:(WKContentView *)view focusedElementInfo:(WKFocusedElementInfo *)elementInfo requiresStrongPasswordAssistance:(BOOL)requiresStrongPasswordAssistance;
+- (void)endEditing;
+- (void)invalidate;
+
+@end
+
 @interface WKContentView () {
     RetainPtr<UIWebTouchEventsGestureRecognizer> _touchEventGestureRecognizer;
 
@@ -348,6 +359,7 @@
 - (void)_accessibilityRetrieveRectsAtSelectionOffset:(NSInteger)offset withText:(NSString *)text;
 - (void)_accessibilityStoreSelection;
 - (void)_accessibilityClearSelection;
+- (WKFormInputSession *)_formInputSession;
 
 @property (nonatomic, readonly) WebKit::InteractionInformationAtPosition currentPositionInformation;
 - (void)doAfterPositionInformationUpdate:(void (^)(WebKit::InteractionInformationAtPosition))action forRequest:(WebKit::InteractionInformationRequest)request;

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2018-08-31 16:49:21 UTC (rev 235556)
@@ -60,6 +60,7 @@
 #import "WKWebViewConfigurationPrivate.h"
 #import "WKWebViewInternal.h"
 #import "WKWebViewPrivate.h"
+#import "WebDataListSuggestionsDropdownIOS.h"
 #import "WebEvent.h"
 #import "WebIOSEventFactory.h"
 #import "WebPageMessages.h"
@@ -67,7 +68,6 @@
 #import "_WKActivatedElementInfoInternal.h"
 #import "_WKElementAction.h"
 #import "_WKFocusedElementInfo.h"
-#import "_WKFormInputSession.h"
 #import "_WKInputDelegate.h"
 #import <CoreText/CTFont.h>
 #import <CoreText/CTFontDescriptor.h>
@@ -285,13 +285,6 @@
 - (instancetype)initWithAssistedNodeInformation:(const AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated userObject:(NSObject <NSSecureCoding> *)userObject;
 @end
 
-@interface WKFormInputSession : NSObject <_WKFormInputSession>
-
-- (instancetype)initWithContentView:(WKContentView *)view focusedElementInfo:(WKFocusedElementInfo *)elementInfo requiresStrongPasswordAssistance:(BOOL)requiresStrongPasswordAssistance;
-- (void)invalidate;
-
-@end
-
 @implementation WKFormInputSession {
     WeakObjCPtr<WKContentView> _contentView;
     RetainPtr<WKFocusedElementInfo> _focusedElementInfo;
@@ -386,6 +379,12 @@
     [_contentView reloadInputViews];
 }
 
+- (void)endEditing
+{
+    if ([_customInputView conformsToProtocol:@protocol(WKFormControl)])
+        [(id<WKFormControl>)_customInputView.get() controlEndEditing];
+}
+
 - (NSArray<UITextSuggestion *> *)suggestions
 {
     return _suggestions.get();
@@ -393,6 +392,12 @@
 
 - (void)setSuggestions:(NSArray<UITextSuggestion *> *)suggestions
 {
+    // Suggestions that come from a <datalist> should not be overwritten by other clients.
+#if ENABLE(DATALIST_ELEMENT)
+    if ([_contentView assistedNodeInformation].hasSuggestions && ![suggestions.firstObject isKindOfClass:[WKDataListTextSuggestion class]])
+        return;
+#endif
+
     id <UITextInputSuggestionDelegate> suggestionDelegate = (id <UITextInputSuggestionDelegate>)[_contentView inputDelegate];
     _suggestions = adoptNS([suggestions copy]);
     [suggestionDelegate setSuggestions:suggestions];
@@ -596,6 +601,11 @@
     return (assistedNodeInformation.elementType != InputType::None);
 }
 
+- (WKFormInputSession *)_formInputSession
+{
+    return _formInputSession.get();
+}
+
 - (void)_createAndConfigureDoubleTapGestureRecognizer
 {
     _doubleTapGestureRecognizer = adoptNS([[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_doubleTapRecognized:)]);
@@ -1004,6 +1014,8 @@
     if (!_webView->_activeFocusedStateRetainCount) {
         // We need to complete the editing operation before we blur the element.
         [_inputPeripheral endEditing];
+        [_formInputSession endEditing];
+
         _page->blurAssistedNode();
     }
 
@@ -1751,6 +1763,11 @@
     }
 #endif
 
+#if ENABLE(DATALIST_ELEMENT)
+    if (_positionInformation.preventTextInteraction)
+        return NO;
+#endif
+
     // If we're currently editing an assisted node, only allow the selection to move within that assisted node.
     if (self.isAssistingNode)
         return _positionInformation.nodeAtPositionIsAssistedNode;
@@ -3114,6 +3131,8 @@
 
 - (void)accessoryTab:(BOOL)isNext
 {
+    [_formInputSession endEditing];
+
     [_inputPeripheral endEditing];
     _inputPeripheral = nil;
 
@@ -3124,7 +3143,6 @@
         [view endSelectionChange];
         [view reloadInputViews];
     });
-
 }
 
 - (void)_becomeFirstResponderWithSelectionMovingForward:(BOOL)selectingForward completionHandler:(void (^)(BOOL didBecomeFirstResponder))completionHandler
@@ -3223,6 +3241,12 @@
         _page->autofillLoginCredentials([(UITextAutofillSuggestion *)textSuggestion username], [(UITextAutofillSuggestion *)textSuggestion password]);
         return;
     }
+#if ENABLE(DATALIST_ELEMENT)
+    if ([textSuggestion isKindOfClass:[WKDataListTextSuggestion class]]) {
+        _page->setAssistedNodeValue([textSuggestion inputText]);
+        return;
+    }
+#endif
     id <_WKInputDelegate> inputDelegate = [_webView _inputDelegate];
     if ([inputDelegate respondsToSelector:@selector(_webView:insertTextSuggestion:inInputSession:)])
         [inputDelegate _webView:_webView insertTextSuggestion:textSuggestion inInputSession:_formInputSession.get()];

Copied: trunk/Source/WebKit/UIProcess/ios/WebDataListSuggestionsDropdownIOS.h (from rev 235555, trunk/Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.h) (0 => 235556)


--- trunk/Source/WebKit/UIProcess/ios/WebDataListSuggestionsDropdownIOS.h	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/WebDataListSuggestionsDropdownIOS.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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
+
+#if ENABLE(DATALIST_ELEMENT) && PLATFORM(IOS)
+
+#import "UIKitSPI.h"
+#import "WebDataListSuggestionsDropdown.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+OBJC_CLASS WKContentView;
+OBJC_CLASS WKDataListSuggestionsControl;
+
+@interface WKDataListTextSuggestion : UITextSuggestion
+@end
+
+namespace WebKit {
+
+class WebDataListSuggestionsDropdownIOS : public WebDataListSuggestionsDropdown {
+public:
+    static Ref<WebDataListSuggestionsDropdownIOS> create(WebDataListSuggestionsDropdown::Client&, WKContentView *);
+
+    void didSelectOption(const String&);
+
+private:
+    WebDataListSuggestionsDropdownIOS(WebDataListSuggestionsDropdown::Client&, WKContentView *);
+
+    void show(WebCore::DataListSuggestionInformation&&) final;
+    void handleKeydownWithIdentifier(const String&) final;
+    void close() final;
+
+    WKContentView *m_contentView;
+    RetainPtr<WKDataListSuggestionsControl> m_suggestionsControl;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(DATALIST_ELEMENT) && PLATFORM(IOS)

Added: trunk/Source/WebKit/UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm (0 => 235556)


--- trunk/Source/WebKit/UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/WebDataListSuggestionsDropdownIOS.mm	2018-08-31 16:49:21 UTC (rev 235556)
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2018 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 "WebDataListSuggestionsDropdownIOS.h"
+
+#if ENABLE(DATALIST_ELEMENT) && PLATFORM(IOS)
+
+#import "WKContentView.h"
+#import "WKContentViewInteraction.h"
+#import "WKFormPeripheral.h"
+#import "WKFormPopover.h"
+#import "_WKFormInputSession.h"
+
+static const CGFloat maxVisibleSuggestions = 5;
+static const CGFloat suggestionsPopoverCellHeight = 44;
+static const CGFloat suggestionsPopoverWidth = 320;
+static NSString * const suggestionCellReuseIdentifier = @"WKDataListSuggestionCell";
+
+@interface WKDataListSuggestionsControl : NSObject {
+    WebKit::WebDataListSuggestionsDropdownIOS* _dropdown;
+    Vector<String> _suggestions;
+}
+
+@property (nonatomic, weak) WKContentView *view;
+
+- (instancetype)initWithInformation:(WebCore::DataListSuggestionInformation&&)information inView:(WKContentView *)view;
+- (void)updateWithInformation:(WebCore::DataListSuggestionInformation&&)information;
+- (void)showSuggestionsDropdown:(WebKit::WebDataListSuggestionsDropdownIOS *)dropdown activationType:(WebCore::DataListSuggestionActivationType)activationType;
+- (void)didSelectOptionAtIndex:(NSInteger)index;
+- (void)invalidate;
+
+- (NSArray<WKDataListTextSuggestion *> *)textSuggestions;
+- (NSInteger)suggestionsCount;
+- (String)suggestionAtIndex:(NSInteger)index;
+- (NSTextAlignment)textAlignment;
+@end
+
+@interface WKDataListSuggestionsPicker : WKDataListSuggestionsControl <UIPickerViewDataSource, UIPickerViewDelegate>
+@end
+
+@interface WKDataListSuggestionsPickerView : UIPickerView <WKFormControl>
+@property (nonatomic, weak) WKDataListSuggestionsControl *control;
+@end
+
+@interface WKDataListSuggestionsPopover : WKDataListSuggestionsControl
+@end
+
+@interface WKDataListSuggestionsViewController : UITableViewController
+@property (nonatomic, weak) WKDataListSuggestionsControl *control;
+
+- (void)reloadData;
+@end
+
+@implementation WKDataListTextSuggestion
+@end
+
+#pragma mark - WebDataListSuggestionsDropdownIOS
+
+namespace WebKit {
+
+Ref<WebDataListSuggestionsDropdownIOS> WebDataListSuggestionsDropdownIOS::create(WebDataListSuggestionsDropdown::Client& client, WKContentView *view)
+{
+    return adoptRef(*new WebDataListSuggestionsDropdownIOS(client, view));
+}
+
+WebDataListSuggestionsDropdownIOS::WebDataListSuggestionsDropdownIOS(WebDataListSuggestionsDropdown::Client& client, WKContentView *view)
+    : WebDataListSuggestionsDropdown(client)
+    , m_contentView(view)
+{
+}
+
+void WebDataListSuggestionsDropdownIOS::show(WebCore::DataListSuggestionInformation&& information)
+{
+    if (m_suggestionsControl) {
+        [m_suggestionsControl updateWithInformation:WTFMove(information)];
+        return;
+    }
+
+    WebCore::DataListSuggestionActivationType type = information.activationType;
+
+    if (currentUserInterfaceIdiomIsPad())
+        m_suggestionsControl = adoptNS([[WKDataListSuggestionsPopover alloc] initWithInformation:WTFMove(information) inView:m_contentView]);
+    else
+        m_suggestionsControl = adoptNS([[WKDataListSuggestionsPicker alloc] initWithInformation:WTFMove(information) inView:m_contentView]);
+
+    [m_suggestionsControl showSuggestionsDropdown:this activationType:type];
+}
+
+void WebDataListSuggestionsDropdownIOS::handleKeydownWithIdentifier(const String&)
+{
+}
+
+void WebDataListSuggestionsDropdownIOS::close()
+{
+    [m_suggestionsControl invalidate];
+    m_suggestionsControl = nil;
+    m_client->didCloseSuggestions();
+}
+
+void WebDataListSuggestionsDropdownIOS::didSelectOption(const String& selectedOption)
+{
+    if (!m_client)
+        return;
+
+    m_client->didSelectOption(selectedOption);
+    close();
+}
+
+} // namespace WebKit
+
+#pragma mark - WKDataListSuggestionsControl
+
+@implementation WKDataListSuggestionsControl
+
+- (instancetype)initWithInformation:(WebCore::DataListSuggestionInformation&&)information inView:(WKContentView *)view
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _view = view;
+    _suggestions = WTFMove(information.suggestions);
+
+    return self;
+}
+
+- (void)updateWithInformation:(WebCore::DataListSuggestionInformation&&)information
+{
+    _suggestions = WTFMove(information.suggestions);
+}
+
+- (void)showSuggestionsDropdown:(WebKit::WebDataListSuggestionsDropdownIOS *)dropdown activationType:(WebCore::DataListSuggestionActivationType)activationType
+{
+    _dropdown = dropdown;
+}
+
+- (void)didSelectOptionAtIndex:(NSInteger)index
+{
+    _dropdown->didSelectOption(_suggestions[index]);
+}
+
+- (void)invalidate
+{
+}
+
+- (NSArray<WKDataListTextSuggestion *> *)textSuggestions
+{
+    NSMutableArray *suggestions = [NSMutableArray array];
+
+    for (auto suggestion : _suggestions) {
+        [suggestions addObject:[WKDataListTextSuggestion textSuggestionWithInputText:suggestion]];
+        if (suggestions.count == 3)
+            break;
+    }
+
+    return suggestions;
+}
+
+- (NSInteger)suggestionsCount
+{
+    return _suggestions.size();
+}
+
+- (String)suggestionAtIndex:(NSInteger)index
+{
+    return _suggestions[index];
+}
+
+- (NSTextAlignment)textAlignment
+{
+    return _view.assistedNodeInformation.isRTL ? NSTextAlignmentRight : NSTextAlignmentLeft;
+}
+
+@end
+
+#pragma mark - WKDataListSuggestionsPicker
+
+@implementation WKDataListSuggestionsPicker  {
+    RetainPtr<WKDataListSuggestionsPickerView> _pickerView;
+}
+
+- (instancetype)initWithInformation:(WebCore::DataListSuggestionInformation&&)information inView:(WKContentView *)view
+{
+    if (!(self = [super initWithInformation:WTFMove(information) inView:view]))
+        return nil;
+
+    _pickerView = adoptNS([[WKDataListSuggestionsPickerView alloc] initWithFrame:CGRectZero]);
+    [_pickerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
+    [_pickerView setDataSource:self];
+    [_pickerView setDelegate:self];
+    [_pickerView setControl:self];
+    [_pickerView setSize:[UIKeyboard defaultSizeForInterfaceOrientation:UIApp.interfaceOrientation]];
+
+    return self;
+}
+
+- (void)updateWithInformation:(WebCore::DataListSuggestionInformation&&)information
+{
+    [super updateWithInformation:WTFMove(information)];
+    if (information.activationType != WebCore::DataListSuggestionActivationType::IndicatorClicked) {
+        [[self.view _formInputSession] setCustomInputView:nil];
+        [[self.view _formInputSession] setSuggestions:[self textSuggestions]];
+        return;
+    }
+
+    [[self.view _formInputSession] setCustomInputView:_pickerView.get()];
+
+    [_pickerView reloadAllComponents];
+    [_pickerView selectRow:0 inComponent:0 animated:NO];
+}
+
+- (void)showSuggestionsDropdown:(WebKit::WebDataListSuggestionsDropdownIOS *)dropdown activationType:(WebCore::DataListSuggestionActivationType)activationType
+{
+    [super showSuggestionsDropdown:dropdown activationType:activationType];
+    if (activationType == WebCore::DataListSuggestionActivationType::IndicatorClicked) {
+        [[self.view _formInputSession] setCustomInputView:_pickerView.get()];
+        [_pickerView selectRow:0 inComponent:0 animated:NO];
+    } else
+        [[self.view _formInputSession] setSuggestions:[self textSuggestions]];
+}
+
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
+{
+    return 1;
+}
+
+- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)columnIndex
+{
+    return [self suggestionsCount];
+}
+
+- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+    return [self suggestionAtIndex:row];
+}
+
+- (void)invalidate
+{
+    if ([[self.view _formInputSession] customInputView] == _pickerView.get())
+        [[self.view _formInputSession] setCustomInputView:nil];
+
+    [_pickerView setDelegate:nil];
+    [_pickerView setDataSource:nil];
+    [_pickerView setControl:nil];
+}
+
+@end
+
+@implementation WKDataListSuggestionsPickerView
+
+- (UIView *)controlView
+{
+    return self;
+}
+
+- (void)controlBeginEditing
+{
+}
+
+- (void)controlEndEditing
+{
+    [self.control didSelectOptionAtIndex:[self selectedRowInComponent:0]];
+}
+
+@end
+
+#pragma mark - WKDataListSuggestionsPopover
+
+@implementation WKDataListSuggestionsPopover  {
+    RetainPtr<WKFormRotatingAccessoryPopover> _popover;
+    RetainPtr<WKDataListSuggestionsViewController> _suggestionsViewController;
+}
+
+- (instancetype)initWithInformation:(WebCore::DataListSuggestionInformation&&)information inView:(WKContentView *)view
+{
+    if (!(self = [super initWithInformation:WTFMove(information) inView:view]))
+        return nil;
+
+    _popover = adoptNS([[WKFormRotatingAccessoryPopover alloc] initWithView:view]);
+
+    return self;
+}
+
+- (void)updateWithInformation:(WebCore::DataListSuggestionInformation&&)information
+{
+    [super updateWithInformation:WTFMove(information)];
+    [_suggestionsViewController reloadData];
+    [[self.view _formInputSession] setSuggestions:[self textSuggestions]];
+}
+
+- (void)showSuggestionsDropdown:(WebKit::WebDataListSuggestionsDropdownIOS *)dropdown activationType:(WebCore::DataListSuggestionActivationType)activationType
+{
+    [super showSuggestionsDropdown:dropdown activationType:activationType];
+
+    _suggestionsViewController = adoptNS([[WKDataListSuggestionsViewController alloc] initWithStyle:UITableViewStylePlain]);
+    [_suggestionsViewController setControl:self];
+    [_suggestionsViewController reloadData];
+    [[self.view _formInputSession] setSuggestions:[self textSuggestions]];
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [_popover setPopoverController:[[[UIPopoverController alloc] initWithContentViewController:_suggestionsViewController.get()] autorelease]];
+#pragma clang diagnostic pop
+
+    [_popover presentPopoverAnimated:NO];
+}
+
+- (void)invalidate
+{
+    [_suggestionsViewController setControl:nil];
+}
+
+- (void)didSelectOptionAtIndex:(NSInteger)index
+{
+    [super didSelectOptionAtIndex:index];
+    [[_popover popoverController] dismissPopoverAnimated:YES];
+    [[self.view _formInputSession] setSuggestions:@[ [WKDataListTextSuggestion textSuggestionWithInputText:[self suggestionAtIndex:index]] ]];
+}
+
+@end
+
+@implementation WKDataListSuggestionsViewController
+
+- (void)reloadData
+{
+    [self.tableView reloadData];
+    [self setPreferredContentSize:CGSizeMake(suggestionsPopoverWidth, maxVisibleSuggestions * suggestionsPopoverCellHeight + suggestionsPopoverCellHeight / 2)];
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+    return [self.control suggestionsCount];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:suggestionCellReuseIdentifier];
+    if (!cell)
+        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:suggestionCellReuseIdentifier] autorelease];
+
+    cell.textLabel.text = [self.control suggestionAtIndex:indexPath.row];
+    cell.textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+    cell.textLabel.textAlignment = [self.control textAlignment];
+
+    return cell;
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    [self.control didSelectOptionAtIndex:indexPath.row];
+}
+
+@end
+
+#endif // ENABLE(DATALIST_ELEMENT) && PLATFORM(IOS)

Modified: trunk/Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.h (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.h	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.h	2018-08-31 16:49:21 UTC (rev 235556)
@@ -39,7 +39,7 @@
     static Ref<WebDataListSuggestionsDropdownMac> create(WebDataListSuggestionsDropdown::Client&, NSView *);
     ~WebDataListSuggestionsDropdownMac();
 
-    void didSelectOption(String&);
+    void didSelectOption(const String&);
 
 private:
     WebDataListSuggestionsDropdownMac(WebDataListSuggestionsDropdown::Client&, NSView *);

Modified: trunk/Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.mm (235555 => 235556)


--- trunk/Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.mm	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.mm	2018-08-31 16:49:21 UTC (rev 235556)
@@ -106,7 +106,7 @@
     [m_dropdownUI showSuggestionsDropdown:this];
 }
 
-void WebDataListSuggestionsDropdownMac::didSelectOption(String& selectedOption)
+void WebDataListSuggestionsDropdownMac::didSelectOption(const String& selectedOption)
 {
     if (!m_client)
         return;

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (235555 => 235556)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2018-08-31 16:49:21 UTC (rev 235556)
@@ -1811,6 +1811,7 @@
 		E548EBD121015F0E00BE3C32 /* WKFormColorPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = E548EBCF21015F0E00BE3C32 /* WKFormColorPicker.h */; };
 		E568B91F20A3AB2F00E3C856 /* WebDataListSuggestionsDropdown.h in Headers */ = {isa = PBXBuildFile; fileRef = E568B91E20A3AB2F00E3C856 /* WebDataListSuggestionsDropdown.h */; };
 		E568B92220A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.h in Headers */ = {isa = PBXBuildFile; fileRef = E568B92020A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.h */; };
+		E5BEF6822130C48000F31111 /* WebDataListSuggestionsDropdownIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = E5BEF6802130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.h */; };
 		E5CB07DC20E1678F0022C183 /* WKFormColorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */; };
 		ECA680D81E690E2500731D20 /* WebProcessCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = ECA680D71E690DF800731D20 /* WebProcessCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		ED82A7F2128C6FAF004477B3 /* WKBundlePageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A22F0FF1289FCD90085E74F /* WKBundlePageOverlay.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4656,6 +4657,8 @@
 		E568B91E20A3AB2F00E3C856 /* WebDataListSuggestionsDropdown.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebDataListSuggestionsDropdown.h; sourceTree = "<group>"; };
 		E568B92020A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebDataListSuggestionsDropdownMac.h; sourceTree = "<group>"; };
 		E568B92120A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = WebDataListSuggestionsDropdownMac.mm; sourceTree = "<group>"; };
+		E5BEF6802130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebDataListSuggestionsDropdownIOS.h; path = ios/WebDataListSuggestionsDropdownIOS.h; sourceTree = "<group>"; };
+		E5BEF6812130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebDataListSuggestionsDropdownIOS.mm; path = ios/WebDataListSuggestionsDropdownIOS.mm; sourceTree = "<group>"; };
 		E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKFormColorControl.h; path = ios/forms/WKFormColorControl.h; sourceTree = "<group>"; };
 		E5CB07DB20E1678F0022C183 /* WKFormColorControl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKFormColorControl.mm; path = ios/forms/WKFormColorControl.mm; sourceTree = "<group>"; };
 		ECA680D31E6904B500731D20 /* ExtraPrivateSymbolsForTAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtraPrivateSymbolsForTAPI.h; sourceTree = "<group>"; };
@@ -5977,6 +5980,8 @@
 				2DAF06D518BD1A470081CEB1 /* SmartMagnificationController.mm */,
 				2DA944A91884E9BA00ED86DB /* TextCheckerIOS.mm */,
 				2DF9593418A42412009785A1 /* ViewGestureControllerIOS.mm */,
+				E5BEF6802130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.h */,
+				E5BEF6812130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.mm */,
 				2D3EF4411917646300034184 /* WebMemoryPressureHandlerIOS.h */,
 				2D3EF4401917646300034184 /* WebMemoryPressureHandlerIOS.mm */,
 				2DA944AB1884E9BA00ED86DB /* WebPageProxyIOS.mm */,
@@ -9510,6 +9515,7 @@
 				1AA83F6D1A5B63FF00026EC6 /* WebDatabaseProvider.h in Headers */,
 				E52CF55220A35C3A00DADA27 /* WebDataListSuggestionPicker.h in Headers */,
 				E568B91F20A3AB2F00E3C856 /* WebDataListSuggestionsDropdown.h in Headers */,
+				E5BEF6822130C48000F31111 /* WebDataListSuggestionsDropdownIOS.h in Headers */,
 				E568B92220A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.h in Headers */,
 				CD19A26E1A13E834008D650E /* WebDiagnosticLoggingClient.h in Headers */,
 				1A5B1C5518987EDF004FCF9B /* WebDocumentLoader.h in Headers */,

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (235555 => 235556)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-08-31 16:49:21 UTC (rev 235556)
@@ -3593,7 +3593,8 @@
 
 void WebPage::didCloseSuggestions()
 {
-    m_activeDataListSuggestionPicker->didCloseSuggestions();
+    if (m_activeDataListSuggestionPicker)
+        m_activeDataListSuggestionPicker->didCloseSuggestions();
     m_activeDataListSuggestionPicker = nullptr;
 }
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (235555 => 235556)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2018-08-31 16:44:23 UTC (rev 235555)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2018-08-31 16:49:21 UTC (rev 235556)
@@ -2209,6 +2209,18 @@
         }
     }
 
+    // Prevent the callout bar from showing when tapping on the datalist button.
+#if ENABLE(DATALIST_ELEMENT)
+    if (is<HTMLInputElement>(*hitNode)) {
+        const HTMLInputElement& input = downcast<HTMLInputElement>(*hitNode);
+        if (input.list()) {
+            HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(request.point, HitTestRequest::ReadOnly | HitTestRequest::Active);
+            if (result.innerNode() == input.dataListButtonElement())
+                info.preventTextInteraction = true;
+        }
+    }
+#endif
+
 #if ENABLE(DATA_INTERACTION)
     info.hasSelectionAtPosition = m_page->hasSelectionAtPosition(adjustedPoint);
 #endif
@@ -2477,6 +2489,9 @@
         }
 #endif
 
+#if ENABLE(DATALIST_ELEMENT)
+        information.hasSuggestions = !!element.list();
+#endif
         information.inputMode = element.canonicalInputMode();
         information.isReadOnly = element.isReadOnly();
         information.value = element.value();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to