Bug 427928 - part 2, Add NS_THEME_FOCUS_OUTLINE to support drawing a native themed focus outline. r=roc
authorMats Palmgren <mats@mozilla.com>
Sat, 14 Jun 2014 12:48:07 +0000
changeset 188752 f0b66757843a823d1f7beca302b8b483ec055ceb
parent 188751 c1d28cf0b805b8d2601e4621baa9acd1f16e22c3
child 188753 dde12de3eedf06a341f805a3606af06265e2ee75
push id44905
push usermpalmgren@mozilla.com
push dateSat, 14 Jun 2014 12:48:24 +0000
treeherdermozilla-inbound@eda22df589d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs427928
milestone33.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 427928 - part 2, Add NS_THEME_FOCUS_OUTLINE to support drawing a native themed focus outline. r=roc
gfx/src/nsThemeConstants.h
layout/base/nsCSSRendering.cpp
layout/generic/nsFrame.cpp
--- a/gfx/src/nsThemeConstants.h
+++ b/gfx/src/nsThemeConstants.h
@@ -13,16 +13,19 @@
 
 // A checkbox element. 
 #define NS_THEME_CHECKBOX                                  3
 
 // A rectangular button that contains complex content
 // like images (e.g. HTML <button> elements)
 #define NS_THEME_BUTTON_BEVEL                              7
 
+// A themed focus outline (for outline:auto)
+#define NS_THEME_FOCUS_OUTLINE                             8
+
 // The toolbox that contains the toolbars.
 #define NS_THEME_TOOLBOX                                   11
 
 // A toolbar in an application window.
 #define NS_THEME_TOOLBAR                                   12
 
 // A single toolbar button (with no associated dropdown)
 #define NS_THEME_TOOLBAR_BUTTON                            13
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -26,16 +26,17 @@
 #include "nsIDocumentInlines.h"
 #include "nsIScrollableFrame.h"
 #include "imgIRequest.h"
 #include "imgIContainer.h"
 #include "ImageOps.h"
 #include "nsCSSRendering.h"
 #include "nsCSSColorUtils.h"
 #include "nsITheme.h"
+#include "nsThemeConstants.h"
 #include "nsLayoutUtils.h"
 #include "nsBlockFrame.h"
 #include "gfxContext.h"
 #include "nsRenderingContext.h"
 #include "nsStyleStructInlines.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsCSSProps.h"
 #include "nsContentUtils.h"
@@ -766,20 +767,21 @@ nsCSSRendering::PaintOutline(nsPresConte
 {
   nscoord             twipsRadii[8];
 
   // Get our style context's color struct.
   const nsStyleOutline* ourOutline = aStyleContext->StyleOutline();
   MOZ_ASSERT(ourOutline != NS_STYLE_BORDER_STYLE_NONE,
              "shouldn't have created nsDisplayOutline item");
 
+  uint8_t outlineStyle = ourOutline->GetOutlineStyle();
   nscoord width;
   ourOutline->GetOutlineWidth(width);
 
-  if (width == 0) {
+  if (width == 0 && outlineStyle != NS_STYLE_BORDER_STYLE_AUTO) {
     // Empty outline
     return;
   }
 
   nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame
     (aForFrame, false);
   nsStyleContext* bgContext = bgFrame->StyleContext();
   nscolor bgColor =
@@ -820,18 +822,27 @@ nsCSSRendering::PaintOutline(nsPresConte
   // get the outer rectangles
   gfxRect oRect(nsLayoutUtils::RectToGfxRect(outerRect, twipsPerPixel));
 
   // convert the radii
   nsMargin outlineMargin(width, width, width, width);
   gfxCornerSizes outlineRadii;
   ComputePixelRadii(twipsRadii, twipsPerPixel, &outlineRadii);
 
-  uint8_t outlineStyle = ourOutline->GetOutlineStyle();
   if (outlineStyle == NS_STYLE_BORDER_STYLE_AUTO) {
+    nsITheme* theme = aPresContext->GetTheme();
+    if (theme && theme->ThemeSupportsWidget(aPresContext, aForFrame,
+                                            NS_THEME_FOCUS_OUTLINE)) {
+      theme->DrawWidgetBackground(&aRenderingContext, aForFrame,
+                                  NS_THEME_FOCUS_OUTLINE, innerRect,
+                                  aDirtyRect);
+      return;
+    } else if (width == 0) {
+      return; // empty outline
+    }
     // http://dev.w3.org/csswg/css-ui/#outline
     // "User agents may treat 'auto' as 'solid'."
     outlineStyle = NS_STYLE_BORDER_STYLE_SOLID;
   }
 
   uint8_t outlineStyles[4] = { outlineStyle, outlineStyle,
                                outlineStyle, outlineStyle };
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -81,16 +81,19 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/css/ImageLoader.h"
 #include "mozilla/gfx/Tools.h"
 #include "nsPrintfCString.h"
 #include "ActiveLayerTracker.h"
 
+#include "nsITheme.h"
+#include "nsThemeConstants.h"
+
 using namespace mozilla;
 using namespace mozilla::css;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 
 // Struct containing cached metrics for box-wrapped frames.
 struct nsBoxLayoutMetrics
@@ -7110,24 +7113,25 @@ UnionBorderBoxes(nsIFrame* aFrame, bool 
   return u;
 }
 
 static void
 ComputeAndIncludeOutlineArea(nsIFrame* aFrame, nsOverflowAreas& aOverflowAreas,
                              const nsSize& aNewSize)
 {
   const nsStyleOutline* outline = aFrame->StyleOutline();
-  if (outline->GetOutlineStyle() == NS_STYLE_BORDER_STYLE_NONE) {
+  const uint8_t outlineStyle = outline->GetOutlineStyle();
+  if (outlineStyle == NS_STYLE_BORDER_STYLE_NONE) {
     return;
   }
 
   nscoord width;
   DebugOnly<bool> result = outline->GetOutlineWidth(width);
   NS_ASSERTION(result, "GetOutlineWidth had no cached outline width");
-  if (width <= 0) {
+  if (width <= 0 && outlineStyle != NS_STYLE_BORDER_STYLE_AUTO) {
     return;
   }
 
   // When the outline property is set on :-moz-anonymous-block or
   // :-moz-anonymous-positioned-block pseudo-elements, it inherited
   // that outline from the inline that was broken because it
   // contained a block.  In that case, we don't want a really wide
   // outline if the block inside the inline is narrow, so union the
@@ -7171,29 +7175,40 @@ ComputeAndIncludeOutlineArea(nsIFrame* a
           r = nsDisplayTransform::TransformRect(r, parent, nsPoint(0, 0));
         }
       }
 
       innerRect.UnionRect(innerRect, r);
     }
   }
 
+  // Keep this code in sync with GetOutlineInnerRect in nsCSSRendering.cpp.
   aFrame->Properties().Set(nsIFrame::OutlineInnerRectProperty(),
                            new nsRect(innerRect));
-
-  nscoord offset = outline->mOutlineOffset;
-  nscoord inflateBy = std::max(width + offset, 0);
-
-  // Keep this code (and the storing of properties just above) in
-  // sync with GetOutlineInnerRect in nsCSSRendering.cpp.
+  const nscoord offset = outline->mOutlineOffset;
   nsRect outerRect(innerRect);
-  outerRect.Inflate(inflateBy, inflateBy);
+  bool useOutlineAuto = outlineStyle == NS_STYLE_BORDER_STYLE_AUTO;
+  if (MOZ_UNLIKELY(useOutlineAuto)) {
+    nsPresContext* presContext = aFrame->PresContext();
+    nsITheme* theme = presContext->GetTheme();
+    if (theme && theme->ThemeSupportsWidget(presContext, aFrame,
+                                            NS_THEME_FOCUS_OUTLINE)) {
+      outerRect.Inflate(offset);
+      theme->GetWidgetOverflow(presContext->DeviceContext(), aFrame,
+                               NS_THEME_FOCUS_OUTLINE, &outerRect);
+    } else {
+      useOutlineAuto = false;
+    }
+  }
+  if (MOZ_LIKELY(!useOutlineAuto)) {
+    outerRect.Inflate(width + offset);
+  }
 
   nsRect& vo = aOverflowAreas.VisualOverflow();
-  vo.UnionRectEdges(vo, outerRect);
+  vo.UnionRectEdges(vo, innerRect.Union(outerRect));
 }
 
 bool
 nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
                                  nsSize aNewSize, nsSize* aOldSize)
 {
   NS_ASSERTION(FrameMaintainsOverflow(this),
                "Don't call - overflow rects not maintained on these SVG frames");