[Datalist] Add button to TextFieldInputs with a datalist
authorakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 15 Aug 2018 20:42:26 +0000 (20:42 +0000)
committerakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 15 Aug 2018 20:42:26 +0000 (20:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187741

Reviewed by Tim Horton.

Source/WebCore:

TextFieldInputs that have an associated datalist element should be drawn as
combo boxes. However, we cannot use NSComboBox for this control, as NSComboBox
is not height-resizable. Furthermore, the input should also be able to contain
additional elements, such as the stepper for type=number and the cancel button
for type=search. For these reasons, we draw a button at the end of the input,
mimicking appearance of a combo box.

The list-button -webkit-appearance value was added to display the new button.

Tests: fast/forms/datalist/datalist-searchinput-appearance.html
       fast/forms/datalist/datalist-textinput-appearance.html

* Resources/ListButtonArrow.png: Added.
* Resources/ListButtonArrow@2x.png: Added.
* WebCore.xcodeproj/project.pbxproj:
* css/CSSPrimitiveValueMappings.h:
(WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
* css/CSSProperties.json:
* css/CSSValueKeywords.in:
* css/html.css:
(input::-webkit-list-button):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::dataListButtonElement const):
* html/HTMLInputElement.h:
* html/InputType.h:
(WebCore::InputType::dataListButtonElement const):
* html/TextFieldInputType.cpp:
(WebCore::TextFieldInputType::needsContainer const):
(WebCore::TextFieldInputType::createShadowSubtree):
(WebCore::TextFieldInputType::destroyShadowSubtree):
(WebCore::TextFieldInputType::listAttributeTargetChanged):
(WebCore::TextFieldInputType::dataListButtonElement const):
(WebCore::TextFieldInputType::dataListButtonElementWasClicked):
(WebCore::TextFieldInputType::didCloseSuggestions):
* html/TextFieldInputType.h:
* html/shadow/DataListButtonElement.cpp: Added.
(WebCore::DataListButtonElement::create):
(WebCore::DataListButtonElement::DataListButtonElement):
(WebCore::DataListButtonElement::~DataListButtonElement):
(WebCore::DataListButtonElement::defaultEventHandler):
* html/shadow/DataListButtonElement.h: Added.
* platform/ThemeTypes.h:
* rendering/RenderTheme.cpp:
(WebCore::RenderTheme::adjustStyle):
(WebCore::RenderTheme::adjustListButtonStyle const):
* rendering/RenderTheme.h:
* rendering/RenderThemeMac.h:
* rendering/RenderThemeMac.mm:
(-[WebListButtonCell drawWithFrame:inView:]):
(WebCore::RenderThemeMac::paintListButtonForInput):
(WebCore::RenderThemeMac::adjustListButtonStyle const):
(WebCore::RenderThemeMac::paintTextField):
(WebCore::RenderThemeMac::paintSearchField):
(WebCore::RenderThemeMac::paintSearchFieldCancelButton):
(WebCore::RenderThemeMac::listButton const):

Source/WebCore/PAL:

* pal/spi/cocoa/NSColorSPI.h: Added NSColorGetUserAccentColor().

Source/WebInspectorUI:

Add keyword completion for 'list-button'.

* UserInterface/External/CodeMirror/css.js:
* UserInterface/Models/CSSKeywordCompletions.js:

LayoutTests:

Added tests to verify appearance of TextFieldInputs with a datalist.

* fast/forms/datalist/datalist-searchinput-appearance.html: Added.
* fast/forms/datalist/datalist-textinput-appearance.html: Added.
* platform/ios/TestExpectations:
* platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.png: Added.
* platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.txt: Added.
* platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.png: Added.
* platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234898 268f45cc-cd09-0410-ab3c-d52691b4dbfc

33 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/forms/datalist/datalist-searchinput-appearance.html [new file with mode: 0644]
LayoutTests/fast/forms/datalist/datalist-textinput-appearance.html [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/PAL/ChangeLog
Source/WebCore/PAL/pal/spi/cocoa/NSColorSPI.h
Source/WebCore/Resources/ListButtonArrow.png [new file with mode: 0644]
Source/WebCore/Resources/ListButtonArrow@2x.png [new file with mode: 0644]
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSPrimitiveValueMappings.h
Source/WebCore/css/CSSProperties.json
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/css/html.css
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/InputType.h
Source/WebCore/html/TextFieldInputType.cpp
Source/WebCore/html/TextFieldInputType.h
Source/WebCore/html/shadow/DataListButtonElement.cpp [new file with mode: 0644]
Source/WebCore/html/shadow/DataListButtonElement.h [new file with mode: 0644]
Source/WebCore/platform/ThemeTypes.h
Source/WebCore/rendering/RenderTheme.cpp
Source/WebCore/rendering/RenderTheme.h
Source/WebCore/rendering/RenderThemeMac.h
Source/WebCore/rendering/RenderThemeMac.mm
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/External/CodeMirror/css.js
Source/WebInspectorUI/UserInterface/Models/CSSKeywordCompletions.js

index 6322941..74712e9 100644 (file)
@@ -1,3 +1,20 @@
+2018-08-15  Aditya Keerthi  <akeerthi@apple.com>
+
+        [Datalist] Add button to TextFieldInputs with a datalist
+        https://bugs.webkit.org/show_bug.cgi?id=187741
+
+        Reviewed by Tim Horton.
+
+        Added tests to verify appearance of TextFieldInputs with a datalist.
+
+        * fast/forms/datalist/datalist-searchinput-appearance.html: Added.
+        * fast/forms/datalist/datalist-textinput-appearance.html: Added.
+        * platform/ios/TestExpectations:
+        * platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.png: Added.
+        * platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.txt: Added.
+        * platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.png: Added.
+        * platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.txt: Added.
+
 2018-08-15  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r234870.
diff --git a/LayoutTests/fast/forms/datalist/datalist-searchinput-appearance.html b/LayoutTests/fast/forms/datalist/datalist-searchinput-appearance.html
new file mode 100644 (file)
index 0000000..8156c46
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<input id="fruit" list="fruits" type="search"/>
+<datalist id="fruits">
+    <option>Apple</option>
+    <option>Orange</option>
+    <option>Pear</option>
+</datalist>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/forms/datalist/datalist-textinput-appearance.html b/LayoutTests/fast/forms/datalist/datalist-textinput-appearance.html
new file mode 100644 (file)
index 0000000..deceeb9
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<input id="fruit" list="fruits" type="text"/>
+<datalist id="fruits">
+    <option>Apple</option>
+    <option>Orange</option>
+    <option>Pear</option>
+</datalist>
+
+</body>
+</html>
index 1bf6f6e..e562f91 100644 (file)
@@ -3199,6 +3199,8 @@ fast/block/block-only/relative-auto-with-parent-offset.html [ Failure ]
 # Datalist
 webkit.org/b/186714 fast/forms/datalist/datalist-show-hide.html [ Skip ]
 webkit.org/b/186714 fast/forms/datalist/datalist-textinput-keydown.html [ Skip ]
+fast/forms/datalist/datalist-searchinput-appearance.html [ Skip ]
+fast/forms/datalist/datalist-textinput-appearance.html  [ Skip ]
 
 # We are only accepting GLSL3 for macOS. 
 webkit.org/b/187982 webgl/2.0.0/conformance2/glsl3 [ Skip ]
diff --git a/LayoutTests/platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.png b/LayoutTests/platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.png
new file mode 100644 (file)
index 0000000..3ccea8a
Binary files /dev/null and b/LayoutTests/platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.txt b/LayoutTests/platform/mac/fast/forms/datalist/datalist-searchinput-appearance-expected.txt
new file mode 100644 (file)
index 0000000..2f96324
--- /dev/null
@@ -0,0 +1,14 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x39
+  RenderBlock {HTML} at (0,0) size 800x39
+    RenderBody {BODY} at (8,8) size 784x23
+      RenderTextControl {INPUT} at (2,2) size 173x19 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+        RenderFlexibleBox {DIV} at (3,0) size 167x19
+          RenderBlock {DIV} at (0,0) size 8x19
+          RenderBlock {DIV} at (8,3) size 128x13
+          RenderBlock {DIV} at (135,0) size 20x19
+      RenderText {#text} at (0,0) size 0x0
+      RenderText {#text} at (0,0) size 0x0
+layer at (21,13) size 128x13
+  RenderBlock {DIV} at (0,0) size 128x13
diff --git a/LayoutTests/platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.png b/LayoutTests/platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.png
new file mode 100644 (file)
index 0000000..ba67a71
Binary files /dev/null and b/LayoutTests/platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.txt b/LayoutTests/platform/mac/fast/forms/datalist/datalist-textinput-appearance-expected.txt
new file mode 100644 (file)
index 0000000..14c0805
--- /dev/null
@@ -0,0 +1,12 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x39
+  RenderBlock {HTML} at (0,0) size 800x39
+    RenderBody {BODY} at (8,8) size 784x23
+      RenderTextControl {INPUT} at (2,2) size 146x19 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+        RenderFlexibleBox {DIV} at (3,3) size 140x13
+          RenderBlock {DIV} at (0,0) size 128x13
+      RenderText {#text} at (0,0) size 0x0
+      RenderText {#text} at (0,0) size 0x0
+layer at (13,13) size 128x13
+  RenderBlock {DIV} at (0,0) size 128x13
index ac0011f..27f4473 100644 (file)
@@ -1,3 +1,66 @@
+2018-08-15  Aditya Keerthi  <akeerthi@apple.com>
+
+        [Datalist] Add button to TextFieldInputs with a datalist
+        https://bugs.webkit.org/show_bug.cgi?id=187741
+
+        Reviewed by Tim Horton.
+
+        TextFieldInputs that have an associated datalist element should be drawn as
+        combo boxes. However, we cannot use NSComboBox for this control, as NSComboBox
+        is not height-resizable. Furthermore, the input should also be able to contain
+        additional elements, such as the stepper for type=number and the cancel button
+        for type=search. For these reasons, we draw a button at the end of the input,
+        mimicking appearance of a combo box.
+
+        The list-button -webkit-appearance value was added to display the new button.
+
+        Tests: fast/forms/datalist/datalist-searchinput-appearance.html
+               fast/forms/datalist/datalist-textinput-appearance.html
+
+        * Resources/ListButtonArrow.png: Added.
+        * Resources/ListButtonArrow@2x.png: Added.
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSPrimitiveValueMappings.h:
+        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
+        * css/CSSProperties.json:
+        * css/CSSValueKeywords.in:
+        * css/html.css:
+        (input::-webkit-list-button):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::dataListButtonElement const):
+        * html/HTMLInputElement.h:
+        * html/InputType.h:
+        (WebCore::InputType::dataListButtonElement const):
+        * html/TextFieldInputType.cpp:
+        (WebCore::TextFieldInputType::needsContainer const):
+        (WebCore::TextFieldInputType::createShadowSubtree):
+        (WebCore::TextFieldInputType::destroyShadowSubtree):
+        (WebCore::TextFieldInputType::listAttributeTargetChanged):
+        (WebCore::TextFieldInputType::dataListButtonElement const):
+        (WebCore::TextFieldInputType::dataListButtonElementWasClicked):
+        (WebCore::TextFieldInputType::didCloseSuggestions):
+        * html/TextFieldInputType.h:
+        * html/shadow/DataListButtonElement.cpp: Added.
+        (WebCore::DataListButtonElement::create):
+        (WebCore::DataListButtonElement::DataListButtonElement):
+        (WebCore::DataListButtonElement::~DataListButtonElement):
+        (WebCore::DataListButtonElement::defaultEventHandler):
+        * html/shadow/DataListButtonElement.h: Added.
+        * platform/ThemeTypes.h:
+        * rendering/RenderTheme.cpp:
+        (WebCore::RenderTheme::adjustStyle):
+        (WebCore::RenderTheme::adjustListButtonStyle const):
+        * rendering/RenderTheme.h:
+        * rendering/RenderThemeMac.h:
+        * rendering/RenderThemeMac.mm:
+        (-[WebListButtonCell drawWithFrame:inView:]):
+        (WebCore::RenderThemeMac::paintListButtonForInput):
+        (WebCore::RenderThemeMac::adjustListButtonStyle const):
+        (WebCore::RenderThemeMac::paintTextField):
+        (WebCore::RenderThemeMac::paintSearchField):
+        (WebCore::RenderThemeMac::paintSearchFieldCancelButton):
+        (WebCore::RenderThemeMac::listButton const):
+
 2018-08-15  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r234870.
index 7d40285..188d7b6 100644 (file)
@@ -1,3 +1,12 @@
+2018-08-15  Aditya Keerthi  <akeerthi@apple.com>
+
+        [Datalist] Add button to TextFieldInputs with a datalist
+        https://bugs.webkit.org/show_bug.cgi?id=187741
+
+        Reviewed by Tim Horton.
+
+        * pal/spi/cocoa/NSColorSPI.h: Added NSColorGetUserAccentColor().
+
 2018-08-15  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r234870.
index b43a018..8161652 100644 (file)
 
 #import <AppKit/NSColor_Private.h>
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+#import <AppKit/NSColor_UserAccent.h>
+#endif
+
 #else
 
 @interface NSColor ()
 + (NSColor *)placeholderTextColor;
 @end
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+typedef NS_ENUM(NSInteger, NSUserAccentColor) {
+    NSUserAccentColorRed = 0,
+    NSUserAccentColorOrange,
+    NSUserAccentColorYellow,
+    NSUserAccentColorGreen,
+    NSUserAccentColorBlue,
+    NSUserAccentColorPurple,
+    NSUserAccentColorPink,
+
+    NSUserAccentColorNoColor = -1,
+};
+
+extern "C" NSUserAccentColor NSColorGetUserAccentColor(void);
+#endif
+
 #endif
diff --git a/Source/WebCore/Resources/ListButtonArrow.png b/Source/WebCore/Resources/ListButtonArrow.png
new file mode 100644 (file)
index 0000000..c01e778
Binary files /dev/null and b/Source/WebCore/Resources/ListButtonArrow.png differ
diff --git a/Source/WebCore/Resources/ListButtonArrow@2x.png b/Source/WebCore/Resources/ListButtonArrow@2x.png
new file mode 100644 (file)
index 0000000..c66e2ea
Binary files /dev/null and b/Source/WebCore/Resources/ListButtonArrow@2x.png differ
index d34f8b0..8128842 100644 (file)
                E4E9B1191810916F003ACCDF /* SimpleLineLayoutResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E9B1181810916F003ACCDF /* SimpleLineLayoutResolver.h */; };
                E4E9B11D1814569C003ACCDF /* SimpleLineLayoutFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E9B11C1814569C003ACCDF /* SimpleLineLayoutFunctions.h */; };
                E4F9EEF3156DA00700D23E7E /* StyleSheetContents.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               E59DD4B821098287003C8B47 /* ListButtonArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = E59DD4B721098285003C8B47 /* ListButtonArrow.png */; };
+               E516699120FF9918009D2C27 /* ListButtonArrow@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E516698F20FF9916009D2C27 /* ListButtonArrow@2x.png */; };
                E517670320B88C1400D41167 /* DataListSuggestionInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = E517670220B88C1400D41167 /* DataListSuggestionInformation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E52CF54D20A268AC00DADA27 /* DataListSuggestionsClient.h in Headers */ = {isa = PBXBuildFile; fileRef = E52CF54C20A268AC00DADA27 /* DataListSuggestionsClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E52CF54F20A35A2800DADA27 /* DataListSuggestionPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = E52CF54E20A35A2800DADA27 /* DataListSuggestionPicker.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               E58B45BA20AD07DD00991025 /* DataListButtonElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E58B45B820AD07DD00991025 /* DataListButtonElement.h */; };
+               E58B45BB20AD07DD00991025 /* DataListButtonElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E58B45B920AD07DD00991025 /* DataListButtonElement.cpp */; };
                E5BA7D63151437CA00FE1E3F /* LengthFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = E5BA7D62151437CA00FE1E3F /* LengthFunctions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                EBF5121C1696496C0056BD25 /* JSTypeConversions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBF5121A1696496C0056BD25 /* JSTypeConversions.cpp */; };
                EBF5121D1696496C0056BD25 /* JSTypeConversions.h in Headers */ = {isa = PBXBuildFile; fileRef = EBF5121B1696496C0056BD25 /* JSTypeConversions.h */; };
                E4E9B11C1814569C003ACCDF /* SimpleLineLayoutFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleLineLayoutFunctions.h; sourceTree = "<group>"; };
                E4F9EEF0156D84C400D23E7E /* StyleSheetContents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleSheetContents.cpp; sourceTree = "<group>"; };
                E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleSheetContents.h; sourceTree = "<group>"; };
+               E59DD4B721098285003C8B47 /* ListButtonArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ListButtonArrow.png; sourceTree = "<group>"; };
+               E516698F20FF9916009D2C27 /* ListButtonArrow@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ListButtonArrow@2x.png"; sourceTree = "<group>"; };
                E517670220B88C1400D41167 /* DataListSuggestionInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataListSuggestionInformation.h; sourceTree = "<group>"; };
                E51A81DE17298D7700BFCA61 /* JSPerformance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPerformance.cpp; sourceTree = "<group>"; };
                E526AF3E1727F8F200E41781 /* Performance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Performance.cpp; sourceTree = "<group>"; };
                E52CF54C20A268AC00DADA27 /* DataListSuggestionsClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataListSuggestionsClient.h; sourceTree = "<group>"; };
                E52CF54E20A35A2800DADA27 /* DataListSuggestionPicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataListSuggestionPicker.h; sourceTree = "<group>"; };
                E55F4979151B888000BB67DB /* LengthFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LengthFunctions.cpp; sourceTree = "<group>"; };
+               E58B45B820AD07DD00991025 /* DataListButtonElement.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataListButtonElement.h; sourceTree = "<group>"; };
+               E58B45B920AD07DD00991025 /* DataListButtonElement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DataListButtonElement.cpp; sourceTree = "<group>"; };
                E5BA7D62151437CA00FE1E3F /* LengthFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LengthFunctions.h; sourceTree = "<group>"; };
                EB081CD81696084400553730 /* TypeConversions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeConversions.h; sourceTree = "<group>"; };
                EB081CD91696084400553730 /* TypeConversions.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = TypeConversions.idl; sourceTree = "<group>"; };
                                51C4AA5118B28357007BFE9B /* mac */,
                                7C1E97251A9F9834007BF0FB /* AutoFillButtonElement.cpp */,
                                7C1E97261A9F9834007BF0FB /* AutoFillButtonElement.h */,
+                               E58B45B920AD07DD00991025 /* DataListButtonElement.cpp */,
+                               E58B45B820AD07DD00991025 /* DataListButtonElement.h */,
                                A7C9ABF61357A3BF00F5503F /* DetailsMarkerControl.cpp */,
                                A7C9ABF71357A3BF00F5503F /* DetailsMarkerControl.h */,
                                510192D318B6B9B7007FC7A1 /* ImageControlsRootElement.cpp */,
                                2D50A4B61CE10E0000198049 /* AttachmentPlaceholder@2x.png */,
                                D02B64B014089E56006EFA21 /* DictationPhraseWithAlternativesDot.png */,
                                D02B64B114089E56006EFA21 /* DictationPhraseWithAlternativesDot@2x.png */,
+                               E59DD4B721098285003C8B47 /* ListButtonArrow.png */,
+                               E516698F20FF9916009D2C27 /* ListButtonArrow@2x.png */,
                                BE8C753010681324001E93F5 /* SpellingDot.png */,
                                01E6C2E31194B2820050821C /* SpellingDot@2x.png */,
                                1C2417B91992C04100EF9938 /* SpellingDot@3x.png */,
                                BE23480D18A9871400E4B6E8 /* DataCue.h in Headers */,
                                C5227DF11C3C6DF100F5ED54 /* DataDetection.h in Headers */,
                                7C7941E51C56C29300A4C58E /* DataDetectorsCoreSoftLink.h in Headers */,
+                               E58B45BA20AD07DD00991025 /* DataListButtonElement.h in Headers */,
                                E517670320B88C1400D41167 /* DataListSuggestionInformation.h in Headers */,
                                E52CF54F20A35A2800DADA27 /* DataListSuggestionPicker.h in Headers */,
                                E52CF54D20A268AC00DADA27 /* DataListSuggestionsClient.h in Headers */,
                                D02B64B314089E56006EFA21 /* DictationPhraseWithAlternativesDot@2x.png in Resources */,
                                7CC7E3D717208C0F003C5277 /* IDNScriptWhiteList.txt in Resources */,
                                2D9F0E1314FF1CBF00BA0FF7 /* linearSRGB.icc in Resources */,
+                               E59DD4B821098287003C8B47 /* ListButtonArrow.png in Resources */,
+                               E516699120FF9918009D2C27 /* ListButtonArrow@2x.png in Resources */,
                                BCAD180A131C7A0D00990406 /* Localizable.strings in Resources */,
                                837A80131E1E127300026B9F /* Localizable.stringsdict in Resources */,
                                311C08BD18EB7CAF00B65615 /* mediaControlsApple.css in Resources */,
                                46C696CC1E7205FC00597937 /* CPUMonitor.cpp in Sources */,
                                1ABA76CA11D20E50004C201C /* CSSPropertyNames.cpp in Sources */,
                                BE23480C18A9870B00E4B6E8 /* DataCue.cpp in Sources */,
+                               E58B45BB20AD07DD00991025 /* DataListButtonElement.cpp in Sources */,
                                515BE18F1D54F5FB00DD7C68 /* EmptyGamepadProvider.cpp in Sources */,
                                724ED32C1A3A7E5400F5F13C /* EXTBlendMinMax.cpp in Sources */,
                                72F1ADA21A3904DC00014E18 /* EXTFragDepth.cpp in Sources */,
index 37936ea..6794ef9 100644 (file)
@@ -626,6 +626,11 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e)
         m_value.valueID = CSSValueColorWell;
         break;
 #endif
+#if ENABLE(DATALIST_ELEMENT)
+    case ListButtonPart:
+        m_value.valueID = CSSValueListButton;
+        break;
+#endif
     }
 }
 
index 4bbda84..537dd70 100644 (file)
                 "attachment",
                 "caps-lock-indicator",
                 "color-well",
+                "list-button",
                 "none"
             ],
             "status": {
index 211ff4c..9423127 100644 (file)
@@ -839,6 +839,9 @@ image-controls-button
 #if defined(ENABLE_INPUT_TYPE_COLOR) && ENABLE_INPUT_TYPE_COLOR
 color-well
 #endif
+#if defined(ENABLE_DATALIST_ELEMENT) && ENABLE_DATALIST_ELEMENT
+list-button
+#endif
 textarea
 #if defined(ENABLE_ATTACHMENT_ELEMENT) && ENABLE_ATTACHMENT_ELEMENT
 attachment
index f0ccb76..e6b189e 100644 (file)
@@ -616,6 +616,20 @@ input::-webkit-caps-lock-indicator {
     -webkit-user-select: none;
 }
 
+#if defined(ENABLE_DATALIST_ELEMENT) && ENABLE_DATALIST_ELEMENT
+input::-webkit-list-button {
+    -webkit-appearance: list-button;
+    display: block;
+    position: relative;
+    cursor: default;
+    align-self: stretch;
+    flex: none;
+    -webkit-user-select: none;
+    width: 16px;
+    height: 100%;
+}
+#endif
+
 keygen, select {
     border-radius: 5px;
 }
index 9db84a8..724de1d 100644 (file)
@@ -241,6 +241,13 @@ HTMLElement* HTMLInputElement::placeholderElement() const
     return m_inputType->placeholderElement();
 }
 
+#if ENABLE(DATALIST_ELEMENT)
+HTMLElement* HTMLInputElement::dataListButtonElement() const
+{
+    return m_inputType->dataListButtonElement();
+}
+#endif
+
 bool HTMLInputElement::shouldAutocomplete() const
 {
     if (m_autocomplete != Uninitialized)
index 8dd0cdf..fedb742 100644 (file)
@@ -150,6 +150,9 @@ public:
     HTMLElement* sliderTrackElement() const;
     HTMLElement* placeholderElement() const final;
     WEBCORE_EXPORT HTMLElement* autoFillButtonElement() const;
+#if ENABLE(DATALIST_ELEMENT)
+    HTMLElement* dataListButtonElement() const;
+#endif
 
     bool checked() const { return m_isChecked; }
     WEBCORE_EXPORT void setChecked(bool, TextFieldEventBehavior = DispatchNoEvent);
index d131ad5..828b4c0 100644 (file)
@@ -228,6 +228,9 @@ public:
     virtual HTMLElement* sliderThumbElement() const { return nullptr; }
     virtual HTMLElement* sliderTrackElement() const { return nullptr; }
     virtual HTMLElement* placeholderElement() const;
+#if ENABLE(DATALIST_ELEMENT)
+    virtual HTMLElement* dataListButtonElement() const { return nullptr; }
+#endif
 
     // Miscellaneous functions.
 
index 6fefffd..13c31ba 100644 (file)
@@ -285,6 +285,9 @@ RenderPtr<RenderElement> TextFieldInputType::createInputRenderer(RenderStyle&& s
 
 bool TextFieldInputType::needsContainer() const
 {
+#if ENABLE(DATALIST_ELEMENT)
+    return element()->hasAttributeWithoutSynchronization(listAttr);
+#endif
     return false;
 }
 
@@ -343,6 +346,12 @@ void TextFieldInputType::createShadowSubtree()
     }
 
     updateAutoFillButton();
+
+#if ENABLE(DATALIST_ELEMENT)
+    m_dataListDropdownIndicator = DataListButtonElement::create(element()->document(), *this);
+    m_dataListDropdownIndicator->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone, true);
+    m_container->appendChild(*m_dataListDropdownIndicator);
+#endif
 }
 
 HTMLElement* TextFieldInputType::containerElement() const
@@ -392,6 +401,9 @@ void TextFieldInputType::destroyShadowSubtree()
     m_innerSpinButton = nullptr;
     m_capsLockIndicator = nullptr;
     m_autoFillButton = nullptr;
+#if ENABLE(DATALIST)
+    m_dataListDropdownIndicator = nullptr;
+#endif
     m_container = nullptr;
 }
 
@@ -785,6 +797,25 @@ void TextFieldInputType::updateAutoFillButton()
 
 #if ENABLE(DATALIST_ELEMENT)
 
+void TextFieldInputType::listAttributeTargetChanged()
+{
+    if (!m_dataListDropdownIndicator)
+        return;
+
+    m_dataListDropdownIndicator->setInlineStyleProperty(CSSPropertyDisplay, element()->list() ? CSSValueBlock : CSSValueNone, true);
+}
+
+HTMLElement* TextFieldInputType::dataListButtonElement() const
+{
+    return m_dataListDropdownIndicator.get();
+}
+
+void TextFieldInputType::dataListButtonElementWasClicked()
+{
+    if (element()->list())
+        displaySuggestions(DataListSuggestionActivationType::IndicatorClicked);
+}
+
 IntRect TextFieldInputType::elementRectInRootViewCoordinates() const
 {
     if (!element()->renderer())
@@ -819,6 +850,8 @@ void TextFieldInputType::didSelectDataListOption(const String& selectedOption)
 void TextFieldInputType::didCloseSuggestions()
 {
     m_suggestionPicker = nullptr;
+    if (element()->renderer())
+        element()->renderer()->repaint();
 }
 
 void TextFieldInputType::displaySuggestions(DataListSuggestionActivationType type)
@@ -844,6 +877,11 @@ void TextFieldInputType::closeSuggestions()
         m_suggestionPicker->close();
 }
 
+bool TextFieldInputType::isPresentingAttachedView() const
+{
+    return !!m_suggestionPicker;
+}
+
 #endif
 
 } // namespace WebCore
index 34081bb..75d96c7 100644 (file)
@@ -32,6 +32,7 @@
 #pragma once
 
 #include "AutoFillButtonElement.h"
+#include "DataListButtonElement.h"
 #include "DataListSuggestionPicker.h"
 #include "DataListSuggestionsClient.h"
 #include "InputType.h"
@@ -46,7 +47,7 @@ class TextControlInnerTextElement;
 // It supports not only the types for BaseTextInputType but also type=number.
 class TextFieldInputType : public InputType, protected SpinButtonElement::SpinButtonOwner, protected AutoFillButtonElement::AutoFillButtonOwner
 #if ENABLE(DATALIST_ELEMENT)
-    , private DataListSuggestionsClient
+    , private DataListSuggestionsClient, protected DataListButtonElement::DataListButtonOwner
 #endif
 {
 protected:
@@ -64,6 +65,9 @@ protected:
     HTMLElement* innerSpinButtonElement() const final;
     HTMLElement* capsLockIndicatorElement() const final;
     HTMLElement* autoFillButtonElement() const final;
+#if ENABLE(DATALIST_ELEMENT)
+    HTMLElement* dataListButtonElement() const final;
+#endif
 
     virtual bool needsContainer() const;
     void createShadowSubtree() override;
@@ -120,6 +124,8 @@ private:
     void createAutoFillButton(AutoFillButtonType);
 
 #if ENABLE(DATALIST_ELEMENT)
+    bool isPresentingAttachedView() const final;
+    void listAttributeTargetChanged() final;
     void displaySuggestions(DataListSuggestionActivationType);
     void closeSuggestions();
 
@@ -129,6 +135,9 @@ private:
     void didSelectDataListOption(const String&) final;
     void didCloseSuggestions() final;
 
+    void dataListButtonElementWasClicked() final;
+    RefPtr<DataListButtonElement> m_dataListDropdownIndicator;
+
     std::unique_ptr<DataListSuggestionPicker> m_suggestionPicker;
 #endif
 
diff --git a/Source/WebCore/html/shadow/DataListButtonElement.cpp b/Source/WebCore/html/shadow/DataListButtonElement.cpp
new file mode 100644 (file)
index 0000000..a437f0d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 "DataListButtonElement.h"
+
+#if ENABLE(DATALIST_ELEMENT)
+
+#include "Event.h"
+#include "EventNames.h"
+#include "HTMLNames.h"
+#include "MouseEvent.h"
+#include <wtf/IsoMallocInlines.h>
+
+namespace WebCore {
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(DataListButtonElement);
+
+using namespace HTMLNames;
+
+Ref<DataListButtonElement> DataListButtonElement::create(Document& document, DataListButtonOwner& owner)
+{
+    return adoptRef(*new DataListButtonElement(document, owner));
+}
+
+DataListButtonElement::DataListButtonElement(Document& document, DataListButtonOwner& owner)
+    : HTMLDivElement(divTag, document)
+    , m_owner(owner)
+{
+    setPseudo(AtomicString("-webkit-list-button", AtomicString::ConstructFromLiteral));
+}
+
+DataListButtonElement::~DataListButtonElement() { }
+
+void DataListButtonElement::defaultEventHandler(Event& event)
+{
+    if (!is<MouseEvent>(event)) {
+        if (!event.defaultHandled())
+            HTMLDivElement::defaultEventHandler(event);
+        return;
+    }
+
+    MouseEvent& mouseEvent = downcast<MouseEvent>(event);
+
+    if (mouseEvent.type() == eventNames().clickEvent) {
+        m_owner.dataListButtonElementWasClicked();
+        event.setDefaultHandled();
+    }
+
+    if (!event.defaultHandled())
+        HTMLDivElement::defaultEventHandler(event);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(DATALIST_ELEMENT)
diff --git a/Source/WebCore/html/shadow/DataListButtonElement.h b/Source/WebCore/html/shadow/DataListButtonElement.h
new file mode 100644 (file)
index 0000000..fd95864
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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)
+
+#include "HTMLDivElement.h"
+
+namespace WebCore {
+
+class TextFieldInputType;
+
+class DataListButtonElement final : public HTMLDivElement {
+    WTF_MAKE_ISO_ALLOCATED(DataListButtonElement);
+public:
+    class DataListButtonOwner {
+    public:
+        virtual ~DataListButtonOwner() = default;
+        virtual void dataListButtonElementWasClicked() = 0;
+    };
+
+    ~DataListButtonElement();
+
+    static Ref<DataListButtonElement> create(Document&, DataListButtonOwner&);
+
+private:
+    explicit DataListButtonElement(Document&, DataListButtonOwner&);
+
+    void defaultEventHandler(Event&) override;
+
+    DataListButtonOwner& m_owner;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DATALIST_ELEMENT)
index 2a4bc09..cb6fa36 100644 (file)
@@ -54,6 +54,9 @@ enum ControlPart {
 #if ENABLE(INPUT_TYPE_COLOR)
     ColorWellPart,
 #endif
+#if ENABLE(DATALIST_ELEMENT)
+    ListButtonPart,
+#endif
     TextAreaPart,
 #if ENABLE(ATTACHMENT_ELEMENT)
     AttachmentPart, BorderlessAttachmentPart,
index 06d4cb4..34f3a1e 100644 (file)
@@ -272,6 +272,10 @@ void RenderTheme::adjustStyle(StyleResolver& styleResolver, RenderStyle& style,
     case BorderlessAttachmentPart:
         return adjustAttachmentStyle(styleResolver, style, element);
 #endif
+#if ENABLE(DATALIST_ELEMENT)
+    case ListButtonPart:
+        return adjustListButtonStyle(styleResolver, style, element);
+#endif
     default:
         break;
     }
@@ -1031,6 +1035,10 @@ bool RenderTheme::paintAttachment(const RenderObject&, const PaintInfo&, const I
 
 #if ENABLE(DATALIST_ELEMENT)
 
+void RenderTheme::adjustListButtonStyle(StyleResolver&, RenderStyle&, const Element*) const
+{
+}
+
 LayoutUnit RenderTheme::sliderTickSnappingThreshold() const
 {
     return 0;
index 75393b4..5e07f40 100644 (file)
@@ -339,6 +339,10 @@ protected:
     virtual bool paintAttachment(const RenderObject&, const PaintInfo&, const IntRect&);
 #endif
 
+#if ENABLE(DATALIST_ELEMENT)
+    virtual void adjustListButtonStyle(StyleResolver&, RenderStyle&, const Element*) const;
+#endif
+
     virtual void adjustProgressBarStyle(StyleResolver&, RenderStyle&, const Element*) const;
     virtual bool paintProgressBar(const RenderObject&, const PaintInfo&, const IntRect&) { return true; }
 
index 5c18d4d..d98de3a 100644 (file)
@@ -155,6 +155,11 @@ private:
     void adjustSearchFieldResultsButtonStyle(StyleResolver&, RenderStyle&, const Element*) const final;
     bool paintSearchFieldResultsButton(const RenderBox&, const PaintInfo&, const IntRect&) final;
 
+#if ENABLE(DATALIST_ELEMENT)
+    void paintListButtonForInput(const RenderObject&, GraphicsContext&, const FloatRect&);
+    void adjustListButtonStyle(StyleResolver&, RenderStyle&, const Element*) const;
+#endif
+
 #if ENABLE(VIDEO)
     bool supportsClosedCaptioning() const final { return true; }
 #endif
@@ -219,6 +224,9 @@ private:
     NSSliderCell *sliderThumbHorizontal() const;
     NSSliderCell *sliderThumbVertical() const;
     NSTextFieldCell *textField() const;
+#if ENABLE(DATALIST_ELEMENT)
+    NSCell *listButton() const;
+#endif
 
 #if ENABLE(METER_ELEMENT)
     NSLevelIndicatorStyle levelIndicatorStyleFor(ControlPart) const;
@@ -247,6 +255,9 @@ private:
 #if ENABLE(SERVICE_CONTROLS)
     mutable RetainPtr<NSServicesRolloverButtonCell> m_servicesRolloverButton;
 #endif
+#if ENABLE(DATALIST_ELEMENT)
+    mutable RetainPtr<NSCell> m_listButton;
+#endif
 
     bool m_isSliderThumbHorizontalPressed { false };
     bool m_isSliderThumbVerticalPressed { false };
index e2ead86..b889dac 100644 (file)
@@ -197,6 +197,76 @@ static const double progressAnimationNumFrames = 256;
 @implementation WebCoreRenderThemeBundle
 @end
 
+#if ENABLE(DATALIST_ELEMENT)
+
+static const CGFloat listButtonWidth = 16.0f;
+static const CGFloat listButtonCornerRadius = 5.0f;
+
+@interface WebListButtonCell : NSCell
+@end
+
+@implementation WebListButtonCell
+- (void)drawWithFrame:(NSRect)cellFrame inView:(__unused NSView *)controlView
+{
+    CGFloat listButtonCornerRadius = 5.0f;
+    NSPoint topLeft = NSMakePoint(NSMinX(cellFrame), NSMinY(cellFrame));
+    NSPoint topRight = NSMakePoint(NSMaxX(cellFrame), NSMinY(cellFrame));
+    NSPoint bottomRight = NSMakePoint(NSMaxX(cellFrame), NSMaxY(cellFrame));
+    NSPoint bottomLeft = NSMakePoint(NSMinX(cellFrame), NSMaxY(cellFrame));
+
+    NSBezierPath *path = [NSBezierPath bezierPath];
+    [path moveToPoint:topLeft];
+
+    [path lineToPoint:NSMakePoint(topRight.x - listButtonCornerRadius, topRight.y)];
+    [path curveToPoint:NSMakePoint(topRight.x, topRight.y + listButtonCornerRadius) controlPoint1:topRight controlPoint2:topRight];
+
+    [path lineToPoint:NSMakePoint(bottomRight.x, bottomRight.y - listButtonCornerRadius)];
+    [path curveToPoint:NSMakePoint(bottomRight.x - listButtonCornerRadius, bottomRight.y) controlPoint1:bottomRight controlPoint2:bottomRight];
+
+    [path lineToPoint:bottomLeft];
+    [path lineToPoint:topLeft];
+
+    if ([self userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft) {
+        NSAffineTransform *transform = [NSAffineTransform transform];
+        [transform translateXBy:NSMidX(cellFrame) yBy:NSMidY(cellFrame)];
+        [transform rotateByDegrees:180];
+        [transform translateXBy:-1 * NSMidX(cellFrame) yBy:-1 * NSMidY(cellFrame)];
+        [path transformUsingAffineTransform:transform];
+    }
+
+    // FIXME: Obtain the gradient colors from CoreUI or AppKit
+    RetainPtr<NSGradient> gradient;
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+    NSUserAccentColor accentColor = NSColorGetUserAccentColor();
+    if (accentColor == NSUserAccentColorRed)
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(212.0 / 255) green:(122.0 / 255) blue:(117.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(189.0 / 255) green:(34.0 / 255) blue:(23.0 / 255) alpha:1.0]]);
+    else if (accentColor == NSUserAccentColorOrange)
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(242.0 / 255) green:(185.0 / 255) blue:(113.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(242.0 / 255) green:(145.0 / 255) blue:(17.0 / 255) alpha:1.0]]);
+    else if (accentColor == NSUserAccentColorYellow)
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(241.0 / 255) green:(212.0 / 255) blue:(119.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(239.0 / 255) green:(193.0 / 255) blue:(27.0 / 255) alpha:1.0]]);
+    else if (accentColor == NSUserAccentColorGreen)
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(132.0 / 255) green:(186.0 / 255) blue:(120.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(46.0 / 255) green:(145.0 / 255) blue:(30.0 / 255) alpha:1.0]]);
+    else if (accentColor == NSUserAccentColorPurple)
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(178.0 / 255) green:(128.0 / 255) blue:(175.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(130.0 / 255) green:(43.0 / 255) blue:(123.0 / 255) alpha:1.0]]);
+    else if (accentColor == NSUserAccentColorPink)
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(225.0 / 255) green:(126.0 / 255) blue:(165.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(211.0 / 255) green:(42.0 / 255) blue:(105.0 / 255) alpha:1.0]]);
+    else if (accentColor == NSUserAccentColorNoColor)
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(177.0 / 255) green:(177.0 / 255) blue:(182.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(145.0 / 255) green:(145.0 / 255) blue:(150.0 / 255) alpha:1.0]]);
+    else
+#endif
+        gradient = adoptNS([[NSGradient alloc] initWithStartingColor:[NSColor colorWithRed:(114.0 / 255) green:(164.0 / 255) blue:(243.0 / 255) alpha:1.0] endingColor:[NSColor colorWithRed:(45.0 / 255) green:(117.0 / 255) blue:(246.0 / 255) alpha:1.0]]);
+
+    [gradient drawInBezierPath:path angle:90];
+    if ([self isHighlighted]) {
+        NSColor *overlay = [NSColor colorWithWhite:0 alpha:0.1];
+        [overlay setFill];
+        [path fill];
+    }
+}
+@end
+
+#endif // ENABLE(DATALIST_ELEMENT)
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -1048,6 +1118,54 @@ NSControlSize RenderThemeMac::controlSizeForSystemFont(const RenderStyle& style)
     return NSControlSizeMini;
 }
 
