Bug 508724 - Native theming for button[type=menu], widget part. r=roc
authorMarkus Stange <mstange@themasta.com>
Tue, 11 Aug 2009 09:23:50 +1200
changeset 31298 424b7ecb49f515cb5ab7ddbbb002b58a4c854f94
parent 31297 c4dd242192e7bdad936f8ac28cf86da8b4d4fa42
child 31299 eb6d574f86db2494ae306bc4a29ca43f7ac0eadb
push id8484
push usermstange@themasta.com
push dateMon, 10 Aug 2009 21:34:34 +0000
treeherdermozilla-central@005a9a447d4a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs508724
milestone1.9.2a2pre
Bug 508724 - Native theming for button[type=menu], widget part. r=roc
widget/src/cocoa/nsNativeThemeCocoa.h
widget/src/cocoa/nsNativeThemeCocoa.mm
widget/src/xpwidgets/nsNativeTheme.cpp
widget/src/xpwidgets/nsNativeTheme.h
--- a/widget/src/cocoa/nsNativeThemeCocoa.h
+++ b/widget/src/cocoa/nsNativeThemeCocoa.h
@@ -118,17 +118,17 @@ protected:
   void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect, nsIFrame* aFrame);
   void DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect,
                       PRBool inDisabled, PRInt32 inState, nsIFrame* aFrame);
   void DrawButton(CGContextRef context, ThemeButtonKind inKind,
                   const HIRect& inBoxRect, PRBool inIsDefault, 
                   PRBool inDisabled, ThemeButtonValue inValue,
                   ThemeButtonAdornment inAdornment, PRInt32 inState, nsIFrame* aFrame);
   void DrawDropdown(CGContextRef context, const HIRect& inBoxRect, PRInt32 inState,
-                    PRBool aIsEditable, nsIFrame* aFrame);
+                    PRUint8 aWidgetType, nsIFrame* aFrame);
   void DrawSpinButtons(CGContextRef context, ThemeButtonKind inKind,
                        const HIRect& inBoxRect,
                        PRBool inDisabled, ThemeDrawState inDrawState,
                        ThemeButtonAdornment inAdornment, PRInt32 inState,
                        nsIFrame* aFrame);
   void DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect,
                           nsIFrame *aFrame);
   void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect,
--- a/widget/src/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/src/cocoa/nsNativeThemeCocoa.mm
@@ -861,28 +861,31 @@ static const CellRenderSettings editable
       {0, 0, 3, 2},    // small
       {0, 1, 3, 3}     // regular
     }
   }
 };
 
 void
 nsNativeThemeCocoa::DrawDropdown(CGContextRef cgContext, const HIRect& inBoxRect,
-                                 PRInt32 inState, PRBool aIsEditable, nsIFrame* aFrame)
+                                 PRInt32 inState, PRUint8 aWidgetType, nsIFrame* aFrame)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
-  NSCell* cell = aIsEditable ? (NSCell*)mComboBoxCell : (NSCell*)mDropdownCell;
+  [mDropdownCell setPullsDown:(aWidgetType == NS_THEME_BUTTON)];
+
+  BOOL isEditable = (aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD);
+  NSCell* cell = isEditable ? (NSCell*)mComboBoxCell : (NSCell*)mDropdownCell;
 
   [cell setEnabled:!IsDisabled(aFrame)];
   [cell setShowsFirstResponder:(IsFocused(aFrame) || (inState & NS_EVENT_STATE_FOCUS))];
   [cell setHighlighted:((inState & NS_EVENT_STATE_ACTIVE) && (inState & NS_EVENT_STATE_HOVER))];
   [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)];
 
-  const CellRenderSettings& settings = aIsEditable ? editableMenulistSettings : dropdownSettings;
+  const CellRenderSettings& settings = isEditable ? editableMenulistSettings : dropdownSettings;
   DrawCellWithSnapping(cell, cgContext, inBoxRect, settings,
                        0.5f, NativeViewForFrame(aFrame), IsFrameRTL(aFrame));
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void
 nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind,
@@ -1583,16 +1586,18 @@ nsNativeThemeCocoa::DrawWidgetBackground
                           IsDisabled(aFrame), eventState, aFrame);
     }
       break;
 
     case NS_THEME_BUTTON:
       if (IsDefaultButton(aFrame)) {
         DrawButton(cgContext, kThemePushButton, macRect, true, IsDisabled(aFrame), 
                    kThemeButtonOff, kThemeAdornmentNone, eventState, aFrame);
+      } else if (IsButtonTypeMenu(aFrame)) {
+        DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame);
       } else {
         DrawPushButton(cgContext, macRect, IsDisabled(aFrame), eventState, aFrame);
       }
       break;
 
     case NS_THEME_BUTTON_BEVEL:
       DrawButton(cgContext, kThemeMediumBevelButton, macRect,
                  IsDefaultButton(aFrame), IsDisabled(aFrame), 
@@ -1659,18 +1664,17 @@ nsNativeThemeCocoa::DrawWidgetBackground
       break;
 
     case NS_THEME_STATUSBAR: 
       DrawStatusBar(cgContext, macRect, aFrame);
       break;
 
     case NS_THEME_DROPDOWN:
     case NS_THEME_DROPDOWN_TEXTFIELD:
-      DrawDropdown(cgContext, macRect, eventState,
-                   (aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD), aFrame);
+      DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame);
       break;
 
     case NS_THEME_DROPDOWN_BUTTON:
       DrawButton(cgContext, kThemeArrowButton, macRect, PR_FALSE,
                  IsDisabled(aFrame), kThemeButtonOn,
                  kThemeAdornmentArrowDownArrow, eventState, aFrame);
       break;
 
@@ -1888,17 +1892,21 @@ nsNativeThemeCocoa::GetWidgetBorder(nsID
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   aResult->SizeTo(0, 0, 0, 0);
 
   switch (aWidgetType) {
     case NS_THEME_BUTTON:
     {
-      aResult->SizeTo(7, 1, 7, 3);
+      if (IsButtonTypeMenu(aFrame)) {
+        *aResult = RTLAwareMargin(kAquaDropdownBorder, aFrame);
+      } else {
+        aResult->SizeTo(7, 1, 7, 3);
+      }
       break;
     }
 
     case NS_THEME_CHECKBOX:
     case NS_THEME_RADIO:
     {
       // nsFormControlFrame::GetIntrinsicWidth and nsFormControlFrame::GetIntrinsicHeight
       // assume a border width of 2px.
--- a/widget/src/xpwidgets/nsNativeTheme.cpp
+++ b/widget/src/xpwidgets/nsNativeTheme.cpp
@@ -156,16 +156,27 @@ nsNativeTheme::GetCheckedOrSelected(nsIF
     }
   }
 
   return CheckBooleanAttr(aFrame, aCheckSelected ? nsWidgetAtoms::selected
                                                  : nsWidgetAtoms::checked);
 }
 
 PRBool
+nsNativeTheme::IsButtonTypeMenu(nsIFrame* aFrame)
+{
+  if (!aFrame)
+    return PR_FALSE;
+
+  nsIContent* content = aFrame->GetContent();
+  return content->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::type,
+                              NS_LITERAL_STRING("menu"), eCaseMatters);
+}
+
+PRBool
 nsNativeTheme::GetIndeterminate(nsIFrame* aFrame)
 {
   if (!aFrame)
     return PR_FALSE;
 
   nsIContent* content = aFrame->GetContent();
 
   if (content->IsNodeOfType(nsINode::eXUL)) {
--- a/widget/src/xpwidgets/nsNativeTheme.h
+++ b/widget/src/xpwidgets/nsNativeTheme.h
@@ -88,16 +88,18 @@ class nsNativeTheme
   // RTL chrome direction
   PRBool IsFrameRTL(nsIFrame* aFrame);
 
   // button:
   PRBool IsDefaultButton(nsIFrame* aFrame) {
     return CheckBooleanAttr(aFrame, nsWidgetAtoms::_default);
   }
 
+  PRBool IsButtonTypeMenu(nsIFrame* aFrame);
+
   // checkbox:
   PRBool IsChecked(nsIFrame* aFrame) {
     return GetCheckedOrSelected(aFrame, PR_FALSE);
   }
 
   // radiobutton:
   PRBool IsSelected(nsIFrame* aFrame) {
     return GetCheckedOrSelected(aFrame, PR_TRUE);