[macOS] Color wells should appear pressed when presenting a color picker
authorakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 12 Aug 2018 20:19:25 +0000 (20:19 +0000)
committerakeerthi@apple.com <akeerthi@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 12 Aug 2018 20:19:25 +0000 (20:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188477

Reviewed by Tim Horton.

Source/WebCore:

Currently, when clicking on a color well, the color well loses its pressed
appearance once the mouse is lifted. Because of this behavior, the color well
does not appear to be active when the color picker is displayed.

Added the color-well -webkit-appearance value to control the drawing of the color
well separate from other buttons. Also added a new ControlState, named
PresentingState. A control can be in this state whenever it is presenting some
attached view. In the case of the color well this is the color picker. The
Information as to whether a form control is in the presenting state comes from
isPresentingAttachedView() in HTMLInputElement.

* css/CSSPrimitiveValueMappings.h:
(WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
* css/CSSProperties.json:
* css/CSSValueKeywords.in:
* css/html.css:
(input[type="color"]::-webkit-color-swatch):
* html/ColorInputType.cpp:
(WebCore::ColorInputType::isPresentingAttachedView const):
(WebCore::ColorInputType::elementDidBlur):
(WebCore::ColorInputType::didEndChooser):
* html/ColorInputType.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::isPresentingAttachedView const):
* html/HTMLInputElement.h:
* html/InputType.cpp:
(WebCore::InputType::isPresentingAttachedView const):
* html/InputType.h:
* platform/ControlStates.h:
* platform/ThemeTypes.h:
* platform/mac/ThemeMac.mm:
(WebCore::updateStates):
(WebCore::setUpButtonCell):
(WebCore::paintColorWell):
(WebCore::ThemeMac::minimumControlSize const):
(WebCore::ThemeMac::controlBorder const):
(WebCore::ThemeMac::paint):
* rendering/RenderTheme.cpp:
(WebCore::RenderTheme::adjustStyle):
(WebCore::RenderTheme::paint):
(WebCore::RenderTheme::paintBorderOnly):
(WebCore::RenderTheme::paintDecorations):
(WebCore::RenderTheme::isControlStyled const):
(WebCore::RenderTheme::extractControlStatesForRenderer const):
(WebCore::RenderTheme::isPresenting const):
* rendering/RenderTheme.h:
* rendering/RenderThemeMac.mm:
(WebCore::RenderThemeMac::adjustRepaintRect):

Source/WebInspectorUI:

Add keyword completion for 'color-well'.

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

Source/WebKit:

In order for the color well to accurately reflect the state of the picker, it is
necessary to ensure that the picker is destroyed at the appropriate time.

Added windowWillClose and didClosePopover delegate methods to destroy the picker
it has been closed. Also added a call to WebColorPicker::endPicker in
WebColorPickerMac's implementation of endPicker to ensure that the object is
destroyed. Removed redundant calls to endPicker in the WebPageProxy.

The hitTest method was overridden in WKPopoverColorWell to ensure that AppKit's
view does not block our drawn color well from receiving click events.

* UIProcess/WebColorPicker.cpp:
(WebKit::WebColorPicker::endPicker):
* UIProcess/WebColorPicker.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::endColorPicker):
(WebKit::WebPageProxy::didEndColorPicker):
(WebKit::WebPageProxy::resetState):
(WebKit::WebPageProxy::closeOverlayedViews):
* UIProcess/mac/WebColorPickerMac.mm:
(WebKit::WebColorPickerMac::~WebColorPickerMac):
(WebKit::WebColorPickerMac::endPicker):
(-[WKPopoverColorWell popoverDidClose:]):
(-[WKPopoverColorWell hitTest:]):
(-[WKColorPopoverMac setAndShowPicker:withColor:suggestions:]):
(-[WKColorPopoverMac invalidate]):
(-[WKColorPopoverMac windowWillClose:]):
(-[WKColorPopoverMac didClosePopover]):

LayoutTests:

Rebaseline tests to match new color-well appearance.

* platform/mac/fast/forms/color/input-appearance-color-expected.png:
* platform/mac/fast/forms/color/input-appearance-color-expected.txt:

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

28 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png
LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/css/CSSPrimitiveValueMappings.h
Source/WebCore/css/CSSProperties.json
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/css/html.css
Source/WebCore/html/ColorInputType.cpp
Source/WebCore/html/ColorInputType.h
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/InputType.cpp
Source/WebCore/html/InputType.h
Source/WebCore/platform/ControlStates.h
Source/WebCore/platform/ThemeTypes.h
Source/WebCore/platform/mac/ThemeMac.mm
Source/WebCore/rendering/RenderTheme.cpp
Source/WebCore/rendering/RenderTheme.h
Source/WebCore/rendering/RenderThemeMac.mm
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/External/CodeMirror/css.js
Source/WebInspectorUI/UserInterface/Models/CSSKeywordCompletions.js
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebColorPicker.cpp
Source/WebKit/UIProcess/WebColorPicker.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/mac/WebColorPickerMac.mm

index 932161c..75f50ea 100644 (file)
@@ -1,3 +1,15 @@
+2018-08-12  Aditya Keerthi  <akeerthi@apple.com>
+
+        [macOS] Color wells should appear pressed when presenting a color picker
+        https://bugs.webkit.org/show_bug.cgi?id=188477
+
+        Reviewed by Tim Horton.
+
+        Rebaseline tests to match new color-well appearance.
+
+        * platform/mac/fast/forms/color/input-appearance-color-expected.png:
+        * platform/mac/fast/forms/color/input-appearance-color-expected.txt:
+
 2018-08-12  Zalan Bujtas  <zalan@apple.com>
 
         [LFC] Float prev/next sibling should prevent top/bottom margin collapsing with parent.
index bc2eda5..53ef125 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png and b/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png differ
index f70b56d..1aa356b 100644 (file)
@@ -12,10 +12,10 @@ layer at (0,0) size 800x600
         RenderBR {BR} at (456,14) size 1x0
         RenderBlock {INPUT} at (0,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#000000] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#000000] [border: (1px solid #8A8A8A)]
         RenderBlock {INPUT} at (44,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#000000] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#000000] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {H3} at (0,100) size 784x23
         RenderText {#text} at (0,0) size 162x22
@@ -26,32 +26,32 @@ layer at (0,0) size 800x600
         RenderBR {BR} at (589,14) size 1x0
         RenderBlock {INPUT} at (0,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (44,21) size 4x18
           text run at (44,21) width 4: " "
         RenderBlock {INPUT} at (48,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (92,21) size 4x18
           text run at (92,21) width 4: " "
         RenderBlock {INPUT} at (96,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (140,21) size 4x18
           text run at (140,21) width 4: " "
         RenderBlock {INPUT} at (144,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (188,21) size 4x18
           text run at (188,21) width 4: " "
         RenderBlock {INPUT} at (192,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (236,21) size 4x18
           text run at (236,21) width 4: " "
         RenderBlock {INPUT} at (240,18) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {H3} at (0,200) size 784x23
         RenderText {#text} at (0,0) size 122x22
@@ -59,52 +59,52 @@ layer at (0,0) size 800x600
       RenderBlock (anonymous) at (0,241) size 784x24
         RenderBlock {INPUT} at (0,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#FF0000] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#FF0000] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (44,3) size 4x18
           text run at (44,3) width 4: " "
         RenderBlock {INPUT} at (48,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (92,3) size 4x18
           text run at (92,3) width 4: " "
         RenderBlock {INPUT} at (96,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#0000FF] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#0000FF] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (140,3) size 4x18
           text run at (140,3) width 4: " "
         RenderBlock {INPUT} at (144,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#EC008C] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#EC008C] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (188,3) size 4x18
           text run at (188,3) width 4: " "
         RenderBlock {INPUT} at (192,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#40E0D0] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#40E0D0] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (236,3) size 4x18
           text run at (236,3) width 4: " "
         RenderBlock {INPUT} at (240,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#FF0000] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#FF0000] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (284,3) size 4x18
           text run at (284,3) width 4: " "
         RenderBlock {INPUT} at (288,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (332,3) size 4x18
           text run at (332,3) width 4: " "
         RenderBlock {INPUT} at (336,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#0000FF] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#0000FF] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (380,3) size 4x18
           text run at (380,3) width 4: " "
         RenderBlock {INPUT} at (384,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#EC008C] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#EC008C] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (428,3) size 4x18
           text run at (428,3) width 4: " "
         RenderBlock {INPUT} at (432,0) size 44x23 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 38x21
-            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#40E0D0] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 34x13 [bgcolor=#40E0D0] [border: (1px solid #8A8A8A)]
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {H3} at (0,283) size 784x23
         RenderText {#text} at (0,0) size 118x22
@@ -112,4 +112,4 @@ layer at (0,0) size 800x600
       RenderBlock (anonymous) at (0,324) size 784x31
         RenderBlock {INPUT} at (0,0) size 100x30 [bgcolor=#FFFFFF] [border: none (2px inset #000000) none (2px inset #000000)]
           RenderFlexibleBox {DIV} at (3,1) size 94x28
-            RenderBlock {DIV} at (2,4) size 90x20 [bgcolor=#FF0000] [border: (1px solid #777777)]
+            RenderBlock {DIV} at (2,4) size 90x20 [bgcolor=#FF0000] [border: (1px solid #8A8A8A)]
index 3aee6be..ba71a19 100644 (file)
@@ -1,3 +1,59 @@
+2018-08-12  Aditya Keerthi  <akeerthi@apple.com>
+
+        [macOS] Color wells should appear pressed when presenting a color picker
+        https://bugs.webkit.org/show_bug.cgi?id=188477
+
+        Reviewed by Tim Horton.
+
+        Currently, when clicking on a color well, the color well loses its pressed
+        appearance once the mouse is lifted. Because of this behavior, the color well
+        does not appear to be active when the color picker is displayed.
+
+        Added the color-well -webkit-appearance value to control the drawing of the color
+        well separate from other buttons. Also added a new ControlState, named
+        PresentingState. A control can be in this state whenever it is presenting some
+        attached view. In the case of the color well this is the color picker. The
+        Information as to whether a form control is in the presenting state comes from
+        isPresentingAttachedView() in HTMLInputElement.
+
+        * css/CSSPrimitiveValueMappings.h:
+        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
+        * css/CSSProperties.json:
+        * css/CSSValueKeywords.in:
+        * css/html.css:
+        (input[type="color"]::-webkit-color-swatch):
+        * html/ColorInputType.cpp:
+        (WebCore::ColorInputType::isPresentingAttachedView const):
+        (WebCore::ColorInputType::elementDidBlur):
+        (WebCore::ColorInputType::didEndChooser):
+        * html/ColorInputType.h:
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::isPresentingAttachedView const):
+        * html/HTMLInputElement.h:
+        * html/InputType.cpp:
+        (WebCore::InputType::isPresentingAttachedView const):
+        * html/InputType.h:
+        * platform/ControlStates.h:
+        * platform/ThemeTypes.h:
+        * platform/mac/ThemeMac.mm:
+        (WebCore::updateStates):
+        (WebCore::setUpButtonCell):
+        (WebCore::paintColorWell):
+        (WebCore::ThemeMac::minimumControlSize const):
+        (WebCore::ThemeMac::controlBorder const):
+        (WebCore::ThemeMac::paint):
+        * rendering/RenderTheme.cpp:
+        (WebCore::RenderTheme::adjustStyle):
+        (WebCore::RenderTheme::paint):
+        (WebCore::RenderTheme::paintBorderOnly):
+        (WebCore::RenderTheme::paintDecorations):
+        (WebCore::RenderTheme::isControlStyled const):
+        (WebCore::RenderTheme::extractControlStatesForRenderer const):
+        (WebCore::RenderTheme::isPresenting const):
+        * rendering/RenderTheme.h:
+        * rendering/RenderThemeMac.mm:
+        (WebCore::RenderThemeMac::adjustRepaintRect):
+
 2018-08-12  Zalan Bujtas  <zalan@apple.com>
 
         [LFC] Float prev/next sibling should prevent top/bottom margin collapsing with parent.
index 5ec5127..eb47772 100644 (file)
@@ -621,6 +621,11 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e)
         m_value.valueID = CSSValueApplePayButton;
         break;
 #endif
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+        m_value.valueID = CSSValueColorWell;
+        break;
+#endif
     }
 }
 
index a51b2e6..49dde2e 100644 (file)
                 "textarea",
                 "attachment",
                 "caps-lock-indicator",
+                "color-well",
                 "none"
             ],
             "status": {
index 02047b5..211ff4c 100644 (file)
@@ -836,6 +836,9 @@ image-controls-button
 #if defined(ENABLE_APPLE_PAY) && ENABLE_APPLE_PAY
 -apple-pay-button
 #endif
+#if defined(ENABLE_INPUT_TYPE_COLOR) && ENABLE_INPUT_TYPE_COLOR
+color-well
+#endif
 textarea
 #if defined(ENABLE_ATTACHMENT_ELEMENT) && ENABLE_ATTACHMENT_ELEMENT
 attachment
index 1dc3d92..f0ccb76 100644 (file)
@@ -873,10 +873,11 @@ select:focus {
 
 input[type="color"] {
 #if !(defined(WTF_PLATFORM_IOS) && WTF_PLATFORM_IOS)
-    -webkit-appearance: square-button;
+    -webkit-appearance: color-well;
 #endif
     width: 44px;
     height: 23px;
+    outline: none;
 }
 
 input[type="color"]::-webkit-color-swatch-wrapper {
@@ -889,7 +890,7 @@ input[type="color"]::-webkit-color-swatch-wrapper {
 
 input[type="color"]::-webkit-color-swatch {
     background-color: #000000;
-    border: 1px solid #777777;
+    border: 1px solid #8A8A8A;
     flex: 1;
 }
 
index 2a135f9..1415782 100644 (file)
@@ -104,6 +104,11 @@ bool ColorInputType::isColorControl() const
     return true;
 }
 
+bool ColorInputType::isPresentingAttachedView() const
+{
+    return !!m_chooser;
+}
+
 const AtomicString& ColorInputType::formControlType() const
 {
     return InputTypeNames::color();
@@ -185,6 +190,11 @@ void ColorInputType::detach()
     endColorChooser();
 }
 
+void ColorInputType::elementDidBlur()
+{
+    endColorChooser();
+}
+
 bool ColorInputType::shouldRespectListAttribute()
 {
     return true;
@@ -214,6 +224,8 @@ void ColorInputType::didChooseColor(const Color& color)
 void ColorInputType::didEndChooser()
 {
     m_chooser = nullptr;
+    if (element()->renderer())
+        element()->renderer()->repaint();
 }
 
 void ColorInputType::endColorChooser()
index bb2962b..cdae3cb 100644 (file)
@@ -54,6 +54,7 @@ private:
     bool isMouseFocusable() const final;
     bool isKeyboardFocusable(KeyboardEvent*) const final;
     bool isColorControl() const final;
+    bool isPresentingAttachedView() const final;
     const AtomicString& formControlType() const final;
     bool supportsRequired() const final;
     String fallbackValue() const final;
@@ -62,6 +63,7 @@ private:
     void setValue(const String&, bool valueChanged, TextFieldEventBehavior) final;
     void handleDOMActivateEvent(Event&) final;
     void detach() final;
+    void elementDidBlur() final;
     bool shouldRespectListAttribute() final;
     bool typeMismatchFor(const String&) const final;
     bool shouldResetOnDocumentActivation() final;
index dc5aa3d..187a67b 100644 (file)
@@ -1631,6 +1631,11 @@ void HTMLInputElement::listAttributeTargetChanged()
 
 #endif // ENABLE(DATALIST_ELEMENT)
 
+bool HTMLInputElement::isPresentingAttachedView() const
+{
+    return m_inputType->isPresentingAttachedView();
+}
+
 bool HTMLInputElement::isSteppable() const
 {
     return m_inputType->isSteppable();
index 3729b89..8dd0cdf 100644 (file)
@@ -93,6 +93,8 @@ public:
     WEBCORE_EXPORT ExceptionOr<void> stepUp(int = 1);
     WEBCORE_EXPORT ExceptionOr<void> stepDown(int = 1);
 
+    bool isPresentingAttachedView() const;
+
     // stepUp()/stepDown() for user-interaction.
     bool isSteppable() const;
 
index 9167fe9..52317fa 100644 (file)
@@ -941,6 +941,11 @@ bool InputType::shouldAppearIndeterminate() const
     return false;
 }
 
+bool InputType::isPresentingAttachedView() const
+{
+    return false;
+}
+
 bool InputType::supportsSelectionAPI() const
 {
     return false;
index fe2a40b..d131ad5 100644 (file)
@@ -263,6 +263,7 @@ public:
     virtual String defaultToolTip() const;
     virtual bool matchesIndeterminatePseudoClass() const;
     virtual bool shouldAppearIndeterminate() const;
+    virtual bool isPresentingAttachedView() const;
     virtual bool supportsSelectionAPI() const;
     virtual Color valueAsColor() const;
     virtual void selectColor(StringView);
index 1dce8b7..9db97c5 100644 (file)
@@ -53,6 +53,7 @@ public:
         WindowInactiveState = 1 << 6,
         IndeterminateState = 1 << 7,
         SpinUpState = 1 << 8, // Sub-state for HoverState and PressedState.
+        PresentingState = 1 << 9,
         AllStates = 0xffffffff
     };
 
index 33cb30e..2a4bc09 100644 (file)
@@ -51,6 +51,9 @@ enum ControlPart {
 #if ENABLE(APPLE_PAY)
     ApplePayButtonPart,
 #endif
+#if ENABLE(INPUT_TYPE_COLOR)
+    ColorWellPart,
+#endif
     TextAreaPart,
 #if ENABLE(ATTACHMENT_ELEMENT)
     AttachmentPart, BorderlessAttachmentPart,
index 4831fff..fa94c47 100644 (file)
@@ -212,6 +212,10 @@ static void updateStates(NSCell* cell, const ControlStates& controlStates, bool
         [(NSButtonCell*)cell _setState:newState animated:useAnimation];
     }
 
+    // Presenting state
+    if (states & ControlStates::PresentingState)
+        [(NSButtonCell*)cell _setHighlighted:YES animated:NO];
+
     // Window inactive state does not need to be checked explicitly, since we paint parented to 
     // a view in a window whose key state can be detected.
 }
@@ -492,7 +496,11 @@ static void setUpButtonCell(NSButtonCell *cell, ControlPart part, const ControlS
 {
     // Set the control size based off the rectangle we're painting into.
     const std::array<IntSize, 3>& sizes = buttonSizes();
-    if (part == SquareButtonPart || zoomedSize.height() > buttonSizes()[NSControlSizeRegular].height() * zoomFactor) {
+    if (part == SquareButtonPart
+#if ENABLE(INPUT_TYPE_COLOR)
+        || part == ColorWellPart
+#endif
+        || zoomedSize.height() > buttonSizes()[NSControlSizeRegular].height() * zoomFactor) {
         // Use the square button
         if ([cell bezelStyle] != NSBezelStyleShadowlessSquare)
             [cell setBezelStyle:NSBezelStyleShadowlessSquare];
@@ -699,6 +707,46 @@ bool ThemeMac::drawCellOrFocusRingWithViewIntoContext(NSCell *cell, GraphicsCont
     return needsRepaint;
 }
 
+// Color Well
+
+#if ENABLE(INPUT_TYPE_COLOR)
+static void paintColorWell(ControlStates& controlStates, GraphicsContext& context, const FloatRect& zoomedRect, float zoomFactor, ScrollView* scrollView, float deviceScaleFactor, float pageScaleFactor)
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS
+
+    // Determine the width and height needed for the control and prepare the cell for painting.
+    ControlStates::States states = controlStates.states();
+    NSButtonCell *buttonCell = button(ColorWellPart, controlStates, IntSize(zoomedRect.size()), zoomFactor);
+    GraphicsContextStateSaver stateSaver(context);
+
+    NSControlSize controlSize = [buttonCell controlSize];
+    IntSize zoomedSize = buttonSizes()[controlSize];
+    zoomedSize.setWidth(zoomedRect.width()); // Buttons don't ever constrain width, so the zoomed width can just be honored.
+    zoomedSize.setHeight(zoomedSize.height() * zoomFactor);
+    FloatRect inflatedRect = zoomedRect;
+
+    LocalCurrentGraphicsContext localContext(context);
+
+    NSView *view = ThemeMac::ensuredView(scrollView, controlStates);
+    NSWindow *window = [view window];
+    NSButtonCell *previousDefaultButtonCell = [window defaultButtonCell];
+
+    bool useImageBuffer = pageScaleFactor != 1.0f || zoomFactor != 1.0f;
+    bool needsRepaint = ThemeMac::drawCellOrFocusRingWithViewIntoContext(buttonCell, context, inflatedRect, view, true, states & ControlStates::FocusState, useImageBuffer, deviceScaleFactor);
+    if ([previousDefaultButtonCell isEqual:buttonCell])
+        [window setDefaultButtonCell:nil];
+
+    controlStates.setNeedsRepaint(needsRepaint);
+
+    [buttonCell setControlView:nil];
+
+    if (![previousDefaultButtonCell isEqual:buttonCell])
+        [window setDefaultButtonCell:previousDefaultButtonCell];
+
+    END_BLOCK_OBJC_EXCEPTIONS
+}
+#endif
+
 // Theme overrides
 
 int ThemeMac::baselinePositionAdjustment(ControlPart part) const
@@ -749,6 +797,9 @@ LengthSize ThemeMac::minimumControlSize(ControlPart part, const FontCascade& fon
 {
     switch (part) {
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart:
         return { { 0, Fixed }, { static_cast<int>(15 * zoomFactor), Fixed } };
@@ -766,6 +817,9 @@ LengthBox ThemeMac::controlBorder(ControlPart part, const FontCascade& font, con
 {
     switch (part) {
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart:
         return LengthBox(0, zoomedBox.right().value(), 0, zoomedBox.left().value());
@@ -865,6 +919,11 @@ void ThemeMac::paint(ControlPart part, ControlStates& states, GraphicsContext& c
         case SquareButtonPart:
             paintButton(part, states, context, zoomedRect, zoomFactor, scrollView, deviceScaleFactor, pageScaleFactor);
             break;
+#if ENABLE(INPUT_TYPE_COLOR)
+        case ColorWellPart:
+            paintColorWell(states, context, zoomedRect, zoomFactor, scrollView, deviceScaleFactor, pageScaleFactor);
+            break;
+#endif
         case InnerSpinButtonPart:
             paintStepper(states, context, zoomedRect, zoomFactor, scrollView);
             break;
index 56d403b..06d4cb4 100644 (file)
@@ -116,6 +116,9 @@ void RenderTheme::adjustStyle(StyleResolver& styleResolver, RenderStyle& style,
     case RadioPart:
     case PushButtonPart:
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart: {
         // Border
@@ -200,6 +203,9 @@ void RenderTheme::adjustStyle(StyleResolver& styleResolver, RenderStyle& style,
         return adjustRadioStyle(styleResolver, style, element);
     case PushButtonPart:
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart:
         return adjustButtonStyle(styleResolver, style, element);
@@ -300,6 +306,9 @@ bool RenderTheme::paint(const RenderBox& box, ControlStates& controlStates, cons
     case RadioPart:
     case PushButtonPart:
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart:
     case InnerSpinButtonPart:
@@ -322,6 +331,9 @@ bool RenderTheme::paint(const RenderBox& box, ControlStates& controlStates, cons
         return paintRadio(box, paintInfo, integralSnappedRect);
     case PushButtonPart:
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart:
         return paintButton(box, paintInfo, integralSnappedRect);
@@ -450,6 +462,9 @@ bool RenderTheme::paintBorderOnly(const RenderBox& box, const PaintInfo& paintIn
     case RadioPart:
     case PushButtonPart:
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart:
     case MenulistPart:
@@ -503,6 +518,9 @@ bool RenderTheme::paintDecorations(const RenderBox& box, const PaintInfo& paintI
     case PushButtonPart:
         return paintPushButtonDecorations(box, paintInfo, integralSnappedRect);
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
         return paintSquareButtonDecorations(box, paintInfo, integralSnappedRect);
     case ButtonPart:
         return paintButtonDecorations(box, paintInfo, integralSnappedRect);
@@ -715,6 +733,9 @@ bool RenderTheme::isControlStyled(const RenderStyle& style, const BorderData& bo
     switch (style.appearance()) {
     case PushButtonPart:
     case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+    case ColorWellPart:
+#endif
     case DefaultButtonPart:
     case ButtonPart:
     case ListboxPart:
@@ -801,6 +822,8 @@ ControlStates::States RenderTheme::extractControlStatesForRenderer(const RenderO
         states |= ControlStates::WindowInactiveState;
     if (isIndeterminate(o))
         states |= ControlStates::IndeterminateState;
+    if (isPresenting(o))
+        states |= ControlStates::PresentingState;
     return states;
 }
 
@@ -885,6 +908,11 @@ bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject& renderer) const
     return downcast<SpinButtonElement>(*node).upDownState() == SpinButtonElement::Up;
 }
 
+bool RenderTheme::isPresenting(const RenderObject& o) const
+{
+    return is<HTMLInputElement>(o.node()) && downcast<HTMLInputElement>(*o.node()).isPresentingAttachedView();
+}
+
 bool RenderTheme::isDefault(const RenderObject& o) const
 {
     // A button should only have the default appearance if the page is active
index e2248b3..75393b4 100644 (file)
@@ -404,6 +404,7 @@ public:
     bool isSpinUpButtonPartPressed(const RenderObject&) const;
     bool isHovered(const RenderObject&) const;
     bool isSpinUpButtonPartHovered(const RenderObject&) const;
+    bool isPresenting(const RenderObject&) const;
     bool isReadOnlyControl(const RenderObject&) const;
     bool isDefault(const RenderObject&) const;
 
index e2053ad..6ce24c8 100644 (file)
@@ -872,6 +872,9 @@ void RenderThemeMac::adjustRepaintRect(const RenderObject& renderer, FloatRect&
         case RadioPart:
         case PushButtonPart:
         case SquareButtonPart:
+#if ENABLE(INPUT_TYPE_COLOR)
+        case ColorWellPart:
+#endif
         case DefaultButtonPart:
         case ButtonPart:
         case InnerSpinButtonPart:
index 697738c..ef94d4b 100644 (file)
@@ -1,3 +1,15 @@
+2018-08-12  Aditya Keerthi  <akeerthi@apple.com>
+
+        [macOS] Color wells should appear pressed when presenting a color picker
+        https://bugs.webkit.org/show_bug.cgi?id=188477
+
+        Reviewed by Tim Horton.
+
+        Add keyword completion for 'color-well'.
+
+        * UserInterface/External/CodeMirror/css.js:
+        * UserInterface/Models/CSSKeywordCompletions.js:
+
 2018-08-09  Nikita Vasilyev  <nvasilyev@apple.com>
 
         Web Inspector: Dark Mode: SourceCodeTextEditor error/warning text widget is too light
index 0e65c21..75a0e74 100644 (file)
@@ -597,7 +597,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
     "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
     "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
     "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
-    "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
+    "col-resize", "collapse", "color", "color-burn", "color-dodge", "color-well", "column", "column-reverse",
     "compact", "condensed", "contain", "content", "contents",
     "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
     "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
index 019e3fd..3567bed 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"
+        "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"
     ],
     */
     "-webkit-animation-trigger": [
index 4e96af3..9e11b23 100644 (file)
@@ -1,3 +1,39 @@
+2018-08-12  Aditya Keerthi  <akeerthi@apple.com>
+
+        [macOS] Color wells should appear pressed when presenting a color picker
+        https://bugs.webkit.org/show_bug.cgi?id=188477
+
+        Reviewed by Tim Horton.
+
+        In order for the color well to accurately reflect the state of the picker, it is
+        necessary to ensure that the picker is destroyed at the appropriate time.
+
+        Added windowWillClose and didClosePopover delegate methods to destroy the picker
+        it has been closed. Also added a call to WebColorPicker::endPicker in
+        WebColorPickerMac's implementation of endPicker to ensure that the object is
+        destroyed. Removed redundant calls to endPicker in the WebPageProxy.
+
+        The hitTest method was overridden in WKPopoverColorWell to ensure that AppKit's
+        view does not block our drawn color well from receiving click events.
+
+        * UIProcess/WebColorPicker.cpp:
+        (WebKit::WebColorPicker::endPicker):
+        * UIProcess/WebColorPicker.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::endColorPicker):
+        (WebKit::WebPageProxy::didEndColorPicker):
+        (WebKit::WebPageProxy::resetState):
+        (WebKit::WebPageProxy::closeOverlayedViews):
+        * UIProcess/mac/WebColorPickerMac.mm:
+        (WebKit::WebColorPickerMac::~WebColorPickerMac):
+        (WebKit::WebColorPickerMac::endPicker):
+        (-[WKPopoverColorWell popoverDidClose:]):
+        (-[WKPopoverColorWell hitTest:]):
+        (-[WKColorPopoverMac setAndShowPicker:withColor:suggestions:]):
+        (-[WKColorPopoverMac invalidate]):
+        (-[WKColorPopoverMac windowWillClose:]):
+        (-[WKColorPopoverMac didClosePopover]):
+
 2018-08-10  David Kilzer  <ddkilzer@apple.com>
 
         [Cocoa] WebKit::PlatformPopupMenuData should use member initialization
index 1132c07..60263d7 100644 (file)
@@ -39,18 +39,13 @@ WebColorPicker::~WebColorPicker()
 {
 }
 
-void WebColorPicker::invalidate()
-{
-    endPicker();
-    m_client = 0;
-}
-
 void WebColorPicker::endPicker()
 {
     if (!m_client)
         return;
 
     m_client->didEndColorPicker();
+    m_client = nullptr;
 }
 
 void WebColorPicker::setSelectedColor(const WebCore::Color& color)
index 1848d34..df0be5c 100644 (file)
@@ -56,8 +56,6 @@ public:
 
     virtual ~WebColorPicker();
 
-    void invalidate();
-
     virtual void endPicker();
     virtual void setSelectedColor(const WebCore::Color&);
     virtual void showColorPicker(const WebCore::Color&);
index 7a6f275..ac17b42 100644 (file)
@@ -4800,7 +4800,8 @@ void WebPageProxy::setColorPickerColor(const WebCore::Color& color)
 
 void WebPageProxy::endColorPicker()
 {
-    ASSERT(m_colorPicker);
+    if (!m_colorPicker)
+        return;
 
     m_colorPicker->endPicker();
 }
@@ -4818,13 +4819,7 @@ void WebPageProxy::didEndColorPicker()
     if (!isValid())
         return;
 
-#if ENABLE(INPUT_TYPE_COLOR)
-    if (m_colorPicker) {
-        m_colorPicker->invalidate();
-        m_colorPicker = nullptr;
-    }
-#endif
-
+    m_colorPicker = nullptr;
     m_process->send(Messages::WebPage::DidEndColorPicker(), m_pageID);
 }
 #endif
@@ -6113,13 +6108,6 @@ void WebPageProxy::resetState(ResetStateReason resetStateReason)
     m_touchEventTracking.reset();
 #endif
 
-#if ENABLE(INPUT_TYPE_COLOR)
-    if (m_colorPicker) {
-        m_colorPicker->invalidate();
-        m_colorPicker = nullptr;
-    }
-#endif
-
 #if ENABLE(GEOLOCATION)
     m_geolocationPermissionRequestManager.invalidateRequests();
 #endif
@@ -7657,8 +7645,7 @@ void WebPageProxy::closeOverlayedViews()
 #endif
 
 #if ENABLE(INPUT_TYPE_COLOR_POPOVER) && ENABLE(INPUT_TYPE_COLOR)
-    if (m_colorPicker)
-        endColorPicker();
+    endColorPicker();
 #endif
 }
 
index 9505564..60792f0 100644 (file)
@@ -52,14 +52,20 @@ static const CGFloat colorPickerMatrixNumColumns = 12.0;
 static const CGFloat colorPickerMatrixSwatchWidth = 12.0;
 static const CGFloat colorPickerMatrixBorderWidth = 1.0;
 
+@protocol WKPopoverColorWellDelegate <NSObject>
+- (void)didClosePopover;
+@end
+
 @interface WKPopoverColorWell : NSPopoverColorWell {
     RetainPtr<NSColorList> _suggestedColors;
 }
 
+@property (nonatomic, weak) id<WKPopoverColorWellDelegate> webDelegate;
+
 - (void)setSuggestedColors:(NSColorList *)suggestedColors;
 @end
 
-@interface WKColorPopoverMac : NSObject<WKColorPickerUIMac, NSWindowDelegate> {
+@interface WKColorPopoverMac : NSObject<WKColorPickerUIMac, WKPopoverColorWellDelegate, NSWindowDelegate> {
 @private
     BOOL _lastChangedByUser;
     WebColorPickerMac *_picker;
@@ -89,8 +95,10 @@ Ref<WebColorPickerMac> WebColorPickerMac::create(WebColorPicker::Client* client,
 
 WebColorPickerMac::~WebColorPickerMac()
 {
-    if (m_colorPickerUI)
-        endPicker();
+    if (m_colorPickerUI) {
+        [m_colorPickerUI invalidate];
+        m_colorPickerUI = nil;
+    }
 }
 
 WebColorPickerMac::WebColorPickerMac(WebColorPicker::Client* client, const WebCore::Color& initialColor, const WebCore::IntRect& rect, Vector<WebCore::Color>&& suggestions, NSView *view)
@@ -108,6 +116,7 @@ void WebColorPickerMac::endPicker()
 {
     [m_colorPickerUI invalidate];
     m_colorPickerUI = nil;
+    WebColorPicker::endPicker();
 }
 
 void WebColorPickerMac::setSelectedColor(const WebCore::Color& color)
@@ -198,6 +207,15 @@ void WebColorPickerMac::showColorPicker(const WebCore::Color& color)
     [popover showRelativeToRect:self.bounds ofView:self preferredEdge:NSMinYEdge];
 }
 
+- (void)popoverDidClose:(NSNotification *)notification {
+    [self.webDelegate didClosePopover];
+}
+
+- (NSView *)hitTest:(NSPoint)point
+{
+    return nil;
+}
+
 - (void)setSuggestedColors:(NSColorList *)suggestedColors
 {
     _suggestedColors = suggestedColors;
@@ -226,6 +244,7 @@ void WebColorPickerMac::showColorPicker(const WebCore::Color& color)
     _picker = picker;
 
     [_popoverWell setTarget:self];
+    [_popoverWell setWebDelegate:self];
     [_popoverWell setAction:@selector(didChooseColor:)];
     [_popoverWell setColor:color];
 
@@ -238,15 +257,11 @@ void WebColorPickerMac::showColorPicker(const WebCore::Color& color)
 
     [_popoverWell setSuggestedColors:suggestedColors];
     [_popoverWell _showPopover];
+
+    [[NSColorPanel sharedColorPanel] setDelegate:self];
     
     _lastChangedByUser = YES;
 }
-- (void)dealloc
-{
-    ASSERT(!_popoverWell);
-    ASSERT(!_picker);
-    [super dealloc];
-}
 
 - (void)invalidate
 {
@@ -254,14 +269,26 @@ void WebColorPickerMac::showColorPicker(const WebCore::Color& color)
     [_popoverWell setTarget:nil];
     [_popoverWell setAction:nil];
     [_popoverWell deactivate];
+    
     _popoverWell = nil;
     _picker = nil;
+
+    NSColorPanel *panel = [NSColorPanel sharedColorPanel];
+    if (panel.delegate == self) {
+        panel.delegate = nil;
+        [panel close];
+    }
 }
 
 - (void)windowWillClose:(NSNotification *)notification
 {
-    _lastChangedByUser = YES;
-    _picker->endPicker();
+    if (!_picker)
+        return;
+
+    if (notification.object == [NSColorPanel sharedColorPanel]) {
+        _lastChangedByUser = YES;
+        _picker->endPicker();
+    }
 }
 
 - (void)didChooseColor:(id)sender
@@ -284,6 +311,15 @@ void WebColorPickerMac::showColorPicker(const WebCore::Color& color)
     [_popoverWell setColor:color];
 }
 
+- (void)didClosePopover
+{
+    if (!_picker)
+        return;
+
+    if (![NSColorPanel sharedColorPanel].isVisible)
+        _picker->endPicker();
+}
+
 @end
 
 #else