+#if ENABLE(DATALIST_ELEMENT)
+
+void RenderThemeMac::paintListButtonForInput(const RenderObject& o, GraphicsContext& context, const FloatRect& r)
+{
+    // We can't paint an NSComboBoxCell since they are not height-resizable.
+    const auto& input = downcast<HTMLInputElement>(*(o.generatingNode()));
+    NSCell *listButton = this->listButton();
+
+    NSRect listButtonFrame = NSMakeRect(r.maxX() - listButtonWidth, r.y(), listButtonWidth, r.height());
+    if (!o.style().isLeftToRightDirection()) {
+        listButtonFrame.origin.x = r.x();
+        [listButton setUserInterfaceLayoutDirection:NSUserInterfaceLayoutDirectionRightToLeft];
+    } else
+        [listButton setUserInterfaceLayoutDirection:NSUserInterfaceLayoutDirectionLeftToRight];
+
+    [listButton setHighlighted:input.isPresentingAttachedView()];
+    if (!input.isPresentingAttachedView())
+        updatePressedState(listButton, *(input.dataListButtonElement()->renderer()));
+
+    [listButton drawWithFrame:listButtonFrame inView:documentViewFor(o)];
+    [listButton setControlView:nil];
+
+    RefPtr<Image> image;
+    float imageScale = 1;
+    if (o.document().deviceScaleFactor() >= 2) {
+        image = Image::loadPlatformResource("ListButtonArrow@2x");
+        imageScale = 2;
+    } else
+        image = Image::loadPlatformResource("ListButtonArrow");
+
+    FloatRect imageRect(0, 0, image->width() / imageScale, image->height() / imageScale);
+    imageRect.setX(NSMidX(listButtonFrame) - imageRect.width() / 2);
+    imageRect.setY(NSMidY(listButtonFrame) - imageRect.height() / 2);
+
+    context.drawImage(*image, imageRect);
+}
+
+void RenderThemeMac::adjustListButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
+{
+    // Add a margin to place the button at end of the input field.
+    if (style.isLeftToRightDirection())
+        style.setMarginRight(Length(-4, Fixed));
+    else
+        style.setMarginLeft(Length(-4, Fixed));
+}
+
+#endif
+
 bool RenderThemeMac::paintTextField(const RenderObject& o, const PaintInfo& paintInfo, const FloatRect& r)
 {
     LocalCurrentGraphicsContext localContext(paintInfo.context());
@@ -1074,6 +1192,15 @@ bool RenderThemeMac::paintTextField(const RenderObject& o, const PaintInfo& pain
 
     [textField setControlView:nil];
 
+#if ENABLE(DATALIST_ELEMENT)
+    if (!is<HTMLInputElement>(o.generatingNode()))
+        return false;
+
+    const auto& input = downcast<HTMLInputElement>(*(o.generatingNode()));
+    if (input.list())
+        paintListButtonForInput(o, paintInfo.context(), adjustedPaintRect);
+#endif
+
     return false;
 }
 
@@ -1831,6 +1958,15 @@ bool RenderThemeMac::paintSearchField(const RenderObject& o, const PaintInfo& pa
     [search setControlView:nil];
     [search resetSearchButtonCell];
 
+#if ENABLE(DATALIST_ELEMENT)
+    if (!is<HTMLInputElement>(o.generatingNode()))
+        return false;
+
+    const auto& input = downcast<HTMLInputElement>(*(o.generatingNode()));
+    if (input.list())
+        paintListButtonForInput(o, paintInfo.context(), FloatRect(unzoomedRect.x(), unzoomedRect.y() + 1, unzoomedRect.width(), unzoomedRect.height() - 2));
+#endif
+
     return false;
 }
 
@@ -1933,9 +2069,15 @@ bool RenderThemeMac::paintSearchFieldCancelButton(const RenderBox& box, const Pa
     float zoomLevel = box.style().effectiveZoom();
 
     FloatRect localBounds = adjustedCancelButtonRect([search cancelButtonRectForBounds:NSRect(snappedIntRect(inputBox.contentBoxRect()))]);
+
     // Adjust position based on the content direction.
     float adjustedXPosition;
-    if (box.style().direction() == TextDirection::RTL)
+
+    if (is<HTMLInputElement>(*input)) {
+        RenderBox* cancelButtonBox = downcast<RenderBox>(downcast<HTMLInputElement>(*input).cancelButtonElement()->renderer());
+        // The cancel button won't always be the rightmost element.
+        adjustedXPosition = inputBox.contentBoxRect().x() + (cancelButtonBox->absoluteContentBox().x() - inputBox.absoluteContentBox().x());
+    } else if (box.style().direction() == TextDirection::RTL)
         adjustedXPosition = inputBox.contentBoxRect().x();
     else
         adjustedXPosition = inputBox.contentBoxRect().maxX() - localBounds.size().width();
@@ -2270,6 +2412,16 @@ NSTextFieldCell* RenderThemeMac::textField() const
     return m_textField.get();
 }
 
+#if ENABLE(DATALIST_ELEMENT)
+NSCell *RenderThemeMac::listButton() const
+{
+    if (!m_listButton)
+        m_listButton = adoptNS([[WebListButtonCell alloc] init]);
+
+    return m_listButton.get();
+}
+#endif
+
 String RenderThemeMac::fileListNameForWidth(const FileList* fileList, const FontCascade& font, int width, bool multipleFilesAllowed) const
 {
     if (width <= 0)
index 3bb3be7..03e1783 100644 (file)
@@ -1,3 +1,15 @@
+2018-08-15  Aditya Keerthi  <akeerthi@apple.com>
+
+        [Datalist] Add button to TextFieldInputs with a datalist
+        https://bugs.webkit.org/show_bug.cgi?id=187741
+
+        Reviewed by Tim Horton.
+
+        Add keyword completion for 'list-button'.
+
+        * UserInterface/External/CodeMirror/css.js:
+        * UserInterface/Models/CSSKeywordCompletions.js:
+
 2018-08-15  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: REGRESSION(r?): the probe sidebar doesn't show up when adding probes
index 75a0e74..3eb2250 100644 (file)
@@ -626,7 +626,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
     "katakana", "katakana-iroha", "keep-all", "khmer",
     "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
     "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
-    "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
+    "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "list-button", "listitem",
     "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
     "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
     "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
index 3567bed..f225ae3 100644 (file)
@@ -1040,7 +1040,7 @@ WI.CSSKeywordCompletions._propertyKeywordMap = {
     ],
     /*
     "-webkit-appearance": [
-        "none", "checkbox", "radio", "push-button", "square-button", "button", "button-bevel", "default-button", "inner-spin-button", "listbox", "listitem", "media-enter-fullscreen-button", "media-exit-fullscreen-button", "media-fullscreen-volume-slider", "media-fullscreen-volume-slider-thumb", "media-mute-button", "media-play-button", "media-overlay-play-button", "media-seek-back-button", "media-seek-forward-button", "media-rewind-button", "media-return-to-realtime-button", "media-toggle-closed-captions-button", "media-slider", "media-sliderthumb", "media-volume-slider-container", "media-volume-slider", "media-volume-sliderthumb", "media-volume-slider-mute-button", "media-controls-background", "media-controls-fullscreen-background", "media-current-time-display", "media-time-remaining-display", "menulist", "menulist-button", "menulist-text", "menulist-textfield", "meter", "progress-bar", "progress-bar-value", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "caret", "searchfield", "searchfield-decoration", "searchfield-results-decoration", "searchfield-results-button", "searchfield-cancel-button", "snapshotted-plugin-overlay", "textfield", "relevancy-level-indicator", "continuous-capacity-level-indicator", "discrete-capacity-level-indicator", "rating-level-indicator", "textarea", "attachment", "caps-lock-indicator", "color-well"
+        "none", "checkbox", "radio", "push-button", "square-button", "button", "button-bevel", "default-button", "inner-spin-button", "listbox", "listitem", "media-enter-fullscreen-button", "media-exit-fullscreen-button", "media-fullscreen-volume-slider", "media-fullscreen-volume-slider-thumb", "media-mute-button", "media-play-button", "media-overlay-play-button", "media-seek-back-button", "media-seek-forward-button", "media-rewind-button", "media-return-to-realtime-button", "media-toggle-closed-captions-button", "media-slider", "media-sliderthumb", "media-volume-slider-container", "media-volume-slider", "media-volume-sliderthumb", "media-volume-slider-mute-button", "media-controls-background", "media-controls-fullscreen-background", "media-current-time-display", "media-time-remaining-display", "menulist", "menulist-button", "menulist-text", "menulist-textfield", "meter", "progress-bar", "progress-bar-value", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "caret", "searchfield", "searchfield-decoration", "searchfield-results-decoration", "searchfield-results-button", "searchfield-cancel-button", "snapshotted-plugin-overlay", "textfield", "relevancy-level-indicator", "continuous-capacity-level-indicator", "discrete-capacity-level-indicator", "rating-level-indicator", "textarea", "attachment", "caps-lock-indicator", "color-well", "list-button"
     ],
     */
     "-webkit-animation-trigger": [