Bug 638176 - Make <progress> friendly with -moz-appearance:none and author styling. r=bz
authorMounir Lamouri <mounir.lamouri@gmail.com>
Fri, 06 May 2011 12:00:30 +0200
changeset 69389 2bfb06f51613ce15e7ceb9ea53c98fe0a9e3ef9b
parent 69388 78ea30b54e01663116cc7a6df5816df0af66a10d
child 69390 00d5a081d5d319014113353f7b1976b7218f3f85
push id76
push userbzbarsky@mozilla.com
push dateTue, 05 Jul 2011 17:00:57 +0000
treeherdermozilla-beta@d3a2732c35f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs638176
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 638176 - Make <progress> friendly with -moz-appearance:none and author styling. r=bz
layout/forms/nsProgressFrame.cpp
layout/forms/nsProgressFrame.h
widget/reftests/progressbar-fallback-default-style-ref.html
widget/reftests/progressbar-fallback-default-style.html
widget/reftests/reftest.list
widget/src/xpwidgets/Makefile.in
widget/src/xpwidgets/nsNativeTheme.cpp
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -132,16 +132,17 @@ nsProgressFrame::CreateAnonymousContent(
 void
 nsProgressFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
                                           PRUint32 aFilter)
 {
   aElements.MaybeAppendElement(mBarDiv);
 }
 
 NS_QUERYFRAME_HEAD(nsProgressFrame)
+  NS_QUERYFRAME_ENTRY(nsProgressFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLContainerFrame)
 
 
 NS_IMETHODIMP nsProgressFrame::Reflow(nsPresContext*           aPresContext,
                                       nsHTMLReflowMetrics&     aDesiredSize,
                                       const nsHTMLReflowState& aReflowState,
                                       nsReflowStatus&          aStatus)
@@ -208,22 +209,21 @@ nsProgressFrame::ReflowBarFrame(nsIFrame
 
   if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
     xoffset += aReflowState.ComputedWidth() - width;
   }
 
   // The bar width is fixed in these cases:
   // - the progress position is determined: the bar width is fixed according
   //   to it's value.
-  // - the progress position is indeterminate and the bar appearance is the
-  //   native one ('progresschunk'): the bar width is forced to 100%.
+  // - the progress position is indeterminate and the bar appearance should be
+  //   shown as native: the bar width is forced to 100%.
   // Otherwise (when the progress is indeterminate and the bar appearance isn't
   // native), the bar width isn't fixed and can be set by the author.
-  if (position != -1 ||
-      aBarFrame->GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR_CHUNK) {
+  if (position != -1 || ShouldUseNativeStyle()) {
     width -= reflowState.mComputedMargin.LeftRight() +
              reflowState.mComputedBorderPadding.LeftRight();
     width = NS_MAX(width, 0);
     reflowState.SetComputedWidth(width);
   }
 
   xoffset += reflowState.mComputedMargin.left;
   yoffset += reflowState.mComputedMargin.top;
@@ -267,8 +267,23 @@ nsProgressFrame::ComputeAutoSize(nsRende
 
   nsSize autoSize;
   autoSize.height = autoSize.width = fontMet->Font().size; // 1em
   autoSize.width *= 10; // 10em
 
   return autoSize;
 }
 
+bool
+nsProgressFrame::ShouldUseNativeStyle() const
+{
+  // Use the native style if these conditions are satisfied:
+  // - both frames use the native appearance;
+  // - neither frame has author specified rules setting the border or the
+  //   background.
+  return GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR &&
+         mBarDiv->GetPrimaryFrame()->GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR_CHUNK &&
+         !PresContext()->HasAuthorSpecifiedRules(const_cast<nsProgressFrame*>(this),
+                                                 NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND) &&
+         !PresContext()->HasAuthorSpecifiedRules(mBarDiv->GetPrimaryFrame(),
+                                                 NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND);
+}
+
--- a/layout/forms/nsProgressFrame.h
+++ b/layout/forms/nsProgressFrame.h
@@ -87,16 +87,21 @@ public:
                                  nsSize aPadding, PRBool aShrinkWrap);
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
     return nsHTMLContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
+  /**
+   * Returns whether the frame and its child should use the native style.
+   */
+  bool ShouldUseNativeStyle() const;
+
 protected:
   // Helper function which reflow the anonymous div frame.
   void ReflowBarFrame(nsIFrame*                aBarFrame,
                       nsPresContext*           aPresContext,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus);
 
   /**
new file mode 100644
--- /dev/null
+++ b/widget/reftests/progressbar-fallback-default-style-ref.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+  <style>
+    div.progress-element {
+      /**
+       * The purpose of this test is to not show the native style.
+       * -moz-appearance: progressbar;
+       */
+      display: inline-block;
+      height: 1em;
+      width: 10em;
+      vertical-align: -0.2em;
+
+      /* Default style in case of there is -moz-appearance: none; */
+      border: 2px solid;
+      -moz-border-top-colors: ThreeDShadow -moz-Dialog;
+      -moz-border-right-colors: ThreeDHighlight -moz-Dialog;
+      -moz-border-bottom-colors: ThreeDHighlight -moz-Dialog;
+      -moz-border-left-colors: ThreeDShadow -moz-Dialog;
+      background-color: -moz-Dialog;
+    }
+
+    div.progress-bar {
+      /**
+       * The purpose of this test is to not show the native style.
+       * -moz-appearance: progresschunk;
+       */
+
+      height: 100%;
+      width: 100%;
+
+      /* Default style in case of there is -moz-appearance: none; */
+      background-color: ThreeDShadow;
+    }
+
+    div.progress-element { padding: 5px; }
+    body > div:nth-child(1)  { -moz-appearance: none; }
+    body > div:nth-child(2) > .progress-bar { -moz-appearance: none; }
+    body > div:nth-child(3)  { background-color: red; }
+    body > div:nth-child(4) > .progress-bar { background-color: red; }
+    body > div:nth-child(5)  { border: 2px solid red; }
+    body > div:nth-child(6) > .progress-bar { border: 5px solid red; }
+  </style>
+  <body>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+    <div class="progress-element">
+      <div class="progress-bar"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/widget/reftests/progressbar-fallback-default-style.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+  <style>
+    progress { padding: 5px }
+    body > progress:nth-child(1) { -moz-appearance: none; }
+    body > progress:nth-child(2)::-moz-progress-bar { -moz-appearance: none; }
+    body > progress:nth-child(3) { background-color: red; }
+    body > progress:nth-child(4)::-moz-progress-bar { background-color: red; }
+    body > progress:nth-child(5) { border: 2px solid red; }
+    body > progress:nth-child(6)::-moz-progress-bar { border: 5px solid red; }
+  </style>
+  <body>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+    <progress></progress>
+  </body>
+</html>
--- a/widget/reftests/reftest.list
+++ b/widget/reftests/reftest.list
@@ -1,1 +1,2 @@
 skip-if(!cocoaWidget) != 507947.html about:blank
+== progressbar-fallback-default-style.html progressbar-fallback-default-style-ref.html
--- a/widget/src/xpwidgets/Makefile.in
+++ b/widget/src/xpwidgets/Makefile.in
@@ -95,16 +95,19 @@ endif
 SHARED_LIBRARY_LIBS = ../shared/$(LIB_PREFIX)widget_shared.$(LIB_SUFFIX)
 ifdef MOZ_X11
 SHARED_LIBRARY_LIBS += ../shared/x11/$(LIB_PREFIX)widget_shared_x11.$(LIB_SUFFIX)
 endif
 
 LOCAL_INCLUDES	+= \
 		-I$(srcdir)/../$(MOZ_WIDGET_TOOLKIT) \
 		-I$(srcdir)/../shared \
+		-I$(topsrcdir)/layout/forms \
+		-I$(topsrcdir)/layout/generic \
+		-I$(topsrcdir)/layout/xul/base/src \
 		-I$(srcdir) \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/widget/src/xpwidgets/nsNativeTheme.cpp
+++ b/widget/src/xpwidgets/nsNativeTheme.cpp
@@ -46,16 +46,17 @@
 #include "nsEventStateManager.h"
 #include "nsString.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsILookAndFeel.h"
 #include "nsThemeConstants.h"
 #include "nsIComponentManager.h"
 #include "nsPIDOMWindow.h"
+#include "nsProgressFrame.h"
 
 nsNativeTheme::nsNativeTheme()
 : mAnimatedContentTimeout(PR_UINT32_MAX)
 {
 }
 
 NS_IMPL_ISUPPORTS1(nsNativeTheme, nsITimerCallback)
 
@@ -246,16 +247,29 @@ nsNativeTheme::IsWidgetStyled(nsPresCont
       parentFrame = parentFrame->GetParent();
       if (parentFrame) {
         return IsWidgetStyled(aPresContext, parentFrame,
                               parentFrame->GetStyleDisplay()->mAppearance);
       }
     }
   }
 
+  /**
+   * Progress bar appearance should be the same for the bar and the container
+   * frame. nsProgressFrame owns the logic and will tell us what we should do.
+   */
+  if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
+      aWidgetType == NS_THEME_PROGRESSBAR) {
+    nsProgressFrame* progressFrame = do_QueryFrame(aWidgetType == NS_THEME_PROGRESSBAR_CHUNK
+                                       ? aFrame->GetParent() : aFrame);
+    if (progressFrame) {
+      return !progressFrame->ShouldUseNativeStyle();
+    }
+  }
+
   return (aWidgetType == NS_THEME_BUTTON ||
           aWidgetType == NS_THEME_TEXTFIELD ||
           aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
           aWidgetType == NS_THEME_LISTBOX ||
           aWidgetType == NS_THEME_DROPDOWN) &&
          aFrame->GetContent()->IsHTML() &&
          aPresContext->HasAuthorSpecifiedRules(aFrame,
                                                NS_AUTHOR_SPECIFIED_BORDER |