Bug 1428676 Part 4 - Rename menulist-button to menulist-button-orig and make behavior of menulist-button like menulist on Windows. r?mats draft
authorlochang <lochang@mozilla.com>
Thu, 11 Jan 2018 13:33:10 +0800
changeset 719527 46fad9985c854f6229257bfd4feb17ce1b7b271f
parent 719526 e40c3159771b1e1ba305b2ce7ad5768cb02214fa
child 719528 52f7c1987e7129f9cee35dcac6a5f2ad5b8b7c9c
push id95280
push userlochang@mozilla.com
push dateFri, 12 Jan 2018 09:19:41 +0000
reviewersmats
bugs1428676
milestone59.0a1
Bug 1428676 Part 4 - Rename menulist-button to menulist-button-orig and make behavior of menulist-button like menulist on Windows. r?mats MozReview-Commit-ID: GNOviWH6w7B
widget/windows/nsNativeThemeWin.cpp
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -773,16 +773,17 @@ mozilla::Maybe<nsUXThemeClass> nsNativeT
       return Some(eUXSpin);
     case NS_THEME_STATUSBAR:
     case NS_THEME_STATUSBARPANEL:
     case NS_THEME_RESIZERPANEL:
     case NS_THEME_RESIZER:
       return Some(eUXStatus);
     case NS_THEME_MENULIST:
     case NS_THEME_MENULIST_BUTTON:
+    case NS_THEME_MENULIST_BUTTON_ORIG:
       return Some(eUXCombobox);
     case NS_THEME_TREEHEADERCELL:
     case NS_THEME_TREEHEADERSORTARROW:
       return Some(eUXHeader);
     case NS_THEME_LISTBOX:
     case NS_THEME_LISTITEM:
     case NS_THEME_TREEVIEW:
     case NS_THEME_TREETWISTYOPEN:
@@ -1278,16 +1279,53 @@ nsNativeThemeWin::GetThemePartAndState(n
           aState = TS_HOVER;
         else
           aState = TS_NORMAL;
       }
 
       return NS_OK;
     }
     case NS_THEME_MENULIST_BUTTON: {
+      if (mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) {
+        nsIContent* content = aFrame->GetContent();
+        bool isHTML = content && content->IsHTMLElement();
+        bool isChrome = aFrame->GetContent()->IsInChromeDocument();
+        bool useDropBorder = isHTML || (isChrome && IsMenuListEditable(aFrame));
+        EventStates eventState = GetContentState(aFrame, aWidgetType);
+
+        /* On Vista/Win7, we use CBP_DROPBORDER instead of DROPFRAME for HTML
+         * content or for editable menulists; this gives us the thin outline,
+         * instead of the gradient-filled background */
+        if (useDropBorder)
+          aPart = CBP_DROPBORDER;
+        else
+          aPart = CBP_DROPFRAME;
+
+        if (IsDisabled(aFrame, eventState)) {
+          aState = TS_DISABLED;
+        } else if (IsReadOnly(aFrame)) {
+          aState = TS_NORMAL;
+        } else if (IsOpenButton(aFrame)) {
+          aState = TS_ACTIVE;
+        } else {
+          if (useDropBorder && (eventState.HasState(NS_EVENT_STATE_FOCUS) || IsFocused(aFrame)))
+            aState = TS_ACTIVE;
+          else if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
+            aState = TS_ACTIVE;
+          else if (eventState.HasState(NS_EVENT_STATE_HOVER))
+            aState = TS_HOVER;
+          else
+            aState = TS_NORMAL;
+        }
+
+        return NS_OK;
+      }
+      MOZ_FALLTHROUGH;
+    }
+    case NS_THEME_MENULIST_BUTTON_ORIG: {
       bool isHTML = IsHTMLContent(aFrame);
       nsIFrame* parentFrame = aFrame->GetParent();
       bool isMenulist = !isHTML && parentFrame->IsMenuFrame();
       bool isOpen = false;
 
       // HTML select and XUL menulist dropdown buttons get state from the parent.
       if (isHTML || isMenulist)
         aFrame = parentFrame;
@@ -1800,17 +1838,19 @@ RENDER_AGAIN:
       renderRect.left = glyphSize.cx;
       renderRect.right = renderRect.left + glyphSize.cx;
     }
     DrawThemeBGRTLAware(theme, hdc, part, state, &renderRect, &clipRect,
                         IsFrameRTL(aFrame));
   }
   // The following widgets need to be RTL-aware
   else if (aWidgetType == NS_THEME_RESIZER ||
-           aWidgetType == NS_THEME_MENULIST_BUTTON)
+           aWidgetType == NS_THEME_MENULIST_BUTTON_ORIG ||
+           (aWidgetType == NS_THEME_MENULIST_BUTTON &&
+             !mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")))
   {
     DrawThemeBGRTLAware(theme, hdc, part, state,
                         &widgetRect, &clipRect, IsFrameRTL(aFrame));
   }
   else if (aWidgetType == NS_THEME_NUMBER_INPUT ||
            aWidgetType == NS_THEME_TEXTFIELD ||
            aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
     DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
@@ -2089,17 +2129,19 @@ nsNativeThemeWin::GetWidgetPadding(nsDev
     aResult->left = aResult->right = popupSize.cx;
     ScaleForFrameDPI(aResult, aFrame);
     return ok;
   }
 
   if (aWidgetType == NS_THEME_NUMBER_INPUT ||
       aWidgetType == NS_THEME_TEXTFIELD ||
       aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
-      aWidgetType == NS_THEME_MENULIST)
+      aWidgetType == NS_THEME_MENULIST ||
+      (aWidgetType == NS_THEME_MENULIST_BUTTON &&
+        mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")))
   {
     // If we have author-specified padding for these elements, don't do the
     // fixups below.
     if (aFrame->PresContext()->HasAuthorSpecifiedRules(aFrame, NS_AUTHOR_SPECIFIED_PADDING))
       return false;
   }
 
   /* textfields need extra pixels on all sides, otherwise they wrap their
@@ -2110,17 +2152,19 @@ nsNativeThemeWin::GetWidgetPadding(nsDev
    */
   if (aWidgetType == NS_THEME_NUMBER_INPUT ||
       aWidgetType == NS_THEME_TEXTFIELD ||
       aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
     aResult->top = aResult->bottom = 2;
     aResult->left = aResult->right = 2;
     ScaleForFrameDPI(aResult, aFrame);
     return ok;
-  } else if (IsHTMLContent(aFrame) && aWidgetType == NS_THEME_MENULIST) {
+  } else if (IsHTMLContent(aFrame) && (aWidgetType == NS_THEME_MENULIST ||
+               (aWidgetType == NS_THEME_MENULIST_BUTTON &&
+               mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")))) {
     /* For content menulist controls, we need an extra pixel so that we have
      * room to draw our focus rectangle stuff. Otherwise, the focus rect might
      * overlap the control's border.
      */
     aResult->top = aResult->bottom = 1;
     aResult->left = aResult->right = 1;
     ScaleForFrameDPI(aResult, aFrame);
     return ok;
@@ -2187,17 +2231,19 @@ nsNativeThemeWin::GetWidgetOverflow(nsDe
    * This is fairly minor, as by default there is nothing in that area, and
    * a border only shows up if the widget is being hovered.
    */
 #if 0
   /* We explicitly draw dropdown buttons in HTML content 1px bigger up, right,
    * and bottom so that they overlap the dropdown's border like they're
    * supposed to.
    */
-  if (aWidgetType == NS_THEME_MENULIST_BUTTON &&
+  if (((aWidgetType == NS_THEME_MENULIST_BUTTON &&
+        mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) ||
+        aWidgetType == NS_THEME_MENULIST_BUTTON_ORIG) &&
       IsHTMLContent(aFrame) &&
       !IsWidgetStyled(aFrame->GetParent()->PresContext(),
                       aFrame->GetParent(),
                       NS_THEME_MENULIST))
   {
     int32_t p2a = aContext->AppUnitsPerDevPixel();
     /* Note: no overflow on the left */
     nsMargin m(p2a, p2a, p2a, 0);
@@ -2277,16 +2323,22 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
     case NS_THEME_SCROLLBARTHUMB_HORIZONTAL:
     case NS_THEME_SCROLLBARBUTTON_UP:
     case NS_THEME_SCROLLBARBUTTON_DOWN:
     case NS_THEME_SCROLLBARBUTTON_LEFT:
     case NS_THEME_SCROLLBARBUTTON_RIGHT:
     case NS_THEME_SCROLLBAR_HORIZONTAL:
     case NS_THEME_SCROLLBAR_VERTICAL:
     case NS_THEME_MENULIST_BUTTON: {
+      if (mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) {
+        break;
+      }
+      MOZ_FALLTHROUGH;
+    }
+    case NS_THEME_MENULIST_BUTTON_ORIG: {
       rv = ClassicGetMinimumWidgetSize(aFrame, aWidgetType, aResult, aIsOverridable);
       ScaleForFrameDPI(aResult, aFrame);
       return rv;
     }
     case NS_THEME_MENUITEM:
     case NS_THEME_CHECKMENUITEM:
     case NS_THEME_RADIOMENUITEM:
       if(!IsTopLevelMenu(aFrame))
@@ -2490,17 +2542,18 @@ nsNativeThemeWin::WidgetStateChanged(nsI
       aWidgetType == NS_THEME_WINDOW_BUTTON_MAXIMIZE ||
       aWidgetType == NS_THEME_WINDOW_BUTTON_RESTORE) {
     *aShouldRepaint = true;
     return NS_OK;
   }
 
   // We need to repaint the dropdown arrow in vista HTML combobox controls when
   // the control is closed to get rid of the hover effect.
-  if ((aWidgetType == NS_THEME_MENULIST || aWidgetType == NS_THEME_MENULIST_BUTTON) &&
+  if ((aWidgetType == NS_THEME_MENULIST || aWidgetType == NS_THEME_MENULIST_BUTTON ||
+        aWidgetType == NS_THEME_MENULIST_BUTTON) &&
       IsHTMLContent(aFrame))
   {
     *aShouldRepaint = true;
     return NS_OK;
   }
 
   // XXXdwh Not sure what can really be done here.  Can at least guess for
   // specific widgets that they're highly unlikely to have certain states.
@@ -2566,17 +2619,19 @@ nsNativeThemeWin::ThemeSupportsWidget(ns
 
   return false;
 }
 
 bool 
 nsNativeThemeWin::WidgetIsContainer(uint8_t aWidgetType)
 {
   // XXXdwh At some point flesh all of this out.
-  if (aWidgetType == NS_THEME_MENULIST_BUTTON || 
+  if ((aWidgetType == NS_THEME_MENULIST_BUTTON &&
+        !mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) ||
+      aWidgetType == NS_THEME_MENULIST_BUTTON_ORIG ||
       aWidgetType == NS_THEME_RADIO ||
       aWidgetType == NS_THEME_CHECKBOX)
     return false;
   return true;
 }
 
 bool
 nsNativeThemeWin::ThemeDrawsFocusForWidget(uint8_t aWidgetType)
@@ -2716,16 +2771,17 @@ nsNativeThemeWin::ClassicThemeSupportsWi
     case NS_THEME_SCROLLBAR_VERTICAL:
     case NS_THEME_SCROLLBAR_HORIZONTAL:
     case NS_THEME_SCROLLBAR_NON_DISAPPEARING:
     case NS_THEME_SCALE_HORIZONTAL:
     case NS_THEME_SCALE_VERTICAL:
     case NS_THEME_SCALETHUMB_HORIZONTAL:
     case NS_THEME_SCALETHUMB_VERTICAL:
     case NS_THEME_MENULIST_BUTTON:
+    case NS_THEME_MENULIST_BUTTON_ORIG:
     case NS_THEME_INNER_SPIN_BUTTON:
     case NS_THEME_SPINNER_UPBUTTON:
     case NS_THEME_SPINNER_DOWNBUTTON:
     case NS_THEME_LISTBOX:
     case NS_THEME_TREEVIEW:
     case NS_THEME_MENULIST_TEXTFIELD:
     case NS_THEME_MENULIST:
     case NS_THEME_TOOLTIP:
@@ -2776,16 +2832,22 @@ nsNativeThemeWin::ClassicGetWidgetBorder
       break;
     case NS_THEME_STATUSBAR:
       (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
       (*aResult).top = 2;
       break;
     case NS_THEME_LISTBOX:
     case NS_THEME_TREEVIEW:
     case NS_THEME_MENULIST:
+    case NS_THEME_MENULIST_BUTTON: {
+      if (!mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) {
+        break;
+      }
+      MOZ_FALLTHROUGH;
+    }
     case NS_THEME_MENULIST_TEXTFIELD:
     case NS_THEME_TAB:
     case NS_THEME_NUMBER_INPUT:
     case NS_THEME_TEXTFIELD:
     case NS_THEME_TEXTFIELD_MULTILINE:
     case NS_THEME_FOCUS_OUTLINE:
       (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 2;
       break;
@@ -2925,17 +2987,23 @@ nsNativeThemeWin::ClassicGetMinimumWidge
       (*aResult).height = 20;
       *aIsOverridable = false;
       break;
     case NS_THEME_SCALETHUMB_VERTICAL:
       (*aResult).width = 20;
       (*aResult).height = 12;
       *aIsOverridable = false;
       break;
-    case NS_THEME_MENULIST_BUTTON:
+    case NS_THEME_MENULIST_BUTTON: {
+      if (mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) {
+        break;
+      }
+      MOZ_FALLTHROUGH;
+    }
+    case NS_THEME_MENULIST_BUTTON_ORIG:
       (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
       break;
     case NS_THEME_MENULIST:
     case NS_THEME_BUTTON:
     case NS_THEME_GROUPBOX:
     case NS_THEME_LISTBOX:
     case NS_THEME_TREEVIEW:
     case NS_THEME_NUMBER_INPUT:
@@ -3205,16 +3273,22 @@ nsresult nsNativeThemeWin::ClassicGetThe
     case NS_THEME_TABPANEL:
     case NS_THEME_TABPANELS:
     case NS_THEME_MENUBAR:
     case NS_THEME_MENUPOPUP:
     case NS_THEME_GROUPBOX:
       // these don't use DrawFrameControl
       return NS_OK;
     case NS_THEME_MENULIST_BUTTON: {
+      if (mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) {
+        return NS_OK;
+      }
+      MOZ_FALLTHROUGH;
+    }
+    case NS_THEME_MENULIST_BUTTON_ORIG: {
 
       aPart = DFC_SCROLL;
       aState = DFCS_SCROLLCOMBOBOX;
 
       nsIFrame* parentFrame = aFrame->GetParent();
       bool isHTML = IsHTMLContent(aFrame);
       bool isMenulist = !isHTML && parentFrame->IsMenuFrame();
       bool isOpen = false;
@@ -3588,30 +3662,41 @@ RENDER_AGAIN:
     case NS_THEME_RADIO:
     case NS_THEME_SCROLLBARBUTTON_UP:
     case NS_THEME_SCROLLBARBUTTON_DOWN:
     case NS_THEME_SCROLLBARBUTTON_LEFT:
     case NS_THEME_SCROLLBARBUTTON_RIGHT:
     case NS_THEME_INNER_SPIN_BUTTON:
     case NS_THEME_SPINNER_UPBUTTON:
     case NS_THEME_SPINNER_DOWNBUTTON:
-    case NS_THEME_MENULIST_BUTTON:
+    case NS_THEME_MENULIST_BUTTON_ORIG:
     case NS_THEME_RESIZER: {
       int32_t oldTA;
       // setup DC to make DrawFrameControl draw correctly
       oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
       ::DrawFrameControl(hdc, &widgetRect, part, state);
       ::SetTextAlign(hdc, oldTA);
       break;
     }
     // Draw controls with 2px 3D inset border
     case NS_THEME_NUMBER_INPUT:
     case NS_THEME_TEXTFIELD:
     case NS_THEME_TEXTFIELD_MULTILINE:
     case NS_THEME_LISTBOX:
+    case NS_THEME_MENULIST_BUTTON: {
+      if (!mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) {
+        int32_t oldTA;
+        // setup DC to make DrawFrameControl draw correctly
+        oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
+        ::DrawFrameControl(hdc, &widgetRect, part, state);
+        ::SetTextAlign(hdc, oldTA);
+        break;
+      }
+      MOZ_FALLTHROUGH;
+    }
     case NS_THEME_MENULIST:
     case NS_THEME_MENULIST_TEXTFIELD: {
       // Draw inset edge
       ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
       EventStates eventState = GetContentState(aFrame, aWidgetType);
 
       // Fill in background
       if (IsDisabled(aFrame, eventState) ||
@@ -4015,17 +4100,26 @@ nsNativeThemeWin::GetWidgetNativeDrawing
     case NS_THEME_MENUBAR:
     case NS_THEME_MENUPOPUP:
     case NS_THEME_MENUITEM:
       break;
 
     // the dropdown button /almost/ renders correctly with scaling,
     // except that the graphic in the dropdown button (the downward arrow)
     // doesn't get scaled up.
-    case NS_THEME_MENULIST_BUTTON:
+    case NS_THEME_MENULIST_BUTTON: {
+      if (mozilla::Preferences::GetBool("layout.css.webkit-appearance.enabled")) {
+        return
+          gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA |
+          gfxWindowsNativeDrawing::CAN_AXIS_ALIGNED_SCALE |
+          gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM;
+      }
+      MOZ_FALLTHROUGH;
+    }
+    case NS_THEME_MENULIST_BUTTON_ORIG:
     // these are definitely no; they're all graphics that don't get scaled up
     case NS_THEME_CHECKBOX:
     case NS_THEME_RADIO:
     case NS_THEME_GROUPBOX:
     case NS_THEME_CHECKMENUITEM:
     case NS_THEME_RADIOMENUITEM:
     case NS_THEME_MENUCHECKBOX:
     case NS_THEME_MENURADIO